The ensureStoreActive() function was ignoring the user-configured
--lock-timeout flag and always using the 30s default via sqlite.New().
This fix changes ensureStoreActive() to use sqlite.NewWithTimeout()
with the configured lockTimeout, allowing users to specify shorter
timeouts for multi-agent scenarios.
With this change, users can now run:
bd --lock-timeout=500ms sync
to fail fast if the database is locked, rather than waiting 30s.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The `bd update --type` command was rejecting custom types (like role, agent,
rig) even when configured via types.custom. The issue was that type validation
used IsValid() which only checks the 5 core types, ignoring custom types.
Changes:
- CLI (update.go): Use IsValidWithCustom() with types from config
- Storage (validators.go): Add validateIssueTypeWithCustom() function
- Storage (queries.go, transaction.go): Fetch and pass custom types
The error message now dynamically shows all valid types including custom ones.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Under high concurrency (17+ agent sessions), each gt command invokes
bd version to validate minimum beads version. The resolveBranch()
function was spawning git subprocesses (git symbolic-ref) which caused
severe contention and timeouts when many agents ran simultaneously.
Changes:
- Remove git subprocess fallback in resolveBranch()
- Branch info now only comes from ldflags or build info's vcs.branch
- Version number (what gt actually checks) is unaffected
- Update documentation to reflect the change
The fix reduces bd version from potentially 2 git subprocesses to zero,
eliminating the contention issue under high agent concurrency.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Under high concurrency (17+ sessions), each bd version spawning git
processes causes severe contention and timeouts. Remove the runtime
git symbolic-ref fallback - branch info is nice-to-have but not essential.
Fixes: GH#503
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New command showing full context for a bead:
- ANCESTRY: Chain from leaf to epic/goal (upward traversal)
- SIBLINGS: Parallel work under same parent
- DEPENDENCIES: What blocks/is blocked by
- DECISIONS: Key decisions extracted from comments
Output modes:
- Default: Full formatted tree view
- --compact: Single-line summary
- --pr: Copy-paste ready markdown for PR descriptions
- --json: Structured output for scripting
Implements sc-ep0zq.
Epics now require a "Working Model" section in their description,
in addition to "Success Criteria". This provides clear guidance on
HOW the epic will be executed:
- Owner role: Coordinator vs Implementer
- Delegation target: Polecats, crew, external
- Review process: Approval gates
Closes gt-0lp
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add complete documentation for Dolt backend covering:
- Migration from SQLite to Dolt
- Contributor onboarding (bootstrap on clone)
- Troubleshooting common issues
- Recovery procedures
- Server mode setup and management
- Git hooks integration
- Configuration reference
Also improve server mode error handling to suggest gt dolt start
when connection is refused.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When the Dolt database connection is temporarily unavailable (e.g.,
stale connection, server restart), GetCustomTypes() and GetCustomStatuses()
now fall back to reading from config.yaml instead of failing.
This matches the SQLite storage behavior and fixes the stop hook
failure where `gt costs record` would fail with "invalid issue type: event"
when the Dolt connection was broken.
The fallback is checked in two cases:
1. When database query returns an error
2. When database has no custom types/statuses configured
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Daemon now refuses to start when dolt backend is configured
(dolt uses sql-server mode, not the SQLite daemon)
- Add same-directory check in GetRoutedStorageWithOpener to avoid
opening duplicate connections when routing resolves to current dir
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add two new filter flags to the export command:
- --id: Filter by specific issue IDs (comma-separated)
- --parent: Filter by parent issue ID (shows children)
Also fix safety checks (empty DB, staleness) to skip when filters
are active, since filtered exports intentionally produce subsets.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Add extensive test coverage for the Dolt storage implementation:
- dependencies_extended_test.go: Extended dependency operation tests
- dolt_benchmark_test.go: Performance benchmarks for Dolt operations
- history_test.go: Version history query tests
- labels_test.go: Label operation tests
These tests validate Dolt backend correctness and provide performance
baselines for comparison with SQLite.
Co-authored-by: upstream_syncer <matthew.baker@pihealth.ai>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Refactors UpdateIssue, CloseIssue, CreateTombstone, and DeleteIssues
to use the withTx helper with BEGIN IMMEDIATE instead of BeginTx.
This completes the GH#1272 fix by ensuring all write transactions
acquire write locks early, preventing deadlocks.
Changes:
- UpdateIssue: now uses withTx and markDirty helper
- CloseIssue: now uses withTx and markDirty helper
- CreateTombstone: now uses withTx and markDirty helper
- DeleteIssues: now uses withTx with dbExecutor interface
- Helper functions (resolveDeleteSet, expandWithDependents,
validateNoDependents, etc.) changed from *sql.Tx to dbExecutor
This is a P3 follow-up to the P1 sqlite lock fix (PR #1274).
Closes: bd-fgzp
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
When no steps are in_progress, bd mol current now checks for molecules
bonded to hooked issues via blocks dependencies. This fixes the case
where a molecule is attached to an agent's hook but no steps have been
claimed yet.
The fix adds findHookedMolecules() as a fallback after findInProgressMolecules()
returns empty. It queries for hooked issues assigned to the agent and checks
for blocks dependencies pointing to molecules (epics or template-labeled issues).
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat(update): add --append-notes flag (bd-b5qu)
Add --append-notes flag that appends to existing notes with a newline
separator instead of overwriting. This prevents data loss in workflows
where multiple steps need to add info to notes (e.g., tackle workflows).
- Errors if both --notes and --append-notes specified
- Handles both daemon and direct mode paths
- Combines existing notes + newline + new content
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test(update): add tests for --append-notes flag
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat: update to use core tap for beads installation
Signed-off-by: Rui Chen <rui@chenrui.dev>
* remove custom tap related code and refs
Signed-off-by: Rui Chen <rui@chenrui.dev>
---------
Signed-off-by: Rui Chen <rui@chenrui.dev>
The daemon server's handleList was returning dependency counts but not
the actual dependency records. This complements PR #1296 which fixed
the direct CLI path.
Code paths now fixed:
- Direct (--no-daemon): cmd/bd/list.go (PR #1296)
- Daemon (default): internal/rpc/server_issues_epics.go (this PR)
Fixes bd-d240
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix(gate): use GateWait RPC for add-waiter command
bd gate add-waiter was calling Update RPC which rejects waiters
field (not in allowedUpdateFields). Changed to use existing GateWait
RPC that handles waiters correctly.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(storage): allow waiters field in UpdateIssue
Add waiters to allowedUpdateFields whitelist and handle JSON
serialization for the array field. This enables bd gate add-waiter
to work in direct mode (--no-daemon).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(storage/dolt): allow waiters field in UpdateIssue
Mirror the SQLite fix: add waiters to allowed fields and handle JSON
serialization for the array field.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix(daemon): skip export when sync-branch matches current
Prevent redundant export operations by checking if the daemon's sync
branch matches the current active branch.
Previously, the daemon would attempt to perform an export even when
already on the target branch. This logic now skips the export step in
such cases to avoid unnecessary overhead and potential conflicts.
Includes a new integration test to verify the guard logic.
* fix(daemon): prevent sync on guarded branches
Add checks to verify if a branch is guarded before performing automated
sync cycles, auto-imports, or branch-specific commit and pull operations.
This prevents the daemon from modifying protected branches or running
synchronization tasks where they are restricted.
Includes comprehensive integration tests to verify the guard logic
during sync-branch operations.
* fix(daemon): warn on sync branch misconfiguration at startup
The daemon now checks for sync branch name conflicts during its startup
loop. This provides early feedback if the sync branch is configured
in a way that might conflict with existing branches or other settings.
The warnIfSyncBranchMisconfigured function performs the validation
and logs a warning to the console. Integration tests verify that
the daemon correctly identifies and reports these misconfigurations
at initialization.
* fix(sync): read sync.mode from yaml first, then database
bd config set sync.mode writes to config.yaml (because sync.* is a
yaml-only prefix), but GetSyncMode() only read from the database.
This caused dolt-native mode to be ignored - JSONL export still
happened because the database had no sync.mode value.
Now GetSyncMode() checks config.yaml first (via config.GetSyncMode()),
falling back to database for backward compatibility.
Fixes: oss-5ca279
* fix(init): respect BEADS_DIR environment variable
Problem:
- `bd init` ignored BEADS_DIR when checking for existing data
- `bd init` created database at CWD/.beads instead of BEADS_DIR
- Contributor wizard used ~/.beads-planning as default, ignoring BEADS_DIR
Solution:
- Add BEADS_DIR check in checkExistingBeadsData() (matches FindBeadsDir pattern)
- Compute beadsDirForInit early, before initDBPath determination
- Use BEADS_DIR as default in contributor wizard when set
- Preserve precedence: --db > BEADS_DB > BEADS_DIR > default
Impact:
- Users with BEADS_DIR set now get consistent behavior across all bd commands
- ACF-style fork tracking (external .beads directory) now works correctly
Fixes: steveyegge/beads#???
* fix(doctor): respect BEADS_DIR environment variable
Also updates documentation to reflect BEADS_DIR support in init and doctor.
Changes:
- doctor.go: Check BEADS_DIR before falling back to CWD
- doctor_test.go: Add tests for BEADS_DIR path resolution
- WORKTREES.md: Document simplified BEADS_DIR+init workflow
- CONTRIBUTOR_NAMESPACE_ISOLATION.md: Note init/doctor BEADS_DIR support
* test(init): add BEADS_DB > BEADS_DIR precedence test
Verifies that BEADS_DB env var takes precedence over BEADS_DIR
when both are set, ensuring the documented precedence order:
--db > BEADS_DB > BEADS_DIR > default
* chore: fill in GH#1277 placeholder in sync_mode comment
Child issues created with --parent were missing from export_hashes table,
which affects integrity tracking and future incremental export features.
This fix ensures SetExportHash() is called for all exported issues:
- Updated ExportResult to include IssueContentHashes map
- Updated finalizeExport() to call SetExportHash() for each exported issue
- Updated exportToJSONLDeferred() to collect content hashes during export
- Updated performIncrementalExport() to collect content hashes for dirty issues
- Updated exportToJSONLWithStore() to call SetExportHash() after export
- Updated daemon's handleExport() to call SetExportHash() after export
Added test TestExportPopulatesExportHashes to verify the fix works for
both regular and hierarchical (child) issue IDs.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
The handleRename function was being called with the raw storage.Storage
interface inside upsertIssuesTx, which runs within a transaction. When
handleRename called store.DeleteIssue() or store.CreateIssue(), these
methods attempted to start new transactions via withTx/BEGIN IMMEDIATE,
causing a deadlock since SQLite cannot nest BEGIN IMMEDIATE transactions.
This fix:
- Adds handleRenameTx that accepts storage.Transaction and uses tx methods
- Updates the call site in upsertIssuesTx to use handleRenameTx(ctx, tx, ...)
The non-transactional upsertIssues continues to use handleRename for
backends that don't support transactions.
Fixes nested transaction deadlock during bd sync when issue renames occur.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- Make beads the DEFAULT for ALL task tracking
- Advise avoiding TodoWrite, TaskCreate, and markdown files for task tracking
- Add workflow guidance: create beads issue BEFORE writing code, mark in_progress when starting
Previously, `bd show` displayed all dependencies under "DEPENDS ON"
regardless of their type. This was confusing because parent-child
relationships (used for molecule/step hierarchy) appeared as if they
were blocking dependencies.
This fix:
- Groups dependencies by type in both daemon and non-daemon modes
- Shows parent-child deps under "PARENT" heading
- Shows blocking deps under "DEPENDS ON" heading
- Shows related deps under "RELATED" heading
- Shows discovered-from deps under "DISCOVERED FROM" heading
The fix applies the same filtering pattern already used for Dependents
(which correctly grouped CHILDREN, BLOCKS, RELATED, DISCOVERED) to the
Dependencies section.
Fixes: bd-69d7
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Previously, `bd list --json` only included dependency_count and
dependent_count but not the actual dependency records. This broke
callers like `gt hook --json` that need to know what each issue
depends on to determine ready steps.
Now populates issue.Dependencies using GetAllDependencyRecords,
matching the behavior of `bd show --json`.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
- FindDatabasePath now handles Dolt server mode (no local dir required)
- main.go uses NewFromConfigWithOptions for Dolt to read server settings
- Routing uses factory via callback to respect backend configuration
- Handle Dolt "database exists" error (error 1007) gracefully
Previously, Dolt server mode failed because:
1. FindDatabasePath required a local directory to exist
2. main.go bypassed server mode config when creating Dolt storage
3. Routing always opened SQLite regardless of backend config
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add dolt_mode, dolt_server_host, dolt_server_port fields to configfile.Config
- Add IsDoltServerMode(), GetDoltServerHost(), GetDoltServerPort() helpers
- Update factory to read server mode config and set Options accordingly
- Skip bootstrap in server mode (database lives on server)
- Pass Database name to dolt.Config for USE statement after connecting
- Disable dolt stats collection to avoid lock issues in embedded mode
This enables bd to connect to a running dolt sql-server (started via
'gt dolt start') instead of using embedded mode, allowing multi-client
access without file locking conflicts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Skip Bootstrap when ServerMode is true (bootstrap is for embedded cold-start)
- Fix doltExists() to follow symlinks using os.Stat
- Pass database name from metadata.json to DoltStore config
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When an issue ID starts with dashes (e.g., gt--kzx), it can be
misinterpreted by Cobra's argument parser. The new --id flag allows
these IDs to be passed safely:
bd show --id=gt--xyz
Multiple --id flags can be used, and they can be combined with
positional arguments.
Closes: bd-ix0ak
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use ui.RenderPassIcon, ui.RenderWarnIcon, ui.RenderFailIcon, etc. for
consistent styling with the rest of the doctor command output.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use parameterized query for INFORMATION_SCHEMA lookup (SQL injection)
- Add isValidIdentifier() to validate database names before USE statement
- Add password support via BEADS_DOLT_PASSWORD env var
- Remove unused variable declaration
- Add unit tests for identifier validation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds bd doctor --server to diagnose Dolt server mode connections:
- Server reachability (TCP connect to host:port)
- Dolt version check (verifies it is Dolt, not vanilla MySQL)
- Database exists and is accessible
- Schema compatible (can query beads tables)
- Connection pool health metrics
Supports --json for machine-readable output.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code review fix: In server mode, Dolt connects to an external sql-server
and should NOT be single-process-only. The whole point of server mode is
to enable multi-writer access.
Changes:
- Add Config.GetCapabilities() method that considers server mode
- Update daemon_guard, daemon_autostart, daemons, main to use GetCapabilities()
- Add TestGetCapabilities test
- Update init command help text to document server mode flags
The existing CapabilitiesForBackend(string) is kept for backward compatibility
but now includes a note to use Config.GetCapabilities() when the full config
is available.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Dolt server mode configuration to metadata.json for multi-writer access:
- Add DoltMode, DoltServerHost, DoltServerPort, DoltServerUser fields to Config
- Add helper methods with sensible defaults (127.0.0.1:3306, root user)
- Update factory to read server mode config and pass to dolt.Config
- Add --server, --server-host, --server-port, --server-user flags to bd init
- Validate that --server requires --backend dolt
- Add comprehensive tests for server mode configuration
Example metadata.json for server mode:
{
"backend": "dolt",
"database": "dolt",
"dolt_mode": "server",
"dolt_server_host": "192.168.1.100",
"dolt_server_port": 3306,
"dolt_server_user": "beads"
}
Password should be set via BEADS_DOLT_PASSWORD env var for security.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds Dolt auto-commit functionality for write commands and sets explicit commit authors.
Includes fix for race condition in commandDidWrite (converted to atomic.Bool).
Original PR: #1267 by @coffeegoddd
Co-authored-by: Dustin Brown <dustin@dolthub.com>
The original PR added retry logic on top of BEGIN IMMEDIATE, but this caused
multi-minute hangs because:
1. Connection has busy_timeout=30s set via pragma
2. Each BEGIN IMMEDIATE waits up to 30s before returning SQLITE_BUSY
3. With 5 retries, worst case was 5 × 30s = 150+ seconds
The fix removes the retry loop since SQLite's busy_timeout already handles
retries internally. BEGIN IMMEDIATE still acquires the write lock early,
preventing deadlocks - we just let busy_timeout handle contention.
Root cause analysis in bd-9ldm.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update withTx to use BEGIN IMMEDIATE with exponential backoff retry
on SQLITE_BUSY errors. This prevents "database is locked" failures
during concurrent operations (daemon + CLI, multi-agent workflows).
Changes:
- withTx now uses beginImmediateWithRetry (same pattern as RunInTransaction)
- Add dbExecutor interface for helper functions that work with both
*sql.Tx and *sql.Conn
- Update all withTx callers to use *sql.Conn
- Refactor DeleteIssue to use withTx (fixes the specific error in auto-import)
- Update markIssuesDirtyTx to accept dbExecutor interface
Affected paths:
- MarkIssuesDirty, ClearDirtyIssuesByID (dirty.go)
- AddDependency, RemoveDependency (dependencies.go)
- executeLabelOperation (labels.go)
- AddComment (events.go)
- ApplyCompaction (compact.go)
- DeleteIssue (queries.go)
Note: Some direct BeginTx calls in queries.go (CloseIssue, UpdateIssue,
ReopenIssue, DeleteIssues) still use the old pattern and could be
refactored in a follow-up.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds operational improvements to the Dolt storage backend for increased
reliability in production environments with concurrent clients:
1. Lock retry with exponential backoff:
- Add LockRetries and LockRetryDelay config options
- Automatic retry on lock contention (default: 30 retries, ~6s window)
- Exponential backoff starting at 100ms
- Handles transient format version errors during manifest updates
2. Stale lock file cleanup:
- Detect and clean orphaned .dolt/noms/LOCK files on startup
- Prevents "database is read only" errors after crashes
- Only removes empty locks older than 5 seconds
3. Transient error detection:
- isTransientDoltError() detects retryable conditions
- isLockError() identifies lock contention scenarios
- cleanupStaleDoltLock() safely removes orphaned locks
These improvements address common issues in multi-process environments
where the Dolt embedded driver creates exclusive locks that persist
after unexpected termination.
Co-authored-by: upstream_syncer <matthew.baker@pihealth.ai>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
When creating issues with explicit IDs via PrefixOverride (for cross-rig
creation), the storage layer was still validating against the local
config prefix, causing errors like:
issue ID 'da-DataArchive-witness' does not match configured prefix 'hq'
The queries.go layer already handled PrefixOverride correctly, but
transaction.go did not. This fix adds the same PrefixOverride handling
to transaction.go:
1. Check if PrefixOverride is set
2. If set, use it as the prefix and skip validation (caller knows best)
3. Otherwise, fall back to existing IDPrefix/configPrefix logic
This allows gt doctor --fix to create agent beads for non-local rigs.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Web UIs:
- beads-kanban-ui: Visual Kanban board with git branch status tracking,
epic/subtask management, design doc viewer, and activity timeline.
Claude Code Orchestration (new section):
- beads-orchestration: Multi-agent orchestration skill for Claude Code.
Orchestrator investigates issues, manages tasks automatically, and
delegates to tech-specific supervisors on isolated branches.
CGO cross-compilation for darwin from Linux CI runner fails without
osxcross. Since Dolt/federation features are now CGO-optional,
darwin builds can use CGO_ENABLED=0.
Users who need Dolt features on macOS can build from source with
CGO enabled.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The dolthub/gozstd dependency requires CGO. Several files were importing
the dolt package without build constraints, causing CI failures when
building with CGO_ENABLED=0 for Linux, FreeBSD, and Android.
Changes:
- Add //go:build cgo to federation.go and doctor/federation.go
- Create dolt_server_cgo.go/nocgo.go to abstract dolt.Server usage
- Create federation_nocgo.go with stub command explaining CGO requirement
- Create doctor/federation_nocgo.go with stub health checks
- Update daemon.go to use the dolt server abstraction
Federation and Dolt-specific features are unavailable in non-CGO builds.
Users are directed to pre-built binaries from GitHub releases.
Fixes v0.49.0 CI failure.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>