Commit Graph

860 Commits

Author SHA1 Message Date
Steve Yegge
f4864c9cc4 feat(import/export): add tombstone support (bd-dve)
Update import/export to handle tombstones for deletion sync propagation:

Exporter:
- Include tombstones in JSONL output by setting IncludeTombstones: true
- Both single-repo and multi-repo exports now include tombstones

Importer:
- Tombstones from JSONL are imported as-is (they're issues with status=tombstone)
- Legacy deletions.jsonl entries are converted to tombstones via convertDeletionToTombstone()
- Non-tombstone issues in deletions manifest are still skipped (backward compat)
- purgeDeletedIssues() now creates tombstones instead of hard-deleting

This is Phase 2 of the tombstone implementation (bd-dli design), enabling
inline soft-delete tracking for cross-clone deletion synchronization.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 20:34:02 +11:00
Steve Yegge
2e40ae80fb Merge branch 'rig-e048/OchreFerret' 2025-12-07 20:24:12 +11:00
Steve Yegge
8b64917d59 feat(doctor): add configuration value validation (bd-alz)
Add comprehensive validation for config values in bd doctor:

YAML config (config.yaml) validations:
- actor: alphanumeric with dashes, underscores, dots, @
- db: valid database extension (.db, .sqlite, .sqlite3)
- Boolean flags: json, no-daemon, no-auto-flush, no-auto-import,
  no-db, auto-start-daemon validate as true/false/yes/no/1/0/on/off
- sync.require_confirmation_on_mass_delete: boolean validation
- repos.primary: must be a directory if path exists
- repos.additional: paths must be directories if they exist

Database config validations:
- status.custom: validates custom status names are lowercase
  alphanumeric with underscores, checks for conflicts with built-in
  statuses (open, in_progress, blocked, closed)
- sync.branch (legacy): validates as git branch name

Includes tests for all new validation functions.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 20:21:22 +11:00
Steve Yegge
213ed65175 test(doctor): add tests for export diagnostics feature (bd-9cc)
Add unit tests verifying the --output flag registration and
exportDiagnostics function for saving doctor results to JSON files.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 20:19:49 +11:00
Steve Yegge
e701e34c38 fix: resolve symlink paths in autoimport.go for macOS
Both findBeadsDir() and findGitRoot() now use filepath.EvalSymlinks()
to resolve to canonical paths before comparison. This fixes the issue
where filepath.Rel() fails on macOS because /var is a symlink to
/private/var, causing path mismatches.

Fixes: TestDatabaseReinitialization failures on macOS

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-05 16:52:16 -08:00
Steve Yegge
2adba0d8e0 feat(tombstone): implement delete-to-tombstone and TTL expiration (bd-3b4, bd-olt)
Phase 1 of tombstone migration: bd delete now creates tombstones instead
of hard-deleting issues.

Key changes:
- Add CreateTombstone() method to SQLiteStorage for soft-delete
- Modify executeDelete() to create tombstones instead of removing rows
- Add IsExpired() method with 30-day default TTL and clock skew grace
- Fix deleted_at schema from TEXT to DATETIME for proper time scanning
- Update delete.go to call CreateTombstone (single issue path)
- Still writes to deletions.jsonl for backward compatibility (dual-write)
- Dependencies are removed when creating tombstones
- Tombstones are excluded from normal searches (bd-1bu)

TTL constants:
- DefaultTombstoneTTL: 30 days
- MinTombstoneTTL: 7 days (safety floor)
- ClockSkewGrace: 1 hour

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 16:20:43 -08:00
Steve Yegge
5c49c25e9e feat(tombstone): add P2 code review improvements (bd-saa, bd-1bu, bd-nyt)
- Add partial index on deleted_at for efficient TTL queries
- Exclude tombstones from SearchIssues by default (new IncludeTombstones filter)
- Report tombstone count separately in GetStatistics
- Display tombstone count in bd stats output

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 15:48:46 -08:00
Steve Yegge
ce119551f6 fix(init): use correct gitRef in error message, remove unused var
Small fixes from code review:
- Error message now shows actual gitRef instead of hardcoded HEAD
- Removed unused lineNum variable in readFirstIssueFromGit

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 14:51:32 -08:00
Steve Yegge
0d2dc53c67 fix(init): bootstrap from sync-branch when configured (bd-0is)
When sync-branch is configured in config.yaml, bd init now reads from
that branch (origin/<branch> first, then local <branch>) instead of
HEAD. This ensures fresh clones correctly import issues from the sync
branch.

Key changes:
- checkGitForIssues() now returns gitRef (third return value)
- New getLocalSyncBranch() reads sync-branch directly from config.yaml
  (not cached global config) to handle test environments where CWD changes
- importFromGit() accepts gitRef parameter to read from correct branch
- Added readFirstIssueFromGit() for prefix auto-detection from git
- Fixed macOS symlink issue: filepath.EvalSymlinks() ensures /var and
  /private/var paths are normalized before filepath.Rel()

Part of GitHub issue #464 (beads deletes issues in multi-clone environments)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 14:47:02 -08:00
Darin
e0734e230f fix: NixOS symlink compatibility for mtime and permission checks (#459)
* fix: use os.Lstat for symlink-safe mtime and permission checks

On NixOS and other systems using symlinks heavily (e.g., home-manager),
os.Stat follows symlinks and returns the target's metadata. This causes:

1. False staleness detection when JSONL is symlinked - mtime of target
   changes unpredictably when symlinks are recreated
2. os.Chmod failing or changing wrong file's permissions when target
   is in read-only location (e.g., /nix/store)
3. os.Chtimes modifying target's times instead of the symlink itself

Changes:
- autoimport.go: Use Lstat for JSONL mtime in CheckStaleness()
- import.go: Use Lstat in TouchDatabaseFile() for JSONL mtime
- export.go: Skip chmod for symlinked files
- multirepo.go: Use Lstat for JSONL mtime cache
- multirepo_export.go: Use Lstat for mtime, skip chmod for symlinks
- doctor/fix/permissions.go: Skip permission fixes for symlinked paths

These changes are safe cross-platform:
- On systems without symlinks, Lstat behaves identically to Stat
- Symlink permission bits are ignored on Unix anyway
- The extra Lstat syscall overhead is negligible

Fixes symlink-related data loss on NixOS. See GitHub issue #379.

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

Co-Authored-By: Claude <noreply@anthropic.com>

* test: add symlink behavior tests for NixOS compatibility

Add tests that verify symlink handling behavior:
- TestCheckStaleness_SymlinkedJSONL: verifies mtime detection uses
  symlink's own mtime (os.Lstat), not target's mtime (os.Stat)
- TestPermissions_SkipsSymlinkedBeadsDir: verifies chmod is skipped
  for symlinked .beads directories
- TestPermissions_SkipsSymlinkedDatabase: verifies chmod is skipped
  for symlinked database files while still fixing .beads dir perms

Also adds devShell to flake.nix for local development with go, gopls,
golangci-lint, and sqlite tools.

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

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-05 13:22:09 -08:00
Tim Haasdyk
07c97a2b74 fix: make bd onboard output generic, not beads-specific (#465)
The copilotInstructionsContent in onboard.go contained content specific to
developing the beads project itself (Go tech stack, SQLite, Cobra, project
structure, release scripts, etc.). This content doesn't make sense when
running bd onboard in other repositories that use bd for issue tracking.

Removed:
- Tech Stack section (Go, SQLite, Cobra, etc.)
- Coding Guidelines section (beads development instructions)
- Project Structure section (beads directory tree)
- Scripts section (bump-version.sh, release.sh, etc.)
- Key Documentation section (beads-specific docs)
- Beads-specific rules (BEADS_DB testing, test issues in production DB)

Kept:
- All bd command examples and workflow (unchanged)
- Priorities and issue types
- MCP server instructions
- Generic rules applicable to any project using bd

The beads repo's own .github/copilot-instructions.md is manually maintained
and still contains the beads-specific development instructions.
2025-12-05 13:20:51 -08:00
Steve Yegge
6789e4fd9a feat: add hooks to plugin.json, eliminating need for global install
The beads plugin now provides SessionStart and PreCompact hooks directly
via plugin.json. Users no longer need to run 'bd setup claude' when using
the plugin - hooks are automatically available.

Changes:
- Add hooks section to .claude-plugin/plugin.json with SessionStart and
  PreCompact hooks that run 'bd prime'
- Update doctor/claude.go to recognize plugin-provided hooks as valid
- Update tips.go to check for plugin installation when determining if
  Claude integration is complete
- Update messaging to recommend plugin installation as primary option

The 'bd setup claude' command remains available for CLI-only users who
do not want to install the plugin.

Closes #462

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 22:44:42 -08:00
Steve Yegge
46abe8caf7 fix: add .local_version to GitignoreTemplate
Fixes #460 - .local_version was added for version tracking but not
included in the gitignore template, causing it to show as untracked.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 20:37:16 -08:00
Abhinav Gupta
ac8ef9b9e3 test: replace manual os.Chdir with t.Chdir in tests (#457)
Replaces manual working directory save/restore patterns
with Go's built-in `t.Chdir()` helper across 23 test files.

The manual pattern involved calling `os.Getwd()` to save
the original directory, using `defer os.Chdir(origWd)` for
restoration, and manually handling errors during directory
changes. This boilerplate has been replaced with single
`t.Chdir(path)` calls that handle cleanup automatically.

The `t.Chdir()` method automatically restores the working
directory when the test completes, eliminating the need for
manual defer statements and error handling.

Total:
~75 instances replaced (assuming Claude's math is right)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-04 11:21:43 -08:00
Steve Yegge
f4b8a7ad4f feat: change deletions TTL default from 7 to 3 days
Reduces the default retention period for deletion manifest entries.
Shorter TTL limits blast radius of stale deletions that can poison
beads installations when agents get out of sync.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 22:44:59 -08:00
Steve Yegge
7f1e45e3db Merge pull request #456 from abhinav/add-setup-stealth-flag
feat(setup claude): add --stealth flag
2025-12-03 20:46:52 -08:00
Steve Yegge
019a90f511 Merge pull request #455 from abhinav/add-prime-stealth-flag
feat(prime): add --stealth flag for flush-only workflow
2025-12-03 20:26:01 -08:00
Steve Yegge
6267f3b7f5 fix: add test parallelism and increase Windows CI timeout
- Increase Windows test timeout from 20m to 30m
- Add -parallel=4 flag to allow concurrent test execution
- Add t.Parallel() to safe table-driven tests in validate_test.go,
  autoimport_test.go, and sync_test.go

This should prevent the Windows CI timeout caused by the cumulative
runtime of cmd/bd tests exceeding 20 minutes.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 18:30:53 -08:00
Abhinav Gupta
4a7d7b0b41 feat(setup claude): add --stealth flag
Add a `--stealth` flag to `bd setup claude` that installs
Claude Code hooks using `bd prime --stealth` instead of
`bd prime`. This extends the stealth workflow introduced for
`bd prime` to the setup command, enabling workflows where git
operations should be deferred or handled separately from bd
database flushing.

When `--stealth` is specified, the installed hooks call
`bd prime --stealth`, which outputs only `bd sync --flush-only`
in the close protocol, omitting all git operations.

Update `RemoveClaude()` to remove both command variants
(`bd prime` and `bd prime --stealth`) for backwards
compatibility with existing installations. Update
`hasBeadsHooks()` to detect either variant as a valid
installation.

Add comprehensive test coverage for stealth mode: hook
installation with stealth command, removal of both variants,
detection of both variants, and idempotency with stealth mode.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 18:10:35 -08:00
Abhinav Gupta
09a9ffa922 feat(prime): add --stealth flag for flush-only workflow
Add a `--stealth` flag to `bd prime` that outputs a simplified
workflow using only `bd sync --flush-only`, omitting all git
operations (commit, push, pull).

This addresses use cases where git operations need to be deferred
or handled separately from the bd workflow (e.g. bd init --stealth),
where committing files is may not desired as part of the Claude
conversation.

In stealth mode, the close protocol shows only the flush step.

Includes tests for current and existing functionality.

To make testing easier,
refactor output functions to accept `io.Writer` parameters
instead of writing directly to `os.Stdout`,
and convert `isEphemeralBranch` from a function to a
variable for stubbing.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 18:08:33 -08:00
Steve Yegge
76f7341cf4 fix: resolve CI lint errors and Windows test timeout
- Fix gosec G204/G304 warnings by adding exclusions for safe subprocess
  launches and file reads in doctor.go, jira.go, migrate_sync.go, and
  syncbranch/worktree.go
- Fix misspell: "cancelled" -> "canceled" in sync.go
- Fix unparam: mark unused ctx params in jira.go placeholder functions
- Fix errcheck: explicitly ignore fmt.Sscanf return in doctor.go and
  use closure pattern for deferred os.RemoveAll in worktree.go
- Increase Windows test timeout from 10m to 20m to prevent CI timeouts

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 17:50:23 -08:00
Steve Yegge
c9eeecf0c3 chore: Bump version to 0.29.0
Updated all component versions:
- bd CLI: 0.28.0 → 0.29.0
- Plugin: 0.28.0 → 0.29.0
- MCP server: 0.28.0 → 0.29.0
- npm package: 0.28.0 → 0.29.0
- Documentation: 0.28.0 → 0.29.0

Generated by scripts/bump-version.sh
2025-12-03 16:24:46 -08:00
Steve Yegge
d451945b00 docs: update changelog and info.go for v0.29.0 release
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 16:24:24 -08:00
Steve Yegge
a1fba65c67 feat: add --estimate flag to bd create/update commands (GH #443)
The estimated_minutes field existed in the Issue schema but wasn't exposed
via CLI. This adds:

- --estimate / -e flag to bd create (e.g., bd create "Task" --estimate 120)
- --estimate / -e flag to bd update (e.g., bd update bd-xyz --estimate 60)
- EstimatedMinutes field to RPC CreateArgs and UpdateArgs
- Server-side handling in handleCreate and updatesFromArgs
- Validation for non-negative values

The value is specified in minutes and is useful for planning and
prioritization. The vscode-beads extension already has an Estimate column
that can now be populated.

Fixes #443

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 15:55:35 -08:00
Ryan Snodgrass
49b3353688 docs: encourage batch close and parallel creation in bd prime output
- Update examples to show `bd close <id1> <id2> ...` for batch closing
- Add quick reference entry for closing multiple issues at once
- Add tip about using parallel subagents for creating multiple issues
- Add comment in example about running bd create in parallel

Cherry-picked from PR #452 (prime.go changes only)

Co-Authored-By: Ryan Snodgrass <rsnodgrass@gmail.com>

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 15:32:39 -08:00
Steve Yegge
fce8699353 feat(doctor): add per-fix confirmation mode (bd-3xl)
Add --interactive/-i flag to bd doctor --fix that prompts for each
fix individually. Users can approve/skip each fix with options:
[y]es, [n]o, [a]ll remaining, or [q]uit.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 13:11:22 -08:00
Steve Yegge
e5de1db585 feat(doctor): add --output flag to export diagnostics (bd-9cc)
Add ability to save doctor diagnostics to a JSON file for historical
analysis and bug reporting. The export includes timestamp and platform
info (OS, Go version, SQLite version) for tracking intermittent issues.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 11:41:00 -08:00
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
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
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
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
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
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
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
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
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
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
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
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