This change fixes the issue where 'bd sync' would fail with a false-positive
"JSONL is newer than database" error after the daemon auto-exports.
Root Cause:
- Daemon exports local changes to JSONL, updating its timestamp
- bd sync sees JSONL.mtime > DB.mtime and incorrectly assumes external changes
- This blocks export even though content is identical
Solution:
- Modified isJSONLNewer() to use SHA256 content hash comparison
- Only triggers auto-import when JSONL is newer AND content differs
- Prevents false positives from daemon auto-export timestamp updates
- Maintains conservative fallback if hashes can't be computed
Changes:
- Added computeJSONLHash() and computeDBHash() helper functions
- Created isJSONLNewerWithStore() to support testing with explicit store
- Added comprehensive tests for content-based comparison logic
- All existing tests pass, including export_mtime tests
Fixes: bd-lm2q
Added Known Issues section to beads-mcp README documenting:
- FastMCP schema generation bug blocking MCP tools in Claude Code
- Workaround using slash commands (/beads:ready, /beads:show, etc.)
- Links to issue #346 and upstream FastMCP issue #2455
- Resolution path once upstream fix is released
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- bd-1h8: Add --no-daemon hint to compact error messages
- bd-8ql: Replace non-existent merge command with actionable guidance
- bd-ayw: Add 'When to use daemon mode' decision tree to daemon.md
- bd-keb: Add database maintenance section to QUICKSTART.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added prominent warning at the top of the Agent Mail section in AGENTS.md
to prevent AI agents from attempting to use mcp-agent-mail tools when the
server is not set up.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Removed all closed beads that were resurrected by the auto-import bug
documented in bd-khnb. Database now at 46 beads (all open/active).
The resurrection happened when:
- Earlier git operation restored old JSONL with 538 issues
- bd migrate --update-repo-id triggered daemon startup
- Auto-import saw "newer" JSONL (recent mtime from git)
- Imported old data over cleaned database
- 490 previously deleted issues resurrected
This cleanup removes those resurrected closed issues.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Filed bug report for critical data loss issue where bd migrate --update-repo-id
(and other operations) can trigger auto-import that resurrects deleted issues.
Root cause: Auto-import uses mtime-based staleness detection, which fails when
git operations restore old JSONL files with recent mtimes.
Impact: User deletions can be silently undone after git checkout/merge/pull.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Resolved conflict in AGENTS.md by keeping our version which emphasizes
that git push is CRITICAL for landing the plane.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The previous instructions mentioned sync carefully but didn't emphasize that
git push is absolutely required for the plane to actually land. Multiple agents
have failed to push, leaving work uncommitted on the runway.
Changes:
- Added explicit 'git push' step with CRITICAL emphasis
- Added verification step to check 'up to date with origin/main'
- Updated example workflow to show push as mandatory step
- Added clear statement: 'The plane has NOT landed until git push completes'
The metaphor is obvious - if you don't push, the plane is still on the ground!
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Changed 'bd clean' to 'bd cleanup' (correct command name)
- Added cleanup step to remove backup files and temporary artifacts
- Ensures clean repository state at end of agent sessions
Extracted repeated priority and ID validation patterns from CLI commands
into reusable functions in internal/validation/bead.go.
Changes:
- Added ValidatePriority(): Combines parsing and error handling
- Added ValidateIDFormat(): Validates ID format and extracts prefix
- Added ValidatePrefix(): Validates prefix matching with database config
- Updated create.go and show.go to use new validation functions
- Simplified force flag logic to always call ValidatePrefix()
- Added comprehensive tests for all validation functions
- Added TODO comment for daemon mode validation enhancement
Results:
- Reduced code duplication by ~20 lines
- Centralized validation logic for easier maintenance
- Consistent error messages across all commands
- All tests passing
Fixes bd-g5p7
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, bd sync would fail with "Pre-export validation failed:
refusing to export: JSONL is newer than database" when JSONL was
modified (e.g., after git pull).
Now bd sync intelligently handles this by:
- Detecting when JSONL is newer than the database
- Automatically importing before exporting
- Continuing with the normal sync flow
This makes the workflow much smoother - users can just run 'bd sync'
and it figures out what needs to be done.
Changes:
- Added isJSONLNewer() helper to check file timestamps
- Modified sync command to auto-import when JSONL is newer
- Extracted timestamp check logic for reusability
Resolves: bd-ca0b
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Ran bd cleanup --force to remove all closed issues, keeping only 48 open issues.
This significantly reduces the database size and makes it easier to work with.
Deleted:
- 490 closed issues
- 221 dependency links
- 54 labels
- 755 events
Orphaned issues (will need parent repair):
- bd-tne, bd-tru, bd-ktng, bd-c362, bd-98c4e1fa.1, bd-7e7ddffa.1, bd-o78
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem:
In direct mode, bd list was making a separate GetLabels() call for
each issue when displaying labels. With 538 issues, this resulted in
538 separate database queries.
While investigating the reported 5+ second slowness, discovered this
N+1 query issue that would impact performance with many issues.
Solution:
1. Added GetLabelsForIssues(issueIDs []string) to Storage interface
2. Implemented bulk fetch in SQLite (already existed, now exposed)
3. Implemented bulk fetch in MemoryStorage
4. Updated list.go to fetch all labels in single query
Changes:
- internal/storage/storage.go: Add GetLabelsForIssues to interface
- internal/storage/memory/memory.go: Implement GetLabelsForIssues
- cmd/bd/list.go: Use bulk fetching in all output modes
Impact:
Eliminates N queries for labels, replacing with 1 bulk query.
This optimization applies to direct mode only (daemon mode already
uses bulk operations via RPC).
Note: The reported 5s slowness was actually caused by daemon auto-start
timeout. Use --no-daemon flag or run 'bd migrate --update-repo-id' to
resolve the legacy database issue causing daemon startup failures.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Removed all closed beads (490 total, 497 including cascade deletions):
- Completed feature implementations
- Fixed bugs and resolved issues
- Test issues from development
- Deprecated/removed features
- Refactoring tasks
Database reduced from 538 to 48 beads (46 open, 2 other states)
All deleted beads preserved in git history for reference.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This command cleans up temporary files created during git merges by reading
patterns directly from .beads/.gitignore (Merge artifacts section).
Files removed:
- 3-way merge snapshots (beads.base.jsonl, beads.left.jsonl, beads.right.jsonl)
- Merge metadata (*.meta.json)
- Git merge driver temp files (*.json[0-9], *.jsonl[0-9])
Files preserved:
- beads.jsonl (source of truth)
- beads.db (SQLite database)
- metadata.json, config.yaml
- All daemon files
Usage:
bd clean # Clean up temporary files
bd clean --dry-run # Preview what would be deleted
Implementation:
- Reads patterns from .beads/.gitignore instead of hardcoding them
- No --force flag needed - just runs by default
- Only cleans truly temporary merge artifacts, never the database
Also:
- Restored beads.jsonl to 538 issues from commit 6cd3a32
- Set issue-prefix to "bd" in config.yaml
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Revert migration to issues.jsonl (was causing data corruption)
- Backup issues.jsonl for reference
- Database and beads.jsonl now in sync (538 issues)
- Clean slate for stable operations
Add comprehensive detection and migration guidance for old beads integration
patterns. This helps users adopt the more efficient bd prime approach.
Changes:
- Enhanced CheckLegacyBeadsSlashCommands with detailed migration steps
and token efficiency benefits (99% reduction: ~10.5k → ~50 tokens)
- Added CheckAgentDocumentation to detect missing AGENTS.md/CLAUDE.md
and suggest bd onboard or bd setup claude
- Enhanced CheckClaude to recommend bd prime hooks for MCP-only setups
with clear token efficiency messaging
- Added comprehensive tests for all new checks
bd doctor now detects:
1. Old slash command patterns (/beads:*) and recommends bd prime hooks
2. Missing agent documentation and suggests creating it
3. MCP-only setups without hooks and shows token savings potential
4. Provides clear migration paths and benefits for all scenarios
Token efficiency messaging:
- MCP mode: ~50 tokens vs ~10.5k for full scan (99% reduction)
- CLI mode: ~1-2k tokens with automatic context recovery
- Hooks auto-refresh context on SessionStart and PreCompact
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements automatic fix capability for bd doctor with user confirmation
and security hardening.
Features:
- Organizes fix implementations under doctor/fix/ directory structure
- Shows all fixable issues and prompts for confirmation (Y/n) before applying
- Provides clear output about what was fixed and any errors encountered
- Re-runs diagnostics after fixes to show updated state
- Each fix is idempotent and safe to run multiple times
Automatic fixes implemented:
- Git hooks (runs bd hooks install)
- Daemon health issues (runs bd daemons killall)
- DB-JSONL sync problems (runs bd sync --import-only)
- File permissions (fixes .beads/ and database permissions)
- Database version mismatches (runs bd migrate)
- Schema compatibility issues (runs bd migrate)
- Gitignore updates (writes canonical template)
Security improvements:
- Prevents command injection by using os.Executable() instead of PATH lookup
- Prevents path traversal attacks with workspace validation
- Fixes race conditions by using cmd.Dir instead of os.Chdir()
- Corrects file permission logic (proper bit masking)
- Validates all operations run in beads workspaces only
Files changed:
- cmd/bd/doctor.go: Enhanced applyFixes() with confirmation and better UX
- cmd/bd/doctor/gitignore.go: Fixed permissions (0600 → 0644)
- cmd/bd/doctor/fix/common.go: Security helpers (getBdBinary, validateBeadsWorkspace)
- cmd/bd/doctor/fix/hooks.go: Git hooks fix
- cmd/bd/doctor/fix/daemon.go: Daemon health fix
- cmd/bd/doctor/fix/sync.go: DB-JSONL sync fix
- cmd/bd/doctor/fix/permissions.go: File permissions fix
- cmd/bd/doctor/fix/migrate.go: Database migration fixes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Ensures cache stays synchronized with dependency and status changes
by calling invalidateBlockedCache() at all mutation points (bd-5qim).
Cache invalidation points:
- AddDependency: when type is 'blocks' or 'parent-child'
- RemoveDependency: when removed dep was 'blocks' or 'parent-child'
- UpdateIssue: when status field changes
- CloseIssue: always (closed issues don't block)
The invalidation strategy is full cache rebuild on any change,
which is fast enough (<1ms for 10K issues) and keeps the logic simple.
Only 'blocks' and 'parent-child' dependency types affect blocking,
so 'relates-to' and other types skip invalidation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replaces expensive recursive CTE query with simple cache lookup,
achieving 96% performance improvement on 10K databases (bd-5qim).
Performance results:
- Before: ~752ms (recursive CTE on every call)
- After: ~29ms (cache lookup + filters)
- Target: <50ms ✓
The query now uses a simple NOT EXISTS check against the
blocked_issues_cache table instead of computing the full
blocked issue tree on every call.
Cache is maintained by invalidateBlockedCache() called on
dependency and status changes (added in next commit).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Introduces a materialized cache table to store blocked issue IDs,
replacing the expensive recursive CTE computation that was causing
~752ms query times on 10K databases (bd-5qim).
The cache is maintained via invalidation on dependency and status
changes, reducing GetReadyWork from O(n²) recursive traversal to
O(1) cache lookup.
Technical details:
- New blocked_issues_cache table with single issue_id column
- ON DELETE CASCADE ensures automatic cleanup
- Migration populates cache using existing recursive CTE logic
- rebuildBlockedCache() fully rebuilds cache on invalidation
- execer interface allows both *sql.DB and *sql.Tx usage
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Type Safety Improvements:
- Change dict → dict[str, Any] throughout codebase for explicit typing
- Add PEP 561 py.typed marker file to export type information
- Add types-requests to dev dependencies
- Improve signal handler typing (FrameType | None)
- Improve decorator typing (Callable[..., Awaitable[T]])
- Add quickstart() abstract method to BdClientBase for interface completeness
Bug Fixes:
- Fix variable shadowing: beads_dir → local_beads_dir in bd_client.py
- Improve error handling in mail.py:_call_agent_mail() to prevent undefined error
- Make working_dir required (not Optional) in BdDaemonClient
- Remove unnecessary 'or' defaults for required Pydantic fields
Validation:
- mypy passes with no errors
- All unit tests passing
- Daemon quickstart returns helpful static text (RPC doesn't support this command)
Automatically creates a promotional README.md in the .beads directory
when bd init is run. The README explains what Beads is, provides
essential commands, highlights key benefits for AI-assisted workflows,
and encourages developers to try Beads in their own projects.
Changes:
- Added createReadme() function to generate compelling README content
- Integrated README creation in both regular and --no-db init modes
- README creation is idempotent (skips if already exists)
- Non-fatal warnings if README creation fails
The README is designed to get open source contributors excited about
using Beads for their AI-assisted development workflows.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>