Root cause: When a bd daemon crashes, its daemon.lock file remains with
the old PID. If that PID gets reused by an unrelated process, the code
would wait 5 seconds for a socket that will never appear.
Fix: Use flock-based check as authoritative source for daemon liveness.
The OS releases flocks when a process dies, so this is immune to PID reuse.
Changes:
- handleExistingSocket: Check daemon flock before waiting for socket
- acquireStartLock: Verify daemon lock is held before waiting
- handleStaleLock: Use flock check to detect stale startlocks
- lockfile/process_*.go: Add pid <= 0 check to prevent false positives
(PID 0 signals process group on Unix, not a specific process)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds a new `bd mol progress` command that shows molecule progress using
indexed queries instead of loading all steps into memory. This makes it
suitable for mega-molecules with millions of steps.
Features:
- Efficient SQL-based counting via idx_dependencies_depends_on_type index
- Progress display: completed / total (percentage)
- Current step identification
- Rate calculation from closure timestamps
- ETA estimation
- JSON output support
New storage interface method: GetMoleculeProgress(ctx, moleculeID)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add CreateTombstone() to MemoryStorage and deleteBatchFallback() to
handle deletion when SQLite is not available. This fixes the error
"tombstone operation not supported by this storage backend" when
using bd delete with --no-db flag.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds "!{{var}}" syntax for negated truthy checks in Step.Condition.
Useful for "skip this step if feature is enabled" patterns.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add compile-time step filtering based on formula variables:
- New EvaluateStepCondition function for {{var}} truthy and equality checks
- FilterStepsByCondition to exclude steps based on conditions
- Integration into pour, wisp, and mol bond commands
- Supports: {{var}}, {{var}} == value, {{var}} != value
Steps with conditions that evaluate to false are excluded from the
cooked formula, along with their children.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added lookupIssueMeta helper to fetch title and assignee before emitting
mutation events. This makes bd activity and gt feed show informative entries
like "gt-xxx updated · Title..." instead of just "gt-xxx updated".
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add TestSet cases for main/master rejection in syncbranch_test.go
- Add TestInitWithSyncBranch to verify --branch flag works
- Add TestInitWithoutBranchFlag to verify no auto-detection (root cause)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds atomic claim operation for work queue messages:
- New --claim flag on bd update command
- Sets assignee to claimer and status to in_progress
- Fails with clear error if already claimed by someone else
- Works in both daemon and direct modes
- Includes comprehensive tests for claim functionality
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This implements sync branch integrity guards that detect when the remote
sync branch has been force-pushed since the last sync, preventing silent
data corruption.
Changes:
- Add internal/syncbranch/integrity.go with:
- CheckForcePush() - detects force-push via stored remote SHA comparison
- UpdateStoredRemoteSHA() - stores current remote SHA after successful sync
- ClearStoredRemoteSHA() - clears stored SHA when resetting
- GetStoredRemoteSHA() - retrieves stored SHA for inspection
- Update cmd/bd/sync.go to:
- Add --accept-rebase flag for non-interactive reset to remote
- Add force-push detection before sync branch pull operations
- Prompt user for confirmation when force-push detected
- Update stored remote SHA after successful sync
The implementation:
1. Tracks the remote sync branch commit SHA in config after each sync
2. On subsequent syncs, checks if stored SHA is ancestor of current remote
3. If not (force-push detected), warns user with details and prompts
4. User can accept reset or abort to investigate manually
5. --accept-rebase flag allows scripted/non-interactive recovery
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The bug: In a bare repo + worktrees setup, jsonlRelPath was calculated
relative to the project root (containing all worktrees), resulting in
paths like "main/.beads/issues.jsonl". But the sync branch worktree uses
sparse checkout for .beads/*, so files are at ".beads/issues.jsonl".
This caused SyncJSONLToWorktreeWithOptions to write to the wrong location
(e.g., worktree/main/.beads/ instead of worktree/.beads/), so changes
made locally never reached the sync branch worktree.
#785 fixed the reverse direction (worktree → local) by adding
normalizeBeadsRelPath(), but the local → worktree direction was missed.
Fix:
- Export NormalizeBeadsRelPath() (uppercase) for cross-package use
- Apply normalization in SyncJSONLToWorktreeWithOptions for dstPath
- Apply normalization in daemon_sync_branch.go for worktreeJSONLPath
in both commit and pull paths
- Add unit tests for the normalization function
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add SQLite read-only mode for commands that only query data (list, ready,
show, stats, blocked, count, search, graph, duplicates, comments, export).
Changes:
- Add NewReadOnly() and NewReadOnlyWithTimeout() to sqlite package
- Opens with mode=ro to prevent any file writes
- Skips WAL pragma, schema init, and migrations
- Skips WAL checkpoint on Close()
- Update main.go to detect read-only commands and use appropriate opener
- Skip auto-migrate, FlushManager, and auto-import for read-only commands
- Add tests verifying file mtime is unchanged after read operations
This fixes the issue where file watchers (like beads-ui) would go into
infinite loops because bd list/show/ready modified the database file.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Two issues fixed:
1. `bd init` was auto-detecting current branch (e.g., main) as sync.branch
when no --branch flag was specified. This caused worktree conflicts.
2. Added validation to reject main/master as sync.branch values.
When sync.branch is set to main, the worktree mechanism creates a checkout
of main at .git/beads-worktrees/main/, which prevents git checkout main
from working in the user's working directory.
The sync branch feature should use a dedicated branch like 'beads-sync'.
🤖 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
db.Exec was being passed %s format specifiers directly in the SQL
string, but db.Exec does not do printf-style formatting - it uses the
variadic args as SQL parameter bindings. This caused the literal %s
to be sent to SQLite, which failed with near percent: syntax error.
Fixed by using fmt.Sprintf to interpolate the column expressions into
the SQL string before passing to db.Exec.
Added regression test that creates an old-schema database with edge
columns (replies_to, relates_to, duplicate_of, superseded_by) and
verifies migration 022 completes successfully.
Fixes#809
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds TypeEvent issue type for recording operational state changes as
immutable beads. Events capture:
- event_category: namespaced category (e.g., patrol.muted, agent.started)
- event_actor: entity URI who caused the event
- event_target: entity URI or bead ID affected
- event_payload: event-specific JSON data
Changes:
- Add TypeEvent constant and IsValid() support in types.go
- Add event fields to Issue struct with ComputeContentHash support
- Add --event-category/actor/target/payload flags to bd create
- Add event fields to RPC CreateArgs and UpdateArgs
- Add migration 033_event_fields to add columns to issues table
- Update insertIssue and queries to include event fields
- Fix migrations_test.go for new column requirements
This enables:
- bd activity --follow showing events
- bd list --type=event --target=agent:deacon
- Full audit trail for operational state
- HOP-compatible transaction records
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds agent-optimized output mode for `bd list` triggered by:
- BD_AGENT_MODE=1 environment variable (explicit)
- CLAUDE_CODE environment variable (auto-detect)
Agent mode provides:
- Ultra-compact format: just "ID: Title" per line
- Lower default limit (20 vs 50) for context efficiency
- No colors, no emojis, no pager
- Defaults to open/in_progress only (existing behavior)
(bd-x2ht)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add composable issue validators to internal/validation package:
- IssueValidator type with Chain() composition function
- Exists(), NotTemplate(), NotPinned(), NotClosed(), NotHooked() validators
- HasStatus(), HasType() for checking allowed values
- ForUpdate(), ForClose(), ForDelete(), ForReopen() convenience chains
Update cmd/bd/show_unit_helpers.go to use centralized validators instead
of duplicated inline validation logic. This enables consistent validation
across all commands with a single source of truth.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When debug mode is enabled, the merge system now logs a message when
an expired tombstone loses to a live issue (resurrection occurs).
This helps understand why previously closed issues reappear.
Example output: "Issue bd-abc resurrected (tombstone expired)"
Changes:
- Add debug parameter to Merge3WayWithTTL and merge3Way functions
- Add debug logging in all 4 resurrection code paths
- Update tests to pass new debug parameter (bd-nl2)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added StatusClosed constant derived from types.StatusClosed alongside
the existing StatusTombstone constant. Replaced hardcoded "closed"
strings with the constant for compile-time type checking consistency.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added actor field to RPC client and set it before daemon requests.
This ensures status changes (like pinned events) show who performed
the action in bd activity output.
Changes:
- Added actor field to Client struct
- Added SetActor method to set actor for audit trail
- Modified ExecuteWithCwd to include actor in RPC requests
- Updated main.go to call SetActor after daemon connection
Fixes gt-1ydd9
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds support for event beads that capture operational state transitions
as immutable records. Events are a new issue type with fields:
- event_kind: namespaced category (patrol.muted, agent.started)
- actor: entity URI who caused the event
- target: entity URI or bead ID affected
- payload: event-specific JSON data
This enables:
- bd activity --follow showing events
- bd list --type=event --target=agent:deacon
- Full audit trail for operational state
- HOP-compatible transaction records
🤖 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 new DependencyType constants: until, caused-by, validates
- Add --refs flag to bd show for reverse reference lookups
- Group refs by type with appropriate emojis
- Update tests for new dependency types
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add TTY detection to automatically disable ANSI colors when stdout is
piped or redirected. Respects standard conventions:
- NO_COLOR environment variable (no-color.org)
- CLICOLOR=0 disables color
- CLICOLOR_FORCE enables color even in non-TTY
Also adds ShouldUseEmoji() helper controlled by BD_NO_EMOJI.
Pager already disabled non-TTY in previous work (bd-jdz3).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
Added actor field to RPC client and set it before daemon requests.
This ensures status changes (like pinned events) show who performed
the action in bd activity output.
Changes:
- Added actor field to Client struct
- Added SetActor method to set actor for audit trail
- Modified ExecuteWithCwd to include actor in RPC requests
- Updated main.go to call SetActor after daemon connection
Fixes gt-1ydd9
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
- Step.Expand and Step.ExpandVars are implemented in ApplyInlineExpansions
(expand.go), but had stale TODO comments claiming they were not
- Updated doc comments to reference the implementation
- Updated bd-7zka to reflect which features are still not implemented
(Step.Condition and Step.Gate remain as future work)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added GetDependenciesWithMetadata and GetDependentsWithMetadata to mockStorage
to match the Storage interface definition.
🤖 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
- 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>
When updating role_type or rig on an agent bead, remove existing
role_type:* or rig:* labels before adding the new one. This prevents
label accumulation that would break filtering.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
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>
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>
Tests were failing when BD_ACTOR or other BD_/BEADS_ environment
variables were set. Added envSnapshot helper to save, clear, and
restore environment variables for proper test isolation.
🤖 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>
Code review caught that ".beads" would incorrectly match prefixes like
".beads-backup". Changed to match ".beads/" (with trailing slash) to
ensure we only match the actual .beads directory.
Added test cases for this edge case.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The bug: In a bare repo + worktrees setup, jsonlRelPath was calculated
relative to the project root (which contains all worktrees), resulting in
paths like "main/.beads/issues.jsonl". But the sync branch worktree uses
sparse checkout for .beads/*, so files are at ".beads/issues.jsonl".
This caused copyJSONLToMainRepo to look in the wrong location, silently
returning when the file was not found.
Fix: Add normalizeBeadsRelPath() to strip leading path components before
".beads", ensuring correct path resolution in both directions:
- copyJSONLToMainRepo (worktree -> local)
- SyncJSONLToWorktreeWithOptions (local -> worktree)
🤖 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>
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.
When the database has orphaned foreign key references (dependencies or labels
pointing to non-existent issues), the migration invariant check would fail,
preventing the database from opening. This created a chicken-and-egg problem:
1. bd doctor --fix tries to open the database
2. Opening triggers migrations with invariant checks
3. Invariant check fails due to orphaned refs
4. Fix never runs because database won't open
The fix adds CleanOrphanedRefs() that runs BEFORE captureSnapshot() in
RunMigrations. This automatically cleans up orphaned dependencies and labels
(preserving external:* refs), allowing the database to open normally.
Added test coverage for the cleanup function.
The routing code now walks up from the current beads directory to find
the Gas Town root (identified by mayor/town.json), then loads routes
from <townRoot>/.beads/routes.jsonl. The '.' path is correctly resolved
to the town beads directory.
Previously, routes.jsonl was only searched in the current beads dir,
which failed when working from rig subdirectories like crew/emma.
🤖 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>
Separates semantics of 'pinned' (identity records) from work-on-hook:
- 'pinned' = domain table / identity record (agents, roles) - non-blocking
- 'hooked' = work on agent's hook (GUPP-driven) - blocks dependents
Changes:
- Add StatusHooked constant to types.go
- Update all blocking queries to include 'hooked' status
- Add cyan styling for 'hooked' in UI output
- Create migration 032 to convert pinned work items to hooked
Generated with Claude Code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>