- Add TypeMessage issue type for inter-agent communication
- Add 6 new Issue fields: Sender, Ephemeral, RepliesTo, RelatesTo,
DuplicateOf, SupersededBy
- Add 4 new dependency types: replies-to, relates-to, duplicates, supersedes
- Create migration 019_messaging_fields with indexes
- Update all CRUD operations across storage layer
- Fix reset_test.go to use correct function names
- Fix redundant newline lint error in sync.go
Closes: bd-kwro.1
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GH#464: Add safety guards to prevent deletion of open/in_progress issues during sync:
- Safety guard in git-history-backfill (importer.go)
- Safety guard in deletions manifest processing
- Warning when uncommitted changes detected before pull (daemon_sync.go)
- Enhanced repo ID mismatch error message
GH#545: Fix bd blocked to show status=blocked issues (sqlite/ready.go):
- Changed from INNER JOIN to LEFT JOIN to include issues without dependencies
- Added WHERE clause to include both status=blocked AND dependency-blocked issues
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The deleted_at column was defined as TEXT in the schema but code was
trying to scan into sql.NullTime. The ncruces/go-sqlite3 driver only
auto-converts TEXT to time.Time for columns declared as DATETIME/DATE/
TIME/TIMESTAMP. For TEXT columns, it returns raw strings which
sql.NullTime.Scan() cannot handle.
Added parseNullableTimeString() helper that manually parses time strings
and changed all deletedAt variables from sql.NullTime to sql.NullString.
Fixes import failure: "sql: Scan error on column index 22, name
deleted_at: unsupported Scan, storing driver.Value type string into
type *time.Time"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add migration 017_close_reason_column.go to create the column
- Update all INSERT statements to include close_reason
- Update all SELECT statements to include close_reason
- Update doctor.go to check for close_reason in schema validation
- Remove workaround code that batch-loaded close reasons from events table
- Fix migrations_test.go to include close_reason in test table schema
This fixes sync loops where close_reason values were silently dropped
because the DB lacked the column despite the struct having the field.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add -u/--unassigned flag to bd ready command to show only issues
with no assignee. This supports the SCAVENGE protocol where polecats
query the 'Salvage Yard' for unassigned ready work.
Changes:
- Add NoAssignee field to WorkFilter struct
- Update SQLite GetReadyWork to filter by empty/null assignee
- Add --unassigned/-u flag to ready command
- Update RPC protocol and daemon handler
- Add test for NoAssignee filter functionality
Fixes: gt-3rp
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Adds the ability to filter ready work for issues with no assignee,
which is useful for the SCAVENGE protocol in Gas Town where polecats
need to query the "Salvage Yard" for unclaimed work.
Changes:
- Add Unassigned bool field to types.WorkFilter
- Add --unassigned/-u flag to bd ready command
- Update SQL query in GetReadyWork to filter for NULL/empty assignee
- Add Unassigned field to RPC ReadyArgs for daemon support
- Add tests for the new functionality
Closes: gt-3rp
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive documentation for the blocked_issues_cache optimization
that improved GetReadyWork performance from 752ms to 29ms (25x speedup).
Documentation locations:
- blocked_cache.go: Detailed package comment covering architecture,
invalidation strategy, transaction safety, edge cases, and future
optimizations
- ready.go: Enhanced comment at query site explaining the optimization
and maintenance triggers
- ARCHITECTURE.md: New section with diagrams, blocking semantics,
performance characteristics, and testing instructions
Closes bd-1w6i
🤖 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>
- Add repo_mtimes table to track JSONL file modification times
- Implement HydrateFromMultiRepo() with mtime-based skip optimization
- Support tilde expansion for repo paths in config
- Add source_repo column via migration (not in base schema)
- Fix schema to allow migration on existing databases
- Comprehensive test coverage for hydration logic
- Resurrect missing parent issues bd-cb64c226 and bd-cbed9619
Implementation:
- internal/storage/sqlite/multirepo.go - Core hydration logic
- internal/storage/sqlite/multirepo_test.go - Test coverage
- docs/MULTI_REPO_HYDRATION.md - Documentation
Schema changes:
- source_repo column added via migration only (not base schema)
- repo_mtimes table for mtime caching
- All SELECT queries updated to include source_repo
Database recovery:
- Restored from 17 to 285 issues
- Created placeholder parents for orphaned hierarchical children
Amp-Thread-ID: https://ampcode.com/threads/T-faa1339a-14b2-426c-8e18-aa8be6f5cde6
Co-authored-by: Amp <amp@ampcode.com>
- Add SortPolicy type with hybrid, priority, oldest constants
- Add SortPolicy field to WorkFilter
- Implement buildOrderByClause() for SQL generation
- Add --sort flag to bd ready command
- Add comprehensive tests for all 3 sort policies
- Update RPC protocol to support sort policy
- Update documentation with sort policy examples
Enables autonomous systems like VC to use strict priority ordering
while preserving hybrid behavior for interactive use.
Amp-Thread-ID: https://ampcode.com/threads/T-9d7ea9db-8d6d-4498-9daa-48a7e104ce1f
Co-authored-by: Amp <amp@ampcode.com>
- Updated label CLI commands to support both daemon and direct modes
- Added label fetching to GetIssue() and scanIssues() methods
- All label operations (add, remove, list, list-all) work with daemon
- Closed bd-162 (label CLI commands), bd-166 (duplicate), bd-141 (daemon support)
Amp-Thread-ID: https://ampcode.com/threads/T-4858f62e-ad06-4cc7-ad05-17ee76861f86
Co-authored-by: Amp <amp@ampcode.com>
- Add bd restore command to view full history of compacted issues from git
- Command temporarily checks out historical commit, reads JSONL, displays original content
- Read-only operation, no database or git state modification
- Flip ready work sort to created_at ASC (older issues first within priority tier)
- Prevents issue treadmill effect, surfaces old P1s for triage
- Update README.md and AGENTS.md with restore documentation
Closes bd-407, bd-383
When an epic is blocked, all its children should also be considered
blocked in the ready work calculation. Previously, only direct blocking
dependencies were checked, allowing children of blocked epics to appear
as ready work.
Implementation:
- Use recursive CTE to propagate blocking from parents to descendants
- Only 'parent-child' dependencies propagate blocking (not 'related')
- Changed NOT IN to NOT EXISTS for better NULL safety and performance
- Added depth limit of 50 to prevent pathological cases
Test coverage:
- TestParentBlockerBlocksChildren: Basic parent→child propagation
- TestGrandparentBlockerBlocksGrandchildren: Multi-level depth
- TestMultipleParentsOneBlocked: Child blocked if ANY parent blocked
- TestBlockerClosedUnblocksChildren: Dynamic unblocking works
- TestRelatedDoesNotPropagate: Only parent-child propagates
Closes: https://github.com/steveyegge/beads/issues/19
Resolves: bd-58
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add nullable external_ref TEXT field to link bd issues with external
systems like GitHub Issues, Jira, etc. Includes automatic schema
migration for backward compatibility.
Changes:
- Added external_ref column to issues table with feature-based migration
- Updated Issue struct with ExternalRef *string field
- Added --external-ref flag to bd create and bd update commands
- Updated all SQL queries across the codebase to include external_ref:
- GetIssue, CreateIssue, UpdateIssue, SearchIssues
- GetDependencies, GetDependents, GetDependencyTree
- GetReadyWork, GetBlockedIssues, GetIssuesByLabel
- Added external_ref handling in import/export logic
- Follows existing patterns for nullable fields (sql.NullString)
This enables tracking relationships between bd issues and external
systems without requiring changes to existing databases or JSONL files.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This is a fundamental architectural shift from binary SQLite to JSONL as
the source of truth for git workflows.
## New Features
- `bd export --format=jsonl` - Export issues to JSON Lines format
- `bd import` - Import issues from JSONL (create new, update existing)
- `--skip-existing` flag for import to only create new issues
## Architecture Change
**Before:** Binary SQLite database committed to git
**After:** JSONL text files as source of truth, SQLite as ephemeral cache
Benefits:
- Git-friendly text format with clean diffs
- AI-resolvable merge conflicts (append-only is 95% conflict-free)
- Human-readable issue tracking in git
- No binary merge conflicts
## Documentation
- Updated README with JSONL-first workflow and git hooks
- Added TEXT_FORMATS.md analyzing JSONL vs CSV vs binary
- Updated GIT_WORKFLOW.md with historical context
- .gitignore now excludes *.db, includes .beads/*.jsonl
## Implementation Details
- Export sorts issues by ID for consistent diffs
- Import handles both creates and updates atomically
- Proper handling of pointer fields (EstimatedMinutes)
- All tests passing
## Breaking Changes
- Database files (*.db) should now be gitignored
- Use export/import workflow for git collaboration
- Git hooks recommended for automation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Core features:
- Dependency-aware issue tracking with SQLite backend
- Ready work detection (issues with no open blockers)
- Dependency tree visualization
- Cycle detection and prevention
- Full audit trail
- CLI with colored output
Security and correctness fixes applied:
- Fixed SQL injection vulnerability in UpdateIssue (whitelisted fields)
- Fixed race condition in ID generation (added mutex)
- Fixed cycle detection to return full paths (not just issue IDs)
- Added cycle prevention in AddDependency (validates before commit)
- Added comprehensive input validation (priority, status, types, etc.)
- Fixed N+1 query in GetBlockedIssues (using GROUP_CONCAT)
- Improved query building in GetReadyWork (proper string joining)
- Fixed P0 priority filter bug (using Changed() instead of value check)
All critical and major issues from code review have been addressed.
🤖 Generated with Claude Code