Fixes#543, #544, #545, #546 (no-db mode regressions)
Memory backend fixes:
- GetReadyWork now properly excludes issues with open blocks dependencies
- GetBlockedIssues now includes issues with status=blocked (even with 0 blockers)
- LoadFromIssues initializes hierarchical child counters from existing IDs
so repeated --parent creates bd-xxx.1, bd-xxx.2, etc.
JSONL path discovery:
- findJSONLPath works in no-db mode when dbPath is empty
- Honors BEADS_JSONL environment variable override
- Falls back to locating .beads directory
Based on PR #547 by @joelklabo - cherry-picked core fixes.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Orphaned issues (children of deleted epics):
- bd-cb64c226.1, .6, .8, .9, .10, .12, .13 (cache removal epic)
- bd-cbed9619.1, .2, .3, .4, .5 (N-way collision epic)
These were completed tasks from October 2025 that became orphans
when their parent epics were deleted.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When multiple polecats run bd sync simultaneously, they race to push to
the shared beads-sync branch. Previously this caused non-fast-forward
errors that blocked all polecats.
Now pushFromWorktree:
- Detects non-fast-forward errors from git push output
- On conflict: fetches remote, rebases local commits on top, retries
- Uses exponential backoff for transient failures (up to 5 retries)
- Aborts rebase cleanly if it fails to leave worktree in good state
Fixes gt-zqor.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added onboard and hooks commands to the noDbCommands list so they
skip database and daemon initialization. These commands don't need
database access - they just output documentation or manage git hooks.
On Windows, if no .beads directory exists, the PersistentPreRun
would attempt database discovery (including git worktree detection)
which could hang due to git command issues.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements single-shot mode improvements for Windows and Docker scenarios:
- Add --lock-timeout global flag (default 30s, 0 = fail immediately)
- Add config file support: lock-timeout: 100ms
- Parameterize SQLite busy_timeout via NewWithTimeout() function
- In --sandbox mode: default lock-timeout to 100ms
- In --sandbox mode: skip FlushManager creation (no background goroutines)
This addresses bd.exe hanging on Windows and locking conflicts when
using beads across host + Docker containers.
Closes: bd-59er, bd-r4od, bd-dh8a
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add JSONL-only mode detection in ensureStoreActive() with context-aware
error messages that suggest correct actions based on project state
- Improve error messages in main.go to detect JSONL presence and suggest
appropriate solutions (bd init, --no-db flag, or config.yaml setting)
- Update documentation to use issues.jsonl as canonical filename:
- AGENT_INSTRUCTIONS.md, README.md, resolve-beads-conflict.md
- docs/GIT_INTEGRATION.md
- Update hook template comments to clarify issues.jsonl is canonical
while maintaining backward compatibility for beads.jsonl
Fixes#534🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Stealth mode was adding generic `.beads/` pattern to global gitignore,
which ignored ALL .beads/ folders across all repositories. Users who
want stealth mode in one project but open beads usage in others were
blocked.
Now uses absolute project paths instead:
- `/path/to/project/.beads/`
- `/path/to/project/.claude/settings.local.json`
This allows multiple stealth projects while other repos can use beads
openly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix daemon auto-sync delete mutation not reflected in sync branch
When deleting an issue with `bd delete <id> --force`, the daemon auto-sync now properly removes the deleted issue from the sync branch.
**Problem:** The merge logic saw fewer local issues (due to deletion) and would re-add the deleted issue.
**Solution:** Add `ForceOverwrite` option to bypass merge logic when mutations occur. Mutation-triggered exports are authoritative and should overwrite, not merge.
Reviewed-by: stevey
Add two new doctor checks for tombstone health:
1. Updated Deletions Manifest check:
- Warns when legacy deletions.jsonl has entries (suggests migration)
- Shows "Migrated to tombstones" when .migrated file exists
- Shows "Using inline tombstones" for new repos
2. New Tombstones check:
- Reports total tombstone count
- Warns about expired tombstones (older than 30 days)
- Shows tombstones expiring within 7 days
- Suggests 'bd compact' to prune expired tombstones
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Reorganize the claude-code-skill into a publishable plugin that can be
installed through the beads-marketplace. Users can now reference the
'beads' skill right after installing the marketplace.
Co-authored-by: Steve Yegge <steve.yegge@gmail.com>
* fix(daemon): check for stale startlock before waiting 5 seconds
When a previous daemon startup left behind a bd.sock.startlock file
(e.g., from a crashed process), the code was waiting 5 seconds before
checking if the lock was stale. This caused unnecessary delays on
every bd command when the daemon wasn't running.
Now checks if the PID in the startlock file is alive BEFORE waiting.
If the PID is dead or unreadable, the stale lock is cleaned up
immediately and lock acquisition is retried.
Fixes ~5s delay when startlock file exists from crashed process.
* perf: add benchmarks for large descriptions, bulk operations, and sync merge
Added three new performance benchmarks to identify bottlenecks in common operations:
1. BenchmarkLargeDescription - Tests handling of 100KB+ issue descriptions
- Measures string allocation/parsing overhead
- Result: 3.3ms/op, 874KB/op allocation
2. BenchmarkBulkCloseIssues - Tests closing 100 issues sequentially
- Measures batch write performance
- Result: 1.9s total, shows write amplification
3. BenchmarkSyncMerge - Tests JSONL merge cycle with creates/updates
- Simulates real sync operations (10 creates + 10 updates per iteration)
- Result: 29ms/op, identifies sync bottlenecks
Added BENCHMARKS.md documentation describing:
- How to run benchmarks with various options
- All available benchmark categories
- Performance targets on M2 Pro hardware
- Dataset caching strategy
- CPU profiling integration
- Optimization workflow
This completes performance testing coverage for previously unmeasured scenarios.
* docs: clarify daemon lock acquisition logic in comments
Improve comments to clarify that acquireStartLock does both:
1. Immediately check for stale locks from crashed processes (avoids 5s delay)
2. If PID is alive, properly wait for legitimate daemon startup (5s timeout)
No code changes - only clarified comment documentation for maintainability.
---------
Co-authored-by: Steve Yegge <steve.yegge@gmail.com>
The .beads/.gitignore now ignores everything by default and explicitly
whitelists tracked files. This fixes confusion about which files to
commit when using protected branches workflow.
Changes:
- Use `*` to ignore all by default, then `!file` to whitelist
- Fix config.json -> config.yaml (wrong filename in negation)
- Update doctor check to validate new patterns
- Update PROTECTED_BRANCHES.md documentation
- Simplify git add instructions to just `git add .beads/`
Fixes#473🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements the bd reset command for GitHub issue #479:
- CLI command with flags: --hard, --force, --backup, --dry-run, --skip-init, --verbose
- Impact summary showing issues/tombstones to be deleted
- Confirmation prompt (skippable with --force)
- Colored output for better UX
- Unit tests for reset.go and git.go
- Fix: use --force flag in git rm to handle staged files
Part of epic bd-aydr.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove Force from core ResetOptions (CLI concern)
- Clarify file locations (internal/reset/)
- Add ImpactSummary struct with open/closed counts
- Note backup dirs should be gitignored
- Add --verbose flag to CLI spec
- Clarify TDD approach for unit tests
- Add bd-aydr.9 for gitignore template update
Changed Priority from hardcoded 2 to 0 (unset) to distinguish legacy tombstones
from user-set values. IssueType remains TypeTask as empty fails validation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Track legacy deletions.jsonl entries converted to tombstones during import:
- Add Result.ConvertedToTombstone counter
- Add Result.ConvertedTombstoneIDs for the converted IDs
- Update test to verify the new counter
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add TestIsExpiredTombstone with edge cases for merge package
- Add TestImportIssues_LegacyDeletionsConvertedToTombstones for importer
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Close bd-6y5 (getLocalSyncBranch tests)
- Include tombstone export logic fix (bd-81x6)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
bd-2e0 'Add TTL to deletions manifest entries' was accidentally removed
when commit d5a3963 reduced issues.jsonl from 384 to 130 issues.
Root cause analysis:
- metadata.json pointed to 'issues.jsonl' which was deleted
- Database had 65 'open' issues vs 12 in JSONL (zombie resurrection)
- Rebuilt database from correct JSONL
- Recreated the one legitimate open issue (bd-2e0)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
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>
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>
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
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>
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>
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>
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>
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>