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>
fix(daemon): prevent zombie state after database file replacement
Adds checkFreshness() to health check paths (GetMetadata, GetConfig, GetAllConfig) and refactors reconnect() to validate new connection before closing old.
PR-URL: https://github.com/steveyegge/beads/pull/1213
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The autoimport fix PR accidentally included local beads data changes.
This reverts the data files while keeping the code fixes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(autoimport): auto-correct deleted status to tombstone for JSONL compatibility (GH#1223)
This fix addresses the 'Stuck in sync diversion loop' issue where v0.48.0
encountered validation errors during JSONL import. The issue occurs when
JSONL files from older versions have issues with status='deleted' but the
current code expects status='tombstone' for deleted issues.
Changes:
- Add migration logic in parseJSONL to auto-correct 'deleted' status to 'tombstone'
- Ensure tombstones always have deleted_at timestamp set
- Add debug logging for both migration operations
- Prevents users from being stuck in sync divergence when upgrading
Fixes GH#1223: Stuck in sync diversion loop
* fix(autoimport): comprehensively fix corrupted deleted_at on non-tombstone issues (GH#1223)
The initial fix for GH#1223 only caught issues with status='deleted', but the real
data in the wild had issues with status='closed' (or other statuses) but also
had deleted_at set, which violates the validation rule.
Changes:
- Add broader migration logic: any non-tombstone issue with deleted_at should become tombstone
- Apply fix in all three JSONL parsing locations:
- internal/autoimport/autoimport.go (parseJSONL for auto-import)
- cmd/bd/import.go (import command)
- cmd/bd/daemon_sync.go (daemon sync helper)
- Add comprehensive test case for corrupted closed issues with deleted_at
- Fixes the 'non-tombstone issues cannot have deleted_at timestamp' validation error
during fresh bd init or import
Fixes GH#1223: Stuck in sync diversion loop
* Add merge driver comment to .gitattributes
* fix: properly clean up .gitattributes during bd admin reset
Fixes GH#1223 - Stuck in sync diversion loop
The removeGitattributesEntry() function was not properly cleaning up
beads-related entries from .gitattributes. It only removed lines
containing "merge=beads" but left behind:
- The comment line "# Use bd merge for beads JSONL files"
- Empty lines following removed entries
This caused .gitattributes to remain in a modified state after
bd admin reset --force, triggering sync divergence warning loop.
The fix now:
- Skips lines containing "merge=beads" (existing behavior)
- Skips beads-related comment lines
- Skips empty lines that follow removed beads entries
- Properly cleans up file so it's either empty (and gets deleted)
or contains only non-beads content
---------
Co-authored-by: Amp <amp@example.com>
The Codex setup feature PR accidentally included local beads data changes.
This reverts just the data file while keeping the code changes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(routing): auto-enable hydration and flush JSONL after routed create
Fixes split-brain bug where issues routed to different repos (via routing.mode=auto)
weren't visible in bd list because JSONL wasn't updated and hydration wasn't configured.
**Problem**: When routing.mode=auto routes issues to a separate repo (e.g., ~/.beads-planning),
those issues don't appear in 'bd list' because:
1. Target repo's JSONL isn't flushed after create
2. Multi-repo hydration (repos.additional) not configured automatically
3. No doctor warnings about the misconfiguration
**Changes**:
1. **Auto-flush JSONL after routed create** (cmd/bd/create.go)
- After routing issue to target repo, immediately flush to JSONL
- Tries target daemon's export RPC first (if daemon running)
- Falls back to direct JSONL export if no daemon
- Ensures hydration can read the new issue immediately
2. **Enable hydration in bd init --contributor** (cmd/bd/init_contributor.go)
- Wizard now automatically adds planning repo to repos.additional
- Users no longer need to manually run 'bd repo add'
- Routed issues appear in bd list immediately after setup
3. **Add doctor check for hydrated repo daemons** (cmd/bd/doctor/daemon.go)
- New CheckHydratedRepoDaemons() warns if daemons not running
- Without daemons, JSONL becomes stale and hydration breaks
- Suggests: cd <repo> && bd daemon start --local
4. **Add doctor check for routing+hydration mismatch** (cmd/bd/doctor/config_values.go)
- Validates routing targets are in repos.additional
- Catches split-brain configuration before users encounter it
- Suggests: bd repo add <routing-target>
**Testing**: Builds successfully. Unit/integration tests pending.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* test(routing): add comprehensive tests for routing fixes
Add unit tests for all 4 routing/hydration fixes:
1. **create_routing_flush_test.go** - Test JSONL flush after routing
- TestFlushRoutedRepo_DirectExport: Verify direct JSONL export
- TestPerformAtomicExport: Test atomic file operations
- TestFlushRoutedRepo_PathExpansion: Test path handling
- TestRoutingWithHydrationIntegration: E2E routing+hydration test
2. **daemon_test.go** - Test hydrated repo daemon check
- TestCheckHydratedRepoDaemons: Test with/without daemons running
- Covers no repos, daemons running, daemons missing scenarios
3. **config_values_test.go** - Test routing+hydration validation
- Test routing without hydration (should warn)
- Test routing with correct hydration (should pass)
- Test routing target not in hydration list (should warn)
- Test maintainer="." edge case (should pass)
All tests follow existing patterns and use t.TempDir() for isolation.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix(tests): fix test failures and refine routing validation logic
Fixes test failures and improves validation accuracy:
1. **Fix routing+hydration validation** (config_values.go)
- Exclude "." from hasRoutingTargets check (current repo doesn't need hydration)
- Prevents false warnings when maintainer="." or contributor="."
2. **Fix test ID generation** (create_routing_flush_test.go)
- Use auto-generated IDs instead of hard-coded "beads-test1"
- Respects test store prefix configuration (test-)
- Fixed json.NewDecoder usage (file handle, not os.Open result)
3. **Fix config validation tests** (config_values_test.go)
- Create actual directories for routing paths to pass path validation
- Tests now verify both routing+hydration AND path existence checks
4. **Fix daemon test expectations** (daemon_test.go)
- When database unavailable, check returns "No additional repos" not error
- This is correct behavior (graceful degradation)
All tests now pass:
- TestFlushRoutedRepo* (3 tests)
- TestPerformAtomicExport
- TestCheckHydratedRepoDaemons (3 subtests)
- TestCheckConfigValues routing tests (5 subtests)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* docs: clarify when git config beads.role maintainer is needed
Clarify that maintainer role config is only needed in edge case:
- Using GitHub HTTPS URL without credentials
- But you have write access (are a maintainer)
In most cases, beads auto-detects correctly via:
- SSH URLs (git@github.com:owner/repo.git)
- HTTPS with credentials
This prevents confusion - users with SSH or credential-based HTTPS
don't need to manually configure their role.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* fix(lint): address linter warnings in routing flush code
- Add missing sqlite import in daemon.go
- Fix unchecked client.Close() error return
- Fix unchecked tempFile.Close() error returns
- Mark unused parameters with _ prefix
- Add nolint:gosec for safe tempPath construction
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Roland Tritsch <roland@ailtir.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
The Dolt storage was scanning created_at and updated_at directly into
time.Time fields, but SQLite stores these as TEXT strings. The Go SQLite
driver cannot automatically convert TEXT to time.Time.
Added parseTimeString() helper and fixed all scan functions:
- issues.go: scanIssue()
- dependencies.go: scanIssueRow()
- history.go: GetIssueHistory(), GetIssueAsOf()
- transaction.go: scanIssueTx()
Fixes bd-4dqmy
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When bd create --id=pq-xxx is called with an ID prefix that does not
match the current database, automatically route to the correct database
based on routes.jsonl configuration.
Changes:
- Add auto-routing logic before explicit --rig/--prefix handling
- Extract prefix from explicit ID and look it up in routes.jsonl
- If prefix matches a different rig, call createInRig automatically
- Update createInRig to accept explicitID parameter
- Pass explicitID through to issue creation
This fixes the prefix mismatch error when creating issues with
explicit IDs across rigs in multi-repo setups like Gas Town.
Example:
cd ~/gt # Root with hq- prefix
bd create --id=pq-xxx --title="Test"
# Now automatically routes to pgqueue/.beads/beads.db
Fixes: gt doctor --fix failing to create agent beads
Closes: #1188
Cherry-picked from Team-Ailtir/beads PR #1188 with build fix.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move LocalProvider from cmd/bd/doctor/git.go to internal/storage/local_provider.go
where it belongs alongside StorageProvider. Both implement IssueProvider for
orphan detection - LocalProvider for direct SQLite access (--db flag),
StorageProvider for the global Storage interface.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Inspired by PR #1164 from Piyush Jha (@Hackinet). Groups commands
under 'bd kv' subcommand for cleaner namespacing.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Users naturally try 'bd view <id>' when they want to see an issue.
Adding 'view' as an alias improves discoverability and UX.
Fixes bd-bpx35
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix(orphans): honor --db flag for cross-repo orphan detection
Problem:
- `bd orphans --db /path` ignored the --db flag entirely
- FindOrphanedIssues() hardcoded local .beads/ directory
Solution:
- Introduce IssueProvider interface for abstract issue lookup
- Add StorageProvider adapter wrapping Storage instances
- Update FindOrphanedIssues to accept provider instead of path
- Wire orphans command to create provider from --db flag
Closes: steveyegge/beads#1196
* test(orphans): add cross-repo and provider tests for --db flag fix
- Add TestFindOrphanedIssues_WithMockProvider (table-driven, UT-01 through UT-09)
- Add TestFindOrphanedIssues_CrossRepo (validates --db flag honored)
- Add TestFindOrphanedIssues_LocalProvider (backward compat RT-01)
- Add TestFindOrphanedIssues_ProviderError (error handling UT-07)
- Add TestFindOrphanedIssues_IntegrationCrossRepo (IT-02 full)
- Add TestLocalProvider_* unit tests
Coverage for IssueProvider interface and cross-repo orphan detection.
* docs: add bd orphans command to CLI reference
Document the orphan detection command including the cross-repo
workflow enabled by the --db flag fix in this PR.
- repair.go: Extract validateRepairPaths(), findAllOrphans(), printOrphansText()
- config_values.go: Extract findConfigPath(), validateDurationConfig(), etc.
- Target: CC < 20 for each extracted function
Implements configurable per-field merge strategies (hq-ew1mbr.11):
- Add FieldStrategy type with strategies: newest, max, union, manual
- Add conflict.fields config section for per-field overrides
- compaction_level defaults to "max" (highest value wins)
- estimated_minutes defaults to "manual" (flags for user resolution)
- labels defaults to "union" (set merge)
Manual conflicts are displayed during sync with resolution options:
bd sync --ours / --theirs, or bd resolve <id> <field> <value>
Config example:
conflict:
strategy: newest
fields:
compaction_level: max
estimated_minutes: manual
labels: union
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add --message/-m as a hidden alias for --description on bd create,
matching the git commit -m convention for muscle memory.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(ready): exclude molecule steps from bd ready by default (GH#1239)
Add ID prefix constants (IDPrefixMol, IDPrefixWisp) to types.go as single
source of truth. Update pour.go and wisp.go to use these constants.
GetReadyWork now excludes issues with -mol- in their ID when no explicit
type filter is specified. Users can still see mol steps with --type=task.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(ready): config-driven ID pattern exclusion (GH#1239)
Add ready.exclude_id_patterns config for excluding IDs from bd ready.
Default patterns: -mol-, -wisp- (molecule steps and wisps).
Changes:
- Add IncludeMolSteps to WorkFilter for internal callers
- Update findGateReadyMolecules and getMoleculeCurrentStep to use it
- Make exclusion patterns config-driven via ready.exclude_id_patterns
- Remove hardcoded MolStepIDPattern() in favor of config
- Add test for custom patterns (e.g., gastown's -role-)
Usage: bd config set ready.exclude_id_patterns "-mol-,-wisp-,-role-"
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: remove -role- example from ready.go comments
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: remove GH#1239 references from code comments
Issue references belong in commit messages, not code.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Fixes from code review:
1. **Data completeness**: Now migrates events (including comments)
and all config values, not just issues/labels/deps
2. **formatJSONArray**: Fixed to use JSON encoding for waiters field
to match Dolt schema (was using comma-separated format)
3. **Cleanup on failure**: Removes partial Dolt directory or SQLite
files if import fails mid-way
4. **Progress indicator**: Shows "Importing issues: N/M" for large
migrations (100+ issues)
5. **Code deduplication**: Extracted common logic into:
- migrationData struct
- storageReader interface
- extractFromStore() shared extraction
- Helper functions for output formatting
6. **Improved dry-run output**: Now shows event count and config
key count in migration plan
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add integration tests for the Gas Town hub+spokes topology where:
- Hub (mayor rig) runs dolt sql-server with remotesapi
- Spokes (crew clones) configure hub as their only peer
- Data flows through hub in star topology
Tests included:
- TestHubSpokes_MultiCloneSync: Basic two-spoke convergence
- TestHubSpokes_WorkDispatch: Hub dispatches work, spokes complete it
- TestHubSpokes_ThreeSpokesConverge: Three-spoke convergence test
Note: These tests follow the same pattern as peer_sync_integration_test.go
and document current behavior including the no common ancestor limitation
that affects cross-database sync.
Closes bd-phwci
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The default package now includes fish, bash, and zsh completions
at standard paths. This means users only need to install the
default package to get both the binary and completions.
The separate completion packages are kept for backwards
compatibility but now simply symlink to the default package.
Standard completion paths:
- share/fish/vendor_completions.d/bd.fish
- share/bash-completion/completions/bd
- share/zsh/site-functions/_bd
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>