diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 6651f334..2c5fa041 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -42,12 +42,12 @@ {"id":"bd-6rf","title":"bd doctor: detect and fix stale beads-sync branch","description":"## Problem\n\nWhen beads-sync diverges significantly from main (on source code, not just .beads/), it needs to be reset. After a force-push reset, other clones/contributors will have orphaned local beads-sync branches.\n\n## Symptoms\n- Local beads-sync is many commits behind main on source files\n- Local beads-sync doesn't share recent history with remote beads-sync (after force-push)\n- bd sync may behave unexpectedly\n\n## Proposed bd doctor checks\n\n1. **Check beads-sync alignment with main**\n - If beads-sync exists and is \u003eN commits behind main on non-.beads/ files, warn\n - Suggests: reset beads-sync to main\n\n2. **Check beads-sync alignment with remote**\n - If local beads-sync has diverged from origin/beads-sync (no common recent ancestor)\n - This happens after someone force-pushed a reset\n - Suggests: reset local beads-sync to origin/beads-sync\n\n## Proposed fixes (--fix)\n\n- Reset local beads-sync branch to origin/beads-sync or main\n- Handle worktree if present (git worktree remove, then recreate on next sync)\n\n## Context\nDiscovered when beads-sync drifted 126 commits behind main. Required manual reset and force-push. Contributors will need to reset their local branches too.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-02T23:45:40.607538-08:00","updated_at":"2025-12-03T22:13:21.727319-08:00","closed_at":"2025-12-03T22:13:21.727319-08:00"} {"id":"bd-6rl","title":"Merge3Way public API does not expose TTL parameter","description":"The public Merge3Way() function in merge.go does not allow callers to configure the tombstone TTL. It hard-codes the default via merge3WayWithTTL(). While merge3WayWithTTL() exists, it is unexported (lowercase). This means the CLI and tests cannot configure TTL at merge time. Use cases: testing with different TTL values, per-repository TTL configuration, debugging with short TTL, supporting --ttl flag in bd merge command (mentioned in design doc bd-zvg). Recommendation: Export Merge3WayWithTTL (rename to uppercase). Files: internal/merge/merge.go:77, 292-298","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-05T16:36:15.756814-08:00","updated_at":"2025-12-05T16:36:15.756814-08:00"} {"id":"bd-6x5","title":"mergeTombstones does not handle empty DeletedAt timestamps","description":"The mergeTombstones() function uses isTimeAfter() to compare deleted_at timestamps, but does not handle the edge case where one or both tombstones have empty DeletedAt fields. Current behavior with isTimeAfter() semantics: empty string returns false when compared, which means if left.DeletedAt is empty, right wins. If both are empty, behavior depends on isTimeAfter tie-breaker. This should be explicitly handled with a comment or validation. Recommendation: Add explicit handling or documentation for invalid tombstones. Files: internal/merge/merge.go:448-456","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-05T16:36:43.002612-08:00","updated_at":"2025-12-05T17:15:57.633147-08:00","closed_at":"2025-12-05T17:15:57.633147-08:00"} -{"id":"bd-6y5","title":"Add unit tests for getLocalSyncBranch","description":"The new getLocalSyncBranch() function in autoimport.go (bd-0is fix) has no dedicated unit tests.\n\nShould test:\n- Returns empty string when no config.yaml exists\n- Returns empty string when config.yaml has no sync-branch key\n- Returns value when sync-branch is set with double quotes\n- Returns value when sync-branch is set with single quotes\n- Returns value when sync-branch is set without quotes\n- Returns BEADS_SYNC_BRANCH env var when set (takes precedence)\n- Handles edge cases: empty file, whitespace-only lines, comments\n\nLocation: cmd/bd/autoimport_test.go","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-05T14:51:07.129329-08:00","updated_at":"2025-12-05T14:51:07.129329-08:00"} +{"id":"bd-6y5","title":"Add unit tests for getLocalSyncBranch","description":"The new getLocalSyncBranch() function in autoimport.go (bd-0is fix) has no dedicated unit tests.\n\nShould test:\n- Returns empty string when no config.yaml exists\n- Returns empty string when config.yaml has no sync-branch key\n- Returns value when sync-branch is set with double quotes\n- Returns value when sync-branch is set with single quotes\n- Returns value when sync-branch is set without quotes\n- Returns BEADS_SYNC_BRANCH env var when set (takes precedence)\n- Handles edge cases: empty file, whitespace-only lines, comments\n\nLocation: cmd/bd/autoimport_test.go","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-05T14:51:07.129329-08:00","updated_at":"2025-12-07T01:57:11.69579-08:00","closed_at":"2025-12-07T01:57:11.69579-08:00"} {"id":"bd-736d","title":"Refactor path canonicalization into helper function","description":"The path canonicalization logic (filepath.Abs + EvalSymlinks) is duplicated in 3 places:\n- beads.go:131-137 (BEADS_DIR handling)\n- cmd/bd/main.go:446-451 (--no-db cleanup)\n- cmd/bd/nodb.go:26-31 (--no-db initialization)\n\nRefactoring suggestion:\nExtract to a helper function like:\n func canonicalizePath(path string) string\n\nThis would:\n- Reduce code duplication\n- Make the logic easier to maintain\n- Ensure consistent behavior across all path handling\n\nRelated to bd-e16b implementation.","status":"closed","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:33:47.727443-08:00","updated_at":"2025-11-25T22:27:33.738672-08:00","closed_at":"2025-11-25T22:27:33.738672-08:00"} {"id":"bd-73u","title":"Refactor daemon local-only sync functions to reduce duplication","description":"PR #433 added three new local-only sync functions (createLocalSyncFunc, createLocalExportFunc, createLocalAutoImportFunc) that are largely copy-paste of existing ones with git operations removed. Refactor to use a single implementation with a skipGit bool parameter or extract shared logic into helper functions to reduce ~200 lines of duplication.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-01T17:38:02.632264-08:00","updated_at":"2025-12-02T23:28:48.752202-08:00","closed_at":"2025-12-01T21:08:11.952459-08:00"} {"id":"bd-7ch","title":"Auto-push after merge with safety check","description":"Make bd sync a true one-command solution by auto-pushing after successful content merge.\n\nBehavior:\n- After successful content merge, auto-push by default\n- Safety check: detect when \u003e50% issues vanished AND \u003e5 existed before\n- On safety check trigger: warn but still push (do not block happy path)\n\nVanished means issues removed from issues.jsonl entirely, NOT status=closed (closed is legitimate swarm completion).\n\nLocation: internal/syncbranch/worktree.go\nParent issue: bd-3s8","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-02T19:30:59.540636-08:00","updated_at":"2025-12-03T22:12:25.328091-08:00","closed_at":"2025-12-03T22:12:25.328091-08:00"} {"id":"bd-81a","title":"Add programmatic tip injection API","description":"Allow tips to be programmatically injected at runtime based on detected conditions. This enables dynamic tips (not just pre-defined ones) to be shown with custom priority and frequency.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:29:46.645583-08:00","updated_at":"2025-11-25T17:52:35.096882-08:00","closed_at":"2025-11-25T17:52:35.096882-08:00","dependencies":[{"issue_id":"bd-81a","depends_on_id":"bd-d4i","type":"blocks","created_at":"2025-11-11T23:29:46.646327-08:00","created_by":"daemon"}]} -{"id":"bd-81x6","title":"Tombstone export includes tombstones even with --status filter","description":"In export.go, we set IncludeTombstones: true unconditionally. However, if a user runs:\n\n bd export --status=open\n\nThey might not expect tombstones in the output. The IncludeTombstones flag should probably only be set when no status filter is specified, or when --status=tombstone is explicitly requested.\n\nCurrent behavior: exports tombstones regardless of status filter\nExpected behavior: respect status filter, only include tombstones when explicitly requested or no filter","status":"open","priority":2,"issue_type":"bug","created_at":"2025-12-07T01:40:52.762758-08:00","updated_at":"2025-12-07T01:40:52.762758-08:00","dependencies":[{"issue_id":"bd-81x6","depends_on_id":"bd-dve","type":"blocks","created_at":"2025-12-07T01:41:28.320845-08:00","created_by":"daemon"}]} +{"id":"bd-81x6","title":"Tombstone export includes tombstones even with --status filter","description":"In export.go, we set IncludeTombstones: true unconditionally. However, if a user runs:\n\n bd export --status=open\n\nThey might not expect tombstones in the output. The IncludeTombstones flag should probably only be set when no status filter is specified, or when --status=tombstone is explicitly requested.\n\nCurrent behavior: exports tombstones regardless of status filter\nExpected behavior: respect status filter, only include tombstones when explicitly requested or no filter","status":"in_progress","priority":2,"issue_type":"bug","created_at":"2025-12-07T01:40:52.762758-08:00","updated_at":"2025-12-07T01:55:47.446247-08:00","dependencies":[{"issue_id":"bd-81x6","depends_on_id":"bd-dve","type":"blocks","created_at":"2025-12-07T01:41:28.320845-08:00","created_by":"daemon"}]} {"id":"bd-8a5","title":"Refactor: deduplicate FindJSONLInDir and FindJSONLPath","description":"## Background\n\nAfter fixing bd-tqo, we now have two nearly identical functions for finding the JSONL file:\n- `autoimport.FindJSONLInDir(dbDir string)` in internal/autoimport/autoimport.go\n- `beads.FindJSONLPath(dbPath string)` in internal/beads/beads.go\n\nBoth implement the same logic:\n1. Prefer issues.jsonl\n2. Fall back to beads.jsonl for legacy support\n3. Skip deletions.jsonl and merge artifacts\n4. Default to issues.jsonl if nothing found\n\n## Problem\n\nCode duplication means bug fixes need to be applied in multiple places (as we just experienced with bd-tqo).\n\n## Proposed Solution\n\nExtract shared logic to a utility package that both can import. Options:\n1. Create `internal/jsonlpath` package with the core logic\n2. Have `autoimport` import `beads` and call `FindJSONLPath` (but APIs differ slightly)\n3. Move to `internal/utils` if appropriate\n\nNeed to verify no import cycles would be created.\n\n## Affected Files\n- internal/autoimport/autoimport.go\n- internal/beads/beads.go","status":"closed","priority":4,"issue_type":"task","created_at":"2025-11-26T23:45:18.974339-08:00","updated_at":"2025-12-02T17:11:19.733265251-05:00","closed_at":"2025-11-28T23:07:08.912247-08:00"} {"id":"bd-8an","title":"bd import auto-detects wrong prefix from directory name instead of issue IDs","description":"When importing issues.jsonl into a fresh database, 'bd import' prints:\n\n ✓ Initialized database with prefix 'beads' (detected from issues)\n\nBut the issues all have prefix 'bd-' (e.g., bd-03r). It appears to be detecting the prefix from the directory name (.beads/) rather than from the actual issue IDs in the JSONL.\n\nThis causes import to fail with:\n validate ID prefix for bd-03r: issue ID 'bd-03r' does not match configured prefix 'beads'\n\nWorkaround: Run 'bd config set issue_prefix bd' before import, or use 'bd init --prefix bd'.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-26T22:28:01.582564-08:00","updated_at":"2025-12-02T17:11:19.734136748-05:00","closed_at":"2025-11-27T22:38:48.971617-08:00"} {"id":"bd-8f9","title":"Add bd migrate-tombstones command","description":"Create migration command to convert existing deletions.jsonl entries to tombstones. Support --dry-run and --verbose flags. Archive old file with .migrated suffix. Per design bd-dli.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-05T15:14:45.098831-08:00","updated_at":"2025-12-05T15:14:45.098831-08:00","dependencies":[{"issue_id":"bd-8f9","depends_on_id":"bd-dve","type":"blocks","created_at":"2025-12-05T15:14:58.968329-08:00","created_by":"daemon"}]} diff --git a/cmd/bd/export.go b/cmd/bd/export.go index 403cd459..4b0db3b8 100644 --- a/cmd/bd/export.go +++ b/cmd/bd/export.go @@ -179,11 +179,19 @@ Examples: labelsAny = util.NormalizeLabels(labelsAny) // Build filter - // Include tombstones in export for sync propagation (bd-dve) - filter := types.IssueFilter{IncludeTombstones: true} + // Tombstone export logic (bd-81x6): + // - No status filter → include tombstones for sync propagation + // - --status=tombstone → include only tombstones (filter handles this) + // - --status= → exclude tombstones (user wants specific status) + filter := types.IssueFilter{} if statusFilter != "" { status := types.Status(statusFilter) filter.Status = &status + // Only include tombstones if explicitly filtering for them + filter.IncludeTombstones = (status == types.StatusTombstone) + } else { + // No status filter: include tombstones for sync propagation (bd-dve) + filter.IncludeTombstones = true } if assignee != "" { filter.Assignee = &assignee