Update version across all components:
- cmd/bd/version.go
- .claude-plugin/plugin.json, marketplace.json
- npm-package/package.json
- integrations/beads-mcp/pyproject.toml
- Git hook templates
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed all --var flags from StringSlice to StringArray.
StringSlice splits on commas, breaking values like 'desc=A, B, C'.
StringArray only splits on separate --var flags.
Affected commands: pour, cook, wisp, mol distill, mol bond, template instantiate
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tests were failing when BD_ACTOR or other BD_/BEADS_ environment
variables were set. Added envSnapshot helper to save, clear, and
restore environment variables for proper test isolation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add explicit error checking for fmt.Fprintf/Fprintln in claude.go
- Add gosec nolint for safe exec.CommandContext calls in sync_git.go
- Remove unused error return from findTownRoutes in routes.go
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code review caught that ".beads" would incorrectly match prefixes like
".beads-backup". Changed to match ".beads/" (with trailing slash) to
ensure we only match the actual .beads directory.
Added test cases for this edge case.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The bug: In a bare repo + worktrees setup, jsonlRelPath was calculated
relative to the project root (which contains all worktrees), resulting in
paths like "main/.beads/issues.jsonl". But the sync branch worktree uses
sparse checkout for .beads/*, so files are at ".beads/issues.jsonl".
This caused copyJSONLToMainRepo to look in the wrong location, silently
returning when the file was not found.
Fix: Add normalizeBeadsRelPath() to strip leading path components before
".beads", ensuring correct path resolution in both directions:
- copyJSONLToMainRepo (worktree -> local)
- SyncJSONLToWorktreeWithOptions (local -> worktree)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The --cascade flag was documented but not working for single-issue
deletes. The bug had two causes:
1. CLI direct mode: Single-issue deletes bypassed the batch path where
cascade expansion actually happens. Fixed by routing cascade deletes
through deleteBatch() regardless of issue count.
2. Daemon/RPC mode: handleDelete() iterated through IDs individually
without expanding dependents. Fixed by using DeleteIssues() with
cascade flag when SQLite storage is available.
Now `bd delete <id> --cascade --force` correctly deletes the target
issue plus all issues that depend on it (recursively).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The CheckSyncBranchHookCompatibility was checking core.hooksPath first,
while CheckGitHooks always uses .git/hooks/. This caused inconsistent
results when core.hooksPath was set globally.
Fix: Remove core.hooksPath check from CheckSyncBranchHookCompatibility
to match CheckGitHooks behavior. Both now consistently use .git/hooks/.
Note: A future improvement could make both respect core.hooksPath.
The negation patterns (!issues.jsonl, !interactions.jsonl, etc.) in
.beads/.gitignore had higher precedence than the fork protection
exclusion in .git/info/exclude, effectively defeating fork protection.
Contributors could accidentally stage and commit upstream issue
databases because:
1. Fork protection added .beads/issues.jsonl to .git/info/exclude
2. .beads/.gitignore had !issues.jsonl which overrode the exclusion
3. .gitignore files have higher precedence than .git/info/exclude
The negation patterns were unnecessary anyway since no pattern in
.beads/.gitignore matches those files. Added a comment explaining
why negations should not be added.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Solaris/illumos use Statvfs (POSIX standard) rather than Statfs.
Add daemon_health_solaris.go and exclude illumos/solaris from the
generic unix build constraint.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
bd has 70+ commands, which can be overwhelming for human users who just
want to track issues. The new `bd human` command displays a curated list
of ~15 essential commands organized by workflow:
- Working With Issues: create, list, show, update, close, reopen, comment
- Finding Work: ready, search, status, stats
- Dependencies: dep add/remove/tree, graph, blocked
- Setup & Sync: init, sync, doctor
- Getting Help: quickstart, help, --help
Also includes quick examples showing common workflows.
Changes:
- Add cmd/bd/human.go with curated help output
- Add "human" to noDbCommands list in main.go (no database needed)
Consolidated 5 duplicate IssueDetails struct definitions into a single
types.IssueDetails in internal/types/types.go:
- Removed 4 inline definitions from cmd/bd/show.go
- Removed 1 inline definition from internal/rpc/server_issues_epics.go
The shared type embeds types.Issue by value and includes:
Labels, Dependencies, Dependents, Comments, and Parent fields.
This improves maintainability and reduces risk of inconsistency.
bd config list now shows a warning when config.yaml or environment
variables override database settings. This addresses the confusion when
sync.branch from config.yaml takes precedence over the database value.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When the database has orphaned foreign key references (dependencies or labels
pointing to non-existent issues), the migration invariant check would fail,
preventing the database from opening. This created a chicken-and-egg problem:
1. bd doctor --fix tries to open the database
2. Opening triggers migrations with invariant checks
3. Invariant check fails due to orphaned refs
4. Fix never runs because database won't open
The fix adds CleanOrphanedRefs() that runs BEFORE captureSnapshot() in
RunMigrations. This automatically cleans up orphaned dependencies and labels
(preserving external:* refs), allowing the database to open normally.
Added test coverage for the cleanup function.
The routing code now walks up from the current beads directory to find
the Gas Town root (identified by mayor/town.json), then loads routes
from <townRoot>/.beads/routes.jsonl. The '.' path is correctly resolved
to the town beads directory.
Previously, routes.jsonl was only searched in the current beads dir,
which failed when working from rig subdirectories like crew/emma.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rename followRedirect to FollowRedirect in internal/beads (export it)
- Update doctor/maintenance.go to use beads.FollowRedirect
- Update doctor/fix/common.go to use beads.FollowRedirect
- Remove 66 lines of duplicated code across 3 implementations
This ensures consistent redirect handling with path canonicalization,
chain prevention, and proper error warnings.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add exitWithError helper to ensure JSON output is used when --json
flag is set during orphan detection errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add resolveBeadsDir helper to fix/common.go to follow redirect files
- Update OrphanedDependencies, ChildParentDependencies, and MergeArtifacts
to use resolveBeadsDir instead of hardcoded .beads path
- Add --verbose/-v flag to bd doctor command
- Only print individual items if verbose or count < 20, always show summary
(bd-dq74, bd-v55y)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Check comments table for orphaned issue_id references
- Check events table for orphaned issue_id references
- Delete orphaned comments/events in repair transaction
- Add --json flag for machine-readable output with:
- orphan_counts by type (dependencies, labels, comments, events)
- orphan_details with full reference info
- status (success, no_orphans, dry_run, error)
- backup_path when applicable
(bd-2wm2, bd-ie7j)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code review fixes for critical issues:
- Wrap all DELETEs in a transaction with rollback on error
- Create .pre-repair backup before any destructive operations
- Mark parent issues as dirty when deleting orphaned depends_on refs
- Fix misleading PreRun comment
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When the database has orphaned dependencies or labels, the migration
invariant check fails and prevents the database from opening. This
creates a chicken-and-egg problem where bd doctor --fix cannot run.
The new bd repair command:
- Opens SQLite directly, bypassing invariant checks
- Deletes orphaned dependencies (issue_id or depends_on_id not in issues)
- Deletes orphaned labels (issue_id not in issues)
- Runs WAL checkpoint to persist changes
- Supports --dry-run to preview what would be cleaned
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Eliminate code duplication between importFromGit and importFromLocalJSONL
by extracting the common JSONL parsing and import logic.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds --from-jsonl flag that imports from the current working tree's
.beads/issues.jsonl file instead of scanning git history. This prevents
deleted issues from being resurrected during re-initialization.
Use case: After running bd compact --purge-tombstones and committing
the cleaned JSONL, a subsequent bd init would previously re-import
all historical issues from git, defeating the cleanup.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Unlike --prune which removes tombstones by age, --purge-tombstones removes
tombstones that have no open issues depending on them, regardless of age.
Also cleans stale deps from closed issues to tombstones.
Usage:
bd compact --purge-tombstones --dry-run # Preview what would be purged
bd compact --purge-tombstones # Actually purge
Note: Use --no-daemon to prevent daemon from re-exporting after cleanup.
Separates semantics of 'pinned' (identity records) from work-on-hook:
- 'pinned' = domain table / identity record (agents, roles) - non-blocking
- 'hooked' = work on agent's hook (GUPP-driven) - blocks dependents
Changes:
- Add StatusHooked constant to types.go
- Update all blocking queries to include 'hooked' status
- Add cyan styling for 'hooked' in UI output
- Create migration 032 to convert pinned work items to hooked
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>