Commit Graph

5370 Commits

Author SHA1 Message Date
ruby
32aea46ca6 test(sync): add unit tests for gitHasUncommittedBeadsChanges (bd-p7i2)
Extract parseGitStatusForBeadsChanges helper function from
gitHasUncommittedBeadsChanges to enable unit testing without git setup.

Add 14 test cases covering:
- Empty/no changes
- Modified files (staged, unstaged, both)
- Added files (staged, with modifications)
- Untracked files (should return false)
- Deleted files (should return false)
- Renamed/copied files
- Edge cases (short status line)

Part of GH#885 follow-up.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 16:22:20 -08:00
beads/witness
9ad6c793cb bd sync: 2026-01-04 16:21:57 2026-01-04 16:21:57 -08:00
beads/crew/wolf
6202711b5c feat(dep): add --blocks shorthand flag for natural dependency syntax (GH#884)
Adds a --blocks (-b) shorthand flag to bd dep command for natural dependency syntax:
  bd dep bd-xyz --blocks bd-abc  # bd-xyz blocks bd-abc

Equivalent to: bd dep add bd-abc bd-xyz

- Full daemon and direct mode support
- Cycle detection and child-parent anti-pattern checks
- JSON output support

Contributed by: kraitsura
2026-01-04 16:20:45 -08:00
beads/crew/emma
426f67db41 fix(dep): ensure cycle detection runs in daemon mode for --blocks flag
The daemon code path was returning early after adding the dependency,
skipping the cycle detection that runs for direct mode. Restructure
so both paths share the cycle detection and output code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 16:20:04 -08:00
kraitsura
44626262e2 feat(dep): add --blocks shorthand flag for natural dependency syntax
Agents naturally try to use 'bd dep <blocker> --blocks <blocked>' when
establishing blocking relationships - a desire path revealing intuitive
mental model for how dependencies should work.

When AI agents set up dependency chains, they consistently attempt:
  bd dep conduit-abc --blocks conduit-xyz

This reveals a desire path - the syntax users naturally reach for before
reading documentation. Instead of fighting this intuition, we embrace it.

- Add --blocks (-b) flag to the bd dep command
- Support syntax: bd dep <blocker-id> --blocks <blocked-id>
- Equivalent to: bd dep add <blocked-id> <blocker-id>
- Full daemon and direct mode support
- Cycle detection and child-parent anti-pattern checks
- JSON output support for programmatic use

This is purely additive. The existing command structure remains:
- 'bd dep add' subcommand works exactly as before
- All other dep subcommands (remove, list, tree, cycles) unchanged
- No breaking changes to existing workflows

  bd dep bd-xyz --blocks bd-abc    # bd-xyz blocks bd-abc
  bd dep bd-xyz -b bd-abc          # Same, using shorthand
  bd dep add bd-abc bd-xyz         # Original syntax still works

- Added TestDepBlocksFlag for flag initialization
- Added TestDepBlocksFlagFunctionality for semantic correctness
- All existing tests pass
2026-01-04 16:20:04 -08:00
beads/crew/dave
d2b40677c0 bd sync: 2026-01-04 16:17:03 2026-01-04 16:17:03 -08:00
beads/crew/dave
f92090344a fix: finalize metadata after commit, not after push (GH#885)
In performExport, if git commit succeeded but push failed, the
finalizeExportMetadata() was never called because we returned early.
This meant metadata would not reflect the successful export+commit.

Now finalize is called:
- Right after syncBranchCommitAndPush succeeds
- Right after gitCommit succeeds (before push attempt)
- When no git changes exist (export still happened)

Push failure still returns early, but metadata is already updated.

🤖 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
2026-01-04 16:16:53 -08:00
beads/crew/fang
9c6f035947 bd sync: 2026-01-04 16:16:06 2026-01-04 16:16:06 -08:00
beads/crew/emma
0f6cbd612a bd sync: 2026-01-04 16:11:57 2026-01-04 16:11:57 -08:00
beads/crew/emma
a1079fcbe1 fix(git): use case-insensitive path comparison for worktree validation (GH#880)
On macOS with case-insensitive filesystem, path casing differences between
the daemon socket path and git worktree registry caused sync failures.

Changed isValidWorktree() to use utils.PathsEqual() which handles
case-insensitivity on macOS/Windows, matching the fix already applied
to daemon registry in GH#869.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 16:11:37 -08:00
beads/crew/grip
b3ebedb063 fix(init): prevent parent hub contamination during bd init (GH#896)
When running bd init in a subdirectory of a hub (e.g., ~/Repos/project
where ~/Repos/.beads exists), the new database was incorrectly inheriting
issues from the parent hub.

Root cause: checkGitForIssues() computed the relative path from gitRoot
to beadsDir but did not validate that beadsDir was actually inside the
git repository. When beadsDir was outside (e.g., ../.beads), it would
still attempt to import, causing contamination.

Fix: Add a guard to reject beadsDir paths that start with .. (outside
the git repository boundary).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 15:43:57 -08:00
beads/crew/grip
c624e3b701 bd sync: 2026-01-04 15:43:41 2026-01-04 15:43:41 -08:00
beads/refinery
dc1e98b25d bd sync: 2026-01-04 15:22:02 2026-01-04 15:22:02 -08:00
garnet
9d69099803 fix(slot): add cross-beads prefix routing to bd slot set (bd-hmeb)
When setting a slot to a bead from a different beads database
(e.g., setting an hq-* role bead on a gt-* agent bead), the command
now uses prefix-based routing via routes.jsonl to resolve the bead
in the correct database.

Previously, bd slot set only looked in the local database, failing
to find cross-db references like hq-polecat-role from rig beads.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 15:21:36 -08:00
beads/witness
3a7c4f9cca bd sync: 2026-01-04 15:17:51 2026-01-04 15:17:51 -08:00
beads/crew/dave
67bbd7f96a bd sync: 2026-01-04 15:16:35 2026-01-04 15:16:35 -08:00
beads/crew/dave
ede940b5d2 fix: defer SQLite metadata updates until after git commit (GH#885)
This fixes the atomicity gap where exportToJSONL would update SQLite
metadata (clear dirty flags, update content hash, last_import_time)
BEFORE the git commit. If git commit failed, SQLite would incorrectly
indicate the sync succeeded.

Changes:
- Add ExportResult struct to capture export metadata for deferred finalization
- Add exportToJSONLDeferred() that exports without updating metadata
- Add finalizeExport() to update metadata after git commit succeeds
- Update daemon_sync.go sync flows to defer metadata updates

Now the sync flow is truly atomic: metadata only updates after git commit.

🤖 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
2026-01-04 15:16:07 -08:00
beads/crew/wolf
ca99ceaa18 bd sync: 2026-01-04 15:14:11 2026-01-04 15:14:11 -08:00
beads/crew/wolf
68f5bb24f8 feat(doctor): add sync divergence check for JSONL/SQLite/git (GH#885)
Add CheckSyncDivergence doctor check that detects:
- JSONL on disk differs from git HEAD version
- SQLite last_import_time does not match JSONL mtime
- Uncommitted .beads/ changes exist

Each issue includes auto-fix suggestions (bd sync, bd export, git commit).
Multiple divergence issues result in error status.

Part of GH#885 recovery mechanism.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 15:13:50 -08:00
beads/crew/fang
45091e4dbb bd sync: 2026-01-04 15:11:00 2026-01-04 15:11:00 -08:00
beads/crew/fang
44a5c3a0ec feat: detect uncommitted JSONL changes before sync (GH#885, bd-vd8e)
Add pre-flight safety check to detect when a previous sync exported
but failed before commit, leaving JSONL in an inconsistent state.

- Add gitHasUncommittedBeadsChanges() helper in sync_git.go
- Call in sync pre-flight checks after merge/rebase check
- If uncommitted changes detected, force re-export to reconcile state

This catches the failure mode early before it compounds across worktrees.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 15:10:47 -08:00
beads/crew/dave
7b90678afe fix: canonicalize path case on macOS for git worktree operations (GH#880)
bd sync fails with exit status 128 when the daemon is started from a
terminal with different path casing than what git has stored. This
happens on macOS case-insensitive filesystem when directory names
are renamed (e.g., MyProject to myproject) but terminal sessions
retain the old casing.

The fix uses realpath(1) on macOS to get the true filesystem case
when canonicalizing paths:
- CanonicalizePath() now calls realpath on macOS
- git.GetRepoRoot() canonicalizes repoRoot via canonicalizeCase()
- syncbranch.GetRepoRoot() uses utils.CanonicalizePath()

This ensures git worktree paths match exactly, preventing the
exit status 128 errors from git operations.

🤖 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
2026-01-04 13:54:07 -08:00
beads/crew/fang
fbc93e3de2 fix: prevent sparse checkout config from leaking to main repo (GH#886)
Use git sparse-checkout command instead of manually setting
core.sparseCheckout config. The sparse-checkout command properly
scopes the setting to the worktree via extensions.worktreeConfig,
avoiding the confusing sparse checkout message in git status.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 13:52:29 -08:00
beads/crew/grip
83030c4353 bd sync: 2026-01-04 12:27:19 2026-01-04 12:27:19 -08:00
beads/refinery
539d48a860 bd sync: 2026-01-04 11:51:17 2026-01-04 11:51:17 -08:00
topaz
b789b99537 fix(daemon): normalize paths for case-insensitive filesystems (GH#880)
On macOS (HFS+/APFS), `bd sync` would fail with exit status 128 when
the daemon was started from a terminal session with different path
casing than what git had stored for the worktree (e.g., /Users/.../
MyProject vs /Users/.../myproject).

Fixed by normalizing workspace paths using `filepath.EvalSymlinks()`
before storing in the registry and comparing during lookups:

- registry.Register(): Canonicalizes workspace path before storing
- registry.Unregister(): Canonicalizes paths before comparison
- FindDaemonByWorkspace(): Canonicalizes paths before lookup

This ensures consistent path matching across case-insensitive
filesystems since EvalSymlinks returns the actual filesystem casing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 11:50:46 -08:00
beads/witness
296c236565 bd sync: 2026-01-04 11:45:43 2026-01-04 11:45:43 -08:00
beads/refinery
7b8b8af914 bd sync: 2026-01-04 11:37:39 2026-01-04 11:37:39 -08:00
obsidian
1a0ad09e23 fix(doctor): detect status mismatches between DB and JSONL (GH#885)
When bd sync fails mid-operation, the local JSONL can become stale while
the SQLite database has the correct state. Previously, bd doctor only
checked count and timestamp differences, missing cases where counts match
but issue statuses differ.

This adds content-level comparison to CheckDatabaseJSONLSync that:
- Compares issue statuses between DB and JSONL
- Samples up to 500 issues for performance on large databases
- Reports detailed mismatches (shows up to 3 examples)
- Suggests 'bd export' to fix the stale JSONL

Example detection:
  Status mismatch: 1 issue(s) have different status in DB vs JSONL
  Status mismatches detected:
    test-1: DB=closed, JSONL=open

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 11:35:59 -08:00
onyx
5229b3e90d feat(dep): add --blocked-by and --depends-on flag aliases (bd-09kt)
Add flag-based alternatives to the positional argument for `bd dep add`:
- `--blocked-by <id>`: Specify the blocking issue via flag
- `--depends-on <id>`: Alias for --blocked-by

This reduces token waste when Claude guesses flag-based syntax, which
is a common pattern. Previously, Claude would attempt commands like:
  bd dep add issue-123 --blocked-by issue-456

This would fail with "unknown flag" and require retry. Now both:
  bd dep add issue-123 issue-456
  bd dep add issue-123 --blocked-by issue-456

work identically.

Closes GH#888

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 11:34:38 -08:00
quartz
563f7e875d fix(merge): preserve close_reason field during merge/sync (GH#891)
The close_reason and closed_by_session fields were being silently dropped
during 3-way merge operations because the simplified Issue struct in
internal/merge/merge.go was missing these fields.

Changes:
- Add CloseReason and ClosedBySession fields to merge.Issue struct
- Implement merge logic that preserves these fields when status is closed
- Use timestamp-based conflict resolution (later closed_at wins)
- Clear close metadata when status becomes non-closed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 11:33:32 -08:00
beads/witness
abffa75c4b bd sync: 2026-01-04 11:31:27 2026-01-04 11:31:27 -08:00
beads/witness
79e763dd2f bd sync: 2026-01-04 11:29:47 2026-01-04 11:29:47 -08:00
jasper
c848c0fce2 fix(npm): add retry logic for Windows zip extraction
On Windows, the downloaded ZIP file may remain locked by antivirus
software or Node.js file handle release delays. This causes
Expand-Archive to fail with "being used by another process" errors.

Added exponential backoff retry logic (5 attempts, 500ms-8s delays)
that detects file lock errors and retries the extraction. Non-lock
errors still fail immediately.

Fixes GH#889 (bd-5dlz)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 11:28:23 -08:00
beads/witness
e0db42404c bd sync: 2026-01-04 11:27:36 2026-01-04 11:27:36 -08:00
beads/refinery
c2d7f2a0c9 bd sync: 2026-01-04 11:25:27 2026-01-04 11:25:27 -08:00
beads/crew/grip
df66ecfe9e fix(worktree): disable sparse checkout on main repo after worktree creation (GH#886)
Git 2.38+ enables core.sparseCheckout on the main repo as a side effect
of worktree creation, causing confusing git status message:
"You are in a sparse checkout with 100% of tracked files present."

The fix explicitly disables sparse checkout on the main repo after
creating the beads worktree. This doesn't affect the worktree's sparse
checkout functionality since the patterns are already applied during
checkout.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 11:24:47 -08:00
beads/crew/grip
6609c049de bd sync: 2026-01-04 11:24:30 2026-01-04 11:24:30 -08:00
biantaishabi2
b3d64d47b3 fix: prevent event storm when gitRefsPath is empty (#883)
When gitRefsPath is empty (not in a git repo), strings.HasPrefix(path, "")
always returns true, causing every file write in .beads/ directory
(including daemon.log) to trigger debouncer and create an event storm.

This fix adds a check to ensure gitRefsPath is not empty before the
HasPrefix comparison.

Fixes the issue where daemon.log grows rapidly (17MB+) due to the
self-triggering loop: write log -> detect change -> write log -> ...

Co-authored-by: Test User <test@example.com>
2026-01-04 11:14:36 -08:00
kustrun
28b44edd13 fix(doctor): detect missing git repo and improve daemon startup message (#890)
When not in a git repository:
- Daemon startup now shows clear message immediately instead of waiting
  5 seconds: "Note: No git repository initialized — running without
  background sync"
- Added new doctor check "Git Sync Setup" that explains the situation

Doctor check now shows three states:
1. No git repo → Warning with fix: "Run 'git init' to enable background sync"
2. Git repo, no sync-branch → OK with hint about team collaboration benefits
3. Git repo + sync-branch → OK, fully configured

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 11:13:48 -08:00
web3dev1337
661556ae62 feat: add multi-prefix support via allowed_prefixes config (#881)
feat: add multi-prefix support via allowed_prefixes config

Adds support for allowing multiple prefixes in a beads database via the
allowed_prefixes config key. This is needed for Gas Town which uses different
prefixes for different purposes (hq-, gt-, rig-specific prefixes).

Usage: bd config set allowed_prefixes "gt,hq,hmc"

PR #881 by @web3dev1337
2026-01-04 11:13:44 -08:00
kustrun
16af63dc73 fix(rename-prefix): sync JSONL before and after prefix rename (#893)
- Pull from sync-branch before rename if configured
- Import all issues from JSONL before rename to prevent data loss
- Export directly to JSONL after rename (don't rely on flushManager)
- Apply same pattern to --repair mode
- Add newSilentLogger() for production use (not test-only)
- Add comprehensive tests for JSONL update scenarios

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 10:53:31 -08:00
wolf
3acf899c8c bd sync: 2026-01-04 10:42:36 2026-01-04 10:42:36 -08:00
wolf
9880eaf734 feat(config): support daemon.auto_* settings in config.yaml (GH#871)
Allow team-wide auto-sync configuration via config.yaml instead of SQLite.
This enables teams to share auto-commit/auto-push settings through version control.

Changes:
- Add daemon.auto_commit, daemon.auto_push, daemon.auto_pull to YamlOnlyKeys
- Add daemon.* prefix to YAML-only prefixes
- Update daemon startup to read from config.yaml first, then fall back to SQLite
- Update bd init --team to write daemon settings to config.yaml

Usage:
  # In .beads/config.yaml (version controlled, shared by team)
  daemon.auto_commit: true
  daemon.auto_push: true

  # Or via bd config set
  bd config set daemon.auto_commit true

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 10:42:22 -08:00
emma
c6ee9cf3bc bd sync: 2026-01-04 10:42:07 2026-01-04 10:42:07 -08:00
emma
4468ff030f feat(sync): add BD_DEBUG_SYNC env for protection debugging
Adds debug logging when timestamp-aware protection triggers, controlled
by BD_DEBUG_SYNC environment variable. Helps diagnose sync issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 10:41:57 -08:00
beads/crew/grip
4021f49445 feat(prime): add PRIME.md override for workflow customization (GH#876)
Users can now place a .beads/PRIME.md file to fully customize the
workflow instructions output by `bd prime`. The --export flag outputs
the default content for use as a starting template.

Local .beads/PRIME.md is checked first, then redirected location,
allowing clone-specific customization even with shared beads.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 21:49:40 -08:00
dave
7df6004605 fix: code review improvements for GH#870
Review findings addressed:
1. Fixed HasSyncBranchGitignoreFlags() - now correctly returns (hasAnyFlag,
   hasSkipWorktree) since skip-worktree takes precedence in git ls-files -v
2. Added interactions.jsonl to list of files to hide (was only issues.jsonl)
3. Added idempotency check - skips setting flags if already set (checks for S)
4. Made output conditional - only prints when flags actually changed
5. Fixed addToGitExclude() pattern matching - now uses exact line match
   instead of substring to prevent false positives
6. Refactored to use setGitIndexFlags() helper to reduce duplication

🤖 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
2026-01-03 21:19:02 -08:00
matt wilkie
625ac5dff2 Add repository guards to deployment workflows (#877)
- Guard deploy-docs job to only run in canonical repository
- Guard goreleaser job to only run in canonical repository
- Guard update-homebrew job to only run in canonical repository
- Guard test-pypi job to only run in canonical repository

Prevents fork workflows from attempting to deploy, release, or publish to external services.
2026-01-03 21:16:09 -08:00
dave
35e6e3319d bd sync: 2026-01-03 21:08:09 2026-01-03 21:08:09 -08:00