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>
The local-install step now includes instructions for developers who
build bd from source. This ensures all bd binaries in PATH are updated,
not just the release binary downloaded by the install script.
Executed-By: beads/crew/emma
Rig: beads
Role: crew
The pre-push hook was checking for uncommitted JSONL changes even in
dolt-native sync mode where JSONL files don't exist. This blocked pushes
unnecessarily. Now skips the check entirely when sync.mode is dolt-native.
Fixes: hq-6ymh
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: mayor
Role: mayor
The doltTransaction.CreateIssue method was missing ID generation logic
that exists in the SQLite transaction implementation. When issues were
created within a transaction with empty IDs (like during wisp creation),
they would all get empty string "" as the primary key, causing
"duplicate primary key given: []" errors.
This fix adds the same ID generation logic from SQLite transaction:
- Get config prefix from database
- Apply IDPrefix/PrefixOverride to determine effective prefix
- Generate hash-based ID using generateIssueID
Fixes wisp creation failures across all rigs running Dolt server mode.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The daemon startup was blocking ALL Dolt backends, but Dolt server mode
actually supports multi-process access. Now checks SingleProcessOnly
capability like the guard function does, allowing daemon start with
Dolt server mode while still blocking embedded Dolt mode.
This silences the "DAEMON NOT SUPPORTED WITH DOLT BACKEND" warning
when using dolt_mode: "server" in the configuration.
Fixes gt-b8ed44
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: mayor
Role: mayor
Add detailed documentation for using Dolt as an alternative storage
backend to SQLite, including:
- Quick start guide with installation instructions
- Server mode vs embedded mode comparison
- Configuration options in metadata.json and config.yaml
- Migration guide from SQLite to Dolt
- AWS S3+DynamoDB remote sync setup
- Performance characteristics and benchmarks
- Troubleshooting common issues
This documentation complements the recently added Dolt test suite
and helps users adopt the Dolt backend for their workflows.
Co-authored-by: upstream_syncer <matthew.baker@pihealth.ai>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
When metadata.json has an empty database field and no beads.db file exists,
filepath.Dir("") returns "." which causes lock file operations to use the
current directory instead of the beads directory. This could lead to stack
overflow or unexpected behavior.
Add early validation in tryAutoStartDaemon to check if dbPath is empty and
return false gracefully, consistent with other early-return conditions.
Add GetDependencyRecordsForIssues method to storage interface that
fetches dependencies only for specified issue IDs instead of all
dependencies in the database.
This optimizes bd list --json which previously called
GetAllDependencyRecords() even when displaying only a few issues
(e.g., bd list --limit 10).
- Add GetDependencyRecordsForIssues to Storage interface
- Implement in SQLite, Dolt, and Memory backends
- Update list.go JSON output to use targeted method
- Update mock storage in tests
Origin: Mayor's review of PR #1296
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat(activity): add --details/-d flag for full issue information
Add a new --details (-d) flag to the `bd activity` command that includes
full issue information in the output, including comments.
* style(activity): simplify --details text output format
Remove ASCII tree characters and use cleaner indentation with
blank lines between events for better readability.
* fix(import): support custom issue types during import
Fixes regression from 7cf67153 where custom issue types (agent, molecule,
convoy, etc.) were rejected during import with "invalid issue type" error.
- Add validateFieldUpdateWithCustom() for both custom statuses and types
- Add validateIssueTypeWithCustom() for custom type validation
- Update queries.go UpdateIssue() to fetch and validate custom types
- Update transaction.go UpdateIssue() to fetch and validate custom types
- Add 15 test cases covering custom type validation scenarios
This aligns UpdateIssue() validation with the federation trust model used
by ValidateForImport().
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix(test): add metadata.json and chdir to temp dir in direct mode tests
Fixes three test failures caused by commit e82f5136 which changed
ensureStoreActive() to use factory.NewFromConfig() instead of respecting
the global dbPath variable.
Root cause:
- Tests create issues in test.db and set dbPath = testDBPath
- ensureStoreActive() calls factory.NewFromConfig() which reads metadata.json
- Without metadata.json, it defaults to beads.db
- Opens empty beads.db instead of test.db with the seeded issues
- Additionally, FindBeadsDir() was finding the real .beads dir, not the test one
Fixes applied:
1. TestFallbackToDirectModeEnablesFlush: Add metadata.json pointing to test.db and chdir to temp dir
2. TestImportFromJSONLInlineAfterDaemonDisconnect: Same fix
3. TestIsBeadsPluginInstalledProjectLevel: Set temp HOME to avoid detecting plugin from real ~/.claude/settings.json
All three tests now pass.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
When running `bd list -w` with the daemon active, watchIssues() was
called with nil store, causing a panic at store.SearchIssues().
In daemon mode, storage operations are handled via RPC, so the global
`store` variable is nil. The watch mode code path didn't account for
this and used `store` directly.
Fix: Call ensureDirectMode() before watchIssues() to initialize the
store. This follows the same pattern used for other commands that
need direct store access in daemon mode (e.g., graph, ship).
Fixes#1323
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
The daemon is SQLite-specific (handles JSONL sync to git). Dolt has its
own sync mechanism via sql-server and doesn't need the daemon.
Previously, Dolt server mode returned SingleProcessOnly=false (because
multiple bd processes CAN connect to the same SQL server), which
incorrectly triggered daemon auto-start. The daemon would then fail
with 'DAEMON NOT SUPPORTED WITH DOLT BACKEND' warning on every command.
Now we check isDoltBackend() directly instead of relying on the
SingleProcessOnly capability, which has different semantics.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: mayor
Role: mayor
The Dolt stats subdatabase at .dolt/stats/.dolt/noms/LOCK was causing
"cannot update manifest: database is read only" errors after crashes.
Changes:
- cleanupStaleDoltLock now also cleans stats and oldgen subdatabase LOCKs
- Add dolt_stats_stop() call to fully stop stats background worker
- Set dolt_stats_auto_refresh_interval=0 to prevent stats restart
Fixes bd-dolt.1
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: mayor
Role: mayor
Add stale_closed_issues_days config option to metadata.json:
- 0 (default): Check disabled - repos keep unlimited beads
- >0: Enable check with specified day threshold
Design philosophy: Time-based cleanup is a crude proxy for the real
concern (database size). Disabled by default since a repo with 100
closed issues from 5 years ago doesn't need cleanup.
Also adds a warning when check is disabled but database has >10,000
closed issues, recommending users enable the threshold.
Co-Authored-By: SageOx <ox@sageox.ai>
Executed-By: beads/crew/emma
Rig: beads
Role: crew
Port the adaptive ID length algorithm from SQLite to Dolt backend.
The ID length now scales from 3-8 characters based on database size
using birthday paradox collision probability calculations.
- Add adaptive_length.go with length computation based on issue count
- Update generateIssueID to use adaptive length with nonce fallback
- Add collision detection and retry logic matching SQLite behavior
Fixes bd-c40999
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: mayor
Role: mayor
- Add sync state files to .gitignore (.sync.lock, sync_base.jsonl)
- Add types.custom to config.yaml for Gas Town type fallback
- Remove metadata.json from .gitignore (it should be tracked)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: mayor
Role: mayor
Previously `make install` used `go install` which put the binary in ~/go/bin
without codesigning, while PATH used ~/.local/bin - causing chronic stale
binary issues. Now install depends on build (which codesigns on macOS) and
copies to the correct location.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: mayor
Role: mayor
Shim hooks (bd-shim marker) delegate to 'bd hook' command which already
handles Dolt backend correctly. Update both doctor check and migration
warning to recognize shim hooks as OK.
Only inline hooks (older style with embedded logic) need the explicit
Dolt backend check in the shell script.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Two improvements for Dolt backend users with stale git hooks:
1. Migration warning: When running 'bd migrate --to-dolt', warn if
installed hooks lack the Dolt backend check and suggest reinstalling.
2. Doctor check: New CheckGitHooksDoltCompatibility() detects when
hooks exist but lack the Dolt skip logic, surfacing the error with
a clear fix message.
Both changes help users who migrated to Dolt but have pre-migration
hooks that try to run JSONL sync (which fails with Dolt backend).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Pre-commit and post-merge git hooks were unconditionally running
bd sync/import for JSONL sync, which fails with Dolt backend.
Now both hooks check metadata.json for backend type and exit early
if Dolt is configured. Dolt uses its own sync mechanism.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The guardDaemonStartForDolt check was only applied to the 'bd daemon start'
subcommand, but the deprecated 'bd daemon --start' flag path bypassed it.
This adds the same guard check to the deprecated path so both entry points
consistently refuse to start the daemon when Dolt backend is configured.
The --federation flag still allows Dolt since it enables dolt sql-server
mode which supports multi-writer access.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
SQLite-era instruction causing agents to run deprecated bd sync.
With Dolt backend, there is no sync - database is live.
Part of hq-e4eefc (Dolt migration epic)
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.