Commit Graph

87 Commits

Author SHA1 Message Date
Test
0a9bcc2dd0 /internal/importer/importer_test.go: remove skipped tests 2026-01-21 13:40:06 -08:00
Test
b849f598d7 /{cmd,docs,internal}: support import export for dolt backends 2026-01-21 13:13:24 -08:00
dennis
1f59119144 fix(sync): use town-level routes for prefix validation
Follow-up to 828fc11b addressing code review feedback:

1. Added LoadTownRoutes() - exported function that walks up to find
   town-level routes.jsonl (e.g., ~/gt/.beads/routes.jsonl)

2. Updated buildAllowedPrefixSet to use LoadTownRoutes instead of
   LoadRoutes, so it finds routes even when importing from a rig's
   local beads directory

3. Added unit tests for buildAllowedPrefixSet covering:
   - Primary prefix inclusion
   - allowed_prefixes config parsing
   - Routes from routes.jsonl
   - Missing routes.jsonl handling
   - Empty beadsDir handling

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 09:51:46 -08:00
dennis
828fc11b57 fix(sync): allow routed prefixes in import validation
When importing issues in a multi-rig setup (Gas Town), the prefix
validation was failing for issues with prefixes from other rigs
(e.g., hq-* prefixes from town-level beads).

This fix extends buildAllowedPrefixSet to also load prefixes from
routes.jsonl, allowing issues from any routed rig to pass validation.

Fixes: gt-2maz79

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-17 03:45:02 -08:00
dennis
f703237c3d fix(ready): prevent wisps from appearing in bd ready
Add multiple layers of defense against misclassified wisps:
- Importer auto-detects -wisp- pattern and sets ephemeral flag
- GetReadyWork excludes -wisp- IDs via SQL LIKE clause
- Doctor check 26d detects misclassified wisps in JSONL

