Commit Graph

2963 Commits

Author SHA1 Message Date
Steve Yegge
e1e3427d9b fix(ready): show correct message when all issues are closed (bd-r4n)
When bd ready found no ready work, it always showed 'all issues have
blocking dependencies' even when there were no open issues at all.

Now it checks if any open/in_progress issues exist:
- If no open issues: shows 'No open issues' (green)
- If open issues but all blocked: shows 'all issues have blocking
  dependencies' (yellow)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 10:49:17 -08:00
Steve Yegge
a4163e42e7 feat(doctor): add configuration value validation (bd-alz)
Add a new Config Values check to bd doctor that validates:
- flush-debounce: must be a valid duration (e.g., 30s, 1m)
- issue-prefix: must start with letter, alphanumeric with dashes/underscores
- routing.mode: must be auto, maintainer, or contributor
- sync-branch: must be a valid git branch name
- routing paths: warns if configured paths do not exist
- metadata.json database: should be filename (not path), with db extension
- metadata.json jsonl_export: should have .jsonl extension
- deletions_retention_days: must be non-negative if set

This catches misconfigurations before they cause runtime errors.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 10:31:50 -08:00
Steve Yegge
8d4f664b91 feat(doctor): add SQLite integrity check (bd-2au)
Run PRAGMA integrity_check to detect database corruption.
Reports any issues found and suggests recovery options.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 00:11:19 -08:00
Steve Yegge
cbf48672e7 feat(doctor): add --dry-run flag and fix registry parsing (bd-qn5, bd-a5z)
- Add --dry-run flag to preview fixes without applying changes
- Handle corrupted/empty/null-byte registry files gracefully
- Treat corrupted registry as empty instead of failing

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 00:09:25 -08:00
Steve Yegge
18191f5e54 feat(doctor): detect and fix stale sync branches (bd-6rf)
Add 'Sync Branch Health' check that detects:
1. Local sync branch diverged from remote (after force-push reset)
2. Sync branch significantly behind main on source files (20+ commits, 50+ files)

Add --fix support that:
- Handles worktree case (resets within worktree)
- Handles regular branch case (deletes and recreates from main)
- Pushes the reset branch to remote

This helps contributors whose local beads-sync becomes orphaned after
someone else resets the branch.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 23:51:20 -08:00
Steve Yegge
b54616e2ee bd sync: add bd-6rf (doctor check for stale beads-sync)
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 23:46:10 -08:00
Steve Yegge
28a661a320 feat: add --readonly flag for worker sandboxes (gt-ymo)
Add a --readonly flag that blocks all write operations, allowing workers
to read beads state without modifying it. Workers can use:
- bd show, bd list, bd ready (read operations)

Workers cannot use:
- bd create, bd update, bd close, bd sync, etc. (write operations)

The flag can be set via:
- --readonly flag on command line
- BD_READONLY=true environment variable
- readonly: true in config file

This enables swarm workers to see their assigned work from a static
snapshot of the beads database without accidentally modifying it.

Commands protected by readonly mode:
- create, update, close, delete, edit
- sync, import, reopen
- comment add, dep add/remove, label add/remove
- repair-deps, compact, migrate, migrate-hash-ids, migrate-issues
- rename-prefix, validate --fix-all, duplicates --auto-merge
- epic close-eligible, jira sync

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 23:44:22 -08:00
Steve Yegge
cead713b9f bd sync: update issues after bd-gmf and bd-tok fixes
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 23:41:03 -08:00
Steve Yegge
dd8c7595ba fix: store version in gitignored .local_version to prevent notification spam (bd-tok)
Root cause: metadata.json is tracked in git and contains last_bd_version.
When git operations (pull, checkout, merge) reset metadata.json to the
committed version, the upgrade notification would fire repeatedly.

Fix: Store the last used bd version in .beads/.local_version which is
gitignored, so git operations don't affect version tracking.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 23:38:20 -08:00
Steve Yegge
97cfe30bd7 fix: update flake.nix vendorHash after dependency bumps (bd-gmf)
The Nix flake CI was failing due to stale vendorHash after dependabot
updates to go.mod/go.sum (wazero, anthropic-sdk-go, etc.).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 23:21:48 -08:00
Steve Yegge
eae6694ab8 docs: add perles and vscode-beads to Third-Party Tools
Closes #449
Closes #450

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 23:11:31 -08:00
Steve Yegge
c436331544 Merge fix for #446: accept 3-char all-letter base36 hashes
Thanks to @shaunc for the well-documented fix!

