Parse $EDITOR value to handle editors that need flags like
"zeditor --wait" or "code --wait". Previously the entire string
was treated as the executable name.
Fixes#987
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: beads/crew/dave
Rig: beads
Role: crew
Adds a diagnostic check that discovers and reports custom types
used by child repos in multi-repo setups. This is the 'discover'
part of the 'trust + discover' pattern for federation.
The check:
- Lists custom types found in each child repo's config/DB
- Warns about hydrated issues using types not found anywhere
- Is informational only (doesn't fail overall doctor check)
Part of epic: bd-9ji4z
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When database is stale and a read-only command runs in --no-daemon mode,
auto-import from JSONL instead of returning an error. This fixes `gt sling`
failing with 'not a valid bead' after git pull.
Root cause: `ensureDatabaseFresh` would return an error when DB was stale,
but read-only commands like `bd show` should be able to auto-import and
proceed rather than blocking the user.
Changes:
- Modify ensureDatabaseFresh to call autoImportIfNewer() when stale
- Only error if --no-auto-import flag is explicitly set
- Add comprehensive tests for all staleness scenarios
Fixes: bd-9dao
Co-authored-by: Claude <noreply@anthropic.com>
After devcontainer restart (cold-start), `bd --no-daemon show` failed to
find beads because:
1. Read-only commands skipped auto-import
2. Newly created DB had no issue_prefix set, causing import to fail
This fix enables seamless cold-start recovery by:
- Allowing read-only commands (show, list, etc.) to auto-bootstrap when
JSONL exists but DB doesn't
- Setting needsBootstrap flag when falling back from read-only to
read-write mode for missing DB
- Auto-detecting and setting issue_prefix from JSONL during auto-import
when DB is uninitialized
Fixes: gt-b09
Co-authored-by: Claude <noreply@anthropic.com>
* fix(doctor): add .sync.lock and sync_base.jsonl to gitignore
Problem:
- .sync.lock and sync_base.jsonl were missing from GitignoreTemplate
- Files introduced in PR #918 (pull-first sync) appeared as untracked
Solution:
- Add patterns to GitignoreTemplate with explanatory comment
- Add patterns to requiredPatterns for bd doctor validation
Impact:
- Existing users get warning via bd doctor, fix via bd doctor --fix
- New repos get correct gitignore on bd init
Fixes: GH#974
* docs(sync): fix sync_base.jsonl tracking status and add tests
Problem:
- SYNC.md incorrectly documented sync_base.jsonl as "git-tracked"
- No tests validated sync state file gitignore patterns
Solution:
- Update Files Reference table: sync_base.jsonl is "not tracked, per-machine"
- Add TestGitignoreTemplate_ContainsSyncStateFiles
- Add TestRequiredPatterns_ContainsSyncStatePatterns
Relates to: GH#974
Two issues caused `bd migrate sync` to fail when run from a git worktree:
1. Used GetGitDir() instead of GetGitCommonDir() for worktree path
- GetGitDir() returns the worktree-specific path (.bare/worktrees/main)
- GetGitCommonDir() returns the shared git dir (.bare) where new
worktrees can actually be created
2. Used strings.Index instead of LastIndex in GetRepoRoot()
- When user paths contain "worktrees" (e.g., ~/Development/worktrees/),
Index finds the first occurrence and incorrectly strips the path
- LastIndex finds git's internal /worktrees/ directory
Added GetGitCommonDir() to internal/git/gitdir.go for reuse.
Fixes GH#639 (remaining unfixed callsite in migrate_sync.go)
When running `bd sync --import-only` while the daemon is connected, the command
fails with "no database store available for inline import".
Root cause:
1. PersistentPreRun connects to daemon and returns early without initializing
the store global
2. sync command closes the daemon connection (for consistency)
3. sync --import-only calls importFromJSONLInline which requires store != nil
4. Without ensureStoreActive(), the store is never initialized after daemon disconnect
Fix: Call ensureStoreActive() after closing the daemon connection in sync.go.
This ensures the local SQLite store is initialized for all sync operations
that need direct database access.
- Add ensureStoreActive() call after daemon disconnect in sync.go
- Add test documenting the bug and verifying the fix
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add AllowStale field to ListArgs struct to support resilient hook detection.
When set, callers signal they accept potentially stale data rather than
failing on staleness check errors.
This enables gastown checkSlungWork() to fall back gracefully when the
beads database is out of sync with JSONL (common after concurrent agent syncs).
- Add AllowStale bool to ListArgs in internal/rpc/protocol.go
- Pass --allow-stale flag through to RPC in cmd/bd/list.go
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: beads/crew/dave
Rig: beads
Role: crew
Add new command to find molecules where a gate has closed and the workflow
is ready to resume:
- `bd ready --gated` - Flag on existing ready command
- `bd mol ready` - Subcommand for discoverability
The command finds molecules where:
1. A gate bead (type=gate) has been closed
2. The step blocked by that gate is now ready
3. The molecule is not currently hooked by any agent
This enables the Deacon patrol to discover and dispatch gate-ready
molecules without explicit waiter tracking, supporting async molecule
resume workflows.
Includes 5 tests verifying:
- No false positives when no gates exist
- Detection of molecules with closed gates
- Filtering out molecules with open gates
- Filtering out already-hooked molecules
- Handling multiple gate-ready molecules
Part of epic bd-ka761 (Gate-based async molecule resume).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: beads/crew/dave
Rig: beads
Role: crew
bd list --tree:
- Use actual parent-child dependencies instead of dotted ID hierarchy
- Treat epic dependencies as parent-child relationships
- Sort children by priority (P0 first)
- Fix tree display in daemon mode with read-only store access
bd graph:
- Add --all flag to show dependency graph of all open issues
- Add --compact flag for tree-style rendering (reduces 44+ lines to 13)
- Fix "needs:N" cognitive noise by using semantic colors
- Add blocks:N indicator with semantic red coloring
bd show:
- Tufte-aligned header with status icon, priority, and type badges
- Add glamour markdown rendering with auto light/dark mode detection
- Cap markdown line width at 100 chars for readability
- Mute entire row for closed dependencies (work done, no attention needed)
Design system:
- Add shared status icons (○ ◐ ● ✓ ❄) with semantic colors
- Implement priority colors: P0 red, P1 orange, P2 muted gold, P3-P4 neutral
- Add TrueColor profile for distinct hex color rendering
- Type badges for epic (purple) and bug (red)
Design principles:
- Semantic colors only for actionable items
- Closed items fade (muted gray)
- Icons > text labels for better scanability
Co-Authored-By: SageOx <ox@sageox.ai>
- resolve_conflicts.go: Mark unused `num` parameter with `_`
- .golangci.yml: Add resolve_conflicts.go to G306 exclusion (JSONL files use 0644)
- .golangci.yml: Add doctor/git.go to G304 exclusion (safe path construction)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Problem:
- When dbPath is set to relative fallback (".beads/beads.db"),
findJSONLPath() returns a relative path
- daemon_sync_branch.go calls filepath.Rel(absolutePath, relativePath)
which fails with: "Rel: can't make .beads/issues.jsonl relative to ..."
Solution:
- Canonicalize dbPath at assignment in main.go:471 (source fix)
- Add defensive guard in findJSONLPath() (defense-in-depth)
- Use utils.CanonicalizePath() for OS-agnostic handling
(symlinks, case normalization on macOS)
Testing:
- Add TestFindJSONLPath_RelativeDbPath (tracer bullet for bug)
- Add edge case tests for BEADS_JSONL and empty dbPath
- All sync mode tests pass including daemon E2E
Reviewed by beads/crew/wolf. Fixes daemon mode silently ignoring --due and --defer flags. Adds comprehensive tests including TestDualPathParity for regression prevention.
Adds runBDInProcessAllowError helper and dry-run test coverage.
Interrupted work - committing to preserve progress.
Co-Authored-By: Claude <noreply@anthropic.com>
Implements a new command to resolve git merge conflict markers in JSONL files.
Features:
- Mechanical mode (default): deterministic merge using updated_at timestamps
- Closed status wins over open
- Higher priority (lower number) wins
- Notes are concatenated when different
- Dependencies are unioned
- Dry-run mode to preview changes
- JSON output for agent integration
- Automatic backup creation before changes
The command defaults to resolving .beads/beads.jsonl but accepts any file path.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When an external hook manager config file (like .pre-commit-config.yaml) exists
but the actual hooks are bd shims, doctor now correctly reports OK instead of
warning that the manager doesn't call bd.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(sync): implement pull-first synchronization strategy
- Add --pull-first flag and logic to sync command
- Introduce 3-way merge stub for issue synchronization
- Add concurrent edit tests for the pull-first flow
Ensures local changes are reconciled with remote updates before pushing to prevent data loss.
* feat(sync): implement 3-way merge and state tracking
- Implement 3-way merge algorithm for issue synchronization
- Add base state storage to track changes between syncs
- Add comprehensive tests for merge logic and persistence
Ensures data consistency and prevents data loss during concurrent
issue updates.
* feat(sync): implement field-level conflict merging
- Implement field-level merge logic for issue conflicts
- Add unit tests for field-level merge strategies
Reduces manual intervention by automatically resolving overlapping updates at the field level.
* refactor(sync): simplify sync flow by removing ZFC checks
The previous sync implementation relied on Zero-False-Convergence (ZFC)
staleness checks which are redundant following the transition to
structural 3-way merging. This legacy logic added complexity and
maintenance overhead without providing additional safety.
This commit introduces a streamlined sync pipeline:
- Remove ZFC staleness validation from primary sync flow
- Update safety documentation to reflect current merge strategy
- Eliminate deprecated unit tests associated with ZFC logic
These changes reduce codebase complexity while maintaining data
integrity through the robust structural 3-way merge implementation.
* feat(sync): default to pull-first sync workflow
- Set pull-first as the primary synchronization workflow
- Refactor core sync logic for better maintainability
- Update concurrent edit tests to validate 3-way merge logic
Reduces merge conflicts by ensuring local state is current before pushing changes.
* refactor(sync): clean up lint issues in merge code
- Remove unused error return from MergeIssues (never returned error)
- Use _ prefix for unused _base parameter in mergeFieldLevel
- Update callers to not expect error from MergeIssues
- Keep nolint:gosec for trusted internal file path
* test(sync): add mode compatibility and upgrade safety tests
Add tests addressing Steve's PR #918 review concerns:
- TestSyncBranchModeWithPullFirst: Verifies sync-branch config
storage and git branch creation work with pull-first
- TestExternalBeadsDirWithPullFirst: Verifies external BEADS_DIR
detection and pullFromExternalBeadsRepo
- TestUpgradeFromOldSync: Validates upgrade safety when
sync_base.jsonl doesn't exist (first sync after upgrade)
- TestMergeIssuesWithBaseState: Comprehensive 3-way merge cases
- TestLabelUnionMerge: Verifies labels use union (no data loss)
Key upgrade behavior validated:
- base=nil (no sync_base.jsonl) safely handles all cases
- Local-only issues kept (StrategyLocal)
- Remote-only issues kept (StrategyRemote)
- Overlapping issues merged (LWW scalars, union labels)
* fix(sync): report line numbers for malformed JSON
Problem:
- JSON decoding errors when loading sync base state lacked line numbers
- Difficult to identify location of syntax errors in large state files
Solution:
- Include line number reporting in JSON decoder errors during state loading
- Add regression tests for malformed sync base file scenarios
Impact:
- Users receive actionable feedback for corrupted state files
- Faster troubleshooting of manual configuration errors
* fix(sync): warn on large clock skew during sync
Problem:
- Unsynchronized clocks between systems could lead to silent merge errors
- No mechanism existed to alert users of significant timestamp drift
Solution:
- Implement clock skew detection during sync merge
- Log a warning when large timestamp differences are found
- Add comprehensive unit tests for skew reporting
Impact:
- Users are alerted to potential synchronization risks
- Easier debugging of time-related merge issues
* fix(sync): defer state update until remote push succeeds
Problem:
- Base state updated before confirming remote push completion
- Failed pushes resulted in inconsistent local state tracking
Solution:
- Defer base state update until after the remote push succeeds
Impact:
- Ensures local state accurately reflects remote repository status
- Prevents state desynchronization during network or push failures
* fix(sync): prevent concurrent sync operations
Problem:
- Multiple sync processes could run simultaneously
- Overlapping operations risk data corruption and race conditions
Solution:
- Implement file-based locking using gofrs/flock
- Add integration tests to verify locking behavior
Impact:
- Guarantees execution of a single sync process at a time
- Eliminates potential for data inconsistency during sync
* docs: document sync architecture and merge model
- Detail the 3-way merge model logic
- Describe the core synchronization architecture principles
* fix(lint): explicitly ignore lock.Unlock return value
errcheck linter flagged bare defer lock.Unlock() calls. Wrap in
anonymous function with explicit _ assignment to acknowledge
intentional ignore of unlock errors during cleanup.
* fix(lint): add sync_merge.go to G304 exclusions
The loadBaseState and saveBaseState functions use file paths derived
from trusted internal sources (beadsDir parameter from config). Add
to existing G304 exclusion list for safe JSONL file operations.
* feat(sync): integrate sync-branch into pull-first flow
When sync.branch is configured, doPullFirstSync now:
- Calls PullFromSyncBranch before merge
- Calls CommitToSyncBranch after export
This ensures sync-branch mode uses the correct branch for
pull/push operations.
* test(sync): add E2E tests for sync-branch and external BEADS_DIR
Adds comprehensive end-to-end tests:
- TestSyncBranchE2E: verifies pull→merge→commit flow with remote changes
- TestExternalBeadsDirE2E: verifies sync with separate beads repository
- TestExternalBeadsDirDetection: edge cases for repo detection
- TestCommitToExternalBeadsRepo: commit handling
* refactor(sync): remove unused rollbackJSONLFromGit
Function was defined but never called. Pull-first flow saves base
state after successful push, making this safety net unnecessary.
* test(sync): add export-only mode E2E test
Add TestExportOnlySync to cover --no-pull flag which was the only
untested sync mode. This completes full mode coverage:
- Normal (pull-first): sync_test.go, sync_merge_test.go
- Sync-branch: sync_modes_test.go:TestSyncBranchE2E (PR#918)
- External BEADS_DIR: sync_external_test.go (PR#918)
- From-main: sync_branch_priority_test.go
- Local-only: sync_local_only_test.go
- Export-only: sync_modes_test.go:TestExportOnlySync (this commit)
Refs: #911
* docs(sync): add sync modes reference section
Document all 6 sync modes with triggers, flows, and use cases.
Include mode selection decision tree and test coverage matrix.
Co-authored-by: Claude <noreply@anthropic.com>
* test(sync): upgrade sync-branch E2E tests to bare repo
- Replace mocked repository with real bare repo setup
- Implement multi-machine simulation in sync tests
- Refactor test logic to handle distributed states
Coverage: sync-branch end-to-end scenarios
* test(sync): add daemon sync-branch E2E tests
- Implement E2E tests for daemon sync-branch flow
- Add test cases for force-overwrite scenarios
Coverage: daemon sync-branch workflow in cmd/bd
* docs(sync): document sync-branch paths and E2E architecture
- Describe sync-branch CLI and Daemon execution flow
- Document the end-to-end test architecture
* build(nix): update vendorHash for gofrs/flock dependency
New dependency added for file-based sync locking changes the
Go module checksum.
---------
Co-authored-by: Claude <noreply@anthropic.com>
Use flush-only workflow when no git remote is configured
Detects local-only repos (no git remote) and provides appropriate instructions:
- bd sync --flush-only instead of full git workflow
- Clear note about local-only storage
- Prevents confusing git errors for non-git users
Fix git hooks failing when daemon is running
Git hooks were calling bd sync without --no-daemon, causing inline import to fail
with 'no database store available' because daemon mode only initializes daemonClient.
Fix: Add --no-daemon to all bd sync calls in git hooks to ensure direct mode.
Add project_id filter for Linear sync
When linear.project_id is configured, bd linear sync will only fetch issues
belonging to that project instead of all team issues.
Closes#937
Adds --dry-run flag that shows what would be created without actually
creating the issue. Useful for scripting and validation.
- Shows preview in human-readable format by default
- Outputs full issue JSON with --json flag (empty ID, not placeholder string)
- Skips all side effects (hooks, labels, dependencies)
- Works with --rig/--prefix flags (shows target rig)
- Errors gracefully with --file flag (not supported)
- Includes event fields when --type=event
When bd gate check encounters a gh:run gate with a non-numeric await_id
(workflow name hint like release.yml), it now auto-discovers the run ID:
- Queries GitHub directly with gh run list --workflow=X
- Takes the most recent run (deterministic: newest-first from API)
- Updates the gates await_id and proceeds with status check
This is ZFC-compliant: most recent run of workflow X is purely mechanical,
no heuristic scoring. Agents no longer need to run bd gate discover manually.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a formula specifies a gate with id="release.yml", the AwaitID
now properly functions as a workflow name hint:
- gate discover: finds gates where AwaitID is empty OR non-numeric
- gate discover: filters matching runs by workflow name when hint present
- gate check: gracefully handles non-numeric AwaitID with clear message
Added isNumericRunID/isNumericID helpers and tests for the new behavior.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: beads/crew/dave
Rig: beads
Role: crew
The test for "slightly outdated version" was using 0.35.0, which is now
10 minor versions behind the current 0.45.0. This exceeds the threshold
for "very old" (>=10 minor versions), causing the test to fail.
Updated the test version from 0.35.0 to 0.43.0 to stay within the
"slightly outdated" range (2 minor versions behind).
(bd-iw11)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove Gas Town-specific issue types (agent, role, rig, convoy, slot)
from beads core. These types are now identified by labels instead:
- gt:agent, gt:role, gt:rig, gt:convoy, gt:slot
Changes:
- internal/types/types.go: Remove TypeAgent, TypeRole, TypeRig, TypeConvoy, TypeSlot constants
- cmd/bd/agent.go: Create agents with TypeTask + gt:agent label
- cmd/bd/merge_slot.go: Create slots with TypeTask + gt:slot label
- internal/storage/sqlite/queries.go, transaction.go: Query convoys by gt:convoy label
- internal/rpc/server_issues_epics.go: Check gt:agent label for role_type/rig label auto-add
- cmd/bd/create.go: Check gt:agent label for role_type/rig label auto-add
- internal/ui/styles.go: Remove agent/role/rig type colors
- cmd/bd/export_obsidian.go: Remove agent/role/rig/convoy type tag mappings
- Update all affected tests
This enables beads to be a generic issue tracker while Gas Town
uses labels for its specific type semantics.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: beads/crew/dave
Rig: beads
Role: crew
- Add #nosec G304 comment to parseJSONLFile in rename_prefix.go
- Mark unused noGitHistory param in importFromJSONLInline (mirrors import.go pattern)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The daemon socket tests relied on an external assertion library, which
increased the module's dependency footprint and deviated from Go's
idiomatic testing patterns.
This commit introduces a leaner testing approach using the standard
library:
- Replace testify/assert calls with standard if checks and t.Errorf
- Remove testify and associated indirects from go.mod
These changes preserve existing test behavior while simplifying the
build process and reducing external maintenance overhead.
* fix(doctor): handle 's' status in combined git flags
Problem:
- Git status detection failed when 's' was combined with other flags
- Branch synchronization checks produced incorrect results due to missing flag parsing
Solution:
- Update detection logic to correctly identify the 's' status within combined flag strings
Impact:
- Ensures branch synchronization state is accurately reported during doctor checks
* test(doctor): add unit tests for git flag parsing
- Extract git flag parsing logic into parseGitLsFilesFlag helper
- Add unit tests for git flag parsing logic
Coverage: Git flag parsing in sync_branch.go
Add BD_SOCKET environment variable support to override daemon socket path,
enabling parallel test isolation via t.TempDir() + t.Setenv().
Changes:
- getSocketPath() checks BD_SOCKET first, falls back to dbPath-derived path
- getSocketPathForPID() checks BD_SOCKET first (for consistency)
- Add daemon_socket_test.go with isolation pattern examples
This is a minimal tracer bullet to validate the approach before
expanding to full test isolation infrastructure.
Backward compatible: default behavior unchanged without env var set.
Add intelligent shell completions that query the database to provide
issue ID suggestions with titles for commands that take IDs as arguments.
Changes:
- Add issueIDCompletion function that queries storage for all issues
- Register completion for show, update, close, edit, defer, undefer, reopen
- Add comprehensive test suite with 3 test cases
- Completions display ID with title as description (ID\tTitle format)
The completion function opens the database (read-only) and filters issues
based on the partially typed prefix, providing a better UX for commands
that require issue IDs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add TypeRig constant to IssueType enum
- Update IsValid() method to include TypeRig
- Add UI color (orange) and style for rig type
- Update CLI flag descriptions in create and update commands
- Add Obsidian export tag for rig type
- Add comprehensive test cases for rig and other newer types
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When running `bd sync --import-only` from a directory with `.beads/redirect`,
the subprocess-based import could fail to update staleness metadata correctly
because the subprocess might resolve paths differently than the parent process.
The fix uses inline import (calling importIssuesCore directly) instead of
spawning a subprocess. This ensures:
1. The same store and dbPath are used throughout
2. Path resolution is consistent with the parent process
3. Staleness metadata is updated correctly in the redirected database
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Problem:
- Sync branch setup occurred before the config file was initialized
- Persistence only targeted the database, leading to loss on re-init
Solution:
- Reorder initialization to create the config file before sync setup
- Synchronize sync branch state to both config file and database
Impact:
- Settings are preserved across re-initialization and DB clears
- Better consistency between file and database state
Fixes: #927 (Bug 3)
- Extract inode function to platform-specific files (inode_unix.go,
inode_windows.go) to fix syscall.Stat_t compile error on Windows
- Add skipOnWindows helper and skip Unix permission/symlink tests
on Windows where chmod semantics differ
- Increase Windows test timeout from 10m to 20m since full test
suite runs slower without race detector
Fixes Windows CI failures introduced when PR #904 expanded Windows
testing from smoke tests to full test suite.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(daemon): unify auto-sync config for simpler agent workflows
## Problem
Agents running `bd sync` at session end caused delays in the Claude Code
"event loop", slowing development. The daemon was already auto-exporting
DB→JSONL instantly, but auto-commit and auto-push weren't enabled by
default when sync-branch was configured - requiring manual `bd sync`.
Additionally, having three separate config options (auto-commit, auto-push,
auto-pull) was confusing and could get out of sync.
## Solution
Simplify to two intuitive sync modes:
1. **Read/Write Mode** (`daemon.auto-sync: true` or `BEADS_AUTO_SYNC=true`)
- Enables auto-commit + auto-push + auto-pull
- Full bidirectional sync - eliminates need for manual `bd sync`
- Default when sync-branch is configured
2. **Read-Only Mode** (`daemon.auto-pull: true` or `BEADS_AUTO_PULL=true`)
- Only receives updates from team
- Does NOT auto-publish changes
- Useful for experimental work or manual review before sharing
## Benefits
- **Faster agent workflows**: No more `bd sync` delays at session end
- **Simpler config**: Two modes instead of three separate toggles
- **Backward compatible**: Legacy auto_commit/auto_push settings still work
(treated as auto-sync=true)
- **Adaptive `bd prime`**: Session close protocol adapts when daemon is
auto-syncing (shows simplified 4-step git workflow, no `bd sync`)
- **Doctor warnings**: `bd doctor` warns about deprecated legacy config
## Changes
- cmd/bd/daemon.go: Add loadDaemonAutoSettings() with unified config logic
- cmd/bd/doctor.go: Add CheckLegacyDaemonConfig call
- cmd/bd/doctor/daemon.go: Add CheckDaemonAutoSync, CheckLegacyDaemonConfig
- cmd/bd/init_team.go: Use daemon.auto-sync in team wizard
- cmd/bd/prime.go: Detect daemon auto-sync, adapt session close protocol
- cmd/bd/prime_test.go: Add stubIsDaemonAutoSyncing for testing
* docs: add comprehensive daemon technical analysis
Add daemon-summary.md documenting the beads daemon architecture,
memory analysis (explaining the 30-35MB footprint), platform support
comparison, historical problems and fixes, and architectural guidance
for other projects implementing similar daemon patterns.
Key sections:
- Architecture deep dive with component diagrams
- Memory breakdown (SQLite WASM runtime is the main contributor)
- Platform support matrix (macOS/Linux full, Windows partial)
- Historical bugs and their fixes with reusable patterns
- Analysis of daemon usefulness without database (verdict: low value)
- Expert-reviewed improvement proposals (3 recommended, 3 skipped)
- Technical design patterns for other implementations
* feat: add cross-platform CI matrix and dual-mode test framework
Cross-Platform CI:
- Add Windows, macOS, Linux matrix to catch platform-specific bugs
- Linux: full tests with race detector and coverage
- macOS: full tests with race detector
- Windows: full tests without race detector (performance)
- Catches bugs like GH#880 (macOS path casing) and GH#387 (Windows daemon)
Dual-Mode Test Framework (cmd/bd/dual_mode_test.go):
- Runs tests in both direct mode and daemon mode
- Prevents recurring bug pattern (GH#719, GH#751, bd-fu83)
- Provides DualModeTestEnv with helper methods for common operations
- Includes 5 example tests demonstrating the pattern
Documentation:
- Add dual-mode testing section to CONTRIBUTING.md
- Document RunDualModeTest API and available helpers
Test Fixes:
- Fix sync_local_only_test.go gitPull/gitPush calls
- Add gate_no_daemon_test.go for beads-70c4 investigation
* fix(test): isolate TestFindBeadsDir tests with BEADS_DIR env var
The tests were finding the real project's .beads directory instead of
the temp directory because FindBeadsDir() walks up the directory tree.
Using BEADS_DIR env var provides proper test isolation.
* fix(test): stop daemon before running test suite guard
The test suite guard checks that tests don't modify the real repo's .beads
directory. However, a background daemon running auto-sync would touch
issues.jsonl during test execution, causing false positives.
Changes:
- Set BEADS_NO_DAEMON=1 to prevent daemon auto-start from tests
- Stop any running daemon for the repo before taking the "before" snapshot
- Uses exec to call `bd daemon --stop` to avoid import cycle issues
* chore: revert .beads/issues.jsonl to upstream/main
Per CONTRIBUTING.md, .beads/issues.jsonl should not be modified in PRs.
Add config parsing for .pre-commit-config.yaml to detect if bd hooks are
configured. pre-commit is popular enough to warrant full support alongside
lefthook and husky.
Changes:
- Add CheckPrecommitBdIntegration() function to parse YAML config
- Check hooks.*.entry field for 'bd hooks run' pattern
- Handle stages field to determine which git hooks are configured
- Support legacy stage names (commit -> pre-commit, push -> pre-push)
- Add pre-commit to checkManagerBdIntegration switch statement
- Add comprehensive tests for all scenarios
Now supported managers with deep integration checks:
- lefthook (YAML, TOML, JSON)
- husky (.husky/ scripts)
- pre-commit (.pre-commit-config.yaml)
Detection-only managers (cannot verify config):
- overcommit, yorkie, simple-git-hooks
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When bd doctor detects hook managers we can't fully check (pre-commit,
overcommit, yorkie, simple-git-hooks), it now shows an informational
message instead of a warning:
✓ pre-commit detected (cannot verify bd integration)
└─ Ensure your hook config calls 'bd hooks run <hook>'
Previously it incorrectly warned that these managers were "not calling bd"
when we simply couldn't verify their config.
Changes:
- Add DetectionOnly field to HookIntegrationStatus
- Set DetectionOnly=true for unsupported managers in CheckExternalHookManagerIntegration
- Update CheckGitHooks and CheckSyncBranchHookCompatibility to show
informational message for detection-only managers
- Add test coverage for DetectionOnly behavior
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>