Post-merge cleanup of PR #805:
1. Extract duplicate error classification logic into classifyDatabaseError()
helper function (was duplicated in two places in database.go)
2. Fix semantic conflict between --force and --source=db flags:
- --force implies "database is broken, rebuild from JSONL"
- --source=db implies "use database as source of truth"
- These are contradictory; now errors with clear message
- --force with --source=auto or --source=jsonl works as expected
🤖 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
Add two new RPC endpoints to allow CLI commands to work in daemon mode:
1. GetConfig (OpGetConfig) - Retrieves config values from the daemon database.
Used by bd create to validate issue prefix in daemon mode.
2. MolStale (OpMolStale) - Finds stale molecules (complete-but-unclosed
epics). Used by bd mol stale command in daemon mode.
Changes:
- internal/rpc/protocol.go: Add operation constants and request/response types
- internal/rpc/client.go: Add client methods GetConfig() and MolStale()
- internal/rpc/server_issues_epics.go: Add handler implementations
- internal/rpc/server_routing_validation_diagnostics.go: Register handlers
- cmd/bd/create.go: Use GetConfig RPC instead of skipping validation
- cmd/bd/mol_stale.go: Use MolStale RPC instead of requiring --no-daemon
- internal/rpc/coverage_test.go: Add tests for new endpoints
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Apply the same enhanced error classification to PRAGMA integrity_check
failures as we do for database open failures.
This ensures users see detailed, actionable recovery steps regardless of
which stage the corruption is detected (open vs integrity check).
Tested with real corruption scenarios - all error paths now provide
specific recovery guidance with exact commands.
Add pager support following gh cli conventions:
Flags:
- --no-pager: disable pager for this command
Environment variables:
- BD_PAGER / PAGER: pager program (default: less)
- BD_NO_PAGER: disable pager globally
Behavior:
- Auto-enable pager when output exceeds terminal height
- Respect LESS env var for pager options
- Disable pager when stdout is not a TTY (pipes/scripts)
Implementation:
- New internal/ui/pager.go with ToPager() function
- Added formatIssueLong/formatIssueCompact helper functions
- Buffer output before displaying to support pager
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The ProtoID field in BondRef was misleading as it could hold both proto
IDs (from proto+proto bonds) and molecule IDs (from mol+mol bonds).
Rename to SourceID with updated JSON tag to better reflect its purpose.
Changes:
- Rename BondRef.ProtoID to SourceID in types.go
- Update JSON tag from proto_id to source_id
- Update all usages in mol_bond.go and tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The function was marked for removal once all callers migrated to the new
setupDaemonLogger signature with jsonFormat and level parameters.
Audit confirmed no remaining callers - safe to remove.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add TypeConvoy to issue types for cross-project tracking
- Implement reactive completion: when all tracked issues close,
convoy auto-closes with reason "All tracked issues completed"
- Uses 'tracks' dependency type (non-blocking, cross-prefix capable)
- Update help text for --type flag in list/create commands
- Add test for convoy reactive completion behavior
🤖 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
Previously, --older-than=0 was indistinguishable from "flag not set"
because both resulted in compactOlderThan==0. The check `> 0` treated
both as "use default 30 days".
Fix:
- Change flag default to -1 (sentinel for "use default")
- Treat 0 as "expire all tombstones" by passing 1ns TTL
- Explicit positive values work as before (N days)
Closes bd-gigi
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Actor field to MutationEvent struct
- Use new assignee from update args instead of old issue state
- Include actor (who performed the action) in mutation events
- Display actor in bd activity output, falling back to assignee
When pinning/updating status, the activity feed now shows who performed
the action (e.g., "@gastown/crew/jack") instead of showing nothing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive database corruption recovery capabilities to bd doctor.
## Changes
### New Command Flags
- --force: Force repair mode that bypasses database validation
- --source: Choose source of truth (auto/jsonl/db) for recovery
### Enhanced Error Classification
Improved CheckDatabaseIntegrity() to detect and classify:
- Database locked errors (suggests killing processes, removing locks)
- Invalid SQLite files (suggests JSONL recovery with exact commands)
- Migration/validation failures (orphaned dependencies, etc.)
- Generic database errors (context-aware suggestions)
Each error type provides:
- Specific diagnosis
- Step-by-step recovery instructions
- Appropriate command examples with new flags
### Force Recovery Implementation
New DatabaseCorruptionRecoveryWithOptions() function:
- Bypasses database validation when --force is used
- Supports explicit source of truth selection
- Auto-detects best recovery path when source=auto
- Comprehensive rollback on failure
- Uses --force --no-git-history in import during force mode
### Integration
Updated fix orchestration to pass force and source flags to recovery.
## Usage Examples
```bash
# Unopenable database with validation errors
bd doctor --fix --force --source=jsonl
# Choose specific source of truth
bd doctor --fix --source=jsonl # Trust JSONL
bd doctor --fix --source=db # Trust database
bd doctor --fix --source=auto # Auto-detect (default)
# Force recovery with auto-detection
bd doctor --fix --force
```
## Problem Solved
Before: When database had validation errors (orphaned dependencies,
foreign key violations), all bd commands failed in a catch-22 situation.
Could not open database to fix database. Users had to manually delete
database files and reinit.
After: bd doctor --fix --force detects unopenable databases, provides
clear recovery steps, and forces rebuild from JSONL even when database
validation fails.
## Backward Compatibility
- All new flags are optional with safe defaults
- --source defaults to 'auto' (existing behavior)
- --force is opt-in only
- Existing bd doctor behavior unchanged when flags not used
- DatabaseCorruptionRecovery() still exists for compatibility
Fixes: bd-pgza
Automatically adds trailers to commits when running in Gas Town agent context:
- Executed-By: agent identity (e.g., beads/crew/dave)
- Rig: the rig name
- Role: crew, polecat, witness, etc.
- Molecule: pinned molecule ID (if any)
Detection sources:
1. GT_ROLE environment variable (set by Gas Town sessions)
2. cwd path patterns (crew/, polecats/, witness/, refinery/)
Trailers are skipped for:
- Human commits (no agent context detected)
- Merge commits (have their own format)
- Commits that already have Executed-By trailer (avoid duplicates)
Executed-By: beads/crew/dave
Rig: beads
Role: crew
Add role_type and rig labels to agent beads for filtering queries.
Changes:
- Add RoleType/Rig to CreateArgs and UpdateArgs in RPC protocol
- Auto-add role_type:<value> and rig:<value> labels when creating/updating agents
- Add --role-type and --agent-rig flags to bd create (requires --type=agent)
- Add bd agent backfill-labels command to update existing agent beads
This enables queries like:
bd list --type=agent --label=role_type:witness
bd list --type=agent --label=rig:gastown
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- resolveBeadsRedirect now verifies target exists before returning
- Added failure tracking to runTownActivityFollow (warns on rig disconnect)
- Created fetchTownMutationsWithStatus for tracking daemon availability
- Shows reconnection message when rigs come back online
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds --town flag that:
- Discovers all rigs via routes.jsonl
- Connects to each rig daemon
- Aggregates mutations from all daemons
- Sorts by timestamp for unified feed
- Works with --follow for real-time streaming
Usage:
bd activity --town # Aggregated feed from all rigs
bd activity --follow --town # Stream all rig activity
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds non-blocking tracks dependency type for convoy to issue relationships:
- Non-blocking: does not affect ready work calculation
- Cross-prefix capable: convoys in hq-* can track issues in gt-*, bd-*
- Reverse lookup: bd dep list <id> --direction=up -t tracks
Also adds bd dep list command with direction and type filtering for
querying dependencies/dependents.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Safeguard for users with global gitignore patterns like *.jsonl that
could cause issues.jsonl to be ignored, breaking bd sync.
The check runs git check-ignore and warns if issues.jsonl would be
ignored by any gitignore rule (global, parent directory, etc).
- Add BD_JIRA_SCRIPT env var to let users specify script location
- Improve error message with clear instructions for binary users
- Show all locations that were searched
Changes:
- Default to excluding closed issues (use --all to include)
- Default limit of 50 issues (use --limit 0 for unlimited)
- --all flag now overrides the closed filter
This addresses agent context blowout from seeing hundreds of closed issues.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changes:
- Default --limit changed from 0 (unlimited) to 50
- --limit 0 explicitly means unlimited (override default)
- Show truncation hint when results are limited:
"Showing N issues (use --limit 0 for all)"
This protects agents and humans from overwhelming output.
Follows precedent from gh cli (30) and jira-cli (50).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Previously mol burn only worked on wisps (Ephemeral=true), erroring
on persistent mols. Now it works on both:
- Wisps: direct delete without tombstones (original behavior)
- Mols: cascade delete with tombstones (syncs to remotes)
This makes the 'burn' metaphor consistent: burn = destroy a molecule,
regardless of phase.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update version across all components:
- cmd/bd/version.go
- .claude-plugin/plugin.json, marketplace.json
- npm-package/package.json
- integrations/beads-mcp/pyproject.toml
- Git hook templates
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed all --var flags from StringSlice to StringArray.
StringSlice splits on commas, breaking values like 'desc=A, B, C'.
StringArray only splits on separate --var flags.
Affected commands: pour, cook, wisp, mol distill, mol bond, template instantiate
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add explicit error checking for fmt.Fprintf/Fprintln in claude.go
- Add gosec nolint for safe exec.CommandContext calls in sync_git.go
- Remove unused error return from findTownRoutes in routes.go
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The --cascade flag was documented but not working for single-issue
deletes. The bug had two causes:
1. CLI direct mode: Single-issue deletes bypassed the batch path where
cascade expansion actually happens. Fixed by routing cascade deletes
through deleteBatch() regardless of issue count.
2. Daemon/RPC mode: handleDelete() iterated through IDs individually
without expanding dependents. Fixed by using DeleteIssues() with
cascade flag when SQLite storage is available.
Now `bd delete <id> --cascade --force` correctly deletes the target
issue plus all issues that depend on it (recursively).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The CheckSyncBranchHookCompatibility was checking core.hooksPath first,
while CheckGitHooks always uses .git/hooks/. This caused inconsistent
results when core.hooksPath was set globally.
Fix: Remove core.hooksPath check from CheckSyncBranchHookCompatibility
to match CheckGitHooks behavior. Both now consistently use .git/hooks/.
Note: A future improvement could make both respect core.hooksPath.
The negation patterns (!issues.jsonl, !interactions.jsonl, etc.) in
.beads/.gitignore had higher precedence than the fork protection
exclusion in .git/info/exclude, effectively defeating fork protection.
Contributors could accidentally stage and commit upstream issue
databases because:
1. Fork protection added .beads/issues.jsonl to .git/info/exclude
2. .beads/.gitignore had !issues.jsonl which overrode the exclusion
3. .gitignore files have higher precedence than .git/info/exclude
The negation patterns were unnecessary anyway since no pattern in
.beads/.gitignore matches those files. Added a comment explaining
why negations should not be added.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Solaris/illumos use Statvfs (POSIX standard) rather than Statfs.
Add daemon_health_solaris.go and exclude illumos/solaris from the
generic unix build constraint.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
bd has 70+ commands, which can be overwhelming for human users who just
want to track issues. The new `bd human` command displays a curated list
of ~15 essential commands organized by workflow:
- Working With Issues: create, list, show, update, close, reopen, comment
- Finding Work: ready, search, status, stats
- Dependencies: dep add/remove/tree, graph, blocked
- Setup & Sync: init, sync, doctor
- Getting Help: quickstart, help, --help
Also includes quick examples showing common workflows.
Changes:
- Add cmd/bd/human.go with curated help output
- Add "human" to noDbCommands list in main.go (no database needed)
Consolidated 5 duplicate IssueDetails struct definitions into a single
types.IssueDetails in internal/types/types.go:
- Removed 4 inline definitions from cmd/bd/show.go
- Removed 1 inline definition from internal/rpc/server_issues_epics.go
The shared type embeds types.Issue by value and includes:
Labels, Dependencies, Dependents, Comments, and Parent fields.
This improves maintainability and reduces risk of inconsistency.
bd config list now shows a warning when config.yaml or environment
variables override database settings. This addresses the confusion when
sync.branch from config.yaml takes precedence over the database value.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rename followRedirect to FollowRedirect in internal/beads (export it)
- Update doctor/maintenance.go to use beads.FollowRedirect
- Update doctor/fix/common.go to use beads.FollowRedirect
- Remove 66 lines of duplicated code across 3 implementations
This ensures consistent redirect handling with path canonicalization,
chain prevention, and proper error warnings.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add exitWithError helper to ensure JSON output is used when --json
flag is set during orphan detection errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add resolveBeadsDir helper to fix/common.go to follow redirect files
- Update OrphanedDependencies, ChildParentDependencies, and MergeArtifacts
to use resolveBeadsDir instead of hardcoded .beads path
- Add --verbose/-v flag to bd doctor command
- Only print individual items if verbose or count < 20, always show summary
(bd-dq74, bd-v55y)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Check comments table for orphaned issue_id references
- Check events table for orphaned issue_id references
- Delete orphaned comments/events in repair transaction
- Add --json flag for machine-readable output with:
- orphan_counts by type (dependencies, labels, comments, events)
- orphan_details with full reference info
- status (success, no_orphans, dry_run, error)
- backup_path when applicable
(bd-2wm2, bd-ie7j)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Code review fixes for critical issues:
- Wrap all DELETEs in a transaction with rollback on error
- Create .pre-repair backup before any destructive operations
- Mark parent issues as dirty when deleting orphaned depends_on refs
- Fix misleading PreRun comment
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When the database has orphaned dependencies or labels, the migration
invariant check fails and prevents the database from opening. This
creates a chicken-and-egg problem where bd doctor --fix cannot run.
The new bd repair command:
- Opens SQLite directly, bypassing invariant checks
- Deletes orphaned dependencies (issue_id or depends_on_id not in issues)
- Deletes orphaned labels (issue_id not in issues)
- Runs WAL checkpoint to persist changes
- Supports --dry-run to preview what would be cleaned
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Eliminate code duplication between importFromGit and importFromLocalJSONL
by extracting the common JSONL parsing and import logic.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds --from-jsonl flag that imports from the current working tree's
.beads/issues.jsonl file instead of scanning git history. This prevents
deleted issues from being resurrected during re-initialization.
Use case: After running bd compact --purge-tombstones and committing
the cleaned JSONL, a subsequent bd init would previously re-import
all historical issues from git, defeating the cleanup.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Unlike --prune which removes tombstones by age, --purge-tombstones removes
tombstones that have no open issues depending on them, regardless of age.
Also cleans stale deps from closed issues to tombstones.
Usage:
bd compact --purge-tombstones --dry-run # Preview what would be purged
bd compact --purge-tombstones # Actually purge
Note: Use --no-daemon to prevent daemon from re-exporting after cleanup.
- Add findExistingSwarm helper and duplicate swarm check with --force flag
- Add bd swarm list command for discovering swarm molecules with progress stats
- Fix empty coordinator display in swarm create output
- Allow swarm status to accept swarm molecule ID (follows relates-to link)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>