Add GitHub Issues migration script (bd-68)

- New gh2jsonl.py script supports GitHub API and JSON file import
- Maps GitHub labels to bd priority/type/status
- Preserves metadata, assignees, timestamps, external refs
- Auto-detects cross-references and creates dependencies
- Production-ready: User-Agent, rate limit handling, UTF-8 support
- Comprehensive README with examples and troubleshooting
- Tested and reviewed

Amp-Thread-ID: https://ampcode.com/threads/T-2fc85f05-302b-4fc9-8cac-63ac0e03c9af
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Steve Yegge
2025-10-17 23:55:51 -07:00
parent 9fb46d41b8
commit 56a379dc5a
5 changed files with 744 additions and 6 deletions

View File

@@ -36,9 +36,7 @@
{"id":"bd-132","title":"Batch test 1","description":"","status":"open","priority":3,"issue_type":"task","created_at":"2025-10-17T21:01:21.047341-07:00","updated_at":"2025-10-17T21:01:21.047341-07:00"}
{"id":"bd-133","title":"Batch test 2","description":"","status":"open","priority":3,"issue_type":"task","created_at":"2025-10-17T21:01:21.055026-07:00","updated_at":"2025-10-17T21:01:21.055026-07:00"}
{"id":"bd-134","title":"Batch test 3","description":"","status":"open","priority":3,"issue_type":"task","created_at":"2025-10-17T21:01:21.055526-07:00","updated_at":"2025-10-17T21:01:21.055526-07:00"}
{"id":"bd-139","title":"Child issue","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-17T21:01:25.104232-07:00","updated_at":"2025-10-17T21:01:25.104232-07:00"}
{"id":"bd-14","title":"Add --resolve-collisions flag and user reporting","description":"Add import flags: --resolve-collisions (auto-fix) and --dry-run (preview). Display clear report: collisions detected, remappings applied (old→new with scores), reference counts updated. Default behavior: fail on collision (safe).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.645323-07:00","closed_at":"2025-10-16T10:07:34.003238-07:00","dependencies":[{"issue_id":"bd-14","depends_on_id":"bd-48","type":"parent-child","created_at":"2025-10-16T21:51:08.923374-07:00","created_by":"renumber"}]}
{"id":"bd-144","title":"Parent with desc","description":"See [deleted:bd-143] for details","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-17T21:11:37.608527-07:00","updated_at":"2025-10-17T21:11:42.32958-07:00"}
{"id":"bd-148","title":"bd list shows 0 issues despite database containing 115 issues","description":"When running 'bd list --status all' it shows 'Found 0 issues' even though 'bd stats' shows 115 total issues and 'sqlite3 .beads/vc.db \"SELECT COUNT(*) FROM issues\"' returns 115.\n\nReproduction:\n1. cd ~/src/vc/vc\n2. bd stats # Shows 115 issues\n3. bd list --status all # Shows 0 issues\n4. sqlite3 .beads/vc.db 'SELECT COUNT(*) FROM issues;' # Shows 115\n\nExpected: bd list should show all 115 issues\nActual: Shows 'Found 0 issues:'\n\nThis occurs with both /opt/homebrew/bin/bd (v0.9.9) and ~/src/vc/adar/beads/bd (v0.9.10)","design":"Possible causes:\n- Default filter excluding all issues\n- Database query issue in list command\n- Auto-discovery finding wrong database (but stats works?)\n- Recent deletion operation corrupted some index","acceptance_criteria":"bd list --status all shows all issues that bd stats counts","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-10-17T21:19:08.225181-07:00","updated_at":"2025-10-17T21:55:40.788625-07:00","closed_at":"2025-10-17T21:55:40.788625-07:00"}
{"id":"bd-149","title":"Confusing version mismatch warnings with contradictory messages","description":"The version mismatch warning shows contradictory messages depending on which binary version is used:\n\nWhen using v0.9.10 binary with v0.9.9 database:\n'Your bd binary (v0.9.10) differs from the database version (v0.9.9)'\n'Your binary appears to be OUTDATED.'\n\nWhen using v0.9.9 binary with v0.9.10 database:\n'Your bd binary (v0.9.9) differs from the database version (v0.9.10)'\n'Your binary appears NEWER than the database.'\n\nThe first message is incorrect - v0.9.10 \u003e v0.9.9, so the binary is NEWER, not outdated.\n\nReproduction:\n1. Use ~/src/vc/adar/beads/bd (v0.9.10) with a v0.9.9 database\n2. Observe warning says binary is OUTDATED when it's actually newer\n\nExpected: Correct version comparison\nActual: Inverted comparison logic","design":"Fix version comparison in warning message generation. Should compare semantic versions correctly.","acceptance_criteria":"Warning correctly identifies which component (binary vs database) is newer/older","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-17T21:19:19.540274-07:00","updated_at":"2025-10-17T22:14:27.015397-07:00","closed_at":"2025-10-17T22:14:27.015397-07:00"}
{"id":"bd-15","title":"Write comprehensive collision resolution tests","description":"Test cases: simple collision, multiple collisions, dependency updates, text reference updates, chain dependencies, edge cases (partial ID matches, case sensitivity, triple merges). Add to import_test.go and collision_test.go.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.647268-07:00","closed_at":"2025-10-16T10:07:34.007864-07:00","dependencies":[{"issue_id":"bd-15","depends_on_id":"bd-48","type":"parent-child","created_at":"2025-10-16T21:51:08.917092-07:00","created_by":"renumber"}]}
@@ -51,8 +49,6 @@
{"id":"bd-159","title":"Global daemon still requires database and runs sync loop","description":"The --global flag skips git repo check (line 80) but runDaemonLoop still calls FindDatabasePath (line 500-507) and opens a store (line 512). It also runs the single-repo sync loop (lines 563-620).\n\nOracle correctly identified this violates the spec: 'Don't require being in a git repo when --global is used'.\n\nFix: Global mode should skip DB open and sync loop entirely. It should be a pure RPC router that uses per-request context (bd-115) to route to the correct repo's DB.\n\nImpact: Users can't run 'bd daemon --global' outside a repo, defeating the purpose.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-17T22:58:02.138008-07:00","updated_at":"2025-10-17T23:00:08.734632-07:00","closed_at":"2025-10-17T23:00:08.734632-07:00"}
{"id":"bd-16","title":"Update documentation for collision resolution","description":"Update README.md with collision resolution section. Update CLAUDE.md with new workflow. Document --resolve-collisions and --dry-run flags. Add example scenarios showing branch merge workflows.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.648113-07:00","closed_at":"2025-10-16T10:07:34.028648-07:00","dependencies":[{"issue_id":"bd-16","depends_on_id":"bd-48","type":"parent-child","created_at":"2025-10-16T21:51:08.924312-07:00","created_by":"renumber"}]}
{"id":"bd-160","title":"Global daemon should warn/reject --auto-commit and --auto-push","description":"When user runs 'bd daemon --global --auto-commit', it's unclear which repo the daemon will commit to (especially after fixing bd-122 where global daemon won't open a DB).\n\nOptions:\n1. Warn and ignore the flags in global mode\n2. Error out with clear message\n\nLine 87-91 already checks autoPush, but should skip check entirely for global mode. Add user-friendly messaging about flag incompatibility.","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-10-17T22:58:02.137987-07:00","updated_at":"2025-10-17T23:04:30.223432-07:00","closed_at":"2025-10-17T23:04:30.223432-07:00"}
{"id":"bd-161","title":"Test A","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-17T23:06:55.010454-07:00","updated_at":"2025-10-17T23:06:55.010454-07:00"}
{"id":"bd-162","title":"Test B","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-17T23:06:55.060581-07:00","updated_at":"2025-10-17T23:06:55.060581-07:00"}
{"id":"bd-163","title":"Test A","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-17T23:06:59.59343-07:00","updated_at":"2025-10-17T23:06:59.740704-07:00","closed_at":"2025-10-17T23:06:59.740704-07:00","dependencies":[{"issue_id":"bd-163","depends_on_id":"bd-164","type":"blocks","created_at":"2025-10-17T23:06:59.668292-07:00","created_by":"daemon"}]}
{"id":"bd-164","title":"Test B","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-17T23:06:59.626612-07:00","updated_at":"2025-10-17T23:06:59.744519-07:00","closed_at":"2025-10-17T23:06:59.744519-07:00"}
{"id":"bd-17","title":"bd should auto-detect .beads/*.db in current directory","description":"When bd is run without --db flag, it defaults to beads' own database instead of looking for a .beads/*.db file in the current working directory. This causes confusion when working on other projects that use beads for issue tracking (like vc).\n\nExpected behavior: bd should search for .beads/*.db in cwd and use that if found, before falling back to default beads database.\n\nExample: Running 'bd ready' in /Users/stevey/src/vc/vc/ should automatically find and use .beads/vc.db without requiring --db flag every time.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.650584-07:00","closed_at":"2025-10-16T10:07:34.046944-07:00"}
@@ -111,14 +107,14 @@
{"id":"bd-65","title":"Test label dirty tracking","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.898188-07:00","closed_at":"2025-10-14T14:37:52.155733-07:00"}
{"id":"bd-66","title":"Test issue","description":"Testing prefix","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.902423-07:00","closed_at":"2025-10-14T13:39:55.828804-07:00","dependencies":[{"issue_id":"bd-66","depends_on_id":"bd-47","type":"parent-child","created_at":"2025-10-16T21:51:08.914487-07:00","created_by":"renumber"}]}
{"id":"bd-67","title":"Test hash-based import","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.905866-07:00","closed_at":"2025-10-14T13:39:56.958248-07:00"}
{"id":"bd-68","title":"Add migration scripts for GitHub Issues","description":"Create scripts to import from GitHub Issues API or exported JSON","status":"open","priority":2,"issue_type":"feature","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.91077-07:00","dependencies":[{"issue_id":"bd-68","depends_on_id":"bd-47","type":"parent-child","created_at":"2025-10-16T21:51:08.915539-07:00","created_by":"renumber"}]}
{"id":"bd-68","title":"Add migration scripts for GitHub Issues","description":"Create scripts to import from GitHub Issues API or exported JSON","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T23:51:47.390748-07:00","closed_at":"2025-10-17T23:51:47.390748-07:00","dependencies":[{"issue_id":"bd-68","depends_on_id":"bd-47","type":"parent-child","created_at":"2025-10-16T21:51:08.915539-07:00","created_by":"renumber"}]}
{"id":"bd-69","title":"Add test for deep hierarchy blocking (50+ levels)","description":"Current tests verify 2-level depth (grandparent → parent → child). The depth limit is hardcoded to 50 in the recursive CTE, but we don't test edge cases near that limit.\n\n**Test cases needed:**\n1. Verify 50-level deep hierarchy works correctly\n2. Verify depth limit prevents runaway recursion\n3. Measure performance impact of deep hierarchies\n4. Consider if 50 is the right limit (why not 100? why not 20?)\n\n**Rationale:**\n- Most hierarchies are 2-5 levels deep\n- But pathological cases (malicious or accidental) could create 50+ level nesting\n- Need to ensure graceful degradation, not catastrophic failure\n\n**Implementation:**\nAdd TestDeepHierarchyBlocking to ready_test.go","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.915131-07:00","closed_at":"2025-10-14T13:12:16.610152-07:00"}
{"id":"bd-7","title":"Test auto-export timing","description":"","status":"open","priority":4,"issue_type":"task","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.599423-07:00"}
{"id":"bd-70","title":"Document hierarchical blocking behavior in README","description":"The fix for bd-65 changes user-visible behavior: children of blocked epics are now automatically blocked.\n\n**What needs documenting:**\n1. README.md dependency section should explain blocking propagation\n2. Clarify that 'blocks' + 'parent-child' together create transitive blocking\n3. Note that 'related' and 'discovered-from' do NOT propagate blocking\n4. Add example showing epic → child blocking propagation\n\n**Example to add:**\n```bash\n# If epic is blocked, children are too\nbd create \"Epic 1\" -t epic -p 1\nbd create \"Task 1\" -t task -p 1\nbd dep add task-1 epic-1 --type parent-child\n\n# Block the epic\nbd create \"Blocker\" -t task -p 0\nbd dep add epic-1 blocker-1 --type blocks\n\n# Now both epic-1 AND task-1 are blocked\nbd ready # Neither will show up\n```","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:01.020334-07:00","closed_at":"2025-10-14T13:10:38.482538-07:00"}
{"id":"bd-71","title":"Document versioning and release strategy","description":"Create comprehensive versioning strategy for beads ecosystem.\n\nComponents to document:\n1. bd CLI (Go binary) - main version number\n2. Plugin (Claude Code) - tracks CLI version\n3. MCP server (Python) - bundled with plugin\n4. Release workflow - how to sync all three\n\nDecisions to make:\n- Should plugin.json auto-update from bd CLI version?\n- Should we have a VERSION file at repo root?\n- How to handle breaking changes across components?\n- What's the update notification strategy?\n\nReferences:\n- plugin.json engines field now requires bd \u003e=0.9.0\n- /bd-version command added for checking compatibility\n- PLUGIN.md now documents update workflow","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.91836-07:00","closed_at":"2025-10-14T13:55:59.178075-07:00"}
{"id":"bd-72","title":"Create version bump script","description":"Create scripts/bump-version.sh to automate version syncing across all components.\n\nThe script should:\n1. Take a version number as argument (e.g., ./scripts/bump-version.sh 0.9.3)\n2. Update all version files:\n - cmd/bd/version.go (Version constant)\n - .claude-plugin/plugin.json (version field)\n - .claude-plugin/marketplace.json (plugins[].version)\n - integrations/beads-mcp/pyproject.toml (version field)\n - README.md (Alpha version mention)\n - PLUGIN.md (version requirements)\n3. Validate semantic versioning format\n4. Show diff preview before applying\n5. Optionally create git commit with standard message\n\nThis prevents the version mismatch issue that occurred when only version.go was updated.\n\nRelated: bd-73 (version sync issue)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:01.02371-07:00","closed_at":"2025-10-14T13:49:22.368581-07:00"}
{"id":"bd-73","title":"Add system-wide/multi-repo support for beads","description":"GitHub issue #4 requests ability to use beads across multiple projects and for system-wide task tracking.\n\nCurrent limitation: beads is per-repository isolated. Each project has its own .beads/ directory and issues cannot reference issues in other projects.\n\nPotential approaches:\n1. Global beads instance in ~/.beads/global.db for cross-project work\n2. Project references - allow issues to link across repos\n3. Multi-project workspace support - one beads instance managing multiple repos\n4. Integration with existing MCP server to provide remote multi-project access\n\nUse cases:\n- System administrators tracking work across multiple machines/repos\n- Developers working on a dozen+ projects simultaneously\n- Cross-cutting concerns that span multiple repositories\n- Global todo list with project-specific subtasks\n\nRelated:\n- GitHub issue #4: https://github.com/steveyegge/beads/issues/4\n- Comparison to membank MCP which already supports multi-project via centralized server\n- MCP server at integrations/beads-mcp/ could be extended for this\n\nSee also: Testing framework for plugins (also from GH #4)","notes":"Multi-repo support status update:\n\n✅ **COMPLETED (P1 - Core functionality):**\n- bd-121: --global daemon flag ✅ \n- bd-122: Multi-repo documentation ✅\n- bd-115: Per-request context routing ✅\n\n**REMAINING (Optional enhancements):**\n- bd-123 (P2): 'bd repos' command - nice-to-have for UX\n- bd-124 (P2): Daemon auto-start - convenience feature\n- bd-125 (P3): Workspace config - alternative approach\n- bd-126 (P4): Cross-repo references - future feature\n\n**Decision:** Core multi-repo support is COMPLETE and working. Remaining items are independent enhancements, not blockers. \n\nRecommend closing bd-73 as complete. Open new issues for specific enhancements if needed.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T23:15:17.705446-07:00","closed_at":"2025-10-17T23:15:17.705446-07:00"}
{"id":"bd-74","title":"Implement storage driver interface for pluggable backends","description":"Create abstraction layer for storage to support multiple backends (SQLite, Postgres, Turso, in-memory testing, etc.).\n\n**Current state:** All storage logic hardcoded to SQLite in internal/storage/sqlite/sqlite.go\n\n**Proposed design:**\n\n```go\n// internal/storage/storage.go\ntype Store interface {\n // Issue CRUD\n CreateIssue(issue *Issue) error\n GetIssue(id string) (*Issue, error)\n UpdateIssue(id string, updates *Issue) error\n DeleteIssue(id string) error\n ListIssues(filter *Filter) ([]*Issue, error)\n \n // Dependencies\n AddDependency(from, to string, depType DependencyType) error\n RemoveDependency(from, to string, depType DependencyType) error\n GetDependencies(id string) ([]*Dependency, error)\n \n // Counters, stats\n GetNextID(prefix string) (string, error)\n GetStats() (*Stats, error)\n \n Close() error\n}\n```\n\n**Benefits:**\n- Better testing (mock/in-memory stores)\n- Future flexibility (Postgres, cloud APIs, etc.)\n- Clean architecture (business logic decoupled from storage)\n- Enable Turso or other backends without refactoring everything\n\n**Implementation steps:**\n1. Define Store interface in internal/storage/storage.go\n2. Refactor SQLiteStore to implement interface\n3. Update all commands to use interface, not concrete type\n4. Add MemoryStore for testing\n5. Add driver selection via config (storage.driver = sqlite|turso|postgres)\n6. Update tests to use interface\n\n**Note:** This is valuable even without adopting Turso. Good architecture practice.\n\n**Context:** From GH issue #2 RFC evaluation. Driver interface is low-cost, high-value regardless of whether we add alternative backends.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.920278-07:00"}
{"id":"bd-74","title":"Implement storage driver interface for pluggable backends","description":"Create abstraction layer for storage to support multiple backends (SQLite, Postgres, Turso, in-memory testing, etc.).\n\n**Current state:** All storage logic hardcoded to SQLite in internal/storage/sqlite/sqlite.go\n\n**Proposed design:**\n\n```go\n// internal/storage/storage.go\ntype Store interface {\n // Issue CRUD\n CreateIssue(issue *Issue) error\n GetIssue(id string) (*Issue, error)\n UpdateIssue(id string, updates *Issue) error\n DeleteIssue(id string) error\n ListIssues(filter *Filter) ([]*Issue, error)\n \n // Dependencies\n AddDependency(from, to string, depType DependencyType) error\n RemoveDependency(from, to string, depType DependencyType) error\n GetDependencies(id string) ([]*Dependency, error)\n \n // Counters, stats\n GetNextID(prefix string) (string, error)\n GetStats() (*Stats, error)\n \n Close() error\n}\n```\n\n**Benefits:**\n- Better testing (mock/in-memory stores)\n- Future flexibility (Postgres, cloud APIs, etc.)\n- Clean architecture (business logic decoupled from storage)\n- Enable Turso or other backends without refactoring everything\n\n**Implementation steps:**\n1. Define Store interface in internal/storage/storage.go\n2. Refactor SQLiteStore to implement interface\n3. Update all commands to use interface, not concrete type\n4. Add MemoryStore for testing\n5. Add driver selection via config (storage.driver = sqlite|turso|postgres)\n6. Update tests to use interface\n\n**Note:** This is valuable even without adopting Turso. Good architecture practice.\n\n**Context:** From GH issue #2 RFC evaluation. Driver interface is low-cost, high-value regardless of whether we add alternative backends.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T23:46:22.447301-07:00","closed_at":"2025-10-17T23:46:22.447301-07:00"}
{"id":"bd-75","title":"Test issue with --deps flag","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.921065-07:00","closed_at":"2025-10-16T10:07:34.027923-07:00"}
{"id":"bd-76","title":"Fix: bd init --prefix test -q flag not recognized","description":"The init command doesn't recognize the -q flag. When running 'bd init --prefix test -q', it fails silently or behaves unexpectedly. The flag should either be implemented for quiet mode or removed from documentation if not supported.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.921744-07:00","closed_at":"2025-10-17T00:09:18.921816-07:00"}
{"id":"bd-77","title":"Improve session management","description":"Current session management is basic. Need to improve with better expiration handling.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-16T20:46:08.971822-07:00","updated_at":"2025-10-17T01:32:00.922344-07:00","closed_at":"2025-10-14T14:37:17.463188-07:00"}