Commit Graph

456 Commits

Author SHA1 Message Date
Shaun Cutts
3a2e9d5852 fix(multirepo): handle out-of-order dependencies during JSONL import (#414)
* bd sync: 2025-11-29 00:08:58

* fix(multirepo): handle out-of-order dependencies during JSONL import

Fixes #413. When importing issues from multi-repo JSONL files, if issue A
(line 1) has a dependency on issue B (line 5), the import would fail with
FK constraint error because B doesn't exist yet.

Solution:
- Disable FK checks at start of importJSONLFile()
- Re-enable FK checks before commit
- Run PRAGMA foreign_key_check to validate data integrity
- Fail with clear error if orphaned dependencies are detected

This allows out-of-order dependencies while still catching corrupted data.

---------

Co-authored-by: Shaun Cutts <shauncutts@factfiber.com>
2025-11-29 22:07:52 -08:00
Steve Yegge
8becf0d9b9 fix: handle multi-hyphen prefixes with hash IDs (#419)
Fixed bug where issue IDs with multiple hyphens in the prefix and hash
suffixes were incorrectly parsed. For example, `web-app-a3f8e9` was
being parsed with prefix `web-` instead of `web-app`.

Root cause: ExtractIssuePrefix() only checked for numeric suffixes.
When it encountered a hash suffix, it fell back to using the first
hyphen instead of the last hyphen.

Changes:
- Added isLikelyHash() helper to detect hexadecimal hash suffixes (4-8 chars)
- Updated ExtractIssuePrefix() to handle both numeric and hash suffixes
- Added comprehensive test cases for various prefix patterns

Test coverage includes:
- web-app-123 (numeric suffix)
- web-app-a3f8e9 (hash suffix)
- my-cool-app-a3f8e9 (three-part prefix with hash)
- super-long-project-name-1a2b (four-part prefix)
- Various hash lengths and case variations

Co-authored-by: dubstylee <dubstylee@users.noreply.github.com>

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 15:05:25 -08:00
Steve Yegge
a5ec5c6977 feat(bd-1pj6): Add custom status states via config
Users can now define custom status states for multi-step pipelines using:
  bd config set status.custom "awaiting_review,awaiting_testing,awaiting_docs"

Changes:
- Add Status.IsValidWithCustom() method for custom status validation
- Add Issue.ValidateWithCustomStatuses() method
- Add GetCustomStatuses() method to storage interface
- Update CreateIssue/UpdateIssue to support custom statuses
- Add comprehensive tests for custom status functionality
- Update config command help text with custom status documentation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 23:19:21 -08:00
Steve Yegge
f59f8c20d0 refactor: rename last_import_hash to jsonl_content_hash (bd-39o)
The metadata key 'last_import_hash' was misleading because it's updated on
both import AND export. Renamed to 'jsonl_content_hash' which more accurately
describes its purpose - tracking the content hash of the JSONL file.

Added migration support: read operations try new key first, then fall back
to old key for backwards compatibility with existing databases.

Files modified:
- cmd/bd/integrity.go: Update key name with migration support
- cmd/bd/import.go: Update key name
- cmd/bd/sync.go: Update key name
- cmd/bd/autoflush.go: Update key name with migration support
- cmd/bd/daemon_sync.go: Update key name
- cmd/bd/daemon_event_loop.go: Update key name with migration support
- internal/autoimport/autoimport.go: Update key name with migration support
- Updated all related tests

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 23:14:12 -08:00
Steve Yegge
40b07045c7 refactor: deduplicate FindJSONLInDir function (bd-8a5)
Extract shared JSONL file discovery logic to internal/utils/path.go.
Both autoimport and beads packages now use this shared implementation.

Changes:
- Add utils.FindJSONLInDir with common logic
- Update autoimport.go to use utils.FindJSONLInDir
- Update beads.go to delegate to utils.FindJSONLInDir
- Update server_export_import_auto.go to use utils.FindJSONLInDir
- Move FindJSONLInDir test to utils/path_test.go
- Fix pre-existing duplicate countIssuesInJSONLFile in init.go

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 23:07:53 -08:00
Steve Yegge
6f9d8d3add bd-c8x: Stop searching parent directories at git root
Directory discovery (FindBeadsDir, findDatabaseInTree, FindAllDatabases)
now stops at the git repository root to avoid finding unrelated databases
in parent directories (e.g., ~/.beads).

Added findGitRoot() helper that uses 'git rev-parse --show-toplevel'.

Also updated TestCheckDatabaseVersionJSONLMode to properly simulate
no-db mode by creating config.yaml with 'no-db: true'.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 22:16:11 -08:00
Steve Yegge
247672be54 test: improve coverage for config and git packages
- config: Add tests for GetStringSlice, GetMultiRepoConfig, and nil viper
  behavior. Coverage improved from 65.3% to 84.0%.
- git: Add tests for error paths in RemoveBeadsWorktree, SyncJSONLToWorktree,
  CheckWorktreeHealth, and sparse checkout functions. Coverage improved
  from 72.9% to 82.7%.

Closes: bd-t3b, bd-4h3, bd-ge7

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:56:52 -08:00
Steve Yegge
03fa119e85 Add close reason display for closed issues
- Add CloseReason field to Issue struct
- Add GetCloseReason and GetCloseReasonsForIssues queries
- Batch-load close reasons in scanIssues for efficiency
- Display close reason in bd show output

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 17:36:01 -08:00
Steve Yegge
774a57684c Fix auto-import git history backfill bug (bd-4pv)
Auto-import was allowing git history backfill to run, which could
incorrectly purge issues. The fix adds NoGitHistory=true to all
auto-import code paths:
- autoimport.go (importFromGit)
- autoflush.go (autoImportIfNewer)
- daemon_sync.go (importToJSONLWithStore)

Git history backfill is designed to detect deletions that happened
after a local DB was created. During auto-import, there is no local
work to protect - we are importing from the authoritative JSONL source.

Also adds comprehensive tests for NoGitHistory behavior.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 22:51:39 -08:00
Steve Yegge
22d34a22dc Fix bd migrate loop: skip prefix validation during auto-import
When auto-importing issues from JSONL, issues with different prefixes
(e.g., gt-1 vs gastown-) would fail validation and cause an infinite
loop of failed migrations.

The fix adds SkipPrefixValidation option to CreateIssuesWithFullOptions
which propagates through EnsureIDs to skip prefix validation for issues
that already have IDs during import. This allows importing issues with
any prefix while still validating new issues created interactively.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 21:45:42 -08:00
Steve Yegge
1d5fd64383 fix(daemon): add cross-process locking to registry (bd-5bj)
The global daemon registry (~/.beads/registry.json) could be corrupted
when multiple daemons from different workspaces wrote simultaneously.

Changes:
- Add file locking (flock) for cross-process synchronization
- Use atomic writes (temp file + rename) to prevent partial writes
- Keep entire read-modify-write cycle under single lock
- Add FlockExclusiveBlocking and FlockUnlock to lockfile package

This prevents race conditions that caused JSON corruption like `]]`.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 14:22:42 -08:00
Steve Yegge
cdc156428c fix(staleness): use RFC3339Nano precision for last_import_time (#399)
The staleness check compares last_import_time against JSONL file mtime.
File mtime has nanosecond precision, but last_import_time was stored with
only second precision (RFC3339). This caused a race condition where the
stored time could be slightly earlier than the file mtime, triggering
false "Database out of sync" errors - particularly in git worktrees.

Changed all 6 locations that set last_import_time to use RFC3339Nano.
The CheckStaleness parser already handles both formats, so this is
backward compatible.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 00:11:01 -08:00
Steve Yegge
d51ddb0b03 fix(beads): also fix FindJSONLPath to skip deletions.jsonl (bd-tqo)
Code review follow-up:
- Fix misleading docstring in FindJSONLInDir (does not return empty)
- Fix same bug in beads.FindJSONLPath (also fell back to matches[0])
- Add comprehensive tests for FindJSONLPath skipping deletions

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 23:44:04 -08:00
Steve Yegge
887c958567 fix(autoimport): prevent export to wrong JSONL file (bd-tqo)
Add FindJSONLInDir helper that correctly prefers issues.jsonl over other
.jsonl files. Previously, glob patterns could return deletions.jsonl or
merge artifacts (beads.base.jsonl, etc.) first alphabetically, causing
issue data to be written to the wrong file.

This fixes the root cause of deletions.jsonl corruption where full issue
objects were written instead of deletion records, leading to all issues
being purged during sync.

Changes:
- Add FindJSONLInDir() in internal/autoimport with proper file selection
- Update AutoImportIfNewer() to use FindJSONLInDir
- Update CheckStaleness() to use FindJSONLInDir
- Update triggerExport() in RPC server to use FindJSONLInDir
- Add comprehensive tests for FindJSONLInDir

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 23:25:32 -08:00
Steve Yegge
5506486dc5 feat(import,sync): add --no-git-history flag to prevent spurious deletions
Fixes bd-0b2: The git history backfill mechanism was causing data loss
during JSONL filename migrations (beads.jsonl → issues.jsonl). When issues
existed in the old filename's git history, the backfill incorrectly treated
them as "deleted" and purged them from the database.

Changes:
- Add NoGitHistory field to importer.Options and ImportOptions structs
- Modify purgeDeletedIssues() to skip git history check when flag is set
- Add --no-git-history flag to bd import command
- Add --no-git-history flag to bd sync command
- Update purge_test.go to pass Options argument

Usage:
  bd import -i .beads/issues.jsonl --no-git-history
  bd sync --no-git-history

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 23:10:43 -08:00
Steve Yegge
ff3352ab23 bd-6xd: Standardize on issues.jsonl as canonical filename
- Change default JSONL filename from beads.jsonl to issues.jsonl
- Add bd doctor check and fix to auto-migrate legacy beads.jsonl configs
- Update FindJSONLPath to prefer issues.jsonl over beads.jsonl
- Add CheckLegacyJSONLConfig and CheckLegacyJSONLFilename checks
- Add LegacyJSONLConfig fix to rename files and update config
- Update .gitattributes to reference issues.jsonl
- Fix tests to expect new canonical filename
- Add bd-6xd to v0.25.1 release notes

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 22:02:59 -08:00
Steve Yegge
fe6de0a73f fix: CI test failures on Windows
- TestVersionChangesCoverage: Add missing 3rd changelog entry for v0.25.1
- TestDefaultPath: Use filepath.Join for cross-platform path handling
- TestDebouncer_CancelWithNoPendingAction: Increase sleep from 60ms to 100ms
  to account for Windows timer imprecision

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 20:59:07 -08:00
Steve Yegge
d0bb0ad7d4 fix: staleness check fails after write in git worktrees (#399)
After write operations in git worktrees, subsequent reads failed with
"Database out of sync with JSONL" even though the hash check passed.

Root cause: flushToJSONLWithState() updated last_import_hash but not
last_import_time after export. CheckStaleness() compares last_import_time
against JSONL mtime, so after export the JSONL appeared "newer" than the
last import.

Additional issue: RFC3339 only has second precision but file mtimes have
nanosecond precision, causing false positives when times were within the
same second.

Fix:
- Update last_import_time after export in flushToJSONLWithState()
- Use RFC3339Nano format for nanosecond precision
- Update CheckStaleness() to parse both formats for backward compatibility

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 19:04:57 -08:00
Kris Hansen
9931ac9bd9 fix: support multi-part prefixes in issue ID extraction (#398) 2025-11-26 17:42:14 -08:00
Steve Yegge
352b9f7e6b bd sync: 2025-11-26 11:14:59 2025-11-26 11:14:59 -08:00
Steve Yegge
7d765c228b refactor: extract path canonicalization and database search helpers
- Use utils.CanonicalizePath for BEADS_DB and findDatabaseInTree results
  instead of inline filepath.Abs + filepath.EvalSymlinks (bd-736d)
- Extract findDatabaseInBeadsDir helper function that consolidates the
  database search logic used by both FindDatabasePath and findDatabaseInTree,
  with optional warnings for ambiguous/legacy states (bd-c362)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 22:27:54 -08:00
Steve Yegge
ddced40153 fix: add nosec annotations for gosec lint warnings 2025-11-25 18:22:05 -08:00
Steve Yegge
4088e68da7 feat(deletions): complete deletions manifest epic with integration tests
Completes the deletion propagation epic (bd-imj) with all 9 subtasks:
- Cross-clone deletion propagation via deletions.jsonl
- bd deleted command for audit trail
- Auto-compact during sync (opt-in)
- Git history fallback with timeout and regex escaping
- JSON output for pruning results
- Integration tests for deletion scenarios
- Documentation in AGENTS.md, README.md, and docs/DELETIONS.md

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 16:36:46 -08:00
Steve Yegge
4898c424aa feat(deletions): auto-compact during sync and git history fallback fixes
- Add Count function to deletions package for fast line counting
- Add maybeAutoCompactDeletions to sync (opt-in via deletions.auto_compact config)
- Fix regex escaping in batchCheckGitHistory (bd-bgs)
- Add 30s timeout to git history commands (bd-f0n)
- Use git rev-parse --show-toplevel for proper repo root detection (bd-bhd)
- Add tests for Count and auto-compact functionality

Closes: bd-qsm, bd-bgs, bd-f0n, bd-bhd
2025-11-25 15:08:12 -08:00
Steve Yegge
3f84ec3774 feat(deletions): add pruning and git history fallback
Implements two P1 tasks for the deletions manifest epic:

bd-v2x: Add deletions pruning to bd compact
- PruneDeletions function removes records older than retention period
- Default retention: 7 days (configurable via metadata.json)
- CLI --retention flag for override
- Atomic file rewrite prevents corruption
- Called automatically during all compact operations

bd-pnm: Add git history fallback for pruned deletions
- Catches deletions where manifest entry was pruned
- Uses git log -S to search for ID in JSONL history
- Batches multiple IDs for efficiency (git -G regex)
- Self-healing: backfills manifest on hit
- Conservative: keeps issue if git check fails (shallow clone)

Tests added for both features with edge cases covered.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 12:41:36 -08:00
Steve Yegge
be784a0b4b bd sync: 2025-11-25 11:46:06 2025-11-25 11:46:06 -08:00
Steve Yegge
d1d7b0e34a refactor(deletions): improve API based on code review
- Return LoadResult struct instead of multiple values, with Warnings slice
  for testability (no more hardcoded stderr output)
- Add ID validation in AppendDeletion to prevent invalid records
- Add Sync() call in AppendDeletion for durability
- Document that timestamps may lose sub-second precision
- Document that empty slice in WriteDeletions clears all deletions
- Add test for empty ID validation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 11:30:41 -08:00
Steve Yegge
a7f63c6925 bd sync: 2025-11-25 10:59:11 2025-11-25 10:59:11 -08:00
Steve Yegge
a3103d3e59 fix: update last_import_time when hash matches but mtime is newer
When JSONL mtime changes without content change (e.g., git pull, touch),
the staleness check would repeatedly trigger but auto-import would skip
due to hash match, creating an infinite loop of "Database out of sync"
errors.

Now we update last_import_time even when skipping import due to hash
match, breaking the staleness loop.

Fixes #378

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 10:47:24 -08:00
Steve Yegge
4f4b59aba5 fix: prevent internal fields from being exported to JSONL
ContentHash and SourceRepo were being exported to beads.jsonl even though
they are internal database fields. This caused JSONL pollution where every
issue got these extra fields, and re-exports would produce different output
than the original clean JSONL.

Changed JSON tags from `json:"...,omitempty"` to `json:"-"` for:
- ContentHash: Internal optimization field for content-based diffing
- SourceRepo: Internal metadata for multi-repo support

This fixes the ZFC resurrection bug where re-exports after import would
pollute the JSONL with internal fields.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 00:21:28 -08:00
Steve Yegge
ef93b31a74 Export Transaction type for atomic multi-operation support
Add Transaction type alias to both internal/beads and public beads packages.
This allows extensions like VC to use RunInTransaction() with the proper
Transaction interface type for atomic issue creation.

bd-m73k

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 22:55:55 -08:00
Steve Yegge
071fc96206 fix: resolve golangci-lint errors
- Add error check for fmt.Fprintf in tips.go (errcheck)
- Add nolint for safe SQL formatting in transaction.go (gosec G201)
- Fix 'cancelled' -> 'canceled' spelling (misspell)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 22:21:55 -08:00
Steve Yegge
a6990a85ba fix: code review fixes for Transaction API and Search (epic bd-8bq)
- Add safe type assertions in applyUpdatesToIssue (bd-4gs)
- Add --sort and --reverse flags to bd search (bd-4f6)
- Add test cases for SearchIssues priority range, date range, IDs (bd-ew5)
- Handle errors from GetLabelsForIssues in search.go (bd-lce)
- Standardize error wrapping to fmt.Errorf pattern (bd-7kl)
- Extract shared scanIssueRow helper function (bd-ajf)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 20:45:04 -08:00
Steve Yegge
d2f3762969 bd sync: 2025-11-24 20:26:24 2025-11-24 20:26:24 -08:00
Steve Yegge
b453db8832 bd sync: 2025-11-24 20:20:43 2025-11-24 20:20:43 -08:00
Steve Yegge
a8d7d6575c Fix blocked cache invalidation in transaction operations (bd-1c4h)
Transaction operations weren't invalidating the blocked_issues_cache,
causing GetReadyWork to return stale results after transactional changes.

Changes:
- Refactor invalidateBlockedCache to accept execer interface (supports
  both *sql.Tx and *sql.Conn)
- Add cache invalidation in transaction.go for:
  - UpdateIssue (when status changes)
  - CloseIssue (always - closed issues don't block
  - AddDependency (for DepBlocks/DepParentChild types)
  - RemoveDependency (queries type before deletion)

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

Co-Authored-By: Claude <noreply@anthropic.com>
EOF
)
2025-11-24 14:03:11 -08:00
Steve Yegge
0acd9d0a5d bd sync: 2025-11-24 12:25:34 2025-11-24 12:25:35 -08:00
Steve Yegge
fcd6ca694e Document blocked_issues_cache architecture and behavior
Add comprehensive documentation for the blocked_issues_cache optimization
that improved GetReadyWork performance from 752ms to 29ms (25x speedup).

Documentation locations:
- blocked_cache.go: Detailed package comment covering architecture,
  invalidation strategy, transaction safety, edge cases, and future
  optimizations
- ready.go: Enhanced comment at query site explaining the optimization
  and maintenance triggers
- ARCHITECTURE.md: New section with diagrams, blocking semantics,
  performance characteristics, and testing instructions

Closes bd-1w6i

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 01:14:21 -08:00
Steve Yegge
125d02860c Implement transaction retry logic for SQLITE_BUSY (bd-ola6)
Add exponential backoff retry for BEGIN IMMEDIATE transactions to handle
concurrent write load without spurious failures.

Changes:
- Add IsBusyError() helper to detect database locked errors
- Add beginImmediateWithRetry() with exponential backoff (10ms, 20ms, 40ms, 80ms, 160ms)
- Update CreateIssue and CreateIssuesInBatch to use retry logic
- Add comprehensive tests for error detection and retry behavior
- Handles context cancellation between retry attempts
- Fails fast on non-busy errors

This eliminates spurious SQLITE_BUSY failures under normal concurrent usage
while maintaining proper error handling for other failure modes.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 01:10:16 -08:00
Steve Yegge
55fdaf99e7 Centralize error handling patterns in storage layer (bd-bwk2)
Standardized error handling across the SQLite storage layer by
consistently using wrapDBError() helper functions that were already
defined in errors.go.

Changes:
- config.go: Applied wrapDBError to all config/metadata functions
- queries.go: Fixed bare 'return err' in CreateIssue, UpdateIssue, DeleteIssues
- store.go: Changed %v to %w for proper error chain preservation
- errors_test.go: Added comprehensive test coverage for error wrapping

All error paths now:
- Wrap errors with operation context using %w
- Convert sql.ErrNoRows to ErrNotFound consistently
- Preserve error chains for unwrapping and type checking

This improves debugging by maintaining operation context throughout
the error chain and enables type-safe error checking with sentinel
errors.

All tests passing ✓

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 00:59:49 -08:00
Steve Yegge
528f27c053 Add orphan detection migration (bd-3852)
Creates migration to detect orphaned child issues and logs them for user
action. Orphaned children are issues with hierarchical IDs (e.g., "parent.child")
where the parent issue no longer exists in the database.

The migration:
- Queries for issues with IDs like '%.%' where parent doesn't exist
- Logs detected orphans with suggested actions (delete, convert, or restore)
- Does NOT automatically delete or convert orphans
- Is idempotent and safe to run multiple times

Test coverage:
- Detects orphaned child issues correctly
- Handles clean databases with no orphans
- Verifies idempotency

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 00:34:26 -08:00
Steve Yegge
76e3f27eb0 fix: CI test failures and lint errors
- Fixed test file naming: issues.jsonl -> beads.jsonl
  - beads_test.go: Update expected path in TestFindJSONLPath
  - internal/beads/beads_test.go: Update TestFindJSONLPathDefault
  - cmd/bd/main_test.go: Update TestAutoFlushJSONLContent

- Fixed lint errors (gosec):
  - G304: Added nosec comments for file operations with user-provided paths
  - G204: Added nosec comment for subprocess with controlled binary path

- Fixed lint errors (errcheck):
  - cmd/bd/test_wait_helper.go: Acknowledge error return values with _
  - cmd/bd/onboard.go: Handle fmt.Fprintf error return

All tests passing locally. All lint checks passing.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 00:21:01 -08:00
Steve Yegge
d45cff5085 feat: Handle FOREIGN KEY constraint violations gracefully during import (bd-koab)
When importing JSONL after merges that include deletions, FK constraint
violations can occur if an issue references a deleted issue. Previously,
import would fail completely. Now it continues and reports skipped dependencies.

Changes:
- Add SkippedDependencies field to Result/ImportResult structs
- Update importDependencies() to detect FK violations using IsForeignKeyConstraintError()
- Log warnings for each skipped dependency with issue IDs and type
- Continue importing remaining dependencies instead of failing
- Display summary of all skipped dependencies at end of import

Example output:
  Warning: Skipping dependency due to missing reference: bd-b → bd-a (blocks)

  ⚠️  Warning: Skipped 2 dependencies due to missing references:
    - bd-b → bd-a (blocks)
    - bd-c → bd-a (parent-child)

  This can happen after merges that delete issues referenced by other issues.
  The import continued successfully - you may want to review the skipped dependencies.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 23:32:34 -08:00
Steve Yegge
d1641c7d2e Fix bd-afd: Auto-fix metadata.json jsonl_export mismatch
## Summary

When metadata.json gets deleted (git clean, merge conflict, rebase), the
version tracking code auto-recreates it using DefaultConfig() which hardcoded
jsonl_export to 'issues.jsonl'. But many repos (including beads itself) use
'beads.jsonl', causing a mismatch between config and actual JSONL file.

## Changes

1. **bd doctor --fix auto-detection** (cmd/bd/doctor/fix/database_config.go)
   - New DatabaseConfig() fix function that auto-detects actual JSONL file
   - Prefers beads.jsonl over issues.jsonl (canonical name)
   - Skips backup files and merge artifacts
   - Wired into doctor.go applyFixes()

2. **Version tracking auto-detection** (cmd/bd/version_tracking.go)
   - trackBdVersion() now scans for existing JSONL files before defaulting
   - Prevents mismatches when metadata.json gets recreated
   - Added findActualJSONLFile() helper function

3. **Canonical default name** (internal/configfile/configfile.go)
   - DefaultConfig() changed from issues.jsonl to beads.jsonl
   - Aligns with canonical naming convention

4. **FindJSONLPath preference** (internal/beads/beads.go)
   - Now prefers beads.jsonl over issues.jsonl when scanning
   - Default changed from issues.jsonl to beads.jsonl

5. **Test coverage**
   - Added comprehensive tests for DatabaseConfig fix
   - Updated configfile tests for new default
   - Verified backup file skipping logic

## Testing

- All existing tests pass
- New tests verify auto-fix behavior
- Integration tested with simulated mismatches

Closes: bd-afd
2025-11-23 23:11:08 -08:00
Steve Yegge
153f724e95 Fix Windows CI test failures
Two Windows-specific test failures:

1. TestNewSQLiteStorage - File locking on temp cleanup
   - Windows couldn't delete temp database file because connection was still open
   - Added defer store.Close() to properly cleanup the database connection
   - Without this, Windows file locking prevents TempDir cleanup

2. TestFindAllDatabases - Unexpected nil slice return
   - FindAllDatabases could return nil instead of empty slice when os.Getwd() fails
   - Changed from var databases to explicit empty slice initialization
   - Ensures function always returns non-nil slice, matching test expectations

Both issues are more pronounced on Windows due to stricter file locking
and different filesystem behavior.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 23:01:55 -08:00
Steve Yegge
0e6ed91f2e Add explicit cache validation tests for blocked_issues_cache
Implements bd-13gm with 8 comprehensive tests that verify cache
invalidation behavior:

- Cache updates when blocking dependencies added/removed
- Cache updates when issue status changes (close/reopen)
- Cache consistency across multiple operations
- Parent-child transitive blocking propagates to cache
- Related dependencies don't affect cache
- Deep hierarchies handled correctly
- Multiple blockers handled correctly

Tests directly query blocked_issues_cache table to verify implementation
correctness, complementing existing behavior tests in ready_test.go.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 22:05:23 -08:00
Steve Yegge
d4f9a05bb2 Fix bd-pq5k: merge conflicts now prefer closed>open and deletion>modification
CHANGES:
1. Merge logic (internal/merge/merge.go):
   - Added mergeStatus() enforcing closed ALWAYS wins over open
   - Fixed closed_at handling: only set when status='closed'
   - Changed deletion handling: deletion ALWAYS wins over modification

2. Deletion tracking (cmd/bd/snapshot_manager.go):
   - Updated ComputeAcceptedDeletions to accept all merge deletions
   - Removed "unchanged locally" check (deletion wins regardless)

3. FK constraint helper (internal/storage/sqlite/util.go):
   - Added IsForeignKeyConstraintError() for bd-koab
   - Detects FK violations for graceful import handling

TESTS UPDATED:
- TestMergeStatus: comprehensive status merge tests
- TestIsForeignKeyConstraintError: FK constraint detection
- bd-pq5k test: validates no invalid state (status=open with closed_at)
- Deletion tests: reflect new deletion-wins behavior
- All tests pass ✓

This ensures issues never get stuck in invalid states and prevents
the insane situation where issues never die!

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 21:42:43 -08:00
Steve Yegge
18f81051f3 Fix race condition in client socket cleanup (bd-4owj)
- Re-check socket existence after lock check to avoid stale socket state
- If socket is initially missing but daemon lock is held, re-check socket to handle daemon startup race
- Add test TestTryConnectWithTimeout_SocketExistenceRecheck to verify fix

Fixes bd-4owj
2025-11-23 20:58:11 -08:00
Steve Yegge
b75914b8ca Fix: Improve staleness check error handling (bd-2q6d, bd-o4qy, bd-n4td)
Changes:
- CheckStaleness now returns errors for corrupted last_import_time metadata
  instead of silently returning false (bd-o4qy)
- Added handling for empty string metadata (memory store behavior)
- Enhanced warning messages when staleness check fails to be more explicit
  that operation continues with potentially stale data (bd-n4td)
- Added test coverage for corrupted metadata scenario

Closes bd-2q6d, bd-o4qy, bd-n4td

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 20:54:18 -08:00
Steve Yegge
273a4d1cfc feat: Complete command set standardization (bd-au0)
Epic bd-au0: Command Set Standardization & Flag Consistency

Completed all 10 child issues:

P0 tasks:
- Standardize --dry-run flag across all commands (bd-au0.1)
- Add label operations to bd update (bd-au0.2)
- Fix --title vs --title-contains redundancy (bd-au0.3)
- Standardize priority flag parsing (bd-au0.4)

P1 tasks:
- Add date/priority filters to bd search (bd-au0.5)
- Add comprehensive filters to bd export (bd-au0.6)
- Audit and standardize JSON output (bd-au0.7)

P2 tasks:
- Improve clean vs cleanup documentation (bd-au0.8)
- Document rarely-used commands (bd-au0.9)

P3 tasks:
- Add global verbosity flags --verbose/-v and --quiet/-q (bd-au0.10)

Key changes:
- export.go: Added filters (assignee, type, labels, priority, dates)
- main.go: Added --verbose/-v and --quiet/-q global flags
- debug.go: Added SetVerbose/SetQuiet and PrintNormal helpers
- clean.go/cleanup.go: Improved documentation with cross-references
- detect_pollution.go: Added use cases and warnings
- migrate_hash_ids.go: Marked as legacy command
- rename_prefix.go: Added use cases documentation

All success criteria met: flags standardized, feature parity achieved,
naming clarified, JSON output consistent.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 20:33:31 -08:00