Closes #446
2025-12-02 23:01:09 -08:00
Shaun Cutts
d541ff48e3 fix: accept 3-char all-letter base36 hashes in ExtractIssuePrefix (#446)
isLikelyHash() required at least one digit to distinguish hashes from
English words, but base36 hashes can be all-letters by chance.

This caused ExtractIssuePrefix("xa-adt-bat") to return "xa" instead
of "xa-adt", breaking import for 20 issues in xa-adapt.

Fix: Accept all-letter suffixes for 3-char only, keep digit requirement
for 4+ chars where word collision probability is low enough (~0.2%).

Rationale:
- 3-char: 36³ = 46K hashes, ~1000 common words = ~2% collision
- 4-char: 36⁴ = 1.6M hashes, ~3000 words = ~0.2% collision
- 5+ char: collision rate negligible
2025-12-02 23:00:24 -08:00
Steve Yegge
56ac476fca Merge pull request #448 from dbirks/small-edits
Thanks for the fix!
2025-12-02 22:51:28 -08:00
Steve Yegge
cd7830a5a6 fix: replace string(rune()) with strconv.Itoa in tests (bd-fmc)
Also updated CONFIG.md to clarify mass delete threshold requires >5 issues (bd-in6).

The string(rune('0'+i)) pattern produces incorrect characters when i >= 10.
Changed to strconv.Itoa(i) for reliable conversion.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 22:41:07 -08:00
Steve Yegge
a067796055 fix: multiple safety check and sync improvements
- bd-dtm: Changed stderr printing to use SafetyWarnings in worktree.go
- bd-ciu: Fixed non-deterministic output order in formatVanishedIssues
- bd-dmd: Removed duplicate safety check message in sync.go
- bd-k2n: PushSyncBranch now recreates worktree if cleaned up
- bd-c5m: Fixed string(rune()) in tests to use strconv.Itoa
- bd-8uk: Added test for SafetyWarnings population
- bd-1kf: Fixed mergePriority to handle negative priorities
- bd-xo9: Documented sync.require_confirmation_on_mass_delete config

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 22:14:41 -08:00
Steve Yegge
f531691440 feat(sync): add safety check enhancements and merge fixes
- Add forensic logging for mass deletions (bd-lsa): log vanished issue IDs and titles
- Add sync.require_confirmation_on_mass_delete config option (bd-4u8)
- Fix priority merge to treat 0 as "unset" (bd-d0t)
- Fix timestamp tie-breaker to prefer left/local (bd-8nz)
- Add warning log when extraction fails during safety check (bd-feh)
- Refactor safety warnings to return in PullResult (bd-7z4)
- Add TestSafetyCheckMassDeletion integration tests (bd-cnn)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 21:48:18 -08:00
Steve Yegge
c93b755344 feat(sync): auto-push after merge with safety check (bd-7ch)
Add auto-push functionality to PullFromSyncBranch for true one-command sync:
- After successful content merge, auto-push to remote by default
- Safety check: warn (but dont block) if >50% issues vanished AND >5 existed
- Vanished = removed from JSONL entirely, NOT status=closed

Changes:
- Add push parameter to PullFromSyncBranch function
- Add Pushed field to PullResult struct
- Add countIssuesInContent helper for safety check
- Add test for countIssuesInContent function

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 20:57:53 -08:00
Steve Yegge
7f13623683 feat(merge): auto-resolve all field conflicts deterministically (bd-6l8)
Implement deterministic auto-resolve rules for all merge conflicts:
- Title/Description: side with latest updated_at wins
- Notes: concatenate both sides with separator
- Priority: higher priority wins (lower number)
- IssueType: local (left) wins
- Status: closed wins (existing)

Also fixed bug in isTimeAfter where invalid t1 incorrectly beat valid t2.

Removed unused conflict generation code (hasConflict, makeConflict,
makeConflictWithBase, issuesEqual, cmp import).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 20:52:07 -08:00
Steve Yegge
e90577a5ab chore(beads): add bd-3s8 follow-up issues
Created issues for remaining multi-clone sync work:
- bd-6l8: Auto-resolve field conflicts in merge.go
- bd-7ch: Auto-push after merge with safety check
- bd-lsa: Mass deletion logging for forensics
- bd-4u8: Config option for mass delete confirmation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 19:35:13 -08:00
Steve Yegge
875c55c2dc fix(sync): handle diverged histories with content-based merge (bd-3s8)
When multiple clones commit to beads-sync branch and histories diverge,
git merge would fail. This replaces git's commit-level merge with a
content-based merge that extracts JSONL from base/local/remote and
merges at the semantic level.

Key changes:
- Add divergence detection using git rev-list --left-right
- Extract JSONL content from specific commits for 3-way merge
- Reset to remote's history then commit merged content on top
- Pre-emptive fetch before commit to reduce divergence likelihood
- Deletions.jsonl merged by union (keeps all deletions)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 18:25:56 -08:00
David Birks
214be94005 docs: Add -e flag to echo command 2025-12-02 18:38:43 -05:00
Steve Yegge
045591aff7 chore: Bump version to 0.28.0
Updated all component versions:
- bd CLI: 0.27.2 → 0.28.0
- Plugin: 0.27.2 → 0.28.0
- MCP server: 0.27.2 → 0.28.0
- npm package: 0.27.2 → 0.28.0
- Documentation: 0.27.2 → 0.28.0

Generated by scripts/bump-version.sh
2025-12-01 22:34:42 -08:00
Steve Yegge
1a48fa197c docs: prepare v0.28.0 release notes
- Add v0.28.0 entry to CHANGELOG.md with all changes
- Add v0.28.0 to info.go whats-new section
- Trim old versions (0.21.0, 0.22.x) from whats-new
2025-12-01 22:33:23 -08:00
Steve Yegge
e5c3f8b45a fix(test): use --local flag in git config check for merge driver test
The test was picking up global git config when checking that --skip-merge-driver
didn't set the merge.beads.driver config locally.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 22:12:39 -08:00
Steve Yegge
a4260c9660 fix(db): remove redundant GetCloseReason() calls (bd-bbh)
After adding close_reason column to issues table, two functions still
called GetCloseReason() to fetch from events table after already
scanning the column. Removed the redundant code.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 22:06:08 -08:00
Steve Yegge
09fffa4eaf fix(db): add close_reason column to issues table (bd-uyu)
- Add migration 017_close_reason_column.go to create the column
- Update all INSERT statements to include close_reason
- Update all SELECT statements to include close_reason
- Update doctor.go to check for close_reason in schema validation
- Remove workaround code that batch-loaded close reasons from events table
- Fix migrations_test.go to include close_reason in test table schema

This fixes sync loops where close_reason values were silently dropped
because the DB lacked the column despite the struct having the field.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 21:56:41 -08:00
Steve Yegge
d880fceb0f fixed GH issue #444 2025-12-01 21:26:25 -08:00
Steve Yegge
096e51a8b8 bd sync: 2025-12-01 21:24:52 2025-12-01 21:25:06 -08:00
Steve Yegge
a2d1edd865 fix(multi-repo): filter issues by prefix when flushing from non-primary repos (GH #437)
In multi-repo mode, non-primary repos incorrectly wrote ALL issues to their
local issues.jsonl, including foreign issues from other repos. This caused
prefix mismatch errors on subsequent imports.

The fix adds prefix filtering in flushToJSONLWithState() when:
1. Multi-repo mode is configured (repos.primary set)
2. Current repo is not the primary repo
3. The repo has a configured issue_prefix

Issues not matching the local prefix are filtered out before writing to JSONL.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 21:17:56 -08:00
Steve Yegge
64ef220dee feat(cli): add --estimate flag to bd create and bd update commands
Add CLI support for the estimated_minutes field that was already in the
Issue schema but had no way to be set from the command line.

Changes:
- Add --estimate flag to bd create (set estimated time on new issues)
- Add --estimate flag to bd update (modify estimated time on existing issues)
- Add EstimatedMinutes field to RPC CreateArgs and UpdateArgs
- Add handling in daemon RPC handlers for the new field

Example usage:
  bd create --title "Task" --estimate 60    # 60 minutes estimate
  bd update bd-abc --estimate 120           # update to 2 hours

Fixes GH #443

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 21:13:51 -08:00
Steve Yegge
7ea8555bc8 bd sync: update bd-3s8 with description and move to open 2025-12-01 21:12:10 -08:00
Steve Yegge
2d12a080d7 Refactor daemon sync functions to reduce duplication (bd-73u)
Extract shared performSync implementation with skipGit parameter:
- createSyncFunc and createLocalSyncFunc now delegate to performSync
- Follows same pattern as performExport and performAutoImport
- Reduces ~80 lines of duplicated code

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 21:10:56 -08:00
Steve Yegge
d90936116d docs: add go install fallback for Claude Code web (GH #439)
Add documentation for users experiencing npm postinstall failures in Claude Code web environments due to network restrictions.

Closes: bd-8q0

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 21:10:03 -08:00
Steve Yegge
d045da4f13 feat(daemon): add --foreground flag for systemd/supervisord integration
Adds --foreground flag to 'bd daemon --start' that runs the daemon in
foreground instead of forking to background. This enables management by
process supervisors like systemd, supervisord, or similar tools.

Usage: bd daemon --start --foreground

Closes #438

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 21:09:00 -08:00
Steve Yegge
6ebf7d9538 bd sync: 2025-12-01 21:07:46 2025-12-01 21:08:05 -08:00
Steve Yegge
34c370f0e7 refactor(daemon): consolidate sync functions to reduce duplication
Consolidate createSyncFunc and createLocalSyncFunc into a shared
performSync function, following the same pattern used for:
- performExport (used by createExportFunc and createLocalExportFunc)
- performAutoImport (used by createAutoImportFunc and createLocalAutoImportFunc)

The new performSync takes a skipGit bool parameter that skips all git
operations (commits, pulls, pushes) and 3-way merge when true.

This reduces ~60 lines of duplicated code and provides a single
implementation to maintain.

Closes: bd-73u

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 21:07:52 -08:00
Steve Yegge
0456e784f4 fix(deps): improve parent-child dependency UX (GH #440)
- Fix DEPENDENCIES.md: correct parent-child syntax (child depends on parent)
- Update bd show: display Children instead of Blocks for parent-child deps
- Group dependents by type with distinct labels

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 21:07:23 -08:00
Steve Yegge
4c5d90cf46 bd sync: track issue bd-hm8 completion 2025-12-01 21:05:44 -08:00
Steve Yegge
3de3b60b45 Add uninstall documentation (GH #445)
- Create docs/UNINSTALLING.md with comprehensive uninstall steps
- Add link to UNINSTALLING.md from INSTALLING.md
- Cover: daemon, hooks, merge driver, .beads dir, worktree cleanup

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 21:05:19 -08:00
Steve Yegge
d213ec912b fix(jira): migrate from deprecated API v2 to v3
Fixes #441. The JIRA REST API v2 /search endpoint has been deprecated
and returns HTTP 410 Gone. Migrate to API v3 /search/jql endpoint.

Changes:
- Update API endpoint from /rest/api/2/search to /rest/api/3/search/jql
- Add URL encoding for JQL query parameter (Python 3.14 compatibility)
- Add reference to Atlassian migration guide

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 21:02:20 -08:00
Steve Yegge
2300514424 bd sync: 2025-12-01 21:00:26 2025-12-01 21:00:26 -08:00
Steve Yegge
8ef3d81108 fix(sync): prevent final flush after sync.branch restore
When sync.branch is configured, the sync command:
1. Exports changes to JSONL
2. Commits to sync branch via worktree
3. Pulls from sync branch
4. Restores .beads/ from HEAD to keep working directory clean

But PersistentPostRun's flushManager.Shutdown() was re-exporting to JSONL,
undoing the restore and leaving modified files.

Fix: Set skipFinalFlush flag when sync.branch mode completes successfully.
This prevents the final export in PersistentPostRun.

Also: Skip push to main branch when sync.branch is configured - all
pushes should go through the sync branch worktree.
2025-12-01 20:51:54 -08:00
Steve Yegge
9483ab053e fix(sync): restore .beads/ from branch after sync when using sync.branch
When sync.branch is configured, the main branch's .beads/ directory was
showing as modified after every sync, even though the data was correctly
synced to the sync branch worktree.

This happened because:
1. Export writes to main's .beads/
2. Files are copied to worktree and committed there
3. But main's .beads/ now differs from what's committed on main

Fix: After sync completes, restore .beads/ from HEAD to keep the working
directory clean. The actual beads data lives on the sync branch; the main
branch's .beads/ is just a snapshot that should match what's committed.
2025-12-01 20:43:35 -08:00
Steve Yegge
d91f92802a fix(doctor): detect when on sync branch (bd-epn follow-up)
Add detection for when the current branch is the configured sync branch.
This is a misconfiguration that causes bd sync to fail with:

  fatal: 'beads-sync' is already used by worktree

The doctor now reports this as an error with a clear fix:
  Switch to your main working branch: git checkout main

Also shows current branch info in the OK case for better visibility.
2025-12-01 20:39:27 -08:00
Steve Yegge
94105bd9e2 feat: add bd migrate-sync command for sync.branch workflow setup (bd-epn)
Add a new command that encapsulates all the work needed to migrate a clone
to use the sync.branch workflow for multi-clone setups like Gas Town:

- Validates current state (not on sync branch, not already configured)
- Creates sync branch if it doesn't exist (from remote or locally)
- Sets up git worktree for the sync branch
- Syncs current beads data to worktree
- Commits initial state to sync branch
- Sets sync.branch configuration
- Pushes sync branch to remote

Usage:
  bd migrate-sync beads-sync           # Basic migration
  bd migrate-sync beads-sync --dry-run # Preview changes
  bd migrate-sync beads-sync --force   # Reconfigure even if set
2025-12-01 20:07:27 -08:00
Steve Yegge
f84684e314 refactor(daemon): consolidate local-only sync functions to reduce duplication (bd-73u)
Extract performExport() and performAutoImport() shared implementations:
- createExportFunc() and createLocalExportFunc() now use performExport()
  with skipGit parameter
- createAutoImportFunc() and createLocalAutoImportFunc() now use performAutoImport()
  with skipGit parameter
- createLocalSyncFunc() kept as-is (different flow from createSyncFunc)

Reduces daemon_sync.go by 89 lines (1003 -> 914) while maintaining
identical behavior and test coverage.

All existing tests pass. New shared functions use conditional logic
to skip git operations when skipGit=true, eliminating the need for
separate implementations.
2025-12-01 17:39:43 -08:00
Yaakov Nemoy
f761ba1f3a feat(daemon): add --local flag for git-free daemon operation (#433)
* feat(daemon): add --local flag for git-free operation

Add --local mode to the daemon that allows it to run without a git
repository. This decouples the daemon's core functionality (auto-flush
to JSONL, auto-import from JSONL) from git synchronization.

Changes:
- Add --local flag to daemon command
- Skip git repo check when --local is set
- Add validation that --auto-commit and --auto-push cannot be used with --local
- Create local-only sync functions that skip git operations:
  - createLocalSyncFunc: export-only for polling mode
  - createLocalExportFunc: export without git commit/push
  - createLocalAutoImportFunc: import without git pull
- Update startup message to indicate LOCAL mode
- Update event loop to use local functions when in local mode

This enables use cases like:
- Single-machine issue tracking without git
- Auto-flush to JSONL for backup purposes
- Running daemon in environments without git access

Multi-machine sync still requires git (as expected).

* fix(daemon): skip fingerprint validation in local mode

validateDatabaseFingerprint() calls beads.ComputeRepoID() which
executes git commands. This fails in non-git directories even
with --local flag.

Skip fingerprint validation entirely when running in local mode
since there's no git repository to validate against.

* test(daemon): add comprehensive test coverage for --local mode

Add tests for:
- Flag validation (--local incompatible with --auto-commit/--auto-push)
- Git check skip logic in local mode
- createLocalSyncFunc, createLocalExportFunc, createLocalAutoImportFunc
- Fingerprint validation skip in local mode
- Full integration test in non-git directory
- Export/import round-trip test

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-01 17:37:56 -08:00
Steve Yegge
34799a001d bd sync: close Jira integration epic bd-qvj 2025-12-01 10:45:11 -08:00
Steve Yegge
4a8e01f4d2 bd sync: 2025-11-30 22:11:35 2025-11-30 22:11:35 -08:00