The daemon guard was blocking ALL daemon commands when using Dolt
backend, including read-only commands like `status`, `stop`, `logs`.
Changes:
- Rename guard to `guardDaemonStartForDolt` (more accurate)
- Remove `PersistentPreRunE` from `daemonCmd` and `daemonsCmd`
- Add `PreRunE` guard only to `daemonStartCmd` and `daemonsRestartCmd`
- Update test to use new function name and test start command
Now:
- `bd daemon status` works with Dolt backend
- `bd daemon start` blocked unless `--federation` flag
- `bd daemon start --federation` works (starts dolt sql-server)
Fixes: bd-n7o47
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add `bd migrate --to-dolt` and `bd migrate --to-sqlite` commands for
migrating between SQLite and Dolt storage backends.
Features:
- `--to-dolt`: Migrate from SQLite to Dolt backend
- Creates backup of SQLite database before migration
- Imports all issues, labels, and dependencies
- Updates metadata.json to use Dolt backend
- Preserves JSONL export configuration
- `--to-sqlite`: Escape hatch to migrate back to SQLite
- Exports all data from Dolt to new SQLite database
- Updates metadata.json to use SQLite backend
Both commands support:
- `--dry-run` flag to preview changes
- `--yes` flag for automated/scripted usage
- `--json` flag for machine-readable output
- Non-cgo stub for builds without CGO support
This implements Part 7 (Migration Tooling) of DOLT-STORAGE-DESIGN.md.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix sandboxed daemon autostart tests and lint cleanup (bd-1zo)
* Restore issues jsonl to main state (bd-1zo)
* Remove .beads changes from PR (bd-1zo)
* Fix Windows build for dolt SysProcAttr (bd-1zo)
* Reset .beads/issues.jsonl to upstream main (bd-1zo)
* Reset .beads/issues.jsonl to upstream main (bd-1zo)
* Reset .beads/issues.jsonl to upstream main (bd-1zo)
* Fix Windows password prompt fd type (bd-1zo)
* Reset .beads/issues.jsonl to upstream main (bd-1zo)
---------
Co-authored-by: Amp <amp@example.com>
Co-authored-by: beads/crew/darcy <steve.yegge@gmail.com>
CI_REPORT.md and FIX_SUMMARY.md were included in PR #1242 for review
purposes but should not be part of the main codebase.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes stack overflow and database initialization failures when running bd on WSL2 with Docker Desktop bind mounts.
## Problem
The bd CLI crashed with stack overflow when running on WSL2 with repositories on Docker Desktop bind mounts (/mnt/wsl/docker-desktop-bind-mounts/...). SQLite WAL mode fails with 'locking protocol' error on these network filesystems.
## Solution
- Expand WAL mode detection to identify Docker bind mounts at /mnt/wsl/* (in addition to Windows paths at /mnt/[a-zA-Z]/)
- Fall back to DELETE journal mode on these problematic paths
- Add comprehensive unit tests for path detection
Fixes GH #1224, relates to GH #920
Co-authored-by: maphew <matt.wilkie@gmail.com>
Remove recursive tryAutoStartDaemon calls from handleStaleLock that
caused infinite recursion when daemon start lock cleanup looped.
The call chain was: acquireStartLock -> handleStaleLock ->
tryAutoStartDaemon -> acquireStartLock -> ... (unbounded)
Now handleStaleLock just cleans up stale locks and returns false,
letting the caller's bounded retry loop handle retries.
Co-authored-by: Nelson Melo <nmelo@users.noreply.github.com>
Remove Gas Town-specific type constants (TypeMolecule, TypeGate, TypeConvoy,
TypeMergeRequest, TypeSlot, TypeAgent, TypeRole, TypeRig, TypeEvent, TypeMessage)
from internal/types/types.go.
Beads now only has core work types built-in:
- bug, feature, task, epic, chore
All Gas Town types are now purely custom types with no special handling in beads.
Use string literals like "gate" or "molecule" when needed, and configure
types.custom in config.yaml for validation.
Changes:
- Remove Gas Town type constants from types.go
- Remove mr/mol aliases from Normalize()
- Update bd types command to only show core types
- Replace all constant usages with string literals throughout codebase
- Update tests to use string literals
This decouples beads from Gas Town, making it a generic issue tracker.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add CheckPatrolPollution to detect stale patrol beads:
- Patrol digests matching 'Digest: mol-*-patrol'
- Session ended beads matching 'Session ended: *'
Includes auto-fix via 'bd doctor --fix' to clean up pollution.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Improve the federation status command to show more comprehensive
information similar to `git remote -v` with health info:
- Show peer URLs alongside peer names
- Display pending local changes count (uncommitted)
- Test connectivity to each peer (via fetch)
- Track and display last sync time in metadata table
- Show reachability status with error messages on failure
Changes:
- cmd/bd/federation.go: Enhanced status output with URLs, connectivity
checks, pending changes, and last sync time
- internal/storage/dolt/federation.go: Added getLastSyncTime/setLastSyncTime
methods using metadata table, record sync time on successful sync
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
During bd init, auto-import fails with "invalid issue type" errors even
when types.custom is defined in config.yaml. This happens because custom
types are read from the database, but the database is being created
during init and doesn't have the config set yet.
Changes:
- Add GetCustomTypesFromYAML() to internal/config/config.go to read
types.custom from config.yaml via viper
- Modify GetCustomTypes() in sqlite/config.go to fallback to config.yaml
when the database doesn't have types.custom configured
- Add tests for GetCustomTypesFromYAML()
This allows fresh clones with custom types defined in config.yaml (e.g.,
Gas Town types like molecule, gate, convoy, agent, event) to successfully
auto-import their JSONL during bd init.
Fixes GH#1225
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
For repos with 1000+ issues where less than 20% are dirty,
incremental export reads the existing JSONL, merges only
changed issues, and writes back - avoiding full re-export.
- Add exportToJSONLIncrementalDeferred as new default export path
- Add shouldUseIncrementalExport to check thresholds
- Add performIncrementalExport for merge-based export
- Add readJSONLToMap helper for fast JSONL parsing
- Falls back to full export when incremental is not beneficial
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Merge SQL user authentication with Emma federation sync implementation:
- Add federation_peers table for encrypted credential storage
- Add credentials.go with AES-256-GCM encryption, SHA-256 key derivation
- Extend FederatedStorage interface with credential methods
- Add --user, --password, --sovereignty flags to bd federation add-peer
- Integrate credentials into PushTo/PullFrom/Fetch via withPeerCredentials
- DOLT_REMOTE_USER/PASSWORD env vars protected by mutex for concurrency
Credentials automatically used when syncing with peers that have stored auth.
Continues: bd-wkumz.10, Closes: bd-4p67y
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add --federation-port and --remotesapi-port flags (default 3306/8080)
- Fix log file leak in server.go - track and close on Stop()
- Add BEADS_DOLT_PASSWORD env var for server mode authentication
- Update DSN to include password when set
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update guards to allow daemon commands when --federation is set.
Federation mode runs dolt sql-server which enables multi-writer
support, unlike embedded Dolt which is single-process only.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add --federation flag to bd daemon start that runs dolt sql-server
instead of the embedded driver. Enables multi-writer support and
exposes remotesapi on port 8080 for peer-to-peer push/pull.
Changes:
- Add --federation flag to daemon start command
- Create dolt server manager (internal/storage/dolt/server.go)
- Update DoltStore to support server mode via MySQL protocol
- Integrate server lifecycle into daemon (auto-start/stop)
- Add tests for server management and server mode connections
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The ncruces/go-sqlite3 driver does not always auto-convert TEXT columns
to time.Time. This caused scan errors on updated_at/created_at fields,
blocking witness startup.
Fix: Scan timestamps into sql.NullString and parse with parseTimeString()
helper that handles RFC3339Nano, RFC3339, and SQLite native formats.
Fixes: bd-4dqmy
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add support for importing routes.jsonl and interactions.jsonl during
Dolt bootstrap. Previously only issues.jsonl was imported.
Changes:
- Add routes and interactions tables to Dolt schema
- Import routes before issues (no dependencies)
- Import interactions after issues (may reference issue_id)
- Reuse audit.Entry type instead of duplicating
- Add tests for multi-file bootstrap
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add versioned storage methods for incremental export support:
- GetChangesSinceExport: returns changes since a commit hash, with
NeedsFullExport flag for invalid/GC'd commits
- CommitExists: checks if a commit hash exists, supports short prefixes
Also fixes dolt_diff syntax for embedded driver (from_ref, to_ref, table).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add peer-to-peer synchronization for Dolt-backed beads databases:
- New FederatedStorage interface with PushTo, PullFrom, Fetch, ListRemotes,
RemoveRemote, and SyncStatus methods
- DoltStore implementation using DOLT_PUSH, DOLT_PULL, DOLT_FETCH
- Full bd federation command with subcommands:
- sync: bidirectional sync with conflict resolution (--strategy ours|theirs)
- status: show ahead/behind counts and conflict state
- add-peer/remove-peer/list-peers: manage federation remotes
- Comprehensive tests for all federation APIs
Closes: bd-wkumz.4
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When running `bd init` from a directory with a .beads/redirect file
pointing to a canonical .beads/ that already has a database, init
now errors instead of silently overwriting the existing database.
This prevents accidental data loss when:
- A project uses redirect to share a canonical database
- Someone runs `bd init` from the redirected location
- The canonical database was already initialized
The error message clearly explains:
- What happened (redirect target already has database)
- Where the redirect points to
- How to use the existing database (just run bd commands normally)
- How to reinitialize if needed (rm the database first)
Adds test: TestInitWithRedirectToExistingDatabase
Part of GH#bd-0qel
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When bd runs with --no-daemon or during init in a directory that has a
.beads/redirect file, it now correctly follows the redirect to create
the database in the target location instead of locally.
The bug occurred because:
1. init.go hardcoded .beads/beads.db without checking for redirects
2. main.go's fallback path for auto-bootstrap also used local .beads
Both code paths now call beads.FollowRedirect() to resolve the correct
.beads directory before constructing the database path.
Added TestInitWithRedirect to verify the fix.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add jsonlFilePaths constant to eliminate duplicate file list definitions
- Update all usages in hook.go and hooks.go to use the shared constant
- Include beads.jsonl for backwards compatibility with older installations
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add detection and hook support for jujutsu repositories:
- IsJujutsuRepo(): detects .jj directory
- IsColocatedJJGit(): detects colocated jj+git repos
- GetJujutsuRoot(): finds jj repo root
For colocated repos (jj git init --colocate):
- Install simplified hooks without staging (jj auto-commits working copy)
- Worktree handling preserved for git worktrees in colocated repos
For pure jj repos (no git):
- Print alias instructions since jj doesn't have native hooks yet
Closes: hq-ew1mbr.12
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace polling with filesystem watching for near-instant wake-up
(<50ms vs 250ms avg). Watches .beads/dolt/.dolt/noms for Dolt commits.
Falls back to polling if fsnotify unavailable.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Convenience alias for 'bd list --parent <id>'. Lists all child beads
of a specified parent, supporting all standard list flags (--json,
--pretty, etc.).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add new `bd rename <old-id> <new-id>` command that:
- Updates the issue's primary ID
- Updates text references in other issues (title, description, etc.)
- Handles dependencies via storage layer's UpdateIssueID
Also fix sync.go build error where hasSyncBranchConfig/syncBranchName
were referenced but not defined - should use sbc.IsConfigured()/sbc.Branch.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add integration tests validating Dolt APIs needed for peer-to-peer
federation between Gas Towns:
- TestFederationDatabaseIsolation: verify separate towns have isolated DBs
- TestFederationVersionControlAPIs: branch, checkout, merge, commit
- TestFederationRemoteConfiguration: AddRemote accepts dolthub:// URLs
- TestFederationHistoryQueries: commit history, dolt_log, AS OF
Key finding: Production federation uses dolt sql-server remotesapi
(port 8080) for direct peer-to-peer push/pull - no DoltHub required.
Also fixes concurrent_test.go Merge() return value handling.
Refs: bd-wkumz (Federation epic), hq-ew1mbr.7 (prototype task)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix doctor DB-JSONL sync check to exclude ephemeral wisps
The DB-JSONL Sync check was showing a false positive warning when wisps
(ephemeral issues) existed in the database. Wisps are intentionally
excluded from JSONL exports, so they shouldn't be counted when comparing
database and JSONL issue counts.
Changes:
- Updated CheckDatabaseJSONLSync to exclude ephemeral issues from count
using 'WHERE ephemeral = 0 OR ephemeral IS NULL'
- Added 'ephemeral' column to test database schema
- Added test case to verify ephemeral issues are excluded from count
- Updated TestCheckDatabaseJSONLSync_MoleculePrefix to include ephemeral column
This prevents false warnings like 'database has 92 issues, JSONL has 30'
when the difference is entirely due to wisps that should not be exported.
* feat(mol): add 'bd mol seed --patrol' command
Adds `bd mol seed` command to verify formula accessibility before
patrols attempt to spawn work.
## Problem
Gas Town's `gt rig add` calls `bd mol seed --patrol` but this command
didn't exist in beads, causing the call to always fail and fall back
to creating non-functional placeholder beads.
## Solution
Implemented `bd mol seed` with two modes:
1. **With --patrol flag**: Verifies all three patrol formulas are accessible
- mol-deacon-patrol
- mol-witness-patrol
- mol-refinery-patrol
2. **Without --patrol**: Verifies a specific formula is accessible
## Implementation
The command uses `resolveAndCookFormulaWithVars` to verify formulas:
- Checks formula search paths (.beads/formulas/, ~/.beads/formulas/, $GT_ROOT/.beads/formulas/)
- Validates formula syntax and resolution
- Confirms formula can be cooked to subgraph
## Usage
```bash
bd mol seed --patrol # Verify all patrol formulas
bd mol seed mol-feature # Verify specific formula
bd mol seed mol-review --var name=test # With variable substitution
```
## Testing
- ✅ Command compiles without errors
- ✅ Help text displays correctly
- ✅ `--patrol` succeeds when formulas accessible (town level)
- ✅ `--patrol` fails with clear error when formulas missing (rig level)
- ✅ Follows existing beads command patterns (cobra, flags, error handling)
## Impact
- Enables Gas Town's intended patrol formula verification flow
- Eliminates creation of unnecessary placeholder beads
- Provides health check command for formula accessibility
- Foundation for future seed commands (data initialization, etc.)
Fixes the missing command referenced in steveyegge/gastown#715
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Roland Tritsch <roland@ailtir.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
When running in gastown multi-workspace mode, two checks produce false
positives that are expected behavior:
1. routes.jsonl is a valid configuration file (maps issue prefixes to
rig directories), not a duplicate JSONL file
2. Duplicate issues are expected (ephemeral wisps from patrol cycles)
and normal up to ~1000, with GC cleaning them up automatically
This commit adds flags to bd doctor for gastown-specific checks:
- --gastown: Skip routes.jsonl warning and enable duplicate threshold
- --gastown-duplicates-threshold=N: Set duplicate tolerance (default 1000)
Fixes false positive warnings:
Multiple JSONL files found: issues.jsonl, routes.jsonl
70 duplicate issue(s) in 30 group(s)
Changes:
- Add --gastown flag to bd doctor command
- Add --gastown-duplicates-threshold flag (default: 1000)
- Update CheckLegacyJSONLFilename to skip routes.jsonl when gastown mode active
- Update CheckDuplicateIssues to use configurable threshold when gastown mode active
- Add test cases for gastown mode behavior with various thresholds
Co-authored-by: Roland Tritsch <roland@ailtir.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix(sync): use sync-branch worktree for --full --no-pull (#1173)
Bug 1: PullFromSyncBranch was copying uncommitted worktree changes to
main repo when remoteAhead==0. This corrupted the 3-way merge because
local changes appeared as remote changes. Fixed by copying only the
committed state from HEAD instead of the working directory.
Bug 2: doExportOnlySync was checking main repo for changes via
gitHasBeadsChanges, but when sync-branch is configured, changes go to
the worktree, not main. Fixed by detecting sync-branch config and using
CommitToSyncBranch which operates on the worktree.
Fixes#1173
* refactor(sync): consolidate sync-branch detection and commit/push logic
Extract repeated patterns into reusable helpers:
- SyncBranchContext struct: holds branch name and repo root
- getSyncBranchContext(): detects sync-branch config from store
- commitAndPushBeads(): handles both sync-branch and regular git workflows
This eliminates duplicated sync-branch detection code (was in 3 places)
and the duplicated commit/push conditional logic (was in 2 places).
Net reduction of ~20 lines while improving maintainability.
* fix: remove unused bool return from commitAndPushBeads
Motivation:
The existing --parent flag only shows direct children in a flat list,
but users often need to see the complete hierarchy including grandchildren
and deeper levels. This limitation made it difficult to understand the
full scope of work under an epic or parent issue.
Key changes:
- Enhanced list command to detect --tree --parent combination
- Implemented recursive parent filtering instead of GetDependencyTree
- Added DRY refactoring with withStorage() and getHierarchicalChildren() helpers
- Eliminated duplication between daemon and direct modes
- Added comprehensive test coverage with TestHierarchicalChildren
- Fixed cross-repository compatibility issues
Side-effects:
- No breaking changes: existing --parent behavior unchanged
- --tree --parent now shows hierarchical tree instead of flat list
- Parent issue is included as root of the displayed tree
- Works consistently across all repositories and storage modes
- Improved code maintainability with DRY architecture
- Better test coverage ensures reliability and prevents regressions
* feat(linear): add --type and --exclude-type flags for sync filtering
Add type filtering support to `bd linear sync --push` to allow users to
control which issue types are synced to Linear.
New flags:
- --type: Only sync issues matching these types (e.g., --type=task,feature)
- --exclude-type: Exclude issues of these types (e.g., --exclude-type=wisp)
Use cases:
- Sync only work items (tasks, features, bugs) while excluding internal
telemetry (wisps, messages)
- Push only specific issue types to Linear
Fixes#1204
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(linear): update test to match new doPushToLinear signature
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>