fix(ready): exclude molecule steps from bd ready by default (#1246)

* fix(ready): exclude molecule steps from bd ready by default (GH#1239)

Add ID prefix constants (IDPrefixMol, IDPrefixWisp) to types.go as single
source of truth. Update pour.go and wisp.go to use these constants.

GetReadyWork now excludes issues with -mol- in their ID when no explicit
type filter is specified. Users can still see mol steps with --type=task.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(ready): config-driven ID pattern exclusion (GH#1239)

Add ready.exclude_id_patterns config for excluding IDs from bd ready.
Default patterns: -mol-, -wisp- (molecule steps and wisps).

Changes:
- Add IncludeMolSteps to WorkFilter for internal callers
- Update findGateReadyMolecules and getMoleculeCurrentStep to use it
- Make exclusion patterns config-driven via ready.exclude_id_patterns
- Remove hardcoded MolStepIDPattern() in favor of config
- Add test for custom patterns (e.g., gastown's -role-)

Usage: bd config set ready.exclude_id_patterns "-mol-,-wisp-,-role-"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: remove -role- example from ready.go comments

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: remove GH#1239 references from code comments

Issue references belong in commit messages, not code.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
aleiby
2026-01-21 19:30:15 -08:00
committed by GitHub
parent 46b1678274
commit 0b6df198a5
9 changed files with 210 additions and 11 deletions

View File

@@ -184,8 +184,9 @@ func getMoleculeProgress(ctx context.Context, s storage.Storage, moleculeID stri
}
// Get ready issues for this molecule
// IncludeMolSteps: true because we specifically need to see molecule steps here
readyIDs := make(map[string]bool)
readyIssues, err := s.GetReadyWork(ctx, types.WorkFilter{})
readyIssues, err := s.GetReadyWork(ctx, types.WorkFilter{IncludeMolSteps: true})
if err == nil {
for _, issue := range readyIssues {
readyIDs[issue.ID] = true

View File

@@ -131,7 +131,8 @@ func findGateReadyMolecules(ctx context.Context, s storage.Storage) ([]*GatedMol
}
// Step 2: Get ready work to check which steps are ready
readyIssues, err := s.GetReadyWork(ctx, types.WorkFilter{Limit: 500})
// IncludeMolSteps: true because we specifically need to see molecule steps here
readyIssues, err := s.GetReadyWork(ctx, types.WorkFilter{Limit: 500, IncludeMolSteps: true})
if err != nil {
return nil, fmt.Errorf("getting ready work: %w", err)
}

View File

@@ -2682,7 +2682,7 @@ func TestPourRootTitleDescSubstitution(t *testing.T) {
"desc": "My description",
}
result, err := spawnMolecule(ctx, s, subgraph, vars, "", "test", false, "mol")
result, err := spawnMolecule(ctx, s, subgraph, vars, "", "test", false, types.IDPrefixMol)
if err != nil {
t.Fatalf("spawnMolecule failed: %v", err)
}
@@ -2755,7 +2755,7 @@ func TestPourRootTitleOnly(t *testing.T) {
}
vars := map[string]string{"title": "Custom Title"}
result, err := spawnMolecule(ctx, s, subgraph, vars, "", "test", false, "mol")
result, err := spawnMolecule(ctx, s, subgraph, vars, "", "test", false, types.IDPrefixMol)
if err != nil {
t.Fatalf("spawnMolecule failed: %v", err)
}
@@ -2811,7 +2811,7 @@ func TestPourRootNoVars(t *testing.T) {
}
vars := map[string]string{"version": "1.2.3"}
result, err := spawnMolecule(ctx, s, subgraph, vars, "", "test", false, "mol")
result, err := spawnMolecule(ctx, s, subgraph, vars, "", "test", false, types.IDPrefixMol)
if err != nil {
t.Fatalf("spawnMolecule failed: %v", err)
}

View File

@@ -226,8 +226,8 @@ func runPour(cmd *cobra.Command, args []string) {
}
// Spawn as persistent mol (ephemeral=false)
// Use "mol" prefix for distinct visual recognition
result, err := spawnMolecule(ctx, store, subgraph, vars, assignee, actor, false, "mol")
// Use mol prefix for distinct visual recognition (see types.IDPrefixMol)
result, err := spawnMolecule(ctx, store, subgraph, vars, assignee, actor, false, types.IDPrefixMol)
if err != nil {
fmt.Fprintf(os.Stderr, "Error pouring proto: %v\n", err)
os.Exit(1)

View File

@@ -262,8 +262,8 @@ func runWispCreate(cmd *cobra.Command, args []string) {
}
// Spawn as ephemeral in main database (Ephemeral=true, skips JSONL export)
// Use "wisp" prefix for distinct visual recognition
result, err := spawnMolecule(ctx, store, subgraph, vars, "", actor, true, "wisp")
// Use wisp prefix for distinct visual recognition (see types.IDPrefixWisp)
result, err := spawnMolecule(ctx, store, subgraph, vars, "", actor, true, types.IDPrefixWisp)
if err != nil {
fmt.Fprintf(os.Stderr, "Error creating wisp: %v\n", err)
os.Exit(1)