Commit Graph

710 Commits

Author SHA1 Message Date
Steve Yegge
1a818cbced test(rpc): add comprehensive daemon delete RPC handler tests (bd-dxtc)
Add tests for the daemon Delete RPC handler to verify:

- Dry-run mode returns preview without actual deletion
- Error handling for empty issue IDs
- Error handling for non-existent issues
- Partial success when some issues exist and others do not
- Templates cannot be deleted (read-only protection)
- Invalid JSON args are properly rejected
- Reason field is passed through correctly
- Cascade and Force flags are accepted (documents current behavior)

All test scenarios from bd-dxtc issue are covered.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 00:06:51 -08:00
Steve Yegge
143f5c80bf Fix TestMain to find module root before building bd binary
The TestMain in beads_hash_multiclone_test.go was running `go build ./cmd/bd`
from the package directory (internal/beads) instead of the module root, causing
the build to fail with "directory not found".

Now uses `go list -m -f '{{.Dir}}'` to locate the module root and sets cmd.Dir
appropriately before building.

This fixes the integration test setup that was preventing TestRoutingIntegration
from running. (bd-g9eu)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 00:06:41 -08:00
Steve Yegge
e67f27c092 bd sync: 2025-12-23 23:38:57 2025-12-24 00:06:41 -08:00
Steve Yegge
05e10b6759 Add comprehensive RPC test coverage (44.7% → 61.7%)
Removed Gate RPC tests that referenced undefined API methods.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 23:08:04 -08:00
Steve Yegge
f437ce2628 Improve internal/daemon test coverage from 27.3% to 72.0% (bd-n386)
Add discovery_unit_test.go with comprehensive unit tests that run without
the integration build tag. Tests cover:
- walkWithDepth: depth limiting, hidden dir skipping, callback errors
- checkDaemonErrorFile: file presence/absence, content reading
- CleanupStaleSockets: stale removal, alive daemon preservation
- findBeadsDirForWorkspace: regular repos, nonexistent paths
- discoverDaemon: socket missing, not listening, with error file
- discoverDaemonsLegacy: multiple roots, deduplication, filtering
- StopDaemon: not alive error, connection failures
- KillAllDaemons: empty list, not alive daemons, mixed states, force mode

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 22:39:22 -08:00
Steve Yegge
2de1695615 bd sync: 2025-12-23 22:33:32 2025-12-23 22:33:33 -08:00
Steve Yegge
cf9e5a597b bd sync: 2025-12-23 20:50:50 2025-12-23 20:50:50 -08:00
Steve Yegge
9c8761abc9 bd sync: 2025-12-23 20:45:19 2025-12-23 20:45:19 -08:00
Steve Yegge
f777093386 feat(rpc): add GetMoleculeProgress endpoint (bd-0oqz)
New RPC endpoint to get detailed progress for a molecule (parent issue
with child steps). Returns moleculeID, title, assignee, and list of
steps with their status (done/current/ready/blocked) and timestamps.

Used when user expands a worker in the activity feed TUI.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 18:27:35 -08:00
Steve Yegge
3a82ce2929 feat(rpc): add GetWorkerStatus RPC endpoint (bd-l13p)
New RPC endpoint to get all workers and their current molecule/step in one call.
Returns: assignee, moleculeID, moleculeTitle, currentStep, totalSteps, stepTitle,
lastActivity, status. Enables activity feed TUI to show worker state without
multiple round trips.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 17:12:58 -08:00
Steve Yegge
0d66aed954 feat(types): add omitempty to JSONL fields for smaller output
Add omitempty json tag to:
- Issue.Description: often empty for quick tasks
- Dependency.CreatedBy: often empty

This reduces JSONL file size when these fields are empty, leading to
faster syncs and smaller repository size.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 17:11:06 -08:00
Steve Yegge
3405f0c684 feat(rpc): enrich MutationEvent with Title and Assignee fields
Add Title and Assignee fields to MutationEvent struct so activity feeds
can display meaningful context without extra lookups. Updated emitMutation
signature to accept these values and modified all callers:

