Commit Graph

1674 Commits

Author SHA1 Message Date
Peter Chanthamynavong
460d2bf113 fix(doctor): improve diagnostic fix message output (#1187)
Problem:
- Diagnostic fix messages were restricted to single lines
- Inconsistent file path formatting in database sync issues
- Outdated cleanup command suggested in maintenance fixes

Solution:
- Implement multiline support for doctor fix messages
- Standardize issue file paths across database diagnostics
- Update maintenance fix instructions to use 'bd admin cleanup'

Impact:
- Clearer and more accurate recovery instructions for users
- Better readability of complex diagnostic output

Fixes: GH#1170, GH#1171, GH#1172
2026-01-19 10:10:57 -08:00
Steven Syrek
73d4d5ecb2 fix(create): validate explicit IDs against allowed_prefixes using starts-with matching (#1137)
When creating issues with explicit IDs like `bd create --id hq-cv-test`,
the prefix validation was failing even when `hq-cv` was in `allowed_prefixes`.

Root cause: `ExtractIssuePrefix("hq-cv-test")` returns `"hq"` (not `"hq-cv"`)
because "test" looks like an English word, causing the algorithm to fall back
to the first hyphen. The validation then checked if `"hq"` was in the allowed
list containing `"hq-cv"` - which failed.

The fix adds `ValidateIDPrefixAllowed()` which validates the full ID using
"starts with" matching (the same approach the importer uses successfully).
This correctly handles multi-hyphen prefixes like `hq-cv-` regardless of
what the suffix looks like.

Fixes #1135

Co-authored-by: Steven Syrek <steven.syrek@deepl.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 10:08:56 -08:00
Steven Syrek
8e40018701 fix(daemon): Fix double-unlock risk in debouncer on action panic (#1140)
The debouncer's timer callback used a pattern that could cause a
double-unlock panic if the action function panicked:

  d.mu.Lock()
  defer d.mu.Unlock()
  if d.seq == currentSeq {
      d.mu.Unlock()  // Manual unlock
      d.action()     // If this panics...
      d.mu.Lock()    // ...this never runs
  }                  // ...but defer still tries to unlock

Fix: Remove the defer and manually manage lock state. Now if the
action panics, the lock is already released, preventing a
double-unlock panic that would mask the original panic.

Co-authored-by: Steven Syrek <steven.syrek@deepl.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 10:08:53 -08:00
Steven Syrek
ba832c4f37 fix(daemon): Eliminate race condition in sync state load-modify-save (#1139)
The RecordSyncFailure and ResetBackoffOnDaemonStart functions had a
TOCTOU (time-of-check-time-of-use) race condition. They called
LoadSyncState (which locks, reads, unlocks) then modified the state,
then called SaveSyncState (which locks, writes, unlocks).

Between LoadSyncState returning and SaveSyncState being called, another
goroutine could load the old state, modify it, and save it - then this
goroutine's save would overwrite those changes.

Fix: Create internal unlocked helper functions (loadSyncStateUnlocked,
saveSyncStateUnlocked) and have RecordSyncFailure and
ResetBackoffOnDaemonStart hold the lock for the entire load-modify-save
operation.

Co-authored-by: Steven Syrek <steven.syrek@deepl.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 10:08:41 -08:00
beads/crew/emma
4bc0b698a8 fix(staleness): skip auto-import when store is read-only (GH#1089)
Track whether the store was actually opened read-only (vs just requested)
since the fallback logic may change opts.ReadOnly. Use this to skip
auto-import in staleness checks - importing would fail anyway if the
store is read-only.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 18:25:50 -08:00
beads/crew/emma
356ab92b78 feat(sync): wire up sync.mode config to change sync behavior
Implements hq-ew1mbr.27: The sync.mode config now actually changes how
bd sync operates:

- git-portable (default): JSONL exported on push, imported on pull
- realtime: JSONL exported on every change (placeholder for daemon hook)
- dolt-native: Uses Dolt Push/Pull, skips JSONL workflow entirely
- belt-and-suspenders: Both Dolt remotes AND JSONL for redundancy

Changes:
- Add sync_mode.go with mode constants, Get/Set functions, and helpers
- Update bd sync --status to show actual mode from config
- Add --set-mode flag to bd sync for configuring the mode
- Modify doExportSync to respect mode (Dolt push for dolt-native)
- Modify doPullFirstSync to use Dolt pull for dolt-native mode
- Add RemoteStorage interface for Push/Pull operations
- Add comprehensive tests for sync mode functionality

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 10:36:20 -08:00
jane
c99bd00ca7 feat(sync): implement interactive conflict resolution for manual strategy
Adds interactive manual conflict resolution for `bd sync --resolve --manual`:
- Shows field-by-field diff between local and remote versions
- Prompts user to choose: local (l), remote (r), merge (m), skip (s)
- Supports viewing full JSON diff with 'd' option
- Skipped conflicts remain in conflict state for later resolution
- Integrates with existing 3-way merge infrastructure

New files:
- cmd/bd/sync_manual.go: Interactive conflict resolution logic
- cmd/bd/sync_manual_test.go: Unit tests for helper functions

Closes hq-ew1mbr.28

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 14:02:47 -08:00
lizzy
9ddd7a2620 feat(config): add validate command for sync config
Add `bd config validate` command to validate sync-related configuration:

- sync.mode: validates values (local, git-branch, external)
- conflict.strategy: validates values (lww, manual, ours, theirs)
- federation.sovereignty: validates values (none, isolated, federated)
- federation.remote: ensures set when sync.mode is 'external'
- Remote URL format: validates dolthub://, gs://, s3://, file://, etc.

Also validates existing config via doctor.CheckConfigValues (sync.branch,
routing.mode, etc.)

Closes: hq-ew1mbr.29

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 14:02:28 -08:00
darcy
16f8c3d3ae feat(sync): add sync mode configuration (hq-ew1mbr.3)
Add configurable sync modes for Dolt storage integration:

Sync modes:
- git-portable (default): Export JSONL on push, import on pull
- realtime: Export JSONL on every database change
- dolt-native: Use Dolt remotes directly (no JSONL)
- belt-and-suspenders: Both Dolt remote AND JSONL backup

Configuration options in .beads/config.yaml:
- sync.mode: Select sync mode
- sync.export_on: push (default) or change
- sync.import_on: pull (default) or change
- conflict.strategy: newest (default), ours, theirs, manual
- federation.remote: Dolt remote URL for dolt-native mode
- federation.sovereignty: T1-T4 data sovereignty tier

The sync command now displays configuration in `bd sync --status`
and uses configured conflict strategy for resolution.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 10:52:29 -08:00
lydia
ba0e754dc8 feat(hook): implement per-worktree export state tracking (Design Part 21)
Updates ExportState to track Dolt commits (not git commits) for accurate
change detection. This prevents polecats sharing a Dolt DB from exporting
each others uncommitted work.

Changes:
- ExportState now tracks Dolt commit hash via VersionedStorage.GetCurrentCommit()
- Added WorktreeHash and Actor fields for debugging and future filtering
- hookPreCommitDolt uses Diff() to detect changes since last export
- Added hookPreCommitDoltFallback for graceful degradation
- Added exportIncrementalDolt and exportFullDolt helper functions
- Removed unused exportToJSONLFromStore function

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 10:46:44 -08:00
beads/crew/emma
4f0f5744a6 feat(types): remove Gas Town types from core built-in types
Core beads built-in types now only include work types:
- bug, feature, task, epic, chore

Gas Town types (molecule, gate, convoy, merge-request, slot, agent,
role, rig, event, message) are now "well-known custom types":
- Constants still exist for code convenience
- Require types.custom configuration for validation
- bd types command shows core types and configured custom types

Changes:
- types.go: Separate core work types from well-known custom types
- IsValid(): Only accepts core work types
- bd types: Updated to show core types and custom types from config
- memory.go: Use ValidateWithCustom for custom type support
- multirepo.go: Only check core types as built-in
- Updated all tests to configure custom types

This allows Gas Town (and other projects) to define their own types
via config while keeping beads core focused on work tracking.

Closes: bd-find4

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 05:07:11 -08:00
emma
88a6438c80 chore(release): bump version to 0.48.0
Release highlights:
- VersionedStorage interface for pluggable backends
- bd types command and enhancement type alias
- bd close -m flag (git commit convention)
- RepoContext API for centralized git operations
- Dolt backend improvements (WIP)
- Many bug fixes for doctor, sync, hooks, worktrees

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 04:36:41 -08:00
emma
10bdc94294 feat(close): add -m as alias for --reason
Adds -m/--message as a hidden alias for --reason, following the git
commit convention where -m specifies a message. This makes the command
more intuitive for users familiar with git workflows.

Usage: bd close <id> -m "reason for closing"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 03:48:51 -08:00
lydia
feed888b57 fix(duplicates): use combined weight (dependents + dependencies) for merge target selection (GH#1022)
When choosing which duplicate to keep, the merge target now considers
both dependentCount (children/blocked-by) AND dependsOnCount (dependencies).
This ensures issues with ANY structural connections are preferred over
empty shells, rather than only considering children.

- Updated chooseMergeTarget to calculate weight = dependentCount + dependsOnCount
- Updated display output to show weight instead of just dependents
- Updated JSON output to include dependencies and weight fields
- Added tests for dependsOnCount inclusion and combined weight calculation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 03:44:13 -08:00
jane
251ded73be fix(merge-slot): use daemon RPC to get issue_prefix in daemon mode
When running in daemon mode, getMergeSlotID() was not using the daemon
RPC to retrieve the configured issue_prefix, causing it to fall back
to the hardcoded "bd" default. This fix adds the missing daemon path
that uses daemonClient.GetConfig() to properly retrieve the prefix,
matching the pattern used in create.go.

Fixes #1096

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 03:44:02 -08:00
emma
a21a29c283 fix(doctor): remove destructive sync branch health check (GH#1062)
The "Sync Branch Health" check incorrectly warned when the sync branch
differed from main on source files. Since the sync branch only tracks
.beads/ data, source file differences are expected behavior.

The associated --fix action (reset sync branch to main and force push)
was destructive and destroyed legitimate sync branch history.

Removed Check 2 entirely - only Check 1 (detecting divergence from remote
after force-push) remains, which is a legitimate issue.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 03:42:35 -08:00
elinor
f06e742273 fix(daemon): apply git.author config to sync branch commits
The daemon's gitCommitInWorktree function was building git commit
commands directly without checking the git.author and git.no-gpg-sign
config options. This caused daemon sync commits to use the local git
user config instead of the configured beads-specific author.

Now gitCommitInWorktree applies the same config-based author and
signing options that buildCommitArgs uses for regular commits.

Fixes #1051
2026-01-17 03:40:28 -08:00
emma
e60e8f1823 chore: remove placeholder comment in test
Remove `// See: https://github.com/steveyegge/beads/issues/XXX`
placeholder that was left in the regression test from PR #1131.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 02:51:06 -08:00
dave
c220542926 fix(init): use --git-common-dir for worktree exclude paths (GH#1053)
When running bd init --stealth in a worktree, excludes were being
written to .git/worktrees/<name>/info/exclude which has no effect.
Changed setupGitExclude and setupForkExclude to use --git-common-dir
instead of --git-dir so excludes go to the main repo .git/info/exclude.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 02:29:01 -08:00
quartz
94581ab233 feat(storage): add VersionedStorage interface with history/diff/branch operations
Extends Storage interface with Dolt-specific version control capabilities:

- New VersionedStorage interface in storage/versioned.go with:
  - History queries: History(), AsOf(), Diff()
  - Branch operations: Branch(), Merge(), CurrentBranch(), ListBranches()
  - Commit operations: Commit(), GetCurrentCommit()
  - Conflict resolution: GetConflicts(), ResolveConflicts()
  - Helper types: HistoryEntry, DiffEntry, Conflict

- DoltStore implements VersionedStorage interface

- New CLI commands:
  - bd history <id> - Show issue version history
  - bd diff <from> <to> - Show changes between commits/branches
  - bd branch [name] - List or create branches
  - bd vc merge <branch> - Merge branch to current
  - bd vc commit -m <msg> - Create a commit
  - bd vc status - Show current branch/commit

- Added --as-of flag to bd show for time-travel queries

- IsVersioned() helper for graceful SQLite backend detection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 01:55:16 -08:00
onyx
a7cd9136d8 feat(sync): implement bd sync command specification
Changes the default bd sync behavior to export-only per the spec:
- bd sync: Export to JSONL (no staging/committing)
- bd sync --import: Import from JSONL (shorthand for --import-only)
- bd sync --status: Show sync state (mode, last export, pending changes, conflicts)
- bd sync --resolve: Resolve conflicts with strategies (newest/ours/theirs)
- bd sync --force: Force full export/import (skip incremental)
- bd sync --full: Full sync (legacy pull→merge→export→commit→push behavior)

The new --status output format shows:
- Sync mode: git-portable
- Last export: timestamp (commit hash)
- Pending changes: N issues modified since last export
- Import branch: name or none
- Conflicts: count or none

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 01:55:06 -08:00
opal
ca24c17af8 feat(compact): add --dolt flag for Dolt garbage collection
Add `bd compact --dolt` command to run Dolt garbage collection on
.beads/dolt directory. This helps reclaim disk space when using the
Dolt backend, where auto-commit per mutation causes commit history
to grow over time.

Features:
- Runs `dolt gc` in the .beads/dolt directory
- Shows disk space before/after with bytes freed
- Supports --dry-run to preview without running GC
- Supports --json for machine-readable output
- Helpful error messages for missing dolt directory or command

Closes: hq-ew1mbr.14

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 01:54:50 -08:00
gastown/crew/max
87f84c5fa6 fix(create): use agent-aware prefix extraction for agent beads
The generic ValidateIDFormat() used isLikelyHash() which treated
3-character suffixes like "nux" as valid hashes, causing agent IDs
like "nx-nexus-polecat-nux" to extract prefix as "nx-nexus-polecat"
instead of the correct "nx".

Fix: For --type=agent, validate agent ID format first and use
ExtractAgentPrefix() which correctly extracts prefix from the
first hyphen for agent IDs.

Fixes #591

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 00:42:06 -08:00
beads/crew/giles
97adc19cf5 fix(main): move noDbCommands check before expensive git operations
Fixes #1093: `bd version` was spawning 5-7 git subprocesses before
checking if it even needed database access.

Moved the noDbCommands early-return check to run BEFORE:
- ensureForkProtection() (spawns ~5 git commands)
- signalOrchestratorActivity() (spawns git config)

This eliminates unnecessary process churn for simple commands like
`bd version`, `bd help`, `bd completion`, etc.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 00:24:36 -08:00
beads/crew/fang
634b01a609 docs(prime): warn agents about bd edit opening interactive editor
Add warning to bd prime output that bd edit opens $EDITOR which blocks
autonomous agents. Recommends bd update with --title/--description/etc
flags instead. Fixes #1061.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 00:24:34 -08:00
wickham
5fab5f58e6 fix(cli): suppress no-git-repo note with --quiet flag
The "Note: No git repository initialized" message now respects the
--quiet flag, preventing non-essential output in quiet mode.

Fixes #1080

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 00:16:05 -08:00
John Zila
6aa8ebd26f fix(sync): write to worktree JSONL only when sync-branch configured (#1133)
Fixes #1103: bd sync --merge fails when sync-branch configured due to
skip-worktree/daemon write conflict.

Root cause: When sync-branch is configured, daemon/bd writes to main's
.beads/issues.jsonl which has skip-worktree set. This hides changes from
`git status` but `git merge` still detects them, causing merge failures.

Solution: When sync-branch is configured, redirect all JSONL writes to
the worktree's JSONL only. Main's JSONL is now read-only and only updated
via merges from the sync branch.

Changes:
- autoflush.go: findJSONLPath() now returns worktree JSONL path when
  sync-branch configured, with safeguards for test isolation
- sync_branch.go: Remove incomplete skip-worktree manipulation code
  that is no longer needed with this architectural fix

Data flow with sync-branch:
1. bd create -> SQLite
2. bd sync --flush-only -> worktree/.beads/issues.jsonl
3. bd sync --merge -> clean merge (main's JSONL unchanged)
4. auto-import -> SQLite updated from merged JSONL
2026-01-17 00:04:09 -08:00
Steven Syrek
a5140075f1 fix(hooks): prevent bd hooks install --chain from destroying user's original hook
When bd init installs hooks with chaining, it renames the user's original
hook to .old and creates a new bd hook that chains to it. If bd doctor
later runs bd hooks install --chain, it would:

1. Not recognize the inline bd hook (from bd init) as a bd hook
2. Rename it to .old, overwriting the user's original hook
3. Install a new shim hook

This fix addresses two root causes:

1. Detection mismatch: areBdShimsInstalled() and getHookVersion() now
   recognize inline bd hooks (which have "# bd (beads)" marker) in
   addition to shim hooks (which have "# bd-shim" marker)

2. No .old protection: bd hooks install --chain now checks if .old
   already exists before renaming, preserving the user's original hook

Fixes #1120

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 08:44:30 +01:00
gastown/crew/george
aee86dfae2 fix(types): consolidate enhancement alias and fix update command
- Add "enhancement" to util.issueTypeAliases for consistency
- Make types.IssueType.Normalize() case-insensitive and include all aliases
- Fix update.go to normalize type before validation
- Remove duplicate type validation block in update.go

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 16:02:51 -08:00
beads/crew/fang
62dd5f8585 feat(hooks): add DeleteBranch for import branch cleanup
- Add DeleteBranch method to DoltStore for removing branches
- Update hookPostMergeDolt to clean up import branches after merge
- Completes hq-ew1mbr.9 git hook infrastructure

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 16:00:06 -08:00
beads/crew/wolf
13af11768f feat(bd): add 'bd types' command to list valid issue types
Lists all valid issue types with descriptions, organized by category:
- Work types (task, bug, feature, chore, epic)
- System types (molecule, gate, convoy, merge-request, slot)
- Agent types (agent, role, rig, event, message)

Supports --json output for scripting.

Closes: bd-9ilm5

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 15:57:18 -08:00
gastown/crew/george
9ecdc00664 feat(types): add "enhancement" as alias for "feature" type
Support --type enhancement as an alias for --type feature when creating
issues. The normalization happens before validation to ensure consistency
across all code paths.

Closes gt-hzanoe

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 15:44:33 -08:00
Steven Syrek
b51c0101ba Fix stack overflow in acquireStartLock due to infinite recursion (#1131)
The acquireStartLock function would recursively call itself after
attempting to remove a stale lock file. If os.Remove failed (due to
permissions, race conditions, etc.), the error was silently ignored
with `_`, causing infinite recursion until the 1GB stack limit was
exceeded.

Changes:
- Convert recursive calls to a bounded retry loop (max 3 attempts)
- Check removeFileFn return value before retrying
- Apply same fix to handleStaleLock which had the same issue
- Add test to verify function returns false when remove fails

Fixes the stack overflow crash that occurred when running any bd
command with a stale or problematic lock file.

Co-authored-by: Steven Syrek <steven.syrek@deepl.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 14:36:59 -08:00
jasper
3d813c2143 fix(hooks): Fix infinite recursion and update templates for Dolt hooks
- Fix computeJSONLHashForHook calling itself instead of computeJSONLHash
- Update hook templates to call `bd hook` (Dolt-aware) instead of `bd hooks run`
- Add documentation for Dolt-specific features (per-worktree state, branch-then-merge)

The `bd hook` command (singular) provides:
- Per-worktree export state tracking for shared Dolt databases
- Branch-then-merge pattern for cell-level conflict resolution
- Hook chaining configuration with timeout support
- Guard against frequent post-checkout firing

Fixes: hq-ew1mbr.9

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 14:33:08 -08:00
onyx
fc19a94ad9 fix(hooks): Route hook templates to Dolt-aware implementations
- Fix infinite recursion bug in computeJSONLHashForHook (was calling
  itself instead of computeJSONLHash)
- Update pre-commit, post-merge, post-checkout templates to use
  `bd hook <name>` instead of `bd hooks run <name>`, routing to the
  Dolt-aware implementations in hook.go
- Update all hook template versions to 0.48.0 for consistency

The hook infrastructure added in 15d74a9a had a critical bug where
the hash computation function recursed infinitely, and the templates
still pointed to the old hook implementations in hooks.go instead
of the new Dolt-aware ones in hook.go.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 12:44:10 -08:00
quartz
15d74a9a49 feat(hooks): Add git hook infrastructure for Dolt backend
This commit implements the git hook infrastructure for Dolt storage backend
as specified in the design document.

Changes:
- Add `bd hook` command (singular) for git hooks to call directly
- Implement per-worktree export state tracking in .beads/export-state/
- Add post-checkout guard to only import if JSONL changed
- Add hook chaining configuration (chain_strategy, chain_timeout_ms)
- Support hooks in .beads/hooks/ directory with git config core.hooksPath
- Implement branch-then-merge import pattern for Dolt storage
- Update bd init to install hooks to .beads/hooks/ for Dolt backend
- Add --beads flag to `bd hooks install` command

The new `bd hook` command supports:
- pre-commit: Export database to JSONL, stage changes
- post-merge: Import JSONL to database after pull/merge
- post-checkout: Import JSONL after branch checkout (with guard)

For Dolt backend, uses branch-then-merge pattern:
1. Create jsonl-import branch
2. Import JSONL data to branch
3. Merge branch to main (cell-level conflict resolution)
4. Delete branch on success

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 12:24:48 -08:00
Zain Rizvi
e723417168 Fix git hooks not working in worktrees (#1126)
Git hooks are shared across all worktrees and live in the common git
directory (e.g., /repo/.git/hooks), not the worktree-specific directory
(e.g., /repo/.git/worktrees/feature/hooks).

The core issue was in GetGitHooksDir() which used GetGitDir() instead
of GetGitCommonDir(). This caused hooks to be installed to/read from
the wrong location when running in a worktree.

Additionally, several places in the codebase manually constructed
hooks paths using gitDir + "hooks" instead of calling GetGitHooksDir().
These have been updated to use the proper worktree-aware path.

Affected areas:
- GetGitHooksDir() now uses GetGitCommonDir()
- CheckGitHooks() uses GetGitHooksDir()
- installHooks/uninstallHooks use GetGitHooksDir()
- runChainedHook() uses GetGitHooksDir()
- Doctor checks use git-common-dir for hooks paths
- Reset command uses GetGitCommonDir() for hooks and beads-worktrees

Symptoms that this fixes:
- Chained hooks (pre-commit.old) not running in worktrees
- bd hooks install not finding/installing hooks correctly in worktrees
- bd hooks list showing incorrect status in worktrees
- bd doctor reporting incorrect hooks status in worktrees

Co-authored-by: Zain Rizvi <4468967+ZainRizvi@users.noreply.github.com>
2026-01-16 12:01:43 -08:00
Eugene Sukhodolin
493b7008a2 fix(sync): Update jsonl_file_hash in finalizeExport to prevent spurious warnings (#1113)
The JSONL file hash mismatch warning was appearing consistently after
git commit operations, even when no actual data inconsistency existed.

Root Cause:
Two code paths export to JSONL but only one updated jsonl_file_hash:
- flushToJSONLWithState() (used by bd update/create): Updated both
  jsonl_content_hash AND jsonl_file_hash
- finalizeExport() (used by bd sync --flush-only): Updated only
  jsonl_content_hash, NOT jsonl_file_hash

Since validateJSONLIntegrity() checks jsonl_file_hash, any bd command
after a git commit would see a mismatch and trigger the warning.

Steps to Reproduce (before fix):
1. cd /path/to/beads-project
2. bd update -p 3 some-issue-id  # Works fine, stores hash H1
3. git add .beads/issues.jsonl && git commit --amend --no-edit
   # Pre-commit hook runs bd sync --flush-only
   # This updates jsonl_content_hash to H2 but leaves jsonl_file_hash as H1
4. bd update -p 3 some-issue-id  # WARNING appears!
   # validateJSONLIntegrity() compares file (H2) with jsonl_file_hash (H1)
5. Repeat steps 3-4 indefinitely - warning always appears

The fix adds SetJSONLFileHash() call to finalizeExport(), ensuring both
export paths update the same metadata consistently.
2026-01-15 19:23:09 -08:00
Peter Chanthamynavong
e110632afc fix(context): complete RepoContext migration for remaining sync files (#1114)
Follow-up to #1102 - migrates remaining git command locations to use
RepoContext API for correct repo resolution when BEADS_DIR is set.

Files migrated:
- sync_branch.go: getCurrentBranch, showSyncStatus, mergeSyncBranch
- sync_check.go: checkForcedPush
- sync_import.go: doSyncFromMain
- autoimport.go: readFromGitRef, checkGitForIssues
- status.go: getGitActivity
- import.go: attemptAutoMerge (gitRoot lookup)
- reinit_test.go: add ResetCaches for test isolation

Pattern used throughout:
- Try RepoContext first: rc.GitCmd() runs in beads repo
- Fallback to CWD for tests or repos without beads
- Graceful degradation maintains backwards compatibility
2026-01-15 19:23:07 -08:00
aleiby
fabf857b2a fix(test): skip permission test on WSL (#1115)
WSL doesn't fully respect Unix file permission semantics - the file
owner can bypass read-only restrictions, similar to macOS. Add isWSL()
helper and skip TestMergeDriverWithLockedConfig_E2E on WSL.

Fixes bd-srv

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 19:23:04 -08:00
Bobby Johnson
55e733cf62 fix: enable building on Windows without CGO (#1117)
The dolt storage backend requires CGO due to its gozstd dependency.
This change makes the dolt backend optional using build tags, allowing
`go install` to work on Windows where CGO is disabled by default.

Changes:
- Add BackendFactory registration pattern to factory package
- Create factory_dolt.go with `//go:build cgo` constraint that
  registers the dolt backend only when CGO is available
- Update init.go to use factory instead of direct dolt import
- When dolt backend is requested without CGO, provide helpful error
  message directing users to pre-built binaries

The sqlite backend (default) works without CGO and covers the majority
of use cases. Users who need dolt can either:
1. Use pre-built binaries from GitHub releases
2. Enable CGO by installing a C compiler

Fixes #1116
2026-01-15 19:23:02 -08:00
Dmitry Verkhoturov
c1a9dda173 fix: allow shell completions to work without a database (#1118)
Add "__complete" to noDbCommands list so that Cobra's internal completion
command can run without requiring a beads database to be present.

Previously, running shell completions (e.g., `bd show <TAB>`) in a directory
without a .beads database would fail with "no beads database found" error.

Now completions return empty results gracefully when no database exists,
allowing basic command completion to work everywhere while issue ID
completion still requires a database.

Added integration test that verifies __complete command works without a database.
2026-01-15 19:22:55 -08:00
Peter Chanthamynavong
5d93aaf722 fix(sync): remove orphaned restoreBeadsDirFromBranch function (#1121)
Remove dead code that was inadvertently orphaned when PR #918 refactored
the sync flow. The function was never called since v0.47.0.

The function caused GH#1100 by running `git checkout HEAD -- .beads/`
which restored the entire .beads/ directory, overwriting uncommitted
config.yaml changes.

Add regression test (TestConfigPreservedDuringSync) to prevent similar
restoration logic from being reintroduced.

Fixes #1100
2026-01-15 19:22:52 -08:00
mayor
d3db8253ff fix(storage): use factory for cross-repo routing to respect backend config
When routing issues to other repos (via contributor routing or --rig flag),
the code was hardcoding sqlite.New instead of using the storage factory.
This meant Dolt-configured repos would fail when receiving routed issues.

Changed two locations:
- Contributor routing (line 357): use factory.NewFromConfig
- createInRig --rig flag (line 789): use factory.NewFromConfig

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 12:44:12 -08:00
beads/crew/dave
fe67e9e232 fix(test): fix TestInitNoDbMode for no-db mode config persistence
Changes:
- Save issue-prefix in config.yaml when using --no-db mode
  (previously only saved in database which doesn't exist in no-db mode)
- Add config.ResetForTesting() to allow reloading config in tests
- Simplify test to verify config values rather than execute subsequent
  commands (cobra's flag caching makes multi-Execute() testing complex)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 11:37:57 -08:00
beads/crew/dave
81828db6ef fix(test): remove pre-existing issues.jsonl in TestExportOnlySync
setupGitRepo now creates an empty issues.jsonl for RepoContext,
which triggers 'JSONL changed since import' validation in tests
that set up their own .beads/ directory.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 08:02:20 -08:00
Peter Chanthamynavong
0a48519561 feat(context): centralize RepoContext API for git operations (#1102)
Centralizes repository context resolution via RepoContext API, fixing bugs where git commands run in the wrong repo when BEADS_DIR points elsewhere or in worktree scenarios.
2026-01-15 07:55:08 -08:00
beads/crew/emma
159114563b chore(release): v0.47.2
- Dolt backend (experimental)
- bd show --children flag
- NixOS support improvements
- Fix redirect + sync-branch incompatibility
- Fix doctor project-level settings detection
- Fix contributor routing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 21:57:28 -08:00
beads/crew/fang
d1722d9204 docs: update daemon CLI syntax from flags to subcommands
Update all documentation to use the new subcommand syntax:
- `bd daemon --start` → `bd daemon start`
- `bd daemon --stop` → `bd daemon stop`
- `bd daemon --status` → `bd daemon status`
- `bd daemon --health` → `bd daemon status --all`
- `--global=false` → `--local`

The old flag syntax is deprecated but still works with warnings.

Closes: bd-734vd

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 21:47:15 -08:00
mayor
669ea40684 feat(storage): add --backend flag for Dolt backend selection
Phase 2 of Dolt integration - enables runtime backend selection:

- Add --backend flag to bd init (sqlite|dolt)
- Create storage factory for backend instantiation
- Update daemon and main.go to use factory with config detection
- Update database discovery to find Dolt backends via metadata.json
- Fix Dolt schema init to split statements for MySQL compatibility
- Add ReadOnly mode to skip schema init for read-only commands

Usage: bd init --backend dolt --prefix myproject

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 21:42:31 -08:00