This addresses recurring issue where wisps with missing ephemeral
flag would pollute bd ready output after JSONL import.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 00:14:12 -08:00
emma
4468ff030f feat(sync): add BD_DEBUG_SYNC env for protection debugging
Adds debug logging when timestamp-aware protection triggers, controlled
by BD_DEBUG_SYNC environment variable. Helps diagnose sync issues.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 10:41:57 -08:00
emma
62e4eaf7c1 fix(sync): make snapshot protection timestamp-aware (GH#865)
The --protect-left-snapshot mechanism was protecting ALL local issues
by ID alone, ignoring timestamps. This caused newer remote changes to
be incorrectly skipped during cross-worktree sync.

Changes:
- Add BuildIDToTimestampMap() to SnapshotManager for timestamp-aware
  snapshot reading
- Change ProtectLocalExportIDs from map[string]bool to map[string]time.Time
- Add shouldProtectFromUpdate() helper that compares timestamps
- Only protect if local snapshot is newer than incoming; allow update
  if incoming is newer

This fixes data loss scenarios where:
1. Main worktree closes issue at 11:31
2. Test worktree syncs and incorrectly skips the update
3. Test worktree then pushes stale open state, overwriting mains changes

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 13:27:36 -08:00
Steve Yegge
f46cc2e798 chore: remove issue ID references from comments and changelogs
Strip (bd-xxx), (gt-xxx) suffixes from code comments and changelog
entries. The descriptions remain meaningful without the ephemeral
issue IDs.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 10:05:16 -08:00
Steve Yegge
25402184a6 fix: respect allowed_prefixes config during import (gt-2z6s)
The buildAllowedPrefixSet function now parses the allowed_prefixes config
and includes those prefixes when validating imports. This allows mol-*
prefixes to be imported without errors when configured.

Config example: bd config set allowed_prefixes "gt-,mol-"
2025-12-24 14:28:23 -08:00
Steve Yegge
9743b45c6d fix(import): preserve comment created_at timestamps during import (#735)
Comment timestamps were being overwritten with CURRENT_TIMESTAMP during
import, causing infinite sync loops between hosts as each import would
update timestamps.

Added ImportIssueComment() method that accepts and preserves the original
timestamp from JSONL, and updated importComments() to use it.

Closes #735
2025-12-24 12:45:20 -08:00
Steve Yegge
e67f27c092 bd sync: 2025-12-23 23:38:57 2025-12-24 00:06:41 -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
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
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
Gero Hillebrandt
9d30e80fdf fix: skip prefix validation in multi-repo mode (GH#686) (#688)
Issues from additional repos have their own prefixes, which is expected.
Skip validation when multi-repo config is present.
2025-12-22 01:25:19 -08:00
Steve Yegge
5d2daf2e1e fix(pin): add 'pinned' field to allowed update fields (gt-zr0a)
The 'bd pin' command was failing with "invalid field for update: pinned"
because the pinned field was missing from allowedUpdateFields.

Fixes:
- Add 'pinned' to allowedUpdateFields in queries.go
- Update importer to include pinned field in updates during import
- Add equalBool comparator for IssueDataChanged to detect pinned changes
- Fix stats query to count pinned=1 instead of status='pinned'
- Fix pinIndicator in list.go to check issue.Pinned instead of status

This unblocks gt mail --pinned functionality.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 19:57:16 -08:00
Justin Williams
df5ceb5d82 feat: Linear Integration (#655)
* Add Linear integration CLI with sync and status commands

- Add `bd linear sync` for bidirectional issue sync with Linear
- Add `bd linear status` to show configuration and sync state
- Stub pull/push functions pending GraphQL client (bd-b6b.2)

* Implement Linear GraphQL client with full sync support

- Add LinearClient with auth, fetch, create, update methods
- Implement pull/push operations with Beads type mapping
- Clean up redundant comments and remove unused code

* Add configurable data mapping and dependency sync for Linear

- Add LinearMappingConfig with configurable priority/state/label/relation maps
- Import parent-child and issue relations as Beads dependencies
- Support custom workflow states via linear.state_map.* config

* Add incremental sync support for Linear integration

- Add FetchIssuesSince() method using updatedAt filter in GraphQL
- Check linear.last_sync config to enable incremental pulls
- Track sync mode (incremental vs full) in LinearPullStats

* feat(linear): implement push updates for existing Linear issues

Add FetchIssueByIdentifier method to retrieve single issues by identifier
(e.g., "TEAM-123") for timestamp comparison during push.

Update doPushToLinear to:
- Fetch Linear issue to get internal ID and UpdatedAt timestamp
- Compare timestamps: only update if local is newer
- Build update payload with title, description, priority, and state
- Call UpdateIssue for issues where local has newer changes

Closes bd-b6b.5

* Implement Linear conflict resolution strategies

- Add true conflict detection by fetching Linear timestamps via API
- Implement --prefer-linear resolution (re-import from Linear)
- Implement timestamp-based resolution (newer wins as default)
- Fix linter issues: handle resp.Body.Close() and remove unused error return

* Add Linear integration tests and documentation

- Add comprehensive unit tests for Linear mapping (priority, state, labels, relations)
- Update docs/CONFIG.md with Linear configuration reference
- Add examples/linear-workflow guide for bidirectional sync
- Remove AI section header comments from tests

* Fix Linear GraphQL filter construction and improve test coverage

- Refactor filter handling to combine team ID into main filter object
- Add test for duplicate issue relation mapping
- Add HTTP round-trip helper for testing request payload validation

* Refactor Linear queries to use shared constant and add UUID validation

- Extract linearIssuesQuery to deduplicate FetchIssues/FetchIssuesSince
- Add linearMaxPageSize constant and UUID validation with regex
- Expand test coverage for new functionality

* Refactor Linear integration into internal/linear package

- Extract types, client, and mapping logic from cmd/bd/linear.go
- Create internal/linear/ package for better code organization
- Update tests to work with new package structure

* Add linear teams command to list available teams

- Add FetchTeams GraphQL query to Linear client
- Refactor config reading to support daemon mode
- Add tests for teams listing functionality

* Refactor Linear config to use getLinearConfig helper

- Consolidate config/env var lookup using getLinearConfig function
- Add LINEAR_TEAM_ID environment variable support
- Update error messages to include env var configuration options

* Add hash ID generation and improve Linear conflict detection

- Add configurable hash ID mode for Linear imports (matches bd/Jira)
- Improve conflict detection with content hash comparison
- Enhance conflict resolution with skip/force update tracking

* Fix test for updated doPushToLinear signature

- Add missing skipUpdateIDs parameter to test call
2025-12-19 17:58:24 -08:00
Steve Yegge
8b0cd1ec66 refactor(import): remove redundant pre-batch deduplication layer
The early ID deduplication in the main loop (seenIDs check) already
prevents duplicate IDs from reaching newIssues. The pre-batch
deduplication was dead code that could never fire.

Keeping two layers:
1. Early dedup in main loop - catches duplicates in JSONL input
2. INSERT OR IGNORE at DB level - safety net for all code paths

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 11:09:26 -08:00
Marco Del Pin
dba9bb91c3 fix(import): handle duplicate issue IDs in JSONL files gracefully
Implements three-layer deduplication strategy to prevent UNIQUE
constraint errors during import:
1. Early deduplication during processing (importer.go)
2. Pre-batch deduplication (importer.go)
3. INSERT OR IGNORE with explicit error handling (issues.go)
**Problem:**
JSONL files with duplicate issue IDs caused import failures:
  Import failed: UNIQUE constraint failed: issues.id
**Root Cause:**
- Go SQLite driver returns errors even with INSERT OR IGNORE
- Only content hash was deduplicated, not IDs
- Multiple code paths affected (insertIssue, insertIssues)
**Solution:**
Layer 1: Early deduplication by ID in upsertIssues (lines 489-502)
Layer 2: Pre-batch deduplication (lines 713-726)
Layer 3: INSERT OR IGNORE + isUniqueConstraintError() helper
**Testing:**
- Multiple production databases tested
- 9 duplicates handled successfully
- 100% success rate on v0.30.5 databases
- Zero UNIQUE constraint errors
**Impact:**
- Enables importing JSONL with duplicate IDs
- Duplicate count shown in import statistics
- No breaking changes, backward compatible
🤖 Generated with Claude Code
2025-12-18 19:26:29 +01:00
Steve Yegge
0ce039429d fix: tombstone/deletion overhaul for bd-4q8
- IsExpired(): Negative TTL means immediately expired (for --hard mode)
- IsExpired(): ClockSkewGrace only added for TTLs > 1 hour
- bd cleanup --hard: Use negative TTL to prune freshly created tombstones
- bd delete --hard: New flag to immediately prune tombstones from JSONL
- Import: Add early tombstone check before all phases to prevent resurrection

The early tombstone check prevents ghost issues from being created when
tombstones exist in the DB. However, a deeper git merge issue (bd-ncwo)
can still cause resurrection when remote's status:closed wins the merge.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 22:01:31 -08:00
Steve Yegge
d3b0cbb8b8 chore: bump version to 0.30.2
- Update version in version.go, default.nix, hook templates
- Add CHANGELOG.md entry for v0.30.2
- Add v0.30.1 and v0.30.2 to versionChanges in info.go
- Remove stale internal/deletions import from integration test
  (fixes CI failure from bd-fom refactor)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 16:47:43 -08:00
Steve Yegge
9f76cfda01 refactor: remove all deletions.jsonl code (bd-fom)
Complete removal of the legacy deletions.jsonl manifest system.
Tombstones are now the sole deletion mechanism.

Removed:
- internal/deletions/ - entire package
- cmd/bd/deleted.go - deleted command
- cmd/bd/doctor/fix/deletions.go - HydrateDeletionsManifest
- Tests for all removed functionality

Cleaned:
- cmd/bd/sync.go - removed sanitize, auto-compact
- cmd/bd/delete.go - removed dual-writes
- cmd/bd/doctor.go - removed checkDeletionsManifest
- internal/importer/importer.go - removed deletions checks
- internal/syncbranch/worktree.go - removed deletions merge
- cmd/bd/integrity.go - updated validation (warn-only on decrease)

Files removed: 12
Lines removed: ~7500

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 14:20:49 -08:00
Steve Yegge
2c86404d65 fix: resolve P2 sync noise and cleanup issues
- bd-6pni: Auto-filter tombstoned issues with mismatched prefixes during
  import instead of failing. Tombstones from contributor PRs with different
  test prefixes are pollution and safe to ignore.

- bd-ffr9: Stop recreating deletions.jsonl after tombstone migration.
  Added IsTombstoneMigrationComplete() check to all code paths that write
  to the legacy deletions manifest.

- bd-admx: Fix perpetual "JSONL file hash mismatch" warning. Now clears
  both export_hashes AND jsonl_file_hash when mismatch detected, so the
  warning doesn't repeat.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 00:56:06 -08:00
Steve Yegge
8c45069228 fix(doctor,sync): clean up deletions manifest and reduce sync noise
- bd-8v5o: When doctor --fix hydrates issues from git history, also
  remove them from the deletions manifest to prevent perpetual skip
  warnings during sync

- bd-wsqt: Remove verbose per-issue "Skipping bd-xxx" messages during
  sync. Caller already shows summary of skipped issues.

Added RemoveDeletions() function to deletions package with tests.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 00:42:36 -08:00
Ryan Snodgrass
627ac1afb8 fix(import): skip cross-prefix content matches instead of triggering rename
When importing issues, if an incoming issue has the same content hash as an
existing issue but a DIFFERENT prefix, this should not be treated as a rename.
Cross-prefix content matches occur when importing issues from other projects
that happen to have identical content.

Previously, the importer would call handleRename which tries to create an issue
with the incoming prefix, failing prefix validation ("does not match configured
prefix" error).

The fix checks if prefixes differ before calling handleRename:
- Same prefix, different ID suffix → true rename, call handleRename
- Different prefix → skip incoming issue, keep existing unchanged

Added test: TestImportCrossPrefixContentMatch reproduces the bug scenario
where alpha-* issues exist but beta-* issues are imported with same content.
2025-12-16 00:29:19 -08:00
Ryan Snodgrass
421d41dfa0 docs: add detailed comments explaining ID formats and merge deletion logic
Document the intent and nuances of recent fixes:

internal/importer/utils.go:
- RenameImportedIssuePrefixes: explain the three ID formats (sequential,
  hash-based, hierarchical) and how prefix renaming preserves identity
- isValidIDSuffix: document why dots are allowed (hierarchical parent-child
  relationships) and what characters are rejected

cmd/bd/deletion_tracking.go:
- isIssueNotFoundError: explain why "not found" is success during merge
  (issue may be tombstoned, never existed locally, or manually deleted)
- Deletion loop: document what "accepted deletions" means and why we
  tolerate missing issues during the pruning phase
2025-12-16 00:17:40 -08:00
Ryan Snodgrass
c7b45a8a40 fix(import): support hierarchical hash IDs in --rename-on-import
The isNumeric function was rejecting valid hierarchical hash IDs like
'6we.2' that contain dots for parent.child notation. This caused
`bd import --rename-on-import` to fail with "non-numeric suffix" errors.

Changes:
- Rename isNumeric to isValidIDSuffix for clarity
- Accept dots (.) in addition to alphanumeric for hierarchical IDs
- Update test cases to cover hierarchical ID formats
2025-12-16 00:12:10 -08:00
matt wilkie
cd3b0e30be bd-ckej: fix orphan skip count mismatch on fresh import (#572)
* bd-ckej: fix orphan skip count mismatch on fresh import

When OrphanSkip mode is used during import and a child issue's parent doesn't
exist, the issue ID was cleared to '' but then regenerated anyway in
GenerateBatchIssueIDs, causing it to be created in the database. This resulted
in a count mismatch: JSONL had 824 issues but only 823 were in the database (one
orphan was counted but not created).

Fix: Filter out orphaned issues with empty IDs before batch creation and track
them in result.Skipped so the count stays accurate.

* test: add TestImportOrphanSkip_CountMismatch for bd-ckej

Adds comprehensive test that verifies orphaned issues are properly skipped
during import when orphan_handling=OrphanSkip and parent doesn't exist.

Also improves the fix to pre-filter orphaned issues before batch creation,
ensuring they're not inserted then have IDs cleared (preventing count
mismatches).

---------

Co-authored-by: Amp <amp@example.com>
2025-12-15 21:17:32 -08:00
Steve Yegge
8e58c306a7 fix(sync,blocked): add safety guards for issue deletion and include status=blocked in bd blocked
GH#464: Add safety guards to prevent deletion of open/in_progress issues during sync:
- Safety guard in git-history-backfill (importer.go)
- Safety guard in deletions manifest processing
- Warning when uncommitted changes detected before pull (daemon_sync.go)
- Enhanced repo ID mismatch error message

GH#545: Fix bd blocked to show status=blocked issues (sqlite/ready.go):
- Changed from INNER JOIN to LEFT JOIN to include issues without dependencies
- Added WHERE clause to include both status=blocked AND dependency-blocked issues

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 23:07:54 -08:00
Steve Yegge
a612c575f9 fix(sync): include tombstones when building ID map during import
The importer was not seeing tombstones when building the dbByID map,
causing it to treat tombstone IDs as "new" issues. This led to UNIQUE
constraint violations during INSERT.

- Include tombstones in SearchIssues call (IncludeTombstones: true)
- Skip tombstones when matching by ID instead of trying to update them

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 10:20:22 -08:00
Rod Davenport
6985ea94e5 fix(sync): protect local issues from git-history-backfill during sync (#485)
Fix sync bug where newly created issues were incorrectly tombstoned during bd sync.

The root cause was git-history-backfill finding issues in local commits on the sync branch, then tombstoning them when they weren't in the merged JSONL. The fix protects issues from the left snapshot (local export) from git-history-backfill.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2025-12-12 13:28:48 -08:00
Steve Yegge
24917f27c2 fix(importer): use zero for unknown priority in convertDeletionToTombstone (bd-9auw)
Changed Priority from hardcoded 2 to 0 (unset) to distinguish legacy tombstones
from user-set values. IssueType remains TypeTask as empty fails validation.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 21:20:00 +11:00
Steve Yegge
711dd9ccd4 feat(importer): add ConvertedToTombstone counter (bd-wucl)
Track legacy deletions.jsonl entries converted to tombstones during import:
- Add Result.ConvertedToTombstone counter
- Add Result.ConvertedTombstoneIDs for the converted IDs
- Update test to verify the new counter

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 21:18:17 +11:00
Steve Yegge
32f646a303 test(tombstones): add unit tests for tombstone functionality (bd-fmo, bd-hp0m)
- Add TestIsExpiredTombstone with edge cases for merge package
- Add TestImportIssues_LegacyDeletionsConvertedToTombstones for importer

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 21:16:23 +11:00
Steve Yegge
f4864c9cc4 feat(import/export): add tombstone support (bd-dve)
Update import/export to handle tombstones for deletion sync propagation:

Exporter:
- Include tombstones in JSONL output by setting IncludeTombstones: true
- Both single-repo and multi-repo exports now include tombstones

Importer:
- Tombstones from JSONL are imported as-is (they're issues with status=tombstone)
- Legacy deletions.jsonl entries are converted to tombstones via convertDeletionToTombstone()
- Non-tombstone issues in deletions manifest are still skipped (backward compat)
- purgeDeletedIssues() now creates tombstones instead of hard-deleting

This is Phase 2 of the tombstone implementation (bd-dli design), enabling
inline soft-delete tracking for cross-clone deletion synchronization.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 20:34:02 +11:00
Steve Yegge
8d19e75431 fix: add safety guard to prevent git-history-backfill mass deletion (bd-t5m)
When a clone gets reset (git reset --hard origin/main), the
git-history-backfill logic was incorrectly marking ALL issues as
deleted since they appeared in git history but not in the current
JSONL. This caused the entire database to be purged.

Fix:
- Add 50% threshold check: abort if git-history-backfill would delete
  more than 50% of issues (likely a reset scenario, not deletions)
- Add warning when >10 issues would be deleted via backfill
- Print helpful message about manual deletion if needed

Test:
- Added TestMassDeletionSafetyGuard that simulates JSONL reset and
  verifies the safety guard prevents mass deletion

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 21:26:16 -08:00
Steve Yegge
f7dea354d8 fix(import): add warning when issues are skipped due to deletions manifest
When importing JSONL that contains issues in the deletions manifest,
import now:
- Filters out deleted issues before import
- Prints per-issue warning with deletion details (date, actor)
- Shows count of skipped issues in summary
- Suggests --ignore-deletions flag to force import

The new --ignore-deletions flag allows importing issues that are in the
deletions manifest, useful for recovering accidentally deleted issues.

Fixes bd-4zy

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 21:23:04 -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
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
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
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
3a0446c431 Fix test compilation errors: add context.Background() to sqlite.New() calls
Updated all test files to pass context.Background() as the first parameter
to sqlite.New() calls to match the updated function signature.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 14:57:18 -05:00
Steve Yegge
1168f661d1 fix: Add context.Background() to sqlite.New() calls in test files
Multiple test files were still using the old sqlite.New(path) signature
instead of the new sqlite.New(ctx, path) signature. This was causing
compilation failures in the test suite.

Fixed files:
- internal/importer/importer_test.go
- internal/importer/external_ref_test.go
- internal/importer/timestamp_test.go
- internal/rpc/limits_test.go
- internal/rpc/list_filters_test.go
- internal/rpc/rpc_test.go
- internal/rpc/status_test.go
- internal/syncbranch/syncbranch_test.go
2025-11-21 14:48:41 -05:00