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>
Add fish, bash, and zsh completion packages to the Nix flake.
Completions are generated at build time using `bd completion <shell>`.
Usage:
nix build .#fish-completions
nix build .#bash-completions
nix build .#zsh-completions
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* fix(routing): close original store before replacing with target store
Fix "database is closed" error during auto-flush when contributor routing
redirects issue creation to a different repository (e.g., ~/.beads-planning).
When a user is detected as a contributor (based on git remote URL pattern),
the default configuration routes new issues to ~/.beads-planning instead of
the current repository. This routing caused auto-flush to fail with:
Warning: auto-flush failed: failed to get stored JSONL hash:
failed to get jsonl_file_hash: sql: database is closed
In create.go, when switching to the planning repo:
1. targetStore was opened for the planning database
2. A defer was set to close targetStore at function end
3. store = targetStore replaced the global store pointer
4. Issue was created successfully
5. Command Run ended → defer closed targetStore
6. PersistentPostRun tried to flush using the global store → error!
The bug: the defer closed targetStore, but the global `store` variable
pointed to the same object. When PersistentPostRun called flushManager.Shutdown(),
it tried to use the already-closed store for the flush operation.
- Remove the defer that prematurely closed targetStore
- Explicitly close the ORIGINAL store before replacing it (it won't be used)
- Let PersistentPostRun close whatever store is current at exit time
This ensures proper store lifecycle:
- Original store: closed when replaced (no longer needed)
- Target store: closed by PersistentPostRun after flush completes
1. Have a git repo with a remote URL that doesn't match maintainer patterns
(e.g., github-a:org/repo.git instead of git@github.com:org/repo.git)
2. Have ~/.beads-planning directory with beads initialized
3. Run: cd /path/to/repo && bd create "Test issue"
4. Observe: Issue created successfully, but followed by:
Warning: auto-flush failed: ... sql: database is closed
Added debug prints to SQLiteStorage.Close() and GetJSONLFileHash() which
revealed two different databases were involved:
- /path/to/repo/.beads/beads.db (closed first, unexpectedly)
- ~/.beads-planning/.beads/beads.db (used for flush after being closed)
* fix(test): resolve race condition in TestAutoFlushOnExit
Not directly related to the previous routing fix, but exposed by CI timing.
Root cause: The test had a latent race condition between two channel operations:
1. markDirtyAndScheduleFlush() sends event to markDirtyCh
2. Shutdown() sends request to shutdownCh
Without any delay, Go's scheduler might process the shutdown event first.
Since isDirty was still false (markDirty event not yet processed), the
FlushManager would skip the flush entirely, causing the test to fail with
"Expected JSONL file to be created on exit".
The race was always present but only manifested in CI environments with
different timing characteristics (CPU contention, virtualization, scheduler
behavior).
Fix: Add a 10ms sleep after markDirtyAndScheduleFlush() to allow the
FlushManager's background goroutine to process the event before shutdown.
This mimics real-world behavior where there's always some time between
CRUD operations and process exit.
Change routing.mode default from "auto" to "" (empty/disabled).
This fixes GH#1165 where fresh `bd init --prefix X` followed by
`bd create` would unexpectedly route to ~/.beads-planning and fail
with "database not initialized: issue_prefix config is missing".
Auto-routing now requires explicit opt-in via:
- `bd init --contributor` flag, OR
- `bd config set routing.mode auto`
Includes test verifying the default and doc updates clarifying
the opt-in requirement.
The `bd types` command only checked `if store != nil` to fetch custom
types. In daemon mode, `store` is nil (daemonClient handles RPC instead),
so custom types were never displayed even when configured.
This caused a mismatch where `bd config get types.custom` showed the
correct values but `bd types` showed none.
Fix by calling ensureDirectMode() at the start of the command, matching
the pattern used by `bd config get`. This falls back from daemon mode
to direct storage access when needed.
Co-authored-by: Perttulands <perttu.landstrom@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Computes the relative path from the worktree root instead of the .beads directory. This ensures that FollowRedirect resolves paths correctly relative to the parent of .beads.
Code review improvements to internal/config/sync.go:
1. Warning suppression toggle
- Add ConfigWarnings bool to enable/disable warnings
- Add ConfigWarningWriter io.Writer for testable output
2. Consolidate sync mode constants
- cmd/bd/sync_mode.go now imports from internal/config
- Single source of truth for mode values
- Uses shared IsValidSyncMode() for validation
3. Fix empty sovereignty semantics
- Empty now returns SovereigntyNone (no restriction)
- Only non-empty invalid values fall back to T1 with warning
4. Export validation helpers
- IsValidSyncMode(), IsValidConflictStrategy(), IsValidSovereignty()
- ValidSyncModes(), ValidConflictStrategies(), ValidSovereigntyTiers()
- String() methods on all typed values
5. Logger interface
- ConfigWarningWriter allows custom logging destinations
- Tests can capture warnings without os.Stderr manipulation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes from code review:
- Fix duplicate check in merge logic (use else clause)
- Handle io.EOF gracefully (treat as quit)
- Add quit (q) option to abort resolution early
- Add accept-all (a) option to auto-merge remaining conflicts
- Fix skipped conflicts to keep local version (not auto-merge)
- Handle json.MarshalIndent errors properly
- Fix truncateText to use rune count for UTF-8 safety
- Update help text with new options
- Add UTF-8 and emoji test cases
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code review fixes:
- Renamed misleading exportIncrementalDolt to hasDoltChanges (now just checks for changes)
- Extracted stageJSONLFiles() helper to eliminate duplication
- Extracted runJSONLExport() helper
- Removed unused Actor field from ExportState (add back when implementing filtering)
- Consolidated hookPreCommitDoltFallback into doExportAndSaveState
- Added updateExportStateCommit for no-change fast path
Net reduction: 44 lines (-116/+72)
Added tests for:
- getWorktreeHash
- Export state paths
- Save/load export state
- JSON serialization with omitempty
- updateExportStateCommit
- computeJSONLHashForHook
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code review fixes for bd config validate:
- Use filepath.Join instead of string concatenation for paths
- Use filepath.Dir instead of strings.LastIndex for parent directory
- Move gitSSHRemotePattern regex to package-level var (compile once)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Commit 356ab92b deleted internal/config/sync.go while adding
cmd/bd/sync_mode.go, but config.go still references the types and
functions from sync.go, causing build failures.
These serve different purposes:
- internal/config/sync.go: viper-based (config.yaml), has warnings
- cmd/bd/sync_mode.go: storage-based (database), no warnings
Both should coexist. This restores sync.go and sync_test.go from
e82e15a8, and fixes type conversion in sync.go:805.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes#1076.
When git worktrees have sparse-checkout enabled, git add operations can
fail with 'outside of sparse-checkout cone' errors. Adding the --sparse
flag allows git to stage files outside the sparse-checkout cone.
Changes:
- Add --sparse flag to git add in daemon_sync_branch.go (line 165)
- Add --sparse flag to git add in migrate_sync.go (line 343)
- Add --sparse flag to git add in sync_branch.go (line 308)
- Add --sparse flag to git add in worktree.go (line 732)
All changes include comments referencing #1076 for traceability.
The scanIssues and scanIssuesWithDependencyType helper functions were
not checking rows.Err() after iterating through query results. This
could cause errors during iteration (connection drops, context
cancellation, etc.) to be silently ignored.
Per Go database/sql best practices, rows.Err() should always be checked
after a rows.Next() loop completes to catch any errors that occurred
during iteration.
Co-authored-by: Steven Syrek <steven.syrek@deepl.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
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.
Co-authored-by: Roland Tritsch <roland@ailtir.com>
The config.yaml file uses "issue-prefix" (with hyphen) but this setting
was only read during bd init. After initialization, all code read from
the database's "issue_prefix" key, so subsequent changes to config.yaml
were silently ignored.
This fix adds a fallback to config.yaml's "issue-prefix" in the key
locations where the prefix is retrieved from the database:
1. autoflush.go: Auto-import now checks config.yaml before falling back
to auto-detection from JSONL or directory name
2. autoflush.go: filterByMultiRepoPrefix now checks config.yaml as fallback
3. create.go: Direct mode prefix validation now checks config.yaml as fallback
Priority order is preserved:
1. Database issue_prefix (if set)
2. Config.yaml issue-prefix (new fallback)
3. Auto-detection from JSONL/directory (existing fallback)
Fixes#1145
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Fresh clones with sync-branch configured in .beads/config.yaml would show
.beads/issues.jsonl as modified in git status because the git index flags
(skip-worktree, assume-unchanged) are local-only and don't transfer via clone.
This fix ensures bd init sets these flags in two scenarios:
1. `bd init --branch <name>` - when user explicitly sets sync branch
2. `bd init` on cloned repo - when sync-branch already exists in config.yaml
Added SetSyncBranchGitignoreFlags() helper and two tests for coverage.
* fix(config): remove duplicate declarations between config.go and sync.go
Commit e82e15a8 created sync.go with typed constants (SyncMode,
ConflictStrategy, Sovereignty) but didn't remove the original untyped
constants from config.go that were added in 16f8c3d3. This caused
redeclaration errors preventing the project from building.
Changes:
- Remove duplicate SyncMode, ConflictStrategy, Sovereignty constants
from config.go (keep typed versions in sync.go)
- Remove duplicate GetSyncMode, GetConflictStrategy, GetSovereignty
functions from config.go (keep sync.go versions with warnings)
- Update SyncConfig, ConflictConfig, FederationConfig structs to use
typed fields instead of string
- Add IsSyncModeValid, IsConflictStrategyValid, IsSovereigntyValid
wrapper functions that use sync.go's validation maps
- Update cmd/bd/sync.go to use typed ConflictStrategy parameter
- Update tests to work with typed constants
* fix(dolt): handle Merge return values in concurrent test
* fix(test): add --repo flag to show_test.go to bypass auto-routing
The tests were failing because the create command was routing issues
to ~/.beads-planning instead of the test's temp directory. Adding
--repo . overrides auto-routing and creates issues in the test dir.
* fix(config): validate sync-branch at config time
Add sync-branch validation to validateYamlConfigValue() to reject
main/master at config time, preventing the validation bypass in GH#1166.
- Add case for sync-branch and sync.branch keys
- Inline validation logic to avoid import cycle (config <-> syncbranch)
- Add unit tests for rejection (main/master) and acceptance (valid names)
Part of: #1166
* fix(sync): add runtime guard for sync-branch == current-branch
Add dynamic runtime check before worktree operations to catch cases
where sync-branch matches the current branch. This provides defense
in depth for manual YAML edits, pre-fix configs, or non-main/master
branch names (trunk, develop, production, etc.).
- Check IsSyncBranchSameAsCurrent() after hasSyncBranchConfig is set
- Position check BEFORE worktree entry (CWD changes inside worktree)
- Add integration test TestSync_FailsWhenOnSyncBranch
Part of: #1166
* docs: note main/master restriction in sync-branch FAQ
Clarifies that git worktrees cannot checkout the same branch in
multiple locations, so main/master cannot be used as sync branch.