- 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>
gitCommit() was adding the JSONL file but then committing ALL staged
changes (no pathspec). If other files were staged (e.g., deletions from
git add -A), they would be swept into the bd sync commit.
Fixed by adding pathspec to both gitCommit() and commitToExternalBeadsRepo()
so they only commit what they explicitly staged.
This was the root cause of PR #722 files being deleted - they were staged
for deletion in the working tree and got committed by bd sync.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The fix for GH#709 updated FindJSONLInDir to skip interactions.jsonl,
but the doctor check in CheckLegacyJSONLFilename was not updated.
This caused `bd doctor` to warn about multiple JSONL files when
both issues.jsonl and interactions.jsonl exist (which is normal
after `bd init`).
Also skip molecules.jsonl which is another system file that shouldn't
be counted as a duplicate issue database.
Distilled protos (via `bd mol distill`) now get bd-proto-xxx IDs.
Summary of distinct prefixes:
- bd-proto-xxx: templates created via distill
- bd-mol-xxx: instances created via pour
- bd-wisp-xxx: ephemeral instances via wisp create
- bd-xxx: regular issues
🤖 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>
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>
Wisps are now just issues with Wisp=true flag in the main database,
not exported to JSONL. Removes all references to .beads-wisp/ directory.
- Update docs: CLAUDE.md, CLI_REFERENCE.md, MOLECULES.md, DELETIONS.md
- Update code comments: wisp.go
- Update changelog and info.go version notes
🤖 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>
bd should not assume specific orchestrator agents exist. Gates are just
data records - the orchestrator decides who processes them.
- Remove Assignee: deacon/ from gate creation
- Update help text to say orchestrator instead of Deacon patrol
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
bd mol run was a convenience combo (pour + assign + pin + start) that
felt like orchestration but lived in the data layer. This blurred the
architectural boundary between bd (data) and gt (orchestration).
- Delete cmd/bd/mol_run.go entirely
- Update mol.go help text to remove run reference
- Update mol_current.go to suggest bd pour instead
gt spawn will implement the orchestration combo by calling the atomic
bd commands (pour, update, pin) directly.
Closes bd-00u3
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Two issues fixed:
1. bd-c8d5: mol run only created partial children from proto
- Root cause: children with missing/wrong dependencies were not loaded
- Fix: loadDescendants now uses two strategies:
- Strategy 1: Check dependency records for parent-child relationships
- Strategy 2: Find hierarchical children by ID pattern (parent.N)
- This catches children that may have broken dependency data
2. bd-drcx: mol run now supports proto lookup by title
- Can use: bd mol run mol-polecat-work --var issue=gt-xxx
- Or by ID: bd mol run gt-lwuu --var issue=gt-xxx
- Title matching is case-insensitive and supports partial matches
- Shows helpful error on ambiguous matches
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The sync command's exportToJSONL function was not filtering wisps,
causing them to be re-added to JSONL during bd sync re-export step.
autoflush.go had wisp filtering but sync_export.go did not. Added
the same filtering logic to prevent wisps from being exported to JSONL.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>
Adds release notes for v0.36.0 including:
- Formula system and gate issue type
- bd list --pretty --watch enhancements
- Child→parent dep prevention (LLM temporal trap)
- Multiple bug fixes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>
This prevents a common mistake where users add dependencies from child
issues to their parent epics. This creates a deadlock:
- Child can't start (blocked by open parent)
- Parent can't close (children not done)
Changes:
- dep.go: Reject child→parent deps at creation time with clear error
- server_labels_deps_comments.go: Same check for daemon RPC
- doctor/validation.go: New check detects existing bad deps
- doctor/fix/validation.go: Auto-fix removes bad deps
- doctor.go: Wire up check and fix handler
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove the spawn command from bd mol. Proto instantiation now uses:
- bd pour <proto> - Instantiate as persistent mol (liquid phase)
- bd wisp create <proto> - Instantiate as ephemeral wisp (vapor phase)
Rationale:
- 'spawn' doesn't fit the chemistry metaphor
- Two phase transitions (pour/wisp) are clearer than one command with flags
- Avoids confusion about defaults
Changes:
- Delete mol_spawn.go
- Update mol.go, mol_catalog.go, mol_distill.go to reference pour/wisp
- Update pour.go and wisp.go to remove 'Equivalent to spawn' comments
- Update info.go changelog entries
- Update CHANGELOG.md, ARCHITECTURE.md, DELETIONS.md
Closes bd-8y9t
The daemon sync functions (gitPushFromWorktree, syncBranchPull) were
checking git's branch tracking config and falling back to 'origin',
but ignoring bd's sync.remote config setting.
Now these functions check sync.remote config first, matching the
behavior of sync_check.go and sync_import.go.
Closes#736
Removes unnecessary parenthetical explanation about possible JSONL file names since findJSONLPath() already encapsulates that logic.
Co-authored-by: Charles P. Cross <cpdata@users.noreply.github.com>
Remove verbose parenthetical explanation from comment on line 73.
The comment now reads '// Get the actual JSONL path' instead of
'// Get the actual JSONL path (could be issues.jsonl, beads.base.jsonl, etc.)'
This is a documentation cleanup with no functional changes.
When 'bd doctor --fix' detects DB has more issues than JSONL, it runs
'bd export' to sync them. However, 'bd export' without -o flag outputs
to stdout instead of writing to .beads/issues.jsonl, making the fix a
no-op.
Add -o .beads/issues.jsonl --force to the export command to ensure the
JSONL file is actually updated.
Add a new --prune mode to `bd compact` that removes expired tombstones from
issues.jsonl without requiring AI compaction or deleting closed issues.
Features:
- `bd compact --prune` removes tombstones older than 30 days (default TTL)
- `bd compact --prune --older-than N` uses custom N-day TTL
- `bd compact --prune --dry-run` previews what would be pruned
- Supports --json output for programmatic use
This reduces sync overhead by eliminating accumulated tombstones that were
previously only pruned as a side effect of compaction or cleanup operations.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add integration tests for the deleteViaDaemon function that handles
client-side RPC deletion calls:
- TestDeleteViaDaemon_SuccessfulDeletion: Single issue deletion
- TestDeleteViaDaemon_CascadeDeletion: Cascade deletion through daemon
- TestDeleteViaDaemon_ForceDeletion: Force delete bypassing deps
- TestDeleteViaDaemon_DryRunMode: Preview without actual deletion
- TestDeleteViaDaemon_InvalidIssueID: Error handling for invalid IDs
- TestDeleteViaDaemon_BatchDeletion: Multiple issues at once
- TestDeleteViaDaemon_JSONOutput: JSON output validation
- TestDeleteViaDaemon_HumanReadableOutput: Human-readable formatting
- TestDeleteViaDaemon_DependencyConflict: Dependency conflict handling
- TestDeleteViaDaemon_EmptyIDs: Empty ID list handling
- TestDeleteViaDaemon_MultipleErrors: Mixed valid/invalid batch
- TestDeleteViaDaemon_DirectCall: Direct call with global client
- TestDeleteViaDaemon_DirectDryRun: Direct dry-run test
- TestDeleteViaDaemon_DirectHumanOutput: Direct human output test
- TestDeleteViaDaemon_DirectBatch: Direct batch deletion test
Coverage: 59.4% for deleteViaDaemon (remaining 40% is os.Exit paths)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add FatalErrorRespectJSON helper for JSON-aware error output
- Fix bd comments list returning null instead of [] for empty arrays
- Remove redundant local --json flags from show/update/close commands
that were shadowing the global persistent --json flag
- Update show command error handlers to use FatalErrorRespectJSON
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add the --priority (-p) flag to bd export for filtering by exact priority,
matching the behavior of bd list. This completes the comprehensive filtering
support for bd export.
The flag uses cmd.Flags().Changed() to properly handle P0 (priority 0), which
would otherwise be interpreted as "not set" due to Go zero-value semantics.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added daemon-compatible functions for template operations:
- loadTemplateSubgraphViaDaemon: loads template subgraph via RPC calls
- cloneSubgraphViaDaemon: creates new issues from template via RPC
- Updated templateShowCmd and templateInstantiateCmd to use daemon path
The template commands were using storage.Storage directly even when
daemon was connected, causing "no database connection" errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extract readFromGitRef helper function to eliminate duplicate code for
running git show <ref>:<path> commands. The helper is now used by:
- checkGitForIssues() in autoimport.go
- importFromGit() in autoimport.go
- readFirstIssueFromGit() in init.go
The scanning/parsing logic is intentionally kept separate since each
function has different requirements (error handling, SetDefaults, etc).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Test scenarios cover:
- Successful tombstone creation with actor/reason tracking
- Original type preservation in tombstone
- Audit trail recording
- Issue deletion with dependency cleanup
- Error handling for non-existent issues
- Unsupported storage backend fallback
Both functions achieve 100% test coverage.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
`bd config set no-db true` now correctly writes to config.yaml instead of
SQLite. Previously, startup flags like no-db, no-daemon, no-auto-flush were
stored in SQLite but read from config.yaml at startup - making the command
appear to work while having no effect.
This adds:
- yaml_config.go: Defines yaml-only keys and provides SetYamlConfig/GetYamlConfig
- Updated config set/get commands to route yaml-only keys appropriately
- Comprehensive tests for yaml config handling
Startup flags affected: no-db, no-daemon, no-auto-flush, no-auto-import,
json, auto-start-daemon, flush-debounce, lock-timeout, git.*, sync.*, routing.*
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add --template-db flag and auto-discovery for wisp molecule spawning.
When --db contains .beads-wisp, auto-discover the main database to read
templates from while writing spawned instances to wisp storage.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The prefix mismatch detection was using ExtractIssuePrefix() which
tries to guess the prefix by analyzing suffix patterns. This failed
for multi-hyphen prefixes like "asianops-audit-" when issue IDs had
word-like suffixes (e.g., "asianops-audit-test") - the heuristic
would fall back to the first hyphen and report "asianops-" as the
prefix.
Fixed by checking directly if the issue ID starts with the configured
prefix using strings.HasPrefix(). This is more reliable than guessing
since we know the expected prefix from the database config.
Added test case TestImportMultiHyphenPrefix to prevent regression.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
bondProtoMol was hardcoding Wisp=true, ignoring --pour flag.
Now passes pour parameter through the call chain so --pour
correctly creates persistent (non-wisp) issues.
The --stealth flag was writing absolute paths to global gitignore, but
git pattern matching does not support absolute paths in gitignore files.
Patterns are interpreted relative to the gitignore location, making
absolute paths like /home/user/project/.beads/ never match.
Fix: Use .git/info/exclude which is the git-recommended location for
user-specific, per-repository ignores. Patterns here are relative to
repo root, so .beads/ works correctly.
Benefits:
- Patterns actually work (fixes the bug)
- Per-repo isolation (stealth in one repo does not affect others)
- No global gitignore pollution
- Follows git best practices for user-local ignores
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>