From c9247312df2dbc3cdb83c6dd2cf9b2f19e03bbe2 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Thu, 6 Nov 2025 19:22:12 -0800 Subject: [PATCH] Fix bd-6ku3: Update isHashID to recognize Base36 hash IDs - Changed pattern from [a-f] (hex) to [a-z] (Base36) - Added length check: 5+ chars = hash ID (sequential IDs rarely exceed 4 digits) - Fixes test failure where all-digit Base36 IDs were incorrectly identified as sequential --- .beads/beads.jsonl | 7 ++++--- cmd/bd/migrate_hash_ids.go | 16 +++++++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.beads/beads.jsonl b/.beads/beads.jsonl index 7de234e8..0e1fabdb 100644 --- a/.beads/beads.jsonl +++ b/.beads/beads.jsonl @@ -27,7 +27,7 @@ {"id":"bd-1ls","content_hash":"af79708476d560abaac3cbe9c537bcf43c2100dcb1d676954ea604486f75d199","title":"Override test","description":"## Overview\n\n[Describe the high-level goal and scope of this epic]\n\n## Success Criteria\n\n- [ ] Criteria 1\n- [ ] Criteria 2\n- [ ] Criteria 3\n\n## Background\n\n[Provide context and motivation]\n\n## Scope\n\n**In Scope:**\n- Item 1\n- Item 2\n\n**Out of Scope:**\n- Item 1\n- Item 2\n","design":"## Architecture\n\n[Describe the overall architecture and approach]\n\n## Components\n\n- Component 1: [description]\n- Component 2: [description]\n\n## Dependencies\n\n[List external dependencies or constraints]\n","acceptance_criteria":"- [ ] All child issues are completed\n- [ ] Integration tests pass\n- [ ] Documentation is updated\n- [ ] Code review completed\n","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-03T20:15:10.01471-08:00","updated_at":"2025-11-03T22:07:10.946574-08:00","closed_at":"2025-11-03T22:07:10.946574-08:00","source_repo":".","labels":["epic"]} {"id":"bd-1vv","content_hash":"1db907ddb55edaf7a4c06a566c4e1b8244fcd9ba5d7e2fca4d5c053e424ac515","title":"Add WebSocket support","description":"## Feature Request\n\n[Describe the desired feature]\n\n## Motivation\n\n[Why is this feature needed? What problem does it solve?]\n\n## Use Cases\n\n1. **Use Case 1**: [description]\n2. **Use Case 2**: [description]\n\n## Proposed Solution\n\n[High-level approach to implementing this feature]\n\n## Alternatives Considered\n\n- **Alternative 1**: [description and why not chosen]\n- **Alternative 2**: [description and why not chosen]\n","design":"## Technical Design\n\n[Detailed technical approach]\n\n## API Changes\n\n[New commands, flags, or APIs]\n\n## Data Model Changes\n\n[Database schema changes if any]\n\n## Implementation Notes\n\n- Note 1\n- Note 2\n\n## Testing Strategy\n\n- Unit tests: [scope]\n- Integration tests: [scope]\n- Manual testing: [steps]\n","acceptance_criteria":"- [ ] Feature implements all described use cases\n- [ ] All tests pass\n- [ ] Documentation updated (README, commands)\n- [ ] Examples added if applicable\n- [ ] No performance regressions\n","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-03T19:56:41.271215-08:00","updated_at":"2025-11-03T19:56:41.271215-08:00","source_repo":".","labels":["feature"]} {"id":"bd-1yi5","content_hash":"11044802d32a77f8ca574ca5902939bcc7e252880437bea7281aaf445db8db84","title":"Use -short flag in CI for PR checks","description":"Update CI configuration to use -short flag for PR checks, run full tests nightly.\n\nThe slow tests already support testing.Short() and will be skipped.\n\nExpected savings: ~20 seconds for PR checks (fast tests only)\n\nImplementation:\n- Update .github/workflows/ci.yml to add -short flag for PR tests\n- Create/update nightly workflow for full test runs\n- Update README/docs about test strategy\n\nFile: .github/workflows/ci.yml:30","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-04T01:24:17.279618-08:00","updated_at":"2025-11-04T10:25:10.616119-08:00","closed_at":"2025-11-04T10:25:10.616119-08:00","source_repo":".","dependencies":[{"issue_id":"bd-1yi5","depends_on_id":"bd-l5gq","type":"blocks","created_at":"2025-11-04T01:24:17.280453-08:00","created_by":"daemon"}]} -{"id":"bd-23a8","content_hash":"7c54bea4624429ff0842a192489979e0a1eafdd872027a0934b1a1d9b0e80d33","title":"Test simple issue","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T17:11:04.464726-08:00","updated_at":"2025-11-04T11:10:23.529727-08:00","closed_at":"2025-11-04T11:10:23.529731-08:00","source_repo":".","comments":[{"id":1,"issue_id":"bd-23a8","author":"stevey","text":"Testing the new bd comment alias!","created_at":"2025-11-04T19:10:23Z"},{"id":2,"issue_id":"bd-23a8","author":"stevey","text":"Another test with JSON output","created_at":"2025-11-04T19:10:23Z"},{"id":3,"issue_id":"bd-23a8","author":"stevey","text":"Test comment from file\n","created_at":"2025-11-04T19:10:23Z"}]} +{"id":"bd-23a8","content_hash":"7c54bea4624429ff0842a192489979e0a1eafdd872027a0934b1a1d9b0e80d33","title":"Test simple issue","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T17:11:04.464726-08:00","updated_at":"2025-11-04T11:10:23.529727-08:00","closed_at":"2025-11-04T11:10:23.529731-08:00","source_repo":"."} {"id":"bd-248bdc3e","content_hash":"8eaeb2dbef1ed6b25fc1bcf3bc5cd1b38a5cf5a487772558ba9fe12a149978f3","title":"Add optional post-merge git hook example for bd sync","description":"Create example git hook that auto-runs bd sync after git pull/merge.\n\nAdd to examples/git-hooks/:\n- post-merge hook that checks if .beads/issues.jsonl changed\n- If changed: run `bd sync` automatically\n- Make it optional/documented (not auto-installed)\n\nBenefits:\n- Zero-friction sync after git pull\n- Complements auto-detection as belt-and-suspenders\n\nNote: post-merge hook already exists for pre-commit/post-merge. Extend it to support sync.","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-25T22:47:14.668842-07:00","updated_at":"2025-10-30T17:12:58.218887-07:00","source_repo":"."} {"id":"bd-2530","content_hash":"7056a386ee4802bce2b83a981aaac7858b5911938263d212f8f9d1f60bf2a706","title":"Issue with labels","description":"This is a description","design":"Use MVC pattern","acceptance_criteria":"All tests pass","status":"closed","priority":0,"issue_type":"feature","created_at":"2025-10-31T21:40:34.630173-07:00","updated_at":"2025-11-01T11:11:57.93151-07:00","closed_at":"2025-11-01T11:11:57.93151-07:00","source_repo":".","labels":["bug","critical"]} {"id":"bd-27ea","content_hash":"6fed2225c017a7f060eef560279cf166c7dd4965657de0c036d6ed5db13803eb","title":"Improve cmd/bd test coverage from 21% to 40% (multi-session effort)","description":"Current coverage: 21.0% of statements in cmd/bd\nTarget: 40%\nThis is a multi-session incremental effort.\n\nFocus areas:\n- Command handler tests (create, update, close, list, etc.)\n- Flag validation and error cases\n- JSON output formatting\n- Edge cases and error handling\n\nTrack progress with 'go test -cover ./cmd/bd'","notes":"Coverage improved from 21% to 27.4% (package) and 42.9% (total function coverage).\n\nAdded tests for:\n- compact.go test coverage (eligibility checks, dry run scenarios)\n- epic.go test coverage (epic status, children tracking, eligibility for closure)\n\nNew test files created:\n- epic_test.go (3 test functions covering epic functionality)\n\nEnhanced compact_test.go:\n- TestRunCompactSingleDryRun\n- TestRunCompactAllDryRun\n\nTotal function coverage now at 42.9%, exceeding the 40% target.","status":"closed","priority":0,"issue_type":"task","created_at":"2025-10-31T19:35:57.558346-07:00","updated_at":"2025-11-01T12:23:39.158922-07:00","closed_at":"2025-11-01T12:23:39.158926-07:00","source_repo":"."} @@ -88,7 +88,7 @@ {"id":"bd-5f483051","content_hash":"d69f64f7f0bdc46a539dfe0b699a8977309c9c8d59f3e9beffbbe4484275a16b","title":"Implement bd resolve-conflicts (git merge conflicts in JSONL)","description":"Automatically detect and resolve git merge conflicts in .beads/issues.jsonl file.\n\nFeatures:\n- Detect conflict markers in JSONL\n- Parse conflicting issues from HEAD and BASE\n- Provide mechanical resolution (remap duplicate IDs)\n- Support AI-assisted resolution (requires internal/ai package)\n\nSee repair_commands.md lines 125-353 for design.","status":"open","priority":1,"issue_type":"task","created_at":"2025-10-28T19:37:55.722827-07:00","updated_at":"2025-10-30T17:12:58.179718-07:00","source_repo":"."} {"id":"bd-5iv","content_hash":"9260ad77a2fcc64520aa97f156bbf9d868d855b7a3b8491256b316f2563ca958","title":"Test Epic","description":"## Overview\n\n[Describe the high-level goal and scope of this epic]\n\n## Success Criteria\n\n- [ ] Criteria 1\n- [ ] Criteria 2\n- [ ] Criteria 3\n\n## Background\n\n[Provide context and motivation]\n\n## Scope\n\n**In Scope:**\n- Item 1\n- Item 2\n\n**Out of Scope:**\n- Item 1\n- Item 2\n","design":"## Architecture\n\n[Describe the overall architecture and approach]\n\n## Components\n\n- Component 1: [description]\n- Component 2: [description]\n\n## Dependencies\n\n[List external dependencies or constraints]\n","acceptance_criteria":"- [ ] All child issues are completed\n- [ ] Integration tests pass\n- [ ] Documentation is updated\n- [ ] Code review completed\n","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-03T20:15:03.864229-08:00","updated_at":"2025-11-05T00:25:06.538749-08:00","closed_at":"2025-11-05T00:25:06.538749-08:00","source_repo":".","labels":["epic"]} {"id":"bd-5ots","content_hash":"ba3efab3e7a2b9bb2bd2dba3aace56cfbdd1b67efd1cfc4758d9c79919f632af","title":"SearchIssues N+1 query causes context timeout with GetLabels","description":"scanIssues() calls GetLabels in a loop for every issue, causing N+1 queries and context deadline exceeded errors when used with short timeouts or in-memory databases. This is especially problematic since SearchIssues already supports label filtering via SQL WHERE clauses.","acceptance_criteria":"- Optimize scanIssues to batch-load labels for all issues in one query\n- Or make label loading optional/lazy\n- Add test that calls SearchIssues repeatedly with label filters and short context timeouts","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-05T19:12:02.245879-08:00","updated_at":"2025-11-05T19:22:11.668682-08:00","closed_at":"2025-11-05T19:22:11.668682-08:00","source_repo":"."} -{"id":"bd-6049","content_hash":"16c54bc547f4ab180aee39efbb197709a47a39047f5bc2dd59e6e6b57ca8bc87","title":"bd doctor --json flag not working","description":"The --json flag on bd doctor command doesn't produce JSON output. It continues to show human-readable output instead. The flag is registered locally on doctorCmd but the code uses the global jsonOutput variable set by PersistentPreRun. Need to investigate why the flag isn't being honored.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-02T17:08:18.170428-08:00","updated_at":"2025-11-02T18:41:01.376783-08:00","closed_at":"2025-11-02T18:41:01.376786-08:00","source_repo":".","comments":[{"id":4,"issue_id":"bd-6049","author":"stevey","text":"Fixed by removing the local --json flag definition in doctor.go that was shadowing the persistent --json flag from main.go. The doctor command now correctly uses the global jsonOutput variable.","created_at":"2025-11-04T19:10:23Z"}]} +{"id":"bd-6049","content_hash":"16c54bc547f4ab180aee39efbb197709a47a39047f5bc2dd59e6e6b57ca8bc87","title":"bd doctor --json flag not working","description":"The --json flag on bd doctor command doesn't produce JSON output. It continues to show human-readable output instead. The flag is registered locally on doctorCmd but the code uses the global jsonOutput variable set by PersistentPreRun. Need to investigate why the flag isn't being honored.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-02T17:08:18.170428-08:00","updated_at":"2025-11-02T18:41:01.376783-08:00","closed_at":"2025-11-02T18:41:01.376786-08:00","source_repo":"."} {"id":"bd-627d","content_hash":"5b3d3d69ceac28dcbfbc2c7ea2f7a6ff2a3a02bc58ce02dcf6b05f8469e8bddc","title":"AI-supervised database migrations for safer schema evolution","description":"## Problem\n\nDatabase migrations can lose user data through edge cases that are hard to anticipate (e.g., GH #201 where bd migrate failed to set issue_prefix, or bd-d355a07d false positive data loss warnings). Since beads is designed to be run by AI agents, we should leverage AI to make migrations safer.\n\n## Current State\n\nMigrations run blindly with:\n- No pre-flight validation\n- No data integrity verification\n- No rollback on failure\n- Limited post-migration testing\n\nRecent issues:\n- GH #201: Migration didn't set issue_prefix config, breaking commands\n- bd-d355a07d: False positive \"data loss\" warnings on collision resolution\n- Users reported migration data loss (fixed but broader problem remains)\n\n## Proposal: AI-Supervised Migration Framework\n\nUse AI to supervise migrations through structured verification:\n\n### 1. Pre-Migration Analysis\n- AI reads migration code and current schema\n- Identifies potential data loss scenarios\n- Generates validation queries to verify assumptions\n- Creates snapshot queries for before/after comparison\n\n### 2. Migration Execution\n- Take database backup/snapshot\n- Run validation queries (pre-state)\n- Execute migration in transaction\n- Run validation queries (post-state)\n\n### 3. Post-Migration Verification\n- AI compares pre/post snapshots\n- Verifies data integrity invariants\n- Checks for unexpected data loss\n- Validates config completeness (like issue_prefix)\n\n### 4. Rollback on Anomalies\n- If AI detects data loss, rollback transaction\n- Present human-readable error report\n- Suggest fix before retrying\n\n## Example Flow\n\n```\n$ bd migrate\n\n→ Analyzing migration plan...\n→ AI identified 3 potential data loss scenarios\n→ Generating validation queries...\n→ Creating pre-migration snapshot...\n→ Running migration in transaction...\n→ Verifying post-migration state...\n✓ All 247 issues accounted for\n✓ Config table complete (issue_prefix: \"mcp\")\n✓ Dependencies intact (342 relationships verified)\n→ Migration successful!\n```\n\nIf something goes wrong:\n```\n$ bd migrate\n\n→ Analyzing migration plan...\n→ AI identified issue: Missing issue_prefix config after migration\n→ Recommendation: Add prefix detection step\n→ Aborting migration - database unchanged\n```\n\n## Implementation Ideas\n\n### A. Migration Validator Tool\nCreate `bd migrate --validate` that:\n- Simulates migration on copy of database\n- Uses AI to verify data integrity\n- Reports potential issues before real migration\n\n### B. Migration Test Generator\nAI generates test cases for migrations:\n- Edge cases (empty DB, large DB, missing config)\n- Data integrity checks\n- Regression tests\n\n### C. Migration Invariants\nDefine invariants that AI checks:\n- Issue count should not decrease (unless collision resolution)\n- All required config keys present\n- Foreign key relationships intact\n- No orphaned dependencies\n\n### D. Self-Healing Migrations\nAI detects incomplete migrations and suggests fixes:\n- Missing config values (like GH #201)\n- Orphaned data\n- Index inconsistencies\n\n## Benefits\n\n1. **Catch edge cases**: AI explores scenarios humans miss\n2. **Self-documenting**: AI explains what migration does\n3. **Agent-friendly**: Agents can run migrations confidently\n4. **Fewer rollbacks**: Detect issues before committing\n5. **Better testing**: AI generates comprehensive test suites\n\n## Open Questions\n\n1. Which AI model? (Fast: Haiku, Thorough: Sonnet/GPT-4)\n2. How to balance safety vs migration speed?\n3. Should AI validation be required or optional?\n4. How to handle offline scenarios (no API access)?\n5. What invariants should always be checked?\n\n## Related Work\n\n- bd-b245: Migration registry (makes migrations introspectable)\n- GH #201: issue_prefix migration bug (motivating example)\n- bd-d355a07d: False positive data loss warnings","design":"## Architecture: Agent-Supervised Migrations (Inversion of Control)\n\n**Key principle:** Beads provides observability and validation primitives. AI agents supervise using their own reasoning. Beads NEVER makes AI API calls.\n\n## Phase 1: Migration Invariants (Pure Validation)\n\nCreate `internal/storage/sqlite/migration_invariants.go`:\n\n```go\ntype MigrationInvariant struct {\n Name string\n Description string\n Check func(*sql.DB, *Snapshot) error\n}\n\ntype Snapshot struct {\n IssueCount int\n ConfigKeys []string\n DependencyCount int\n LabelCount int\n}\n\nvar invariants = []MigrationInvariant{\n {\n Name: \"required_config_present\",\n Description: \"Required config keys must exist\",\n Check: checkRequiredConfig, // Would have caught GH #201\n },\n {\n Name: \"foreign_keys_valid\",\n Description: \"No orphaned dependencies or labels\",\n Check: checkForeignKeys,\n },\n {\n Name: \"issue_count_stable\",\n Description: \"Issue count should not decrease unexpectedly\",\n Check: checkIssueCount,\n },\n}\n\nfunc checkRequiredConfig(db *sql.DB, snapshot *Snapshot) error {\n required := []string{\"issue_prefix\", \"schema_version\"}\n for _, key := range required {\n var value string\n err := db.QueryRow(\"SELECT value FROM config WHERE key = ?\", key).Scan(\u0026value)\n if err != nil || value == \"\" {\n return fmt.Errorf(\"required config key missing: %s\", key)\n }\n }\n return nil\n}\n```\n\n## Phase 2: Dry-Run \u0026 Inspection Tools\n\nAdd `bd migrate --dry-run --json`:\n\n```json\n{\n \"pending_migrations\": [\n {\"name\": \"dirty_issues_table\", \"description\": \"Adds dirty_issues table\"},\n {\"name\": \"content_hash_column\", \"description\": \"Adds content_hash for collision resolution\"}\n ],\n \"current_state\": {\n \"schema_version\": \"0.9.9\",\n \"issue_count\": 247,\n \"config\": {\"schema_version\": \"0.9.9\"},\n \"missing_config\": [\"issue_prefix\"]\n },\n \"warnings\": [\n \"issue_prefix config not set - may break commands after migration\"\n ],\n \"invariants_to_check\": [\n \"required_config_present\",\n \"foreign_keys_valid\",\n \"issue_count_stable\"\n ]\n}\n```\n\nAdd `bd info --schema --json`:\n\n```json\n{\n \"tables\": [\"issues\", \"dependencies\", \"labels\", \"config\"],\n \"schema_version\": \"0.9.9\",\n \"config\": {},\n \"sample_issue_ids\": [\"mcp-1\", \"mcp-2\"],\n \"detected_prefix\": \"mcp\"\n}\n```\n\n## Phase 3: Pre/Post Snapshots with Rollback\n\nUpdate `RunMigrations()`:\n\n```go\nfunc RunMigrations(db *sql.DB) error {\n // Capture pre-migration snapshot\n snapshot := captureSnapshot(db)\n \n // Run migrations in transaction\n tx, err := db.Begin()\n if err != nil {\n return err\n }\n defer tx.Rollback()\n \n for _, migration := range migrations {\n if err := migration.Func(tx); err != nil {\n return fmt.Errorf(\"migration %s failed: %w\", migration.Name, err)\n }\n }\n \n // Verify invariants before commit\n if err := verifyInvariants(tx, snapshot); err != nil {\n return fmt.Errorf(\"post-migration validation failed (rolled back): %w\", err)\n }\n \n return tx.Commit()\n}\n```\n\n## Phase 4: MCP Tools for Agent Supervision\n\nAdd to beads-mcp:\n\n```python\n@server.tool()\nasync def inspect_migration(workspace_root: str) -\u003e dict:\n \"\"\"Get migration plan and current state for agent analysis.\n \n Agent should:\n 1. Review pending migrations\n 2. Check for warnings (missing config, etc.)\n 3. Verify invariants will pass\n 4. Decide whether to run bd migrate\n \"\"\"\n result = run_bd([\"migrate\", \"--dry-run\", \"--json\"], workspace_root)\n return json.loads(result.stdout)\n\n@server.tool() \nasync def get_schema_info(workspace_root: str) -\u003e dict:\n \"\"\"Get current database schema for migration analysis.\"\"\"\n result = run_bd([\"info\", \"--schema\", \"--json\"], workspace_root)\n return json.loads(result.stdout)\n```\n\n## Agent Workflow Example\n\n```python\n# Agent detects user wants to migrate\nmigration_plan = inspect_migration(\"/path/to/workspace\")\n\n# Agent analyzes (using its own reasoning, no API calls from beads)\nif \"issue_prefix\" in migration_plan[\"missing_config\"]:\n schema = get_schema_info(\"/path/to/workspace\")\n detected_prefix = schema[\"detected_prefix\"]\n \n # Agent fixes issue before migration\n run_bd([\"config\", \"set\", \"issue_prefix\", detected_prefix])\n \n# Now safe to migrate\nrun_bd([\"migrate\"])\n```\n\n## What Beads Provides\n\n✅ Deterministic validation (invariants)\n✅ Structured inspection (--dry-run, --explain)\n✅ Rollback on invariant failure\n✅ JSON output for agent parsing\n\n## What Beads Does NOT Do\n\n❌ No AI API calls\n❌ No external model access\n❌ No agent invocation\n\nAgents supervise migrations using their own reasoning and the inspection tools beads provides.","acceptance_criteria":"Phase 1: Migration invariants implemented and tested, checked after every migration, clear error messages when invariants fail.\n\nPhase 2: Snapshot capture before migrations, comparison after, rollback on verification failure.\n\nPhase 3 (stretch): AI validation optional flag implemented, AI can analyze migration code and generate custom validation queries.\n\nPhase 4 (stretch): Migration test fixtures created, all fixtures pass migrations, CI runs migration tests.","notes":"## Progress\n\n### ✅ Phase 1: Migration Invariants (COMPLETED)\n\n**Implemented:**\n- Created internal/storage/sqlite/migration_invariants.go with 3 invariants\n- Updated RunMigrations() to verify invariants after migrations\n- All tests pass ✓\n\n### ✅ Phase 2: Inspection Tools (COMPLETED \u0026 PUSHED)\n\n**Commit:** 1abe4e7 - \"Add migration inspection tools for AI agents (bd-627d Phase 2)\"\n\n**Implemented:**\n1. ✅ bd migrate --inspect --json - Shows migration plan\n2. ✅ bd info --schema --json - Returns schema details\n3. ✅ Migration warnings system\n4. ✅ Documentation updated in AGENTS.md\n5. ✅ All tests pass\n\n### ✅ Phase 3: MCP Tools (COMPLETED \u0026 PUSHED)\n\n**Commit:** 2493693 - \"Add MCP tools for migration inspection (bd-627d Phase 3)\"\n\n**Implemented:**\n1. ✅ inspect_migration(workspace_root) tool in beads-mcp\n2. ✅ get_schema_info(workspace_root) tool in beads-mcp\n3. ✅ Abstract methods in BdClientBase\n4. ✅ CLI client implementations\n5. ✅ All tests pass\n\n**All phases complete!** Migration inspection fully integrated into MCP server.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-02T12:57:10.722048-08:00","updated_at":"2025-11-02T14:31:25.095296-08:00","closed_at":"2025-11-02T14:31:25.095308-08:00","source_repo":"."} {"id":"bd-62a0","content_hash":"b8b2a58a86211a19aed9d21ec5215b4f14ef341ee95d4ed845e1412840d00fd7","title":"Create WASM build infrastructure (Makefile, scripts)","description":"Set up build tooling for WASM compilation:\n- Add GOOS=js GOARCH=wasm build target\n- Copy wasm_exec.js from Go distribution\n- Create wrapper script for Node.js execution\n- Add build task to Makefile or build script","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-02T21:58:07.286826-08:00","updated_at":"2025-11-02T22:23:49.376789-08:00","closed_at":"2025-11-02T22:23:49.376789-08:00","source_repo":".","dependencies":[{"issue_id":"bd-62a0","depends_on_id":"bd-44d0","type":"parent-child","created_at":"2025-11-02T22:23:49.423064-08:00","created_by":"stevey"}]} {"id":"bd-63e9","content_hash":"7c709804b6d15ce63897344b0674dfae6a4fe97e3ae2768585e2a3407484bad0","title":"Fix Nix flake build test failures","description":"Nix build is failing during test phase with same test errors as Windows.\n\n**Error:**\n```\nerror: Cannot build '/nix/store/rgyi1j44dm6ylrzlg2h3z97axmfq9hzr-beads-0.9.9.drv'.\nReason: builder failed with exit code 1.\nFAIL github.com/steveyegge/beads/cmd/bd 16.141s\n```\n\nThis may be related to test environment setup or the same issues affecting Windows tests.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-02T09:29:37.2851-08:00","updated_at":"2025-11-04T11:10:23.531386-08:00","closed_at":"2025-11-04T11:10:23.531389-08:00","source_repo":".","dependencies":[{"issue_id":"bd-63e9","depends_on_id":"bd-1231","type":"blocks","created_at":"2025-11-02T09:29:37.28618-08:00","created_by":"stevey"}]} @@ -125,7 +125,7 @@ {"id":"bd-85487065","content_hash":"637cbd56af122b175ff060b4df050871fe86124c5d883ba7f8a17f2f95479613","title":"Add tests for internal/autoimport package","description":"Currently 0.0% coverage. Need tests for auto-import functionality that detects and imports updated JSONL files.","status":"open","priority":2,"issue_type":"task","created_at":"2025-10-29T14:06:18.154805-07:00","updated_at":"2025-10-30T17:12:58.182987-07:00","source_repo":"."} {"id":"bd-85d1","content_hash":"afd8d1a606ee5a50369e303537e209f6f8df910f19f7561d67317a18b7f686ff","title":"Add integration tests for multi-repo sync","description":"Test: Clone A deletes issue, Clone B imports Clone A's JSONL. Verify Clone B handles deletion gracefully with resurrection. Test concurrent imports with same orphans (should be idempotent). Test round-trip fidelity (export→delete parent→import→verify structure).","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-04T12:32:21.410318-08:00","updated_at":"2025-11-05T00:25:06.707471-08:00","closed_at":"2025-11-05T00:25:06.707471-08:00","source_repo":"."} {"id":"bd-879d","content_hash":"2f291ca2adead5ee3fb7fade39c088165b5467780599f9a719dcaebc87455ae3","title":"Test issue 1","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T09:44:12.538697729Z","updated_at":"2025-11-02T09:45:20.76214671Z","closed_at":"2025-11-02T09:45:20.76214671Z","source_repo":".","dependencies":[{"issue_id":"bd-879d","depends_on_id":"bd-d3e5","type":"discovered-from","created_at":"2025-11-02T09:44:22.103468321Z","created_by":"mrdavidlaing"}]} -{"id":"bd-87a0","content_hash":"b6c322852ff360ade9f0d46bb2af29a7cf3d3acc8b7469dcbb5d98bf48050240","title":"Publish @beads/bd package to npm registry","description":"Publish the npm package to the public npm registry:\n\n## Prerequisites\n- npm account created\n- Organization @beads created (or use different namespace)\n- npm login completed locally\n- Package tested locally (bd-f282 completed)\n\n## Publishing steps\n1. Verify package.json version matches current bd version\n2. Run npm pack and inspect tarball contents\n3. Test installation from tarball one more time\n4. Run npm publish --access public\n5. Verify package appears on https://www.npmjs.com/package/@beads/bd\n6. Test installation from registry: npm install -g @beads/bd\n\n## Post-publish\n- Add npm badge to README.md\n- Update CHANGELOG.md with npm package release\n- Announce in release notes\n\n## Note\n- May need to choose different name if @beads namespace unavailable\n- Alternative: beads-cli, bd-cli, or unscoped beads-issue-tracker","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-02T23:40:25.263569-08:00","updated_at":"2025-11-03T10:39:41.772338-08:00","closed_at":"2025-11-03T10:39:41.772338-08:00","source_repo":".","dependencies":[{"issue_id":"bd-87a0","depends_on_id":"bd-febc","type":"parent-child","created_at":"2025-11-02T23:40:33.014043-08:00","created_by":"daemon"}],"comments":[{"id":5,"issue_id":"bd-87a0","author":"stevey","text":"Package is ready to publish. All code complete and tested locally. Next steps: 1) npm login, 2) create @beads org if needed, 3) npm publish --access public. See npm-package/PUBLISHING.md for complete instructions.","created_at":"2025-11-04T19:10:23Z"}]} +{"id":"bd-87a0","content_hash":"b6c322852ff360ade9f0d46bb2af29a7cf3d3acc8b7469dcbb5d98bf48050240","title":"Publish @beads/bd package to npm registry","description":"Publish the npm package to the public npm registry:\n\n## Prerequisites\n- npm account created\n- Organization @beads created (or use different namespace)\n- npm login completed locally\n- Package tested locally (bd-f282 completed)\n\n## Publishing steps\n1. Verify package.json version matches current bd version\n2. Run npm pack and inspect tarball contents\n3. Test installation from tarball one more time\n4. Run npm publish --access public\n5. Verify package appears on https://www.npmjs.com/package/@beads/bd\n6. Test installation from registry: npm install -g @beads/bd\n\n## Post-publish\n- Add npm badge to README.md\n- Update CHANGELOG.md with npm package release\n- Announce in release notes\n\n## Note\n- May need to choose different name if @beads namespace unavailable\n- Alternative: beads-cli, bd-cli, or unscoped beads-issue-tracker","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-02T23:40:25.263569-08:00","updated_at":"2025-11-03T10:39:41.772338-08:00","closed_at":"2025-11-03T10:39:41.772338-08:00","source_repo":".","dependencies":[{"issue_id":"bd-87a0","depends_on_id":"bd-febc","type":"parent-child","created_at":"2025-11-02T23:40:33.014043-08:00","created_by":"daemon"}]} {"id":"bd-8931","content_hash":"409c16d9e6c83c2bf6cccfa6ee6cb18e1e1eee032b522fb99500bb40f2a05649","title":"Daemon gets stuck when auto-import blocked by git conflicts","description":"CRITICAL: The daemon enters a corrupt state that breaks RPC commands when auto-import is triggered but git pull fails due to uncommitted changes.\n\nImpact: This is a data integrity and usability issue that could cause users to lose trust in Beads. The daemon silently fails for certain commands while appearing healthy.\n\nReproduction:\n1. Make local changes to issues (creates uncommitted .beads/beads.jsonl)\n2. Remote has updates (JSONL newer, triggers auto-import)\n3. Daemon tries to pull but fails: 'cannot pull with rebase: You have unstaged changes'\n4. Daemon enters bad state - 'bd show' and other commands return EOF\n5. 'bd list' still works, daemon process is running, no errors logged\n\nTechnical details:\n- Auto-import check runs in handleRequest() before processing RPC commands\n- When import is blocked, it appears to corrupt daemon state\n- Likely: deadlock, unclosed transaction, or storage handle corruption\n- Panic recovery (server_lifecycle_conn.go:183) didn't catch anything - not a panic\n\nRequired fix:\n- Auto-import must not block RPC command execution\n- Handle git pull failures gracefully without corrupting state\n- Consider: skip auto-import if git is dirty, queue import for later, or use separate goroutine\n- Add timeout/circuit breaker for import operations\n- Log clear warnings when auto-import is skipped\n\nWithout this fix, users in collaborative environments will frequently encounter mysterious EOF errors that require daemon restarts.","design":"Options to fix:\n\n1. Skip auto-import when git is dirty (safest, simplest)\n - Check git status before pull\n - Log warning and continue without import\n - User must manually import after cleaning git state\n\n2. Async import with timeout (better UX)\n - Run auto-import in background goroutine\n - Don't block RPC command execution\n - Timeout after 5s, log error if stuck\n - Use sync.Once or similar to prevent concurrent imports\n\n3. Transactional import with rollback\n - Wrap import in database transaction\n - Rollback if git operations fail\n - Ensure storage is never left in bad state\n\nRecommended: Combine #1 and #2\n- Check git status first, skip if dirty\n- If clean, do async import with timeout\n- Add metrics to track import success/failure rates","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-02T17:15:25.181425-08:00","updated_at":"2025-11-03T12:08:12.949061-08:00","closed_at":"2025-11-03T12:08:12.949064-08:00","source_repo":".","dependencies":[{"issue_id":"bd-8931","depends_on_id":"bd-1048","type":"blocks","created_at":"2025-11-02T17:15:25.181857-08:00","created_by":"stevey"}]} {"id":"bd-897a","content_hash":"91fa812a079ce0f5b401ef4b96a872c09a9f1d98c88749b7d28e3bcb3f626f0a","title":"Add UNIQUE constraint on external_ref column","description":"The external_ref column should have a UNIQUE constraint to prevent multiple issues from having the same external reference. This ensures data integrity when syncing from external systems (Jira, GitHub, Linear).\n\nCurrent behavior:\n- Multiple issues can have the same external_ref\n- GetIssueByExternalRef returns first match (non-deterministic with duplicates)\n\nProposed solution:\n- Add UNIQUE constraint to external_ref column\n- Add migration to check for and resolve existing duplicates\n- Update tests to verify constraint enforcement\n\nRelated: bd-1022","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-02T15:31:54.718005-08:00","updated_at":"2025-11-02T16:01:45.742666-08:00","closed_at":"2025-11-02T16:01:45.742666-08:00","source_repo":"."} {"id":"bd-89e2","content_hash":"ddf4626e586440f379ff19872eac29941cecb925d0a4aae8a6f9c08c969ca05d","title":"Daemon race condition: stale export overwrites recent DB changes","description":"**Symptom:**\nMerged bd-fc2d into bd-fb05 in ~/src/beads (commit ce4d756), pushed to remote. The ~/src/fred/beads daemon then exported its stale DB state and committed (8cc1bb4), reverting bd-fc2d back to \"open\" status.\n\n**Timeline:**\n1. 21:45:12 - Merge committed from ~/src/beads (ce4d756): bd-fc2d closed\n2. 21:49:42 - Daemon in ~/src/fred/beads exported stale state (8cc1bb4): bd-fc2d open again\n\n**Root cause:**\nThe fred/beads daemon had a stale database (bd-fc2d still open) and didn't auto-import the newer JSONL before exporting. When it exported, it overwrote the merge with its stale state.\n\n**Expected behavior:**\nDaemon should detect that JSONL is newer than its last export and import before exporting.\n\n**Actual behavior:**\nDaemon exported stale DB state, creating a conflicting commit that reverted upstream changes.\n\n**Impact:**\nMulti-workspace setups with daemons can silently lose changes if one daemon has stale state and exports.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-11-01T21:53:07.930819-07:00","updated_at":"2025-11-01T22:01:25.54126-07:00","closed_at":"2025-11-01T22:01:25.54126-07:00","source_repo":"."} @@ -256,6 +256,7 @@ {"id":"bd-q2ri","content_hash":"bd4163ddda01539f4bfa1cc5b6ad3a428c59c5524bbdb170bda657c40df94020","title":"bd-hv01: Add comprehensive edge case tests for deletion tracking","description":"Need to add tests for: corrupted snapshot file, stale snapshot (\u003e 1 hour), concurrent sync operations (daemon + manual), partial deletion failure, empty remote JSONL, multi-repo mode with deletions, git worktree scenario.\n\nAlso refine TestDeletionWithLocalModification to check for specific conflict error instead of accepting any error.\n\nFiles: cmd/bd/deletion_tracking_test.go","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-06T18:16:26.849881-08:00","updated_at":"2025-11-06T18:16:26.849881-08:00","source_repo":".","dependencies":[{"issue_id":"bd-q2ri","depends_on_id":"bd-rbxi","type":"parent-child","created_at":"2025-11-06T18:19:15.104113-08:00","created_by":"daemon"}]} {"id":"bd-qqvw","content_hash":"745b79db79433a49b763685e52e45f7083e49e26ca4dc4e82d16848a09ca1817","title":"Vendor and integrate beads-merge tool","description":"Incorporate @neongreen's beads-merge 3-way merge tool into bd to solve:\n- Multi-workspace deletion sync (bd-hv01)\n- Git merge conflicts in JSONL\n- Field-level intelligent merging\n\n**Repository**: https://github.com/neongreen/mono/tree/main/beads-merge\n\n**Integration approach**: Vendor the Go code with attribution, pending @neongreen's approval (GitHub issue #240)\n\n**Benefits**:\n- Prevents deletion resurrection bug\n- Smart dependency merging (union + dedup)\n- Timestamp handling (max wins)\n- Detects deleted-vs-modified conflicts\n- Works as git merge driver\n\n**Acceptance criteria**:\n- beads-merge code vendored into bd codebase\n- Available as `bd merge` command\n- Git merge driver setup during `bd init`\n- Tests verify 3-way merge logic\n- Documentation updated\n- @neongreen credited","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-05T18:41:59.500359-08:00","updated_at":"2025-11-06T15:51:28.340617-08:00","closed_at":"2025-11-06T15:40:24.796921-08:00","source_repo":"."} {"id":"bd-qs4p","content_hash":"46a4cf3491c85c38d7bf9e3ffc260c939d76e471d9dae41785de197269e3c05c","title":"bd import fails on duplicate external_ref with no resolution options","description":"When JSONL contains duplicate external_ref values (e.g., two issues both have external_ref='BS-170'), bd import fails entirely with no resolution options.\n\nUser must manually edit JSONL to remove duplicates, which is error-prone.\n\nExample error:\n```\nbatch import contains duplicate external_ref values:\nexternal_ref 'BS-170' appears in issues: [opal-39 opal-43]\n```\n\nShould handle this similar to duplicate issue detection - offer to merge, pick one, or clear duplicates.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-11-06T10:53:41.906165-08:00","updated_at":"2025-11-06T11:03:16.975041-08:00","closed_at":"2025-11-06T11:03:16.975041-08:00","source_repo":"."} +{"id":"bd-rb75","content_hash":"18c517e3523c7a9c0deba4ec1b734bcb7842febba76c516fcc72aa84bdf83091","title":"Clean up merge conflict artifacts in .beads directory","description":"After resolving merge conflicts in .beads/beads.jsonl, leftover artifacts remain as untracked files:\n- .beads/beads.base.jsonl\n- .beads/beads.left.jsonl\n\nThese appear to be temporary files created during merge conflict resolution.\n\nOptions to fix:\n1. Add these patterns to .beads/.gitignore automatically\n2. Clean up these files after successful merge resolution\n3. Document that users should delete them manually\n4. Add a check in 'bd sync' or 'bd doctor' to detect and remove stale merge artifacts\n\nPreferred solution: Add *.base.jsonl and *.left.jsonl patterns to .beads/.gitignore during 'bd init', and optionally clean them up automatically after successful import.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-06T19:09:16.114274-08:00","updated_at":"2025-11-06T19:13:44.630402-08:00","closed_at":"2025-11-06T19:13:44.630402-08:00","source_repo":"."} {"id":"bd-rbxi","content_hash":"a84e265e04e332ead9ba8a65e90316fa1b44fe024001bafad4b3de47e22a73bc","title":"bd-hv01: Deletion tracking production readiness","description":"Epic to track all improvements and fixes needed to make the deletion tracking implementation (bd-hv01) production-ready.\n\nThe core 3-way merge algorithm is sound, but there are critical issues around atomicity, error handling, and edge cases that need to be addressed before this can be safely used in production.\n\nCritical path (P1):\n- Non-atomic snapshot operations\n- Brittle JSON string comparison\n- Silent partial deletion failures\n- Race conditions in concurrent scenarios\n\nFollow-up work (P2-P3):\n- Test coverage for edge cases and multi-repo mode\n- Performance optimizations\n- Code refactoring and observability\n\nRelated commit: 708a81c","status":"in_progress","priority":1,"issue_type":"epic","created_at":"2025-11-06T18:18:24.315646-08:00","updated_at":"2025-11-06T18:39:15.739497-08:00","source_repo":"."} {"id":"bd-ry1u","content_hash":"013464efc3cf53d47c2a170040c66099ce77b13d3d1b34c3729e6a5208122799","title":"Publish official devcontainer configuration","description":"","design":"Problem: GH issue #229 shows git hooks aren't available in devcontainers because bd CLI isn't installed. Solution: Provide official .devcontainer/devcontainer.json that installs Go, builds bd from source, runs bd init --quiet, and installs hooks automatically. Benefits: New contributors start immediately, AI assistants work out-of-box, no manual setup. Implementation: Create .devcontainer/devcontainer.json with Go feature, postCreateCommand to build bd and install hooks, environment variables. Acceptance: Container builds with bd installed, hooks functional, documentation updated, tested with Codespaces and VSCode.","notes":"Devcontainer configuration implemented. Manual testing required in actual devcontainer environment (Codespaces or VSCode Remote Containers). All code changes complete, tests pass, linting clean.","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-11-05T15:02:21.783666-08:00","updated_at":"2025-11-05T17:46:42.70998-08:00","closed_at":"2025-11-05T17:46:42.70998-08:00","source_repo":"."} {"id":"bd-s02","content_hash":"911d456e4dabae028dd615b643c99058ef12e55ea523cb81cc933783c7b13546","title":"Manual task","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-03T20:15:10.022202-08:00","updated_at":"2025-11-03T20:15:10.022202-08:00","source_repo":"."} diff --git a/cmd/bd/migrate_hash_ids.go b/cmd/bd/migrate_hash_ids.go index 6d62c6cb..bd14cfa5 100644 --- a/cmd/bd/migrate_hash_ids.go +++ b/cmd/bd/migrate_hash_ids.go @@ -326,21 +326,27 @@ func replaceIDReferences(text string, mapping map[string]string) string { // isHashID checks if an ID is hash-based (not sequential) func isHashID(id string) bool { - // Hash IDs contain hex characters after the prefix - // Sequential IDs are only digits + // Hash IDs are Base36-encoded (0-9, a-z) with adaptive length (3-8 chars) + // Sequential IDs are numeric and typically short (1-4 digits) parts := strings.SplitN(id, "-", 2) if len(parts) != 2 { return false } - // Check if the suffix starts with a hex digit (a-f) suffix := parts[1] if len(suffix) == 0 { return false } - // If it contains any letter a-f, it's a hash ID - return regexp.MustCompile(`[a-f]`).MatchString(suffix) + // If it's 5+ characters long, it's almost certainly a hash ID + // (sequential IDs rarely exceed 9999 = 4 digits) + if len(suffix) >= 5 { + return true + } + + // For shorter IDs, check if it contains any letter (a-z) + // Sequential IDs are purely numeric + return regexp.MustCompile(`[a-z]`).MatchString(suffix) } // saveMappingFile saves the ID mapping to a JSON file