Enables cross-repo issue lookups via routes.jsonl configuration.
Running `bd show gt-xyz` from ~/gt now routes to the correct beads
directory based on the issue ID prefix.
- Add internal/routing/routes.go with routing logic
- Add cmd/bd/routed.go with routed storage helpers
- Update show command to use routed resolution in direct mode
- Support redirect files for canonical database locations
- Debug output available via BD_DEBUG_ROUTING=1
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add a created_by field to track who created each issue, similar to how
comments have an author field.
- Add CreatedBy string field to Issue struct
- Add migration 029 to add created_by column to issues table
- Update all SELECT/INSERT/Scan statements across storage layer
- Populate created_by in bd create from actor chain
- Display created_by in bd show output
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously, tombstones could not have a closed_at timestamp due to:
1. Go validation: `if status != closed && closed_at != nil` failed
2. SQL CHECK constraint: `(status = 'closed') = (closed_at IS NOT NULL)`
This caused import failures for tombstones that were closed before being
deleted - a valid scenario where we want to preserve the historical
closed_at timestamp for audit purposes.
Changes:
- internal/types/types.go: Updated validation to allow tombstones with
closed_at (line 253)
- internal/storage/sqlite/schema.go: Updated CHECK constraint to allow
closed AND tombstone statuses to have closed_at
- internal/storage/sqlite/migrations/028_tombstone_closed_at.go: Migration
to update existing databases with the new constraint
- .beads/issues.jsonl: Fixed bd-6s61 status from 'closed' to 'tombstone'
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Expands the inline comment to serve as a reference for when to use the
COALESCE(NULLIF(?, zero), column) defensive idiom in JSONL imports.
Pattern protects clone-local state (pinned, gate fields) from being
overwritten when importing JSONL where omitempty causes zero values to
represent "field absent" rather than "field is zero".
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Apply COALESCE(NULLIF(...)) pattern to await_type, await_id, timeout_ns,
and waiters fields in upsertIssueInTx. This prevents gate await fields
from being cleared when importing issues from JSONL that don't have
these fields (since gates are wisps and aren't exported to JSONL.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
EOF
)
In git worktrees, any bd command was slow with a 2-3s pause because:
- git.IsWorktree() was called 4+ times per command
- Each call spawned 2 git processes (git-dir and git-common-dir)
- git.GetRepoRoot() and git.GetMainRepoRoot() also called multiple times
Fix: Cache results using sync.Once since these values do not change during
a single command execution:
- IsWorktree() - caches worktree detection
- GetRepoRoot() - caches repo root path
- GetMainRepoRoot() - caches main repo root for worktrees
Added ResetCaches() for test cleanup between subtests that change directories.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add TOML parsing using BurntSushi/toml
- Update formula loader to try .toml first, fall back to .json
- Add `bd formula convert` command for JSON→TOML migration
- Multi-line string support for readable descriptions
- Cache git worktree/reporoot checks for performance
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(ready,blocked): Add --parent flag for scoping by epic/bead descendants
Add --parent flag to `bd ready` and `bd blocked` CLI commands and MCP tools
to filter results to all descendants of a specific epic or bead.
## Backward Compatibility
- CLI: New optional --parent flag; existing usage unchanged
- RPC: New `blocked` operation added (was missing); existing operations unchanged
- MCP: New optional `parent` parameter; existing calls work as before
- Storage interface: GetBlockedIssues signature changed to accept WorkFilter
- All callers updated to pass empty filter for existing behavior
- Empty WorkFilter{} returns identical results to previous implementation
## Implementation Details
SQLite uses recursive CTE to traverse parent-child hierarchy:
WITH RECURSIVE descendants AS (
SELECT issue_id FROM dependencies
WHERE type = 'parent-child' AND depends_on_id = ?
UNION ALL
SELECT d.issue_id FROM dependencies d
JOIN descendants dt ON d.depends_on_id = dt.issue_id
WHERE d.type = 'parent-child'
)
SELECT issue_id FROM descendants
MemoryStorage implements equivalent recursive traversal with visited-set
cycle protection via collectDescendants helper.
Parent filter composes with existing filters (priority, labels, assignee, etc.)
as an additional WHERE clause - all filters are AND'd together.
## RPC Blocked Support
MCP beads_blocked() existed but daemon client raised NotImplementedError.
Added OpBlocked and handleBlocked to enable daemon RPC path, which was
previously broken. Now both CLI and daemon clients work for blocked queries.
## Changes
- internal/types/types.go: Add ParentID *string to WorkFilter
- internal/storage/sqlite/ready.go: Add recursive CTE for parent filtering
- internal/storage/memory/memory.go: Add getAllDescendants/collectDescendants
- internal/storage/storage.go: Update GetBlockedIssues interface signature
- cmd/bd/ready.go: Add --parent flag to ready and blocked commands
- internal/rpc/protocol.go: Add OpBlocked constant and BlockedArgs type
- internal/rpc/server_issues_epics.go: Add handleBlocked RPC handler
- internal/rpc/client.go: Add Blocked client method
- integrations/beads-mcp/: Add BlockedParams model and parent parameter
## Usage
bd ready --parent bd-abc # All ready descendants
bd ready --parent bd-abc --priority 1 # Combined with other filters
bd blocked --parent bd-abc # All blocked descendants
## Testing
Added 4 test cases for parent filtering:
- TestParentIDFilterDescendants: Verifies recursive traversal (grandchildren)
- TestParentIDWithOtherFilters: Verifies composition with priority filter
- TestParentIDWithBlockedDescendants: Verifies blocked issues excluded from ready
- TestParentIDEmptyParent: Verifies empty result for childless parent
* fix: Correct blockedCmd indentation and suppress gosec false positive
- Fix syntax error from incorrect indentation in blockedCmd Run function
- Add nolint:gosec comment for GetBlockedIssues SQL formatting (G201)
The filterSQL variable contains only parameterized WHERE clauses with
? placeholders, not user input
Steps can now declare their own expansion using the Expand field:
steps:
- id: design
expand: rule-of-five
expand_vars:
iterations: 3
This is more convenient than compose.expand for single-step expansions.
The step is replaced by the expansion template with variables substituted.
Reuses existing expandStep() and mergeVars() from gt-8tmz.34.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add vars parameter to expandStep for {varname} substitution
- Add mergeVars to combine formula defaults with rule overrides
- Update ApplyExpansions to merge and pass vars for expand/map rules
- Apply var substitution to step ID, title, description, assignee,
labels, and dependencies
- Add comprehensive tests for var overrides functionality
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When closing an issue, the new --suggest-next flag returns a list of
issues that became unblocked (ready to work on) as a result of the close.
This helps agents and users quickly identify what work is now available
after completing a blocker.
Example:
$ bd close bd-5 --suggest-next
✓ Closed bd-5: Completed
Newly unblocked:
• bd-7 "Implement feature X" (P1)
• bd-8 "Write tests for X" (P2)
Implementation:
- Added GetNewlyUnblockedByClose to storage interface
- Implemented efficient single-query for SQLite using blocked_issues_cache
- Added SuggestNext field to CloseArgs in RPC protocol
- Added CloseResult type for structured response
- CLI handles both daemon and direct modes
Thanks to @kraitsura for the detailed feature request and design.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix YAML → JSON references in formula.go and types.go
- Update MOLECULES.md with ephemeral proto architecture
- Add Distillation section: extract formulas from completed work
- Add Sharing section: Mol Mall formula marketplace
- Update Layer Cake diagram to show ephemeral proto flow
Related: bd-1dez (Mol Mall epic)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Test cases for:
- Unary minus in expression: 3*-2 -> -6
- Parenthesized negative: (-5) -> -5
- Unary minus after power: 2^-1 -> 0 (truncated)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add support for for-each expansion over computed ranges:
loop:
range: "1..2^{disks}-1" # Evaluated at cook time
var: move_num
body: [...]
Features:
- Range field in LoopSpec for computed iterations
- Var field to expose iteration value to body steps
- Expression evaluator supporting + - * / ^ and parentheses
- Variable substitution in range expressions using {name} syntax
- Title/description variable substitution in expanded steps
Example use case: Towers of Hanoi formula where step count is 2^n-1
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add children-of(step-id) syntax for explicit spawner reference
- Add WaitsForSpec type and ParseWaitsFor() helper
- Update cook.go to create DepWaitsFor dependencies with metadata
- Infer spawner from first needs entry when using all-children
- Add validation tests for children-of() syntax
- Add unit tests for ParseWaitsFor()
This completes the Christmas Ornament aggregation pattern:
- survey-workers does for-each → creates N children
- aggregate waits-for children-of(survey-workers)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- ApplyBranches and ApplyGates now clone steps before modifying,
matching the immutability pattern of ApplyLoops and ApplyAdvice
- Added internal applyBranchesWithMap/applyGatesWithMap for efficiency
- ApplyControlFlow builds stepMap once for both (gt-gpgdv optimization)
- Added cloneStepsRecursive helper
- Added TestApplyBranches_Immutability and TestApplyGates_Immutability
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes a bug where outer iteration chaining was lost when nested loops
were expanded. The problem was:
1. chainLoopIterations set: outer.iter2.inner depends on outer.iter1.inner
2. ApplyLoops recursively expanded nested loops
3. outer.iter2.inner became outer.iter2.inner.iter1.work, etc.
4. The dependency was lost (referenced non-existent ID)
The fix:
- Move recursive ApplyLoops BEFORE chaining
- Add chainExpandedIterations that finds iteration boundaries by ID prefix
- Works with variable step counts per iteration (nested loops expand differently)
Now outer.iter2's first step correctly depends on outer.iter1's LAST step,
ensuring sequential execution of outer iterations.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add SourceFormula and SourceLocation fields to track where each step
came from during the cooking process. This enables debugging of complex
compositions with inheritance, expansion, and advice.
Changes:
- Added SourceFormula and SourceLocation fields to Step struct (formula/types.go)
- Added same fields to Issue struct (types/types.go)
- Added SetSourceInfo() to parser.go - sets source on all steps after parsing
- Updated cook.go to copy source fields from Step to Issue
- Updated dry-run output to display source info: [from: formula@location]
- Updated advice.go to set source on advice-generated steps
- Updated controlflow.go to preserve source on loop-expanded steps
- Updated expand.go to preserve source on template-expanded steps
The source location format is:
- steps[N] - regular step at index N
- steps[N].children[M] - child step
- steps[N].loop.body[M] - loop body step
- template[N] - expansion template step
- advice - step inserted by advice transformation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Enables loops within loop bodies to be properly expanded:
- Copy Loop field in expandLoopIteration (was intentionally omitted)
- Add cloneLoopSpec for deep copying of LoopSpec with body steps
- Recursively call ApplyLoops at end of expandLoop to expand nested loops
- Also copy OnComplete field for consistency
Nested IDs follow natural chaining pattern:
outer.iter1.inner.iter2.step
Tested with 2-level and 3-level nesting scenarios.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements the schema and validation for runtime dynamic expansion:
- Add OnCompleteSpec type for step completion triggers
- Add on_complete field to Step struct
- Validate for_each path format (must start with "output.")
- Validate bond is required with for_each (and vice versa)
- Validate parallel and sequential are mutually exclusive
- Add cloneOnComplete for proper step cloning
- Add comprehensive tests for parsing and validation
The runtime executor (in gastown) will interpret these fields to:
- Bond N molecules when step completes based on output.collection
- Run bonded molecules in parallel or sequential order
- Pass item/index context via vars substitution
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Critical bug fixes identified during code review:
1. External dependency rewriting: Dependencies on steps OUTSIDE the loop
are now preserved as-is instead of being incorrectly prefixed.
2. Children dependency rewriting: Child step dependencies are now properly
rewritten with iteration context.
3. Missing fields: Added Expand, ExpandVars, Gate fields to loop expansion.
4. Condition validation: Loop `until` conditions are now validated with
ParseCondition to catch syntax errors early.
5. Label format: Changed gate and loop labels from colon-delimited to
JSON format for unambiguous parsing:
- gate:{"condition":"expr"}
- loop:{"until":"expr","max":N}
Added TestApplyLoops_ExternalDependencies to verify the fix.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add loop, branch, and gate operators for formula step transformation:
- LoopSpec: Fixed-count loops expand body N times with chained iterations.
Conditional loops expand once with runtime metadata labels.
- BranchRule: Fork-join patterns wire dependencies for parallel paths.
- GateRule: Adds condition labels for runtime evaluation before steps.
Types added to types.go:
- LoopSpec (count/until/max/body)
- BranchRule (from/steps/join)
- GateRule (before/condition)
- Loop field on Step
- Branch/Gate arrays on ComposeRules
New controlflow.go with ApplyLoops, ApplyBranches, ApplyGates, and
ApplyControlFlow convenience function. Wired into cook.go before
advice and expansion operators.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Users who want manual control over git commits can now set:
bd config set no-git-ops true
This makes `bd prime` output the stealth-mode session close protocol
(just `bd sync --flush-only`) instead of the full git add/commit/push
workflow. Useful when:
- You want to verify work before committing
- Claude tries to auto-commit after context compaction
- You have a custom git workflow
The --stealth flag still works as before for one-off use.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Empty set 'all' returns false (avoids premature gate passing)
- Add proper error handling for Atoi in count comparisons
- Extract inline regex to package-level var (performance)
- Handle == and != in compareString function
- Add nil/bool value handling in compare function
- Add tests for edge cases: empty children, nil output, bool values
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ApplyAdvice now collects original step IDs before applying rules and
only matches steps in that set. This prevents advice patterns (like "*")
from matching their own inserted before/after steps.
Added test case demonstrating that a "*" pattern only adds advice to
original steps, not to inserted steps.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Aspects field to ComposeRules for listing aspect formulas
- Apply aspects during cooking after expansions
- Aspects are loaded by name and their advice rules are applied
Usage in formula:
"compose": {
"aspects": ["security-audit", "logging"]
}
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The map rule was only iterating over top-level steps, missing nested
children. Now uses buildStepMap to include all steps at any depth.
Added test case for map expansion over nested children.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a step is expanded (e.g., implement -> implement.draft, implement.refine-1,
etc.), any steps that depended on the original step should now depend on the
last step of the expansion.
Call UpdateDependenciesForExpansion after both expand and map operations.
Fixes gt-8tmz.3
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When bd cook encounters a circular extends chain (A extends B extends A),
the error message now shows the full chain: "cycle-a -> cycle-b -> cycle-a"
instead of just "circular extends detected: cycle-a".
This makes debugging circular dependencies much easier by showing exactly
which formulas are involved in the cycle.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add DefaultMaxExpansionDepth constant and depth tracking in expandStep
to prevent runaway nested expansions. The limit applies to template
children during expansion.
Changes:
- Add DefaultMaxExpansionDepth = 5 constant
- Update expandStep to track depth and return error when exceeded
- Update ApplyExpansions callers to handle errors
- Add TestExpandStepDepthLimit test for depth limiting
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add expand and map operators that apply macro-style template expansion:
- expand(target, template) - replace a single step with expanded template
- map(select, template) - replace all matching steps with expanded template
The expansion formula type (e.g., rule-of-five) uses a template field with
{target} and {target.description} placeholders that are substituted when
applied to target steps.
Changes:
- Add Template field to Formula struct for expansion formulas
- Add ExpandRule and MapRule types to ComposeRules
- Implement ApplyExpansions in new expand.go
- Add LoadByName method to Parser for loading expansion formulas
- Integrate expansion into bd cook command
- Add comprehensive tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed prefix logic to combine the database prefix with the type prefix:
- bd-wisp-xxx (was: wisp-xxx)
- bd-mol-xxx (was: mol-xxx)
This ensures IDs like hq-wisp-xxx at town level and gt-mol-xxx for gastown,
maintaining database namespace while adding type recognition.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added type-specific ID prefixes for better visual recognition:
- `bd pour` now generates IDs with "mol-" prefix
- `bd wisp create` now generates IDs with "wisp-" prefix
- Regular issues continue using the configured prefix
Implementation:
- Added IDPrefix field to types.Issue (internal, not exported to JSONL)
- Added Prefix field to CloneOptions for spawning operations
- Added IDPrefix to RPC CreateArgs for daemon communication
- Updated storage layer to use issue.IDPrefix when generating IDs
- Updated pour.go and wisp.go to pass appropriate prefixes
This enables instant visual recognition of entity types and prevents
accidental modification of templates.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change file extension from .formula.yaml to .formula.json
- Replace gopkg.in/yaml.v3 with encoding/json in parser
- Remove yaml struct tags, keep json tags only
- Update all test cases to use JSON format
- Update documentation references
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace fetchAndRebaseInWorktree with contentMergeRecovery in pushFromWorktree.
The problem: When push fails due to non-fast-forward, the old code used git
rebase to recover. But git rebase is text-level and does not invoke the JSONL
merge driver. This could resurrect tombstones - if remote had a tombstone and
local had closed, the rebase would overwrite the tombstone.
The fix: Use the same content-level merge algorithm that PullFromSyncBranch
uses. This respects tombstone semantics - recent tombstones always win over
live issues.
Changes:
- Add contentMergeRecovery() that does content-level merge instead of rebase
- Update pushFromWorktree to call contentMergeRecovery
- Mark fetchAndRebaseInWorktree as deprecated (kept for reference)
- Add tests for tombstone preservation during merge recovery
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Wisps now use Wisp=true flag in the main database. The separate
.beads-wisp/ directory is no longer needed.
Removed:
- WispDirName constant
- FindWispDir()
- FindWispDatabasePath()
- NewWispStorage()
- EnsureWispGitignore()
- IsWispDatabase()
- All related tests
- .beads-wisp/ from .gitignore
- Remove cross-store squash logic from mol_squash.go
- Delete runWispSquash() and squashWispToPermanent() functions
- Simplify runMolSquash() to work with main store only
- Update mol_burn.go to work with main database
- Remove .beads-wisp/ directory references
- Look for Wisp=true issues in main store instead
- Update mol_bond.go to use Wisp flag instead of separate store
- --wisp now creates issues with Wisp=true in main store
- --pour creates issues with Wisp=false (persistent)
- Update bondProtoMol signature to accept both flags
- Deprecate wisp storage functions in beads.go
- WispDirName, FindWispDir, FindWispDatabasePath
- NewWispStorage, EnsureWispGitignore, IsWispDatabase
- All marked deprecated with reference to bd-bkul
- Remove obsolete cross-store squash tests
- TestSquashWispToPermanent
- TestSquashWispToPermanentWithSummary
- TestSquashWispToPermanentKeepChildren
All tests pass. Build succeeds.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Progress on eliminating separate .beads-wisp/ directory:
- Add --wisp flag to bd create (creates issue with Wisp=true)
- Update bd wisp create to use main db instead of separate wisp storage
- Update bd wisp list to query main db with Wisp filter
- Update bd wisp gc to work with main database
- Add Wisp field to RPC ListArgs for daemon mode support
- Fix terminology: use "old/abandoned" for time-based cleanup,
reserve "stale" for graph-pressure staleness (per Gas Town taxonomy)
Still TODO:
- Finish mol squash simplification (remove cross-store logic)
- Remove runWispSquash and squashWispToPermanent functions
- Update mol burn similarly
- Deprecate .beads-wisp/ functions in internal/beads/beads.go
- Test all changes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
extractParentChain was using strings.Split(id, ".") which incorrectly
parsed prefixes containing dots (like "alicealexandra.com"). This caused
--parent to fail with "parent does not exist" even when the parent was
present in the database.
The fix uses IsHierarchicalID to walk up the hierarchy correctly, only
splitting on dots followed by numeric suffixes (the actual hierarchy
delimiter).
Example:
- "test.example-abc.1" now correctly returns ["test.example-abc"]
- Previously it incorrectly returned ["test", "test.example-abc"]
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The buildAllowedPrefixSet function now parses the allowed_prefixes config
and includes those prefixes when validating imports. This allows mol-*
prefixes to be imported without errors when configured.
Config example: bd config set allowed_prefixes "gt-,mol-"
- bd-hr39: Add `needs` field to Step as alias for depends_on. Converts
to blocking dependencies between sibling steps during cooking.
- bd-j4cr: Add `waits_for` field to Step. Values: all-children or
any-children. Preserved as gate:<value> label during cooking.
- bd-47qx: Add --prefix flag to bd cook command to prepend a prefix
to proto IDs, enabling use of project prefixes like gt-.
Includes validation, dry-run output, and comprehensive tests.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes from self-review of formula parser and bd cook:
1. Atomicity: Add cleanup on failure in cookFormula - if labels/deps
transaction fails, delete the already-created issues
2. Validation: Add recursive depends_on validation for child steps
and validate priority ranges for children
3. Documentation: Mark unimplemented fields (Expand, ExpandVars,
Condition, Gate) with TODO(future) comments
4. Thread safety: Add note that Parser is NOT thread-safe
5. Error messages: Track first definition location for duplicate ID
errors (e.g., "duplicate id at steps[1], first defined at steps[0]")
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements a new formula system for defining workflow templates in YAML:
- internal/formula/types.go: YAML schema types for .formula.yaml files
- Formula, Step, VarDef, ComposeRules, BondPoint, Gate types
- Support for workflow, expansion, and aspect formula types
- Variable definitions with required, default, enum, and pattern
- internal/formula/parser.go: Parser with extends/inheritance support
- Parse formula files from multiple search paths
- Resolve extends references for formula inheritance
- Variable extraction and substitution
- Variable validation (required, enum, pattern)
- cmd/bd/cook.go: bd cook command to compile formulas into protos
- Parse and resolve formula YAML
- Create proto bead with template label
- Create child issues for each step
- Set up parent-child and blocking dependencies
- Support --dry-run, --force, --search-path flags
Example workflow:
bd cook mol-feature.formula.yaml
bd pour mol-feature --var component=Auth --var framework=react
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>