- Create: passes issue.Title and issue.Assignee directly
- Update/Close: moved emitMutation after GetIssue to access enriched data
- Delete: uses existing issue lookup before deletion
- Dep/Label/Comment ops: passes empty strings (would require extra lookup)

Fixes bd-gqxd

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 17:09:56 -08:00
Steve Yegge
e0f1d43c2c fix: write startup config keys to config.yaml instead of SQLite (GH#536)
`bd config set no-db true` now correctly writes to config.yaml instead of
SQLite. Previously, startup flags like no-db, no-daemon, no-auto-flush were
stored in SQLite but read from config.yaml at startup - making the command
appear to work while having no effect.

This adds:
- yaml_config.go: Defines yaml-only keys and provides SetYamlConfig/GetYamlConfig
- Updated config set/get commands to route yaml-only keys appropriately
- Comprehensive tests for yaml config handling

Startup flags affected: no-db, no-daemon, no-auto-flush, no-auto-import,
json, auto-start-daemon, flush-debounce, lock-timeout, git.*, sync.*, routing.*

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 17:03:39 -08:00
Steve Yegge
3d924f88f3 fix: handle multi-hyphen prefixes correctly (GH#422)
The prefix mismatch detection was using ExtractIssuePrefix() which
tries to guess the prefix by analyzing suffix patterns. This failed
for multi-hyphen prefixes like "asianops-audit-" when issue IDs had
word-like suffixes (e.g., "asianops-audit-test") - the heuristic
would fall back to the first hyphen and report "asianops-" as the
prefix.

Fixed by checking directly if the issue ID starts with the configured
prefix using strings.HasPrefix(). This is more reliable than guessing
since we know the expected prefix from the database config.

Added test case TestImportMultiHyphenPrefix to prevent regression.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 16:20:04 -08:00
Steve Yegge
fe2ac97597 fix: Exclude workflow types from bd ready by default (gt-7xtn)
merge-request, gate, molecule, and message types are internal workflow
items processed by Refinery/Deacon, not work for polecats to claim.
These are now excluded from bd ready unless explicitly requested via
--type flag.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 15:05:51 -08:00
Steve Yegge
7b671662aa bd sync: 2025-12-23 13:49:07 2025-12-23 14:39:07 -08:00
Steve Yegge
0d31e4209d fix: preserve pinned field during JSONL import (bd-phtv)
Fixed two code paths where pinned=false from JSONL would overwrite
existing pinned=true in database:
- importer.go: Only update pinned if explicitly true in JSONL
- multirepo.go: Use COALESCE to preserve existing pinned value

Added tests for pinned field preservation.

Note: Bug may have additional code path - investigation ongoing.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 13:49:22 -08:00
Steve Yegge
f503a5ae43 test: improve syncbranch coverage from 27% to 67% (bd-io8c)
Add comprehensive tests for internal/syncbranch package:

syncbranch.go:
- TestGetFromYAML: env var and default behavior
- TestIsConfigured: env var presence detection
- TestIsConfiguredWithDB: database and env var checks
- TestGetConfigFromDB: direct DB value retrieval

worktree.go helper functions:
- TestIsNonFastForwardError: git push error detection
- TestHasChangesInWorktree: dirty state detection
- TestCommitInWorktree: worktree commit flow
- TestCopyJSONLToMainRepo: file sync between worktrees
- TestGetRemoteForBranch: remote name resolution
- TestGetRepoRoot: repo root detection including worktrees
- TestHasGitRemote: remote existence check
- TestGetCurrentBranch: branch name detection
- TestFormatVanishedIssues: forensic logging

worktree.go main functions:
- TestCommitToSyncBranch: basic commit flow
- TestPullFromSyncBranch: pull and fast-forward scenarios
- TestResetToRemote: remote reset error handling
- TestPushSyncBranch: push with worktree recreation
- TestPreemptiveFetchAndFastForward: pre-fetch behavior
- TestFetchAndRebaseInWorktree: rebase error handling
- TestRunCmdWithTimeoutMessage: command execution

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 13:48:40 -08:00
Steve Yegge
a129e36054 Add daemon RPC support for gate commands (bd-likt)
- Add gate operation constants (OpGateCreate, OpGateList, OpGateShow,
  OpGateClose, OpGateWait) to protocol.go
- Add Gate*Args and Gate*Result types to protocol.go
- Add gate handler methods (handleGateCreate, handleGateList,
  handleGateShow, handleGateClose, handleGateWait) to server_issues_epics.go
- Register gate handlers in handleRequest switch
- Add gate client methods (GateCreate, GateList, GateShow, GateClose,
  GateWait) to client.go
- Update cmd/bd/gate.go to use daemon client when available, falling
  back to direct store access

Gate commands now work with the daemon, eliminating the need for
--no-daemon flag.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 13:47:24 -08:00
Steve Yegge
1c2e7068ad test: improve internal/compact coverage from 17% to 82% (bd-thgk)
Add comprehensive unit tests for the compact package:

- haiku.go: Mock API tests for SummarizeTier1, retry logic tests for
  callWithRetry (429/500 handling, exhaust retries, context timeout),
  expanded isRetryable tests for network timeouts and API error codes
- git.go: Tests for GetCurrentCommitHash in various git states
  (in repo, outside repo, new repo, empty repo)
- compactor.go: Unit tests for New(), CompactTier1(), CompactTier1Batch()
  with mock API server, config validation, error paths

Small production change: NewHaikuClient now accepts variadic options
for testing (option.WithBaseURL, option.WithMaxRetries).

Coverage: 17.3% → 81.8%

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 13:42:24 -08:00
Steve Yegge
ec0c710718 Split queries.go into focused modules (bd-rgyd)
Split internal/storage/sqlite/queries.go (1586 lines) into logical modules:

- queries.go (650 lines) - Core CRUD: CreateIssue, GetIssue, UpdateIssue, CloseIssue
- queries_search.go (429 lines) - Search/filter: SearchIssues, GetIssueByExternalRef,
  GetCloseReason, GetCloseReasonsForIssues
- queries_delete.go (464 lines) - Delete operations: CreateTombstone, DeleteIssue,
  DeleteIssues and cascade logic
- queries_rename.go (149 lines) - ID/prefix operations: UpdateIssueID,
  RenameDependencyPrefix, RenameCounterPrefix, ResetCounter
- queries_helpers.go (50 lines) - Utilities: parseNullableTimeString,
  parseJSONStringArray, formatJSONStringArray

All tests pass. No functional changes.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 13:41:24 -08:00
Steve Yegge
c46b1a0bbb Add config-based close hooks (bd-g4b4)
Implements on_close hooks in .beads/config.yaml for automation and
notifications. Hooks receive issue data via environment variables
(BEAD_ID, BEAD_TITLE, BEAD_TYPE, BEAD_PRIORITY, BEAD_CLOSE_REASON)
and run via sh -c.

Changes:
- internal/config: Add HookEntry type and GetCloseHooks()
- internal/hooks: Add RunConfigCloseHooks() for executing config hooks
- cmd/bd: Call RunConfigCloseHooks after successful close
- docs/CONFIG.md: Document hooks configuration with examples

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 13:39:51 -08:00
Steve Yegge
ffa5de3181 Improve internal/beads test coverage from 48% to 80%
Add comprehensive tests for fingerprint.go:
- canonicalizeGitURL: URL normalization for HTTPS, SSH, SCP-style, HTTP, git protocol
- ComputeRepoID: With/without remote, not-git-repo, canonical URL consistency
- GetCloneID: Basic, different dirs, worktree, hostname inclusion

Add tests for beads.go:
- findDatabaseInBeadsDir: Direct tests for database discovery
- FindAllDatabases: Multi-database discovery, no-database, stops-at-first

Coverage: 48.4% → 80.2% (bd-tvu3)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 13:38:13 -08:00
Steve Yegge
f2db0a1d42 fix: exclude external deps from orphan check in migration invariants (bd-ucgz)
External dependencies (external:<project>:<capability>) reference issues in
other projects and are expected to not exist in the local issues table.
The orphan check now excludes these with: AND d.depends_on_id NOT LIKE 'external:%'

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 12:42:13 -08:00
Steve Yegge
47b86b35d8 feat: add gate issue type and CLI commands for async coordination (bd-udsi)
Add async gates - coordination primitives for agents to wait on external events
like CI completion, PR merges, timers, or human approval.

Changes:
- Add 'gate' issue type to types.go with gate-specific fields:
  - AwaitType: condition type (gh:run, gh:pr, timer, human, mail)
  - AwaitID: condition identifier
  - Timeout: max wait duration
  - Waiters: mail addresses to notify when gate clears
- Add SQLite migration 027_gate_columns for new fields
- Update all SQLite storage queries to handle gate fields
- Add bd gate commands: create, show, list, close, wait
- All commands support --json output and --no-daemon mode

Closes: bd-2v0f, bd-lz49, bd-u66e

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 12:06:42 -08:00
Steve Yegge
117bdd637e fix: add nolint:misspell for SQL query with British spelling 2025-12-23 05:14:01 -08:00
Steve Yegge
8b49d8f079 fix: resolve golangci-lint errors
- Add _ = prefix for ignored Close/Remove return values
- Fix unused cmd parameter in runMoleculeReady
- Add nolint:misspell for intentional British "cancelled" spelling
- Update comments to use US spelling where not intentional

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 05:10:38 -08:00
Steve Yegge
da809061db fix: emit rich mutation events for status changes (bd-313v)
- Add emitRichMutation() function for events with metadata
- handleClose now emits MutationStatus with old/new status
- handleUpdate detects status changes and emits MutationStatus
- Add comprehensive tests for rich mutation events

Also:
- Add activity.go test coverage (bd-3jcw):
  - Tests for parseDurationString, filterEvents, formatEvent
  - Tests for all mutation type displays
- Fix silent error handling in --follow mode (bd-csnr):
  - Track consecutive daemon failures
  - Show warning after 5 failures (rate-limited to 30s)
  - Show reconnection message on recovery

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 04:16:26 -08:00
Steve Yegge
fa9a88e2a3 feat: add waits-for dependency type for fanout gates (bd-xo1o.2)
Adds 'waits-for' dependency type for dynamic molecule bonding:
- DepWaitsFor blocks an issue until spawner's children are closed
- Two gate types: all-children (wait for all) or any-children (first)
- Updated blocked_cache.go CTE to handle waits-for dependencies
- Added --waits-for and --waits-for-gate flags to bd create command
- Added WaitsForMeta struct for gate metadata storage
- Full test coverage for all gate types and dynamic child scenarios

This enables patrol molecules to wait for dynamically-bonded arms to
complete before proceeding (Christmas Ornament pattern).

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 04:00:00 -08:00
Steve Yegge
be520d90fe feat: add bd activity command for real-time state feed (bd-xo1o.3)
Implements activity feed for watching molecule/issue state changes:
- bd activity: show last 100 events
- bd activity --follow: real-time streaming
- bd activity --mol <id>: filter by molecule prefix
- bd activity --since 5m: time-based filtering
- bd activity --type update: filter by event type

Adds new mutation event types for richer activity display:
- MutationBonded: molecule bonded to parent
- MutationSquashed: wisp squashed to digest
- MutationBurned: wisp discarded
- MutationStatus: status transitions with old/new state

Event symbols: + created, → in_progress, ✓ completed, ⊘ deleted, ◉ squashed

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 03:19:09 -08:00
Steve Yegge
14e1f5a2e0 feat: add --parent flag to bd list command (bd-yqhh)
Filters issues by parent issue ID using parent-child dependencies.

Example: bd list --parent=bd-xyz --status=open

Changes:
- Add ParentID field to IssueFilter type
- Add --parent flag to list command
- Forward parent filter through RPC
- Implement filtering in SQLite and memory storage

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 02:10:42 -08:00
Steve Yegge
7fb92ff78c feat: implement conditional bond type for mol bond (bd-kzda)
Conditional bonds now work as documented: "B runs only if A fails".

Implementation:
- Add DepConditionalBlocks dependency type to types.go
- Add IsFailureClose() helper to detect failure keywords in close_reason
- Update blocked cache to handle conditional-blocks:
  - B is blocked while A is open
  - B stays blocked if A closes with success
  - B becomes unblocked if A closes with failure

Failure keywords: failed, rejected, wontfix, cancelled, abandoned,
blocked, error, timeout, aborted (case-insensitive)

Updated bondProtoProto, bondProtoMol, bondMolMol to use
DepConditionalBlocks for conditional bond type.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 01:32:31 -08:00
Steve Yegge
cfe823da61 refactor: add testEnv helpers, reduce SQLite test file sizes (bd-4opy)
- Add testEnv struct with common test helper methods to test_helpers.go
- Methods include CreateIssue, CreateEpic, AddDep, AddParentChild, Close,
  GetReadyWork, AssertReady, AssertBlocked
- Migrate 12+ tests in ready_test.go to use new helpers (-252 lines)
- Migrate 3 tests in dependencies_test.go to use new helpers (-34 lines)
- Total reduction: ~286 lines from test files

The testEnv pattern makes tests more readable and maintainable by:
- Eliminating boilerplate setup (store, cleanup, ctx)
- Providing semantic helper methods (AddDep vs manual AddDependency)
- Using t.Cleanup for automatic resource management

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 01:30:06 -08:00
Steve Yegge
d677554ef3 fix: prevent parallel execution migration race conditions (GH#720)
When multiple bd commands are run in parallel, they can race during database
migrations, causing "duplicate column name" errors. This happens because:

1. Process A checks if column exists → false
2. Process B checks if column exists → false
3. Process A adds column → succeeds
4. Process B adds column → FAILS (duplicate column)

Changes:
- Wrap RunMigrations in BEGIN EXCLUSIVE transaction to serialize migrations
- Disable foreign keys BEFORE the transaction (PRAGMA must be called outside tx)
- Convert nested BEGIN/COMMIT in migrations 010, 022, 025 to use SAVEPOINTs
  (SQLite does not support nested transactions)
- Remove redundant PRAGMA foreign_keys calls from individual migrations

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 00:55:05 -08:00
Steve Yegge
9480041605 fix: skip interactions.jsonl in FindJSONLInDir (GH#709)
FindJSONLInDir() was returning interactions.jsonl when issues.jsonl
didn't exist. This caused bd sync to write issue data to the wrong
file after fresh init.

Add interactions.jsonl to the skip list alongside deletions.jsonl
and merge artifacts, so the function correctly defaults to issues.jsonl.
2025-12-22 23:37:45 -08:00
Steve Yegge
f795f61108 feat: add performance optimization indexes (bd-bha9, bd-a9y3, bd-jke6, bd-8x3w, bd-lk39)
Migration 026_additional_indexes adds 5 indexes identified during schema review (bd-h0we):

- idx_issues_updated_at: For GetStaleIssues date filtering
- idx_issues_status_priority: For common list query patterns
- idx_labels_label_issue: Covering index for label lookups
- idx_dependencies_issue_type: For blocked issues queries
- idx_events_issue_type: For close reason queries

These indexes improve query performance for common operations,
particularly at scale (10K+ issues).

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 23:16:08 -08:00
Steve Yegge
ad02b80330 feat: display external deps in bd dep tree (bd-vks2, bd-mv6h, bd-d9mu)
External dependencies (external:project:capability) are now visible in
the dependency tree output. Previously they were invisible because the
recursive CTE only JOINed against the issues table.

Changes:
- GetDependencyTree now fetches external deps and adds them as synthetic
  leaf nodes with resolution status (satisfied/blocked)
- formatTreeNode displays external deps with special formatting
- Added helper parseExternalRefParts for parsing external refs

Test coverage added for:
- External deps appearing in dependency tree
- Cycle detection ignoring external refs
- CheckExternalDep when target has no .beads directory
- Various invalid external ref format variations

Closes: bd-vks2, bd-mv6h, bd-d9mu
2025-12-22 22:34:18 -08:00
Steve Yegge
340417f393 fix: filter satisfied external deps from GetBlockedIssues (bd-396j)
GetBlockedIssues was showing external deps as blocking even when they
were satisfied (had a closed issue with provides:capability label).

Added filterBlockedByExternalDeps() which:
- Collects all external refs from blocked issues
- Checks each with CheckExternalDeps() in batch
- Filters satisfied refs from BlockedBy lists
- Updates BlockedByCount accordingly
- Removes issues with no remaining blockers (unless status=blocked/deferred)

This matches the behavior of GetReadyWork which already filters by
external deps correctly.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 21:48:55 -08:00
Steve Yegge
fc0b98730a refactor: consolidate duplicate path-finding utilities (bd-74w1, bd-4nqq)
- Add git.GetRepoRoot() with Windows path normalization
- Update beads.findGitRoot() to delegate to git.GetRepoRoot()
- Replace findBeadsDir() with beads.FindBeadsDir() across 8 files
- Remove duplicate findBeadsDir() and findGitRoot() function definitions
- Remove dead test code (TestInfoCommand, TestInfoWithNoDaemon)
- Update tests to work with consolidated APIs

Part of Code Health Review Dec 2025 epic (bd-tggf).

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 21:15:41 -08:00
Ryan Snodgrass
cafc0b9dfb refactor(doctor): consolidate maintenance commands + improve daemon startup
Consolidate clean, repair-deps, validate into bd doctor:
- Add validation checks to doctor (merge artifacts, orphaned deps, duplicates, test pollution, git conflicts)
- Add auto-fix for merge artifacts and orphaned dependencies
- Delete obsolete command files: clean.go, repair_deps.go, validate.go
- Delete orphaned test files: clean_security_test.go, validate_test.go

Improve daemon startup performance:
- Add fast-fail detection when daemon crashed (check lock before retrying)
- Reduce graceful shutdown timeout from 5s to 1s
- Skip daemon connection for root command (just shows help)
- Extract shutdown timeout as constants (daemonShutdownTimeout, daemonShutdownPollInterval)

Other changes:
- Move rename-prefix command to Maintenance group in help
- Fix Makefile to inject git commit hash via ldflags

New files:
- cmd/bd/doctor/validation.go (5 check functions)
- cmd/bd/doctor/fix/validation.go (2 fix functions)
2025-12-22 20:21:30 -08:00
Steve Yegge
c4fc27de57 Merge pull request #711 from cpdata/fix/worktree-health-check-redundancy
Reviewed by dave (beads crew worker)
2025-12-22 20:17:59 -08:00
Steve Yegge
7c24cf63bd Merge pull request #707 from cpdata/feat/auto-pull-config
Reviewed by dave (beads crew worker)
2025-12-22 20:17:54 -08:00
Steve Yegge
62bbae9c78 feat(types): add HOP entity tracking types (bd-7pwh)
- Add EntityRef type for structured entity references with URI support
- Add Creator field to Issue for tracking who created work
- Add Validation type and Validations field for proof-of-stake approvals
- Fix RemoveDependency FK violation on external deps (bd-a3sj)
- Include all new fields in content hash computation
- Full test coverage for all new types

🤝 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-22 20:10:09 -08:00
Charles P. Cross
665e5b3a87 fix(worktree): integrate health check into CreateBeadsWorktree to prevent redundant checks
The error message 'path exists but is not a valid git worktree' was appearing
in daemon.log when the daemon attempted to use an existing worktree that was
in the git worktree list but had other issues (broken sparse checkout, etc.).

Root cause:
- CreateBeadsWorktree only checked isValidWorktree (is it in git worktree list)
- CheckWorktreeHealth was called separately and checked additional things
- If the worktree passed isValidWorktree but failed health check, an error
  was logged and repair was attempted

Fix:
- CreateBeadsWorktree now performs a full health check when it finds an
  existing worktree that's in the git worktree list
- If the health check fails, it automatically removes and recreates the
  worktree
- Removed redundant CheckWorktreeHealth calls in daemon_sync_branch.go and
  syncbranch/worktree.go since CreateBeadsWorktree now handles this internally

This eliminates the confusing error message and ensures worktrees are always
in a healthy state after CreateBeadsWorktree returns successfully.
2025-12-22 18:57:43 -05:00
Charles P. Cross
03f5afb605 feat(daemon): add auto_pull config parameter for periodic remote sync
Add --auto-pull flag to control whether the daemon periodically pulls from
remote to check for updates from other clones.

Configuration precedence:
1. --auto-pull CLI flag (highest)
2. BEADS_AUTO_PULL environment variable
3. daemon.auto_pull in database config
4. Default: true when sync.branch is configured

When auto_pull is enabled, the daemon creates a remoteSyncTicker that
periodically calls doAutoImport() to pull remote changes. When disabled,
users must manually run 'git pull' to sync remote changes.

Changes:
- cmd/bd/daemon.go: Add --auto-pull flag and config reading logic
- cmd/bd/daemon_event_loop.go: Gate remoteSyncTicker on autoPull parameter
- cmd/bd/daemon_lifecycle.go: Add auto-pull to status output and spawn args
- internal/rpc/protocol.go: Add AutoPull field to StatusResponse
- internal/rpc/server_core.go: Add autoPull to Server struct and SetConfig
- internal/rpc/server_routing_validation_diagnostics.go: Include in status
- Tests updated to pass autoPull parameter

Closes #TBD
2025-12-22 18:47:18 -05:00
Charles P. Cross
737e65afbd fix(daemon): add periodic remote sync to event-driven mode (#698)
* fix(daemon): add periodic remote sync to event-driven mode

The event-driven daemon mode only triggered imports when the local JSONL
file changed (via file watcher) or when the fallback ticker fired (only
if watcher failed). This meant the daemon wouldn't see updates pushed
by other clones until something triggered a local file change.

Bug scenario:
1. Clone A creates an issue and daemon pushes to sync branch
2. Clone B's daemon only watched local file changes
3. Clone B would not see the new issue until something triggered local change
4. With this fix: Clone B's daemon periodically calls doAutoImport

This fix adds a 30-second periodic remote sync ticker that calls
doAutoImport(), which includes syncBranchPull() to fetch and import
updates from the remote sync branch.

This is essential for multi-clone workflows where:
- Clone A creates an issue and daemon pushes to sync branch
- Clone B's daemon needs to periodically pull to see the new issue
- Without periodic sync, Clone B would only see updates if its local
  JSONL file happened to change

The 30-second interval balances responsiveness with network overhead.

Adds integration test TestEventDrivenLoop_PeriodicRemoteSync that
verifies the event-driven loop starts with periodic sync support.

* feat(daemon): add configurable interval for periodic remote sync

- Add BEADS_REMOTE_SYNC_INTERVAL environment variable to configure
  the interval for periodic remote sync (default: 30s)
- Add getRemoteSyncInterval() function to parse the env var
- Minimum interval is 5s to prevent excessive load
- Setting to 0 disables periodic sync (not recommended)
- Add comprehensive integration tests for the configuration

Valid duration formats:
- "30s" (30 seconds)
- "1m" (1 minute)
- "5m" (5 minutes)

Tests added:
- TestEventDrivenLoop_HasRemoteSyncTicker
- TestGetRemoteSyncInterval_Default
- TestGetRemoteSyncInterval_CustomValue
- TestGetRemoteSyncInterval_MinimumEnforced
- TestGetRemoteSyncInterval_InvalidValue
- TestGetRemoteSyncInterval_Zero
- TestSyncBranchPull_FetchesRemoteUpdates

* fix: resolve all golangci-lint errors (cherry-pick from fix/linting-errors)

Cherry-picked linting fixes to ensure CI passes.

* feat(daemon): add config.yaml support for remote-sync-interval

- Add remote-sync-interval to .beads/config.yaml as alternative to
  BEADS_REMOTE_SYNC_INTERVAL environment variable
- Environment variable takes precedence over config.yaml (follows
  existing pattern for flush-debounce)
- Add config binding in internal/config/config.go
- Update getRemoteSyncInterval() to use config.GetDuration()
- Add doctor validation for remote-sync-interval in config.yaml

Configuration sources (in order of precedence):
1. BEADS_REMOTE_SYNC_INTERVAL environment variable
2. remote-sync-interval in .beads/config.yaml
3. DefaultRemoteSyncInterval (30s)

Example config.yaml:
  remote-sync-interval: "1m"

---------

Co-authored-by: Charles P. Cross <cpdata@users.noreply.github.com>
2025-12-22 14:15:33 -08:00
Charles P. Cross
e360a74b61 fix: resolve all golangci-lint errors (#699)
Fix 12 linting issues that were causing CI failures:

errcheck (8 fixes):
- cmd/bd/mol_burn.go: wrap wispStore.Close() in defer func
- cmd/bd/mol_burn.go: handle fmt.Scanln() return value
- cmd/bd/mol_squash.go: wrap wispStore.Close() in defer func (2 locations)
- cmd/bd/wisp.go: wrap wispStore.Close() in defer func (3 locations)
- internal/beads/beads.go: wrap mainStore.Close() and wispStore.Close()

gosec G104 (2 fixes):
- internal/storage/sqlite/multirepo.go: handle rows.Close() errors

misspell (1 fix):
- cmd/bd/mol_burn.go: change "Cancelled" to "Canceled"

unparam (1 fix):
- cmd/bd/mol_squash.go: use blank identifier for unused cmd parameter

All fixes follow existing patterns in the codebase:
- defer func() { _ = store.Close() }() for deferred closes
- _ = rows.Close() for explicit closes with ignored errors
- _, _ = fmt.Scanln() for ignored return values

Co-authored-by: Charles P. Cross <cpdata@users.noreply.github.com>
2025-12-22 14:06:45 -08:00
Steve Yegge
199def9fed release: v0.34.0
## Added
- Wisp commands - bd wisp create/list/gc for ephemeral molecule management
- Chemistry UX - bd pour, bd mol bond --wisp/--pour for phase control
- Cross-project deps - external:<repo>:<id> syntax, bd ship command
- Orphan detection in bd doctor

## Changed
- Multi-repo config uses YAML - bd repo add/remove writes to .beads/config.yaml

## Fixed
- Wisp storage auto-copies issue_prefix from main database
- Prefix validation in multi-repo mode
- Remove orphaned repo_test.go
- Update version tests for 0.34.0 thresholds

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 03:18:55 -08:00
Steve Yegge
8f8e9516df fix: bd repo commands write to YAML and cleanup on remove (#683)
- bd repo add/remove now writes to .beads/config.yaml instead of database
- bd repo remove deletes hydrated issues from the removed repo
- Added internal/config/repos.go for YAML config manipulation
- Added DeleteIssuesBySourceRepo for cleanup on remove

Fixes config disconnect where bd repo add wrote to DB but hydration read from YAML.

Breaking change: bd repo add no longer accepts optional alias argument.

Co-authored-by: Dylan Conlin <dylan.conlin@gmail.com>

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 01:26:45 -08:00
Ryan
a11b20960a fix(doctor): UX improvements for diagnostics and daemon (#687)
* fix(doctor): UX improvements for diagnostics and daemon

- Add Repo Fingerprint check to detect when database belongs to a
  different repository (copied .beads dir or git remote URL change)
- Add interactive fix for repo fingerprint with options: update repo ID,
  reinitialize database, or skip
- Add visible warning when daemon takes >5s to start, recommending
  'bd doctor' for diagnosis
- Detect install method (Homebrew vs script) and show only relevant
  upgrade command
- Improve WARNINGS section:
  - Add icons (⚠ or ✖) next to each item
  - Color numbers by severity (yellow for warnings, red for errors)
  - Render entire error lines in red
  - Sort by severity (errors first)
  - Fix alignment with checkmarks above
- Use heavier fail icon (✖) for better visibility
- Add integration and validation tests for doctor fixes

* fix(lint): address errcheck and gosec warnings

- mol_bond.go: explicitly ignore ephStore.Close() error
- beads.go: add nosec for .gitignore file permissions (0644 is standard)
2025-12-22 01:25:23 -08:00