diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 256cba37..2ed57a3f 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -14,7 +14,7 @@ {"id":"bd-0zp7","title":"Add missing hook calls in mail reply and ack","description":"The mail commands are missing hook calls:\n\n1. runMailReply (mail.go:525-672) creates a message but doesn't call hookRunner.Run(hooks.EventMessage, ...) after creating the reply in direct mode (around line 640)\n\n2. runMailAck (mail.go:432-523) closes messages but doesn't call hookRunner.Run(hooks.EventClose, ...) after closing each message (around line 487 for daemon mode, 493 for direct mode)\n\nThis means GGT hooks won't fire for replies or message acknowledgments.","status":"tombstone","priority":1,"issue_type":"bug","created_at":"2025-12-16T20:52:53.069412-08:00","updated_at":"2025-12-25T01:21:01.952723-08:00","deleted_at":"2025-12-25T01:21:01.952723-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"bug"} {"id":"bd-14ie","title":"Work on beads-2vn: Add simple built-in beads viewer (GH#6...","description":"Work on beads-2vn: Add simple built-in beads viewer (GH#654). Add bd list --pretty with --watch flag, tree view with priority/status symbols. When done, submit MR (not PR) to integration branch for Refinery.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-19T22:56:47.305831-08:00","updated_at":"2025-12-19T23:28:32.429492-08:00","closed_at":"2025-12-19T23:23:13.928323-08:00","close_reason":"Implemented --pretty flag with tree view and symbols. Tests pass."} {"id":"bd-14v0","title":"Add Windows code signing for bd.exe releases","description":"## Context\n\nGo binaries (including bd.exe) are commonly flagged by antivirus software as false positives due to heuristic detection. See docs/ANTIVIRUS.md for full details.\n\n## Problem\n\nKaspersky and other AV software flag bd.exe as PDM:Trojan.Win32.Generic, causing it to be quarantined or deleted.\n\n## Solution\n\nImplement code signing for Windows releases using:\n1. An EV (Extended Validation) code certificate\n2. Integration with GoReleaser to sign Windows binaries during release\n\n## Benefits\n\n- Reduces false positive rates over time as the certificate builds reputation\n- Provides tamper verification for users\n- Improves SmartScreen trust rating on Windows\n- Professional appearance for enterprise users\n\n## Implementation Steps\n\n1. Acquire EV code signing certificate (annual cost ~$300-500)\n2. Set up signtool or osslsigncode in release pipeline\n3. Update .goreleaser.yml to sign Windows binaries\n4. Update checksums to include signed binary hashes\n5. Document signing verification in ANTIVIRUS.md\n\n## References\n\n- docs/ANTIVIRUS.md - Current documentation\n- bd-t4u1 - Original Kaspersky false positive report\n- https://github.com/golang/go/issues/16292 - Go project discussion","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-23T23:46:48.459177-08:00","updated_at":"2025-12-23T23:54:41.912141-08:00","closed_at":"2025-12-23T23:54:41.912141-08:00","close_reason":"Implemented Windows code signing infrastructure. Added signing script, GoReleaser hook, updated release workflow and documentation. Signing is gracefully degraded when certificate secrets are not configured - releases continue as unsigned. Certificate acquisition (EV cert) is still required to actually enable signing.","dependencies":[{"issue_id":"bd-14v0","depends_on_id":"bd-t4u1","type":"discovered-from","created_at":"2025-12-23T23:47:02.024159-08:00","created_by":"daemon"}]} -{"id":"bd-1ban","title":"Test actor direct","status":"open","priority":4,"issue_type":"task","created_at":"2025-12-26T20:46:02.423367-08:00","updated_at":"2025-12-26T20:46:02.423367-08:00"} +{"id":"bd-1ban","title":"Test actor direct","status":"closed","priority":4,"issue_type":"task","created_at":"2025-12-26T20:46:02.423367-08:00","updated_at":"2025-12-28T09:26:06.083095-08:00","closed_at":"2025-12-28T09:26:06.083095-08:00","close_reason":"Removing stale test tasks"} {"id":"bd-1dez","title":"Mol Mall: Formula marketplace using GitHub as backend","description":"Create a marketplace for sharing molecule formulas using GitHub repos as the hosting backend.\n\n## Architecture Update (Dec 2025)\n\n**Formulas are the sharing layer.** With ephemeral protos (bd-rciw), the architecture is:\n\n```\nFormulas ──cook──→ [ephemeral proto] ──pour/wisp──→ Mol/Wisp\n ↑ │\n └────────────────── distill ─────────────────────────┘\n```\n\n- **Formulas**: JSON source files (.formula.json) - the thing you share\n- **Protos**: Transient compilation artifacts - auto-deleted after use\n- **Mols/Wisps**: Execution instances - not shared directly\n\n**Key operations:**\n- `bd distill \u003cmol-id\u003e` → Extract formula from completed work\n- `bd mol publish \u003cformula\u003e` → Share to GitHub\n- `bd mol install \u003curl\u003e` → Fetch from GitHub\n- `bd pour \u003cformula\u003e` → Cook and spawn (proto is ephemeral)\n\n## Why GitHub?\n\nGitHub solves multiple problems at once:\n- **Hosting**: Raw file URLs for formula.json\n- **Versioning**: Git tags (v1.0.0, v1.2.0)\n- **Auth**: GitHub tokens for private formulas\n- **Discovery**: GitHub search, topics, stars\n- **Collaboration**: PRs for contributions, issues for bugs\n- **Organizations**: Natural scoping (@anthropic/, @gastown/)\n\n## URL Scheme\n\n```bash\n# Direct GitHub URL\nbd mol install github.com/anthropics/mol-code-review\n\n# With version tag\nbd mol install github.com/anthropics/mol-code-review@v1.2.0\n\n# Shorthand (via registry lookup)\nbd mol install @anthropic/mol-code-review\n```\n\n## Architecture\n\nEach formula lives in its own repo (like Go modules):\n```\ngithub.com/anthropics/mol-code-review/\n├── formula.json # The formula\n├── README.md # Documentation\n└── CHANGELOG.md # Version history\n```\n\n## ID Namespace\n\n| Entity | ID Format | Example |\n|--------|-----------|---------|\n| Formula (GitHub) | `github.com/org/repo` | `github.com/anthropics/mol-code-review` |\n| Installed formula | `mol-name` | `mol-code-review` |\n| Poured instance | `\u003cdb\u003e-mol-xxx` | `bd-mol-b8c` |","notes":"Deferred - focusing on Christmas launch first","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-25T12:05:17.666574-08:00","updated_at":"2025-12-25T21:53:13.415431-08:00","closed_at":"2025-12-25T21:53:13.415431-08:00","close_reason":"Migrated to gastown rig as gt-uzf2l (Mol Mall is Gas Town infrastructure)"} {"id":"bd-1dez.1","title":"bd distill: Extract formula from mol/epic","description":"Extract a formula from completed work (mol, wisp, or epic).\n\n**Key change**: Distill works on execution artifacts (mols/wisps/epics), not protos.\nProtos are ephemeral - they don't persist. Distillation extracts patterns from\nactual executed work.\n\n## Usage\n```bash\nbd distill bd-mol-xyz -o my-workflow.formula.json\nbd distill bd-epic-abc -o feature-workflow.formula.json\n```\n\n## Use Cases\n- **Emergent patterns**: Structured work manually, want to templatize it\n- **Modified execution**: Poured a formula, added custom steps, want to capture\n- **Learning from success**: Extract what made a complex mol succeed\n\n## Implementation\n1. Load mol/wisp/epic subgraph (root + all children)\n2. Convert to formula JSON structure\n3. Extract variables from patterns (titles, descriptions)\n4. Generate step IDs from issue titles (slugify)\n5. Write .formula.json file\n\n## Output Format\n```json\n{\n \"formula\": \"my-workflow\",\n \"description\": \"...\",\n \"version\": 1,\n \"vars\": { ... },\n \"steps\": [ ... ]\n}\n```\n\n## Architecture Note\nThis closes the formula lifecycle loop:\n Formulas ──cook──→ Mols ──distill──→ Formulas\n\nAll sharing happens via formulas. Mols contain execution context and aren't shared.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T12:05:47.045105-08:00","updated_at":"2025-12-25T18:54:39.967765-08:00","closed_at":"2025-12-25T18:54:39.967765-08:00","close_reason":"Command already implemented; updated help text, added daemon support, and -o shorthand","dependencies":[{"issue_id":"bd-1dez.1","depends_on_id":"bd-1dez","type":"parent-child","created_at":"2025-12-25T12:05:47.045596-08:00","created_by":"daemon"}]} {"id":"bd-1dez.2","title":"bd formula add: Import formula to local catalog","description":"Import a formula file to the local catalog (search path).\n\n**Replaces**: \"bd mol promote\" (proto-to-proto concept is obsolete with ephemeral protos)\n\n## Usage\n```bash\n# Add a formula file to project catalog\nbd formula add my-workflow.formula.json\n\n# Add to user-level catalog\nbd formula add my-workflow.formula.json --scope user\n\n# Add from URL\nbd formula add https://example.com/workflow.formula.json\n```\n\n## Implementation\n1. Parse the formula file (validate JSON structure)\n2. Determine target directory based on scope:\n - project: .beads/formulas/\n - user: ~/.beads/formulas/\n - town: ~/gt/.beads/formulas/\n3. Copy/download formula to target\n4. Verify it is loadable: bd formula show \u003cname\u003e\n\n## Flags\n- `--scope \u003clevel\u003e` - Where to add (project|user|town, default: project)\n- `--name \u003cname\u003e` - Override formula name (default: from file)\n\n## Note\nThis is for manually adding formulas. For GitHub-hosted formulas, use:\n bd mol install github.com/org/formula-name","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T12:05:48.588283-08:00","updated_at":"2025-12-25T19:54:35.242576-08:00","closed_at":"2025-12-25T19:54:35.242576-08:00","close_reason":"Implemented bd formula add command with scope and URL support","dependencies":[{"issue_id":"bd-1dez.2","depends_on_id":"bd-1dez","type":"parent-child","created_at":"2025-12-25T12:05:48.590203-08:00","created_by":"daemon"},{"issue_id":"bd-1dez.2","depends_on_id":"bd-1dez.1","type":"blocks","created_at":"2025-12-25T12:07:06.745686-08:00","created_by":"daemon"}]} @@ -94,7 +94,8 @@ {"id":"bd-56x","title":"Review PR #514: fix plugin install docs","description":"Review and merge PR #514 from aspiers. This PR fixes incorrect docs for installing Claude Code plugin from source in docs/PLUGIN.md. Clarifies shell vs Claude Code commands and fixes the . vs ./beads argument issue. URL: https://github.com/anthropics/beads/pull/514","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-13T08:15:16.865354+11:00","updated_at":"2025-12-25T01:21:01.952723-08:00","deleted_at":"2025-12-25T01:21:01.952723-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"task"} {"id":"bd-581b80b3","title":"bd find-duplicates - AI-powered duplicate detection","description":"Find semantically duplicate issues.\n\nApproaches:\n1. Mechanical: Exact title/description matching\n2. Embeddings: Cosine similarity (cheap, scalable)\n3. AI: LLM-based semantic comparison (expensive, accurate)\n\nUses embeddings by default for \u003e100 issues.\n\nFiles: cmd/bd/find_duplicates.go (new)","status":"tombstone","priority":1,"issue_type":"task","created_at":"2025-10-29T20:49:49.126801-07:00","updated_at":"2025-12-25T01:21:01.952723-08:00","close_reason":"Closed","deleted_at":"2025-12-25T01:21:01.952723-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"task"} {"id":"bd-589x","title":"HANDOFF: Version 0.30.7 release in progress","description":"## Context\nDoing a 0.30.7 patch release with bug fixes.\n\n## What's done\n- Fixed #657: bd graph nil pointer crash (graph.go:102)\n- Fixed #652: Windows npm installer file lock (postinstall.js)\n- Updated CHANGELOG.md and info.go\n- Pushed to main, CI running (run 20390861825)\n- Created version-bump molecule template (bd-6s61) and instantiated for 0.30.7 (bd-8pyn)\n\n## In progress\nMolecule bd-8pyn has 3 remaining tasks:\n - bd-dxo7: Wait for CI to pass\n - bd-7l70: Verify release artifacts \n - bd-5c91: Update local installation\n\n## Check CI\n gh run list --repo steveyegge/beads --limit 1\n gh run view 20390861825 --repo steveyegge/beads\n\n## New feature filed\nbd-n777: Timer beads for scheduled agent callbacks\nDesign for Deacon-managed timers that can interrupt agents via tmux\n\n## Resume commands\n bd --no-daemon show bd-8pyn\n gh run list --repo steveyegge/beads --limit 1","status":"closed","priority":2,"issue_type":"message","assignee":"beads/dave","created_at":"2025-12-19T23:06:14.902334-08:00","updated_at":"2025-12-20T00:49:51.927111-08:00","closed_at":"2025-12-20T00:25:59.596546-08:00"} -{"id":"bd-5b6e","title":"Add tests for helper functions (GetDirtyIssueHash, GetAllDependencyRecords, export hashes)","description":"Several utility functions have 0% coverage:\n- GetDirtyIssueHash (dirty.go)\n- GetAllDependencyRecords (dependencies.go)\n- GetExportHash, SetExportHash, ClearAllExportHashes (hash.go)\n\nThese are lower priority but should have basic coverage.","status":"open","priority":4,"issue_type":"task","created_at":"2025-11-01T22:40:58.989976-07:00","updated_at":"2025-11-01T22:40:58.989976-07:00"} +{"id":"bd-5b6e","title":"Add tests for helper functions (GetDirtyIssueHash, GetAllDependencyRecords, export hashes)","description":"Several utility functions have 0% coverage:\n- GetDirtyIssueHash (dirty.go)\n- GetAllDependencyRecords (dependencies.go)\n- GetExportHash, SetExportHash, ClearAllExportHashes (hash.go)\n\nThese are lower priority but should have basic coverage.","status":"closed","priority":4,"issue_type":"task","created_at":"2025-11-01T22:40:58.989976-07:00","updated_at":"2025-12-28T09:26:06.086196-08:00","closed_at":"2025-12-28T09:26:06.086196-08:00","close_reason":"Removing stale test tasks"} +{"id":"bd-5dmb","title":"Test Agent","status":"tombstone","priority":2,"issue_type":"agent","created_at":"2025-12-28T00:04:29.811433-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-28T00:11:48.074239-08:00","deleted_at":"2025-12-28T00:11:48.074239-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"agent"} {"id":"bd-5e9q","title":"Add backwards-compatible aliases and deprecation warnings","description":"## Task\nEnsure backwards compatibility by adding hidden aliases for all moved commands.\n\n## Implementation\n\n### Create aliases.go\nNew file to centralize alias management:\n```go\npackage main\n\nimport (\n \"fmt\"\n \"os\"\n \n \"github.com/spf13/cobra\"\n)\n\n// Deprecated command aliases for backwards compatibility\n// These will be removed in v0.XX.0\n\nfunc init() {\n // migrate-* → migrate *\n addDeprecatedAlias(\"migrate-hash-ids\", \"migrate hash-ids\")\n addDeprecatedAlias(\"migrate-issues\", \"migrate issues\")\n addDeprecatedAlias(\"migrate-sync\", \"migrate sync\")\n addDeprecatedAlias(\"migrate-tombstones\", \"migrate tombstones\")\n \n // top-level → admin *\n addDeprecatedAlias(\"cleanup\", \"admin cleanup\")\n addDeprecatedAlias(\"compact\", \"admin compact\")\n addDeprecatedAlias(\"reset\", \"admin reset\")\n \n // top-level → formula *\n addDeprecatedAlias(\"cook\", \"formula cook\")\n}\n\nfunc addDeprecatedAlias(old, new string) {\n cmd := \u0026cobra.Command{\n Use: old,\n Hidden: true,\n Run: func(cmd *cobra.Command, args []string) {\n fmt.Fprintf(os.Stderr, \"⚠️ '%s' is deprecated, use '%s' instead\\n\", old, new)\n // Forward execution to new command\n },\n }\n rootCmd.AddCommand(cmd)\n}\n```\n\n### Deprecation behavior\n1. First release: Show warning, execute command\n2. One release later: Show warning, still execute\n3. Third release: Remove aliases entirely\n\n## Files to create\n- cmd/bd/aliases.go\n\n## Files to modify \n- cmd/bd/main.go (ensure aliases loaded)\n","status":"closed","priority":2,"issue_type":"task","assignee":"opal","created_at":"2025-12-27T15:11:33.54574-08:00","created_by":"mayor","updated_at":"2025-12-27T16:06:08.157887-08:00","closed_at":"2025-12-27T16:06:08.157887-08:00","close_reason":"Added aliases.go with infrastructure for backwards-compatible command aliases. Aliases only activate after commands are moved to their new locations.","pinned":true} {"id":"bd-5exm","title":"Merge: bd-49kw","description":"branch: polecat/nux\ntarget: main\nsource_issue: bd-49kw\nrig: beads","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-23T20:43:23.156375-08:00","updated_at":"2025-12-23T21:21:57.693169-08:00","closed_at":"2025-12-23T21:21:57.693169-08:00","close_reason":"stale - no code pushed"} {"id":"bd-5hrq","title":"bd doctor: detect issues referenced in commits but still open","description":"Add a doctor check that finds 'orphaned' issues - ones referenced in git commit messages (e.g., 'fix bug (bd-xxx)') but still marked as open in beads.\n\n**Detection logic:**\n1. Get all open issue IDs from beads\n2. Parse git log for issue ID references matching pattern \\(prefix-[a-z0-9.]+\\)\n3. Report issues that appear in commits but are still open\n\n**Output:**\n⚠ Warning: N issues referenced in commits but still open\n bd-xxx: 'Issue title' (commit abc123)\n bd-yyy: 'Issue title' (commit def456)\n \n These may be implemented but not closed. Run 'bd show \u003cid\u003e' to check.\n\n**Implementation:**\n- Add check to doctor/checks.go\n- Use git log parsing (already have git utilities)\n- Match against configured issue_prefix","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-12-21T21:48:08.473165-08:00","updated_at":"2025-12-21T21:55:37.795109-08:00","closed_at":"2025-12-21T21:55:37.795109-08:00","close_reason":"Implemented CheckOrphanedIssues in git.go with 8 test cases. Detects issues referenced in commits (e.g., 'fix bug (bd-xxx)') that are still open. Shows warning with issue IDs and commit hashes."} @@ -108,7 +109,7 @@ {"id":"bd-68bf","title":"Code review: bd mol bond implementation","description":"Review the mol bond command implementation before shipping.\n\nFocus areas:\n1. runMolBond() - polymorphic dispatch logic correctness\n2. bondProtoProto() - compound proto creation, dependency wiring\n3. bondProtoMol() / bondMolProto() - spawn and attach logic\n4. bondMolMol() - joining molecules, lineage tracking\n5. BondRef usage - is lineage tracked correctly?\n6. Error handling - are all failure modes covered?\n7. Edge cases - what could go wrong?\n\nFile: cmd/bd/mol.go (lines 485-859)\nCommit: 386b513e","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-21T10:13:09.425229-08:00","updated_at":"2025-12-21T11:18:14.206869-08:00","closed_at":"2025-12-21T11:18:14.206869-08:00","close_reason":"Reviewed and fixed label persistence bug","dependencies":[{"issue_id":"bd-68bf","depends_on_id":"bd-o91r","type":"discovered-from","created_at":"2025-12-21T10:13:09.426471-08:00","created_by":"daemon"}]} {"id":"bd-68e4","title":"doctor --fix should export when DB has more issues than JSONL","description":"When 'bd doctor' detects a count mismatch (DB has more issues than JSONL), it currently recommends 'bd sync --import-only', which imports JSONL into DB. But JSONL is the source of truth, not the DB.\n\n**Current behavior:**\n- Doctor detects: DB has 355 issues, JSONL has 292\n- Recommends: 'bd sync --import-only' \n- User runs it: Returns '0 created, 0 updated' (no-op, because JSONL hasn't changed)\n- User is stuck\n\n**Root cause:**\nThe doctor fix is one-directional (JSONL→DB) when it should be bidirectional. If DB has MORE issues, they haven't been exported yet - the fix should be 'bd export' (DB→JSONL), not import.\n\n**Desired fix:**\nIn fix.DBJSONLSync(), detect which has more data:\n- If DB \u003e JSONL: Run 'bd export' to sync JSONL (since DB is the working copy)\n- If JSONL \u003e DB: Run 'bd sync --import-only' to import (JSONL is source of truth)\n- If equal but timestamps differ: Detect based on file mtime\n\nThis makes 'bd doctor --fix' actually fix the problem instead of being a no-op.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-21T11:17:20.994319182-07:00","updated_at":"2025-12-21T11:23:24.38523731-07:00","closed_at":"2025-12-21T11:23:24.38523731-07:00"} {"id":"bd-6a5z","title":"Add stale molecule check to bd doctor","description":"Extend bd doctor to detect stale molecules.\n\n**New check:**\n- Name: 'Stale Molecules'\n- Category: Workflow\n- Severity: Warning (don't fail overall check)\n\n**Detection:**\nReuse logic from bd mol stale command:\n- Find mols where Completed \u003e= Total but root is open\n- Filter to orphaned (not assigned, not pinned)\n- Extra weight if blocking other work\n\n**Output:**\n```\n⚠ Stale Molecules\n Found 2 complete-but-unclosed molecules:\n - bd-xyz: Version bump v0.36.0 (blocking 1 issue)\n - bd-uvw: Old patrol (not blocking)\n Fix: bd close \u003cid\u003e or bd mol squash \u003cid\u003e\n```\n\n**--fix behavior:**\n- Auto-close stale mols (with reason 'Auto-closed by bd doctor')\n- Or prompt interactively with -i flag\n\nDepends on: bd mol stale command","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-24T18:23:24.549941-08:00","updated_at":"2025-12-25T12:42:50.288442-08:00","closed_at":"2025-12-25T12:42:50.288442-08:00","close_reason":"Implemented stale molecules check in bd doctor","dependencies":[{"issue_id":"bd-6a5z","depends_on_id":"bd-anv2","type":"blocks","created_at":"2025-12-24T18:23:48.682552-08:00","created_by":"daemon"}]} -{"id":"bd-6df0","title":"Investigate Claude Code crash logging improvements","description":"## Problem\n\nClaude Code doesn't leave useful crash logs when it terminates unexpectedly. Investigation of a crash on 2025-12-26 showed:\n\n- Debug logs in ~/.claude/debug/ just stop mid-stream with no error/exit message\n- No signal handlers appear to log SIGTERM/SIGKILL/SIGINT\n- No dedicated crash log file exists\n- When Node.js crashes hard or gets killed, there's no record of why\n\n## What we found\n\n- Session debug log (02080b1a-...) stopped at 22:58:40 UTC mid-operation\n- No 'exit', 'error', 'crash', 'signal' entries at end of file\n- macOS DiagnosticReports showed Chrome crashes but no Node crashes\n- System logs showed no relevant kill/OOM events\n\n## Desired improvements\n\n1. Exit handlers that log graceful shutdown\n2. Signal handlers that log SIGTERM/SIGINT before exiting\n3. A dedicated crash log or at least a 'last known state' file\n4. Possibly CLI flags to enable verbose crash debugging\n\n## Investigation paths\n\n- Check if Claude Code has --debug or similar flags\n- Look at Node.js crash handling best practices\n- Consider if we can wrap claude invocations to capture crashes\n\n## Related\n\nThis came up while investigating why a crew worker session crashed at end of a code review task.","status":"open","priority":3,"issue_type":"task","created_at":"2025-12-26T15:20:03.578463-08:00","updated_at":"2025-12-26T15:20:03.578463-08:00","comments":[{"id":1,"issue_id":"bd-6df0","author":"stevey","text":"Found existing flags:\n- `--debug [filter]` - Enable debug mode with optional category filtering (e.g., 'api,hooks' or '!statsig,!file')\n- `--verbose` - Override verbose mode setting from config\n\nThese might help with diagnosing issues, but still won't capture hard crashes. The debug output goes to ~/.claude/debug/\u003csession-id\u003e.txt which is what we were already looking at.\n\nNext step: Could wrap claude invocation to capture exit codes and stderr, or look into Node.js --report-on-signal flags.","created_at":"2025-12-26T23:20:20Z"}]} +{"id":"bd-6df0","title":"Investigate Claude Code crash logging improvements","description":"## Problem\n\nClaude Code doesn't leave useful crash logs when it terminates unexpectedly. Investigation of a crash on 2025-12-26 showed:\n\n- Debug logs in ~/.claude/debug/ just stop mid-stream with no error/exit message\n- No signal handlers appear to log SIGTERM/SIGKILL/SIGINT\n- No dedicated crash log file exists\n- When Node.js crashes hard or gets killed, there's no record of why\n\n## What we found\n\n- Session debug log (02080b1a-...) stopped at 22:58:40 UTC mid-operation\n- No 'exit', 'error', 'crash', 'signal' entries at end of file\n- macOS DiagnosticReports showed Chrome crashes but no Node crashes\n- System logs showed no relevant kill/OOM events\n\n## Desired improvements\n\n1. Exit handlers that log graceful shutdown\n2. Signal handlers that log SIGTERM/SIGINT before exiting\n3. A dedicated crash log or at least a 'last known state' file\n4. Possibly CLI flags to enable verbose crash debugging\n\n## Investigation paths\n\n- Check if Claude Code has --debug or similar flags\n- Look at Node.js crash handling best practices\n- Consider if we can wrap claude invocations to capture crashes\n\n## Related\n\nThis came up while investigating why a crew worker session crashed at end of a code review task.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-26T15:20:03.578463-08:00","updated_at":"2025-12-28T09:28:07.056732-08:00","closed_at":"2025-12-28T09:28:07.056732-08:00","close_reason":"Investigation complete - documented NODE_OPTIONS approach for crash logging","comments":[{"id":1,"issue_id":"bd-6df0","author":"stevey","text":"Found existing flags:\n- `--debug [filter]` - Enable debug mode with optional category filtering (e.g., 'api,hooks' or '!statsig,!file')\n- `--verbose` - Override verbose mode setting from config\n\nThese might help with diagnosing issues, but still won't capture hard crashes. The debug output goes to ~/.claude/debug/\u003csession-id\u003e.txt which is what we were already looking at.\n\nNext step: Could wrap claude invocation to capture exit codes and stderr, or look into Node.js --report-on-signal flags.","created_at":"2025-12-26T23:20:20Z"},{"id":6,"issue_id":"bd-6df0","author":"beads/crew/dave","text":"## Investigation Results\n\n### Key Finding: NODE_OPTIONS works with Claude Code\n\nTested successfully:\n```bash\nNODE_OPTIONS=\"--report-on-fatalerror --report-on-signal --report-uncaught-exception --report-directory=$HOME/.claude/crash-reports\" claude --version\n```\n\nNode.js diagnostic reports will be generated in ~/.claude/crash-reports/ when:\n- Fatal errors occur (--report-on-fatalerror)\n- Signals received (--report-on-signal)\n- Uncaught exceptions (--report-uncaught-exception)\n\n### Implementation Options\n\n1. **User profile (immediate, no code change)**\n Add to ~/.zshrc or ~/.bashrc:\n export NODE_OPTIONS=\"--report-on-fatalerror --report-uncaught-exception --report-directory=$HOME/.claude/crash-reports\"\n\n2. **gastown modification** (requires gastown PR)\n Modify claude invocations in gastown/internal/cmd/*.go to set NODE_OPTIONS env var before spawning claude sessions.\n\n3. **Wrapper script**\n Create ~/.local/bin/claude-wrapped that sets NODE_OPTIONS and execs claude.\n\n### Recommendation\n\nStart with option 1 (user profile) to validate the approach. If useful, implement option 2 in gastown for automatic crash logging in all gt-managed sessions.","created_at":"2025-12-28T17:27:59Z"}]} {"id":"bd-6fe4622f","title":"Remove unreachable utility functions","description":"Several small utility functions are unreachable:\n\nFiles to clean:\n1. `internal/storage/sqlite/hash.go` - `computeIssueContentHash` (line 17)\n - Check if entire file can be deleted if only contains this function\n\n2. `internal/config/config.go` - `FileUsed` (line 151)\n - Delete unused config helper\n\n3. `cmd/bd/git_sync_test.go` - `verifyIssueOpen` (line 300)\n - Delete dead test helper\n\n4. `internal/compact/haiku.go` - `HaikuClient.SummarizeTier2` (line 81)\n - Tier 2 summarization not implemented\n - Options: implement feature OR delete method\n\nImpact: Removes 50-100 LOC depending on decisions","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-10-28T16:20:02.434573-07:00","updated_at":"2025-12-25T01:21:01.952723-08:00","close_reason":"Closed","deleted_at":"2025-12-25T01:21:01.952723-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"task"} {"id":"bd-6gd","title":"Remove legacy MCP Agent Mail integration","description":"## Summary\n\nRemove the legacy MCP Agent Mail system that requires an external HTTP server. Keep the native `bd mail` system which stores messages as git-synced issues.\n\n## Background\n\nTwo mail systems exist in the codebase:\n1. **Legacy Agent Mail** (`bd message`) - External server dependency, complex setup\n2. **Native bd mail** (`bd mail`) - Built-in, git-synced, no dependencies\n\nThe legacy system causes confusion and is no longer needed. Gas Town's Town Mail will use the native `bd mail` system.\n\n## Files to Delete\n\n### CLI Command\n- [ ] `cmd/bd/message.go` - The `bd message` command implementation\n\n### MCP Integration\n- [ ] `integrations/beads-mcp/src/beads_mcp/mail.py` - HTTP wrapper for Agent Mail server\n- [ ] `integrations/beads-mcp/src/beads_mcp/mail_tools.py` - MCP tool definitions\n- [ ] `integrations/beads-mcp/tests/test_mail.py` - Tests for legacy mail\n\n### Documentation\n- [ ] `docs/AGENT_MAIL.md`\n- [ ] `docs/AGENT_MAIL_QUICKSTART.md`\n- [ ] `docs/AGENT_MAIL_DEPLOYMENT.md`\n- [ ] `docs/AGENT_MAIL_MULTI_WORKSPACE_SETUP.md`\n- [ ] `docs/adr/002-agent-mail-integration.md`\n\n## Code to Update\n\n- [ ] Remove `message` command registration from `cmd/bd/main.go`\n- [ ] Remove mail tool imports/registration from MCP server `__init__.py` or `server.py`\n- [ ] Check for any other references to Agent Mail in the codebase\n\n## Verification\n\n- [ ] `bd message` command no longer exists\n- [ ] `bd mail` command still works\n- [ ] MCP server starts without errors\n- [ ] Tests pass\n","status":"tombstone","priority":1,"issue_type":"task","created_at":"2025-12-17T23:04:04.099935-08:00","updated_at":"2025-12-25T01:21:01.952723-08:00","close_reason":"Removed legacy MCP Agent Mail integration. Kept native bd mail system.","deleted_at":"2025-12-25T01:21:01.952723-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"task"} {"id":"bd-6ns7","title":"test hook pin","status":"tombstone","priority":2,"issue_type":"task","assignee":"stevey","created_at":"2025-12-23T04:39:16.619755-08:00","updated_at":"2025-12-23T04:51:29.436788-08:00","deleted_at":"2025-12-23T04:51:29.436788-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} @@ -156,6 +157,7 @@ {"id":"bd-8ca7","title":"Merge: bd-au0.6","description":"branch: polecat/furiosa\ntarget: main\nsource_issue: bd-au0.6\nrig: beads","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-23T20:42:30.870178-08:00","updated_at":"2025-12-23T21:21:57.695179-08:00","closed_at":"2025-12-23T21:21:57.695179-08:00","close_reason":"stale - no code pushed"} {"id":"bd-8e0q","title":"Merge: beads-ocs","description":"branch: polecat/valkyrie\ntarget: main\nsource_issue: beads-ocs\nrig: beads","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-19T23:24:45.281478-08:00","updated_at":"2025-12-20T23:17:26.995706-08:00","closed_at":"2025-12-20T23:17:26.995706-08:00","close_reason":"Branches nuked, MRs obsolete"} {"id":"bd-8fgn","title":"test hash length","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-16T13:49:32.113843-08:00","updated_at":"2025-12-17T16:11:17.070763-08:00","deleted_at":"2025-12-17T16:11:17.070763-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"task"} +{"id":"bd-8fqd","title":"Test role bead","status":"closed","priority":2,"issue_type":"role","created_at":"2025-12-27T23:37:10.275712-08:00","created_by":"mayor","updated_at":"2025-12-27T23:37:15.585821-08:00","closed_at":"2025-12-27T23:37:15.585821-08:00","close_reason":"Test beads for schema change"} {"id":"bd-8g8","title":"Fix G304 potential file inclusion in cmd/bd/tips.go:259","description":"Linting issue: G304: Potential file inclusion via variable (gosec) at cmd/bd/tips.go:259:18. Error: if data, err := os.ReadFile(settingsPath); err == nil {","status":"tombstone","priority":0,"issue_type":"bug","created_at":"2025-12-07T15:34:57.189730843-07:00","updated_at":"2025-12-25T01:21:01.952723-08:00","deleted_at":"2025-12-25T01:21:01.952723-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"bug"} {"id":"bd-8hy","title":"Kill running daemons","description":"Stop all bd daemons before release:\n\n```bash\npkill -f 'bd.*daemon' || true\nsleep 1\npgrep -lf 'bd.*daemon' # Should show nothing\n```","status":"tombstone","priority":1,"issue_type":"task","created_at":"2025-12-18T22:42:58.255478-08:00","updated_at":"2025-12-24T16:25:30.371693-08:00","dependencies":[{"issue_id":"bd-8hy","depends_on_id":"bd-qqc","type":"parent-child","created_at":"2025-12-18T22:43:16.23168-08:00","created_by":"daemon"}],"deleted_at":"2025-12-24T16:25:30.371693-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} {"id":"bd-8pyn","title":"Version Bump: 0.30.7","description":"Release checklist for version 0.30.7. This molecule ensures all release steps are completed properly.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-19T22:56:48.648694-08:00","updated_at":"2025-12-20T00:49:51.927518-08:00","closed_at":"2025-12-20T00:25:59.529183-08:00"} @@ -250,10 +252,11 @@ {"id":"bd-cnwx","title":"Refactor mol.go: split 1200+ line file into subcommands","description":"## Problem\n\ncmd/bd/mol.go has grown to 1200+ lines with all molecule subcommands in one file.\n\n## Current State\n- mol.go: 1218 lines (bond, spawn, run, distill, catalog, show, etc.)\n- Hard to navigate, review, and maintain\n\n## Proposed Structure\nSplit into separate files by subcommand:\n```\ncmd/bd/\n├── mol.go # Root command, shared helpers\n├── mol_bond.go # bd mol bond\n├── mol_spawn.go # bd mol spawn \n├── mol_run.go # bd mol run\n├── mol_distill.go # bd mol distill\n├── mol_catalog.go # bd mol catalog\n├── mol_show.go # bd mol show\n└── mol_test.go # Tests (already separate)\n```\n\n## Benefits\n- Easier code review\n- Better separation of concerns\n- Simpler navigation\n- Each subcommand self-contained","status":"closed","priority":2,"issue_type":"chore","created_at":"2025-12-21T11:30:58.832192-08:00","updated_at":"2025-12-21T11:42:49.390824-08:00","closed_at":"2025-12-21T11:42:49.390824-08:00","close_reason":"Refactored mol.go into 7 files. Build and tests pass."} {"id":"bd-co29","title":"Merge: bd-n386","description":"branch: polecat/immortan\ntarget: main\nsource_issue: bd-n386\nrig: beads","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-23T20:41:45.644113-08:00","updated_at":"2025-12-23T21:21:57.70152-08:00","closed_at":"2025-12-23T21:21:57.70152-08:00","close_reason":"stale - no code pushed"} {"id":"bd-crgr","title":"GH#517: Claude sets priority wrong on new install","description":"Claude uses 'medium/high/low' for priority instead of P0-P4. Update bd prime/onboard output to be clearer about priority syntax. See GitHub issue #517.","status":"tombstone","priority":2,"issue_type":"bug","created_at":"2025-12-16T01:03:34.803084-08:00","updated_at":"2025-12-17T16:11:17.070763-08:00","deleted_at":"2025-12-17T16:11:17.070763-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"bug"} +{"id":"bd-cs2l","title":"Test Agent","status":"tombstone","priority":2,"issue_type":"agent","created_at":"2025-12-28T01:55:35.621013-08:00","created_by":"beads/crew/dave","updated_at":"2025-12-28T02:21:06.391783-08:00","deleted_at":"2025-12-28T02:21:06.391783-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"agent"} {"id":"bd-csnr","title":"activity --follow: Silent error handling","description":"In activity.go:175-179, when the daemon is down or errors occur during polling in --follow mode, errors are silently ignored:\n\n```go\nnewEvents, err := fetchMutations(lastPoll)\nif err != nil {\n // Daemon might be down, continue trying\n continue\n}\n```\n\nThis means:\n- Users won't know if the daemon is unreachable\n- Could appear frozen when actually failing\n- No indication of lost events\n\nShould at least show a warning after N consecutive failures, or show '...' indicator to show polling status.\n\nDiscovered during code review of bd-xo1o implementation.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-23T04:06:18.590743-08:00","updated_at":"2025-12-23T04:16:04.64978-08:00","closed_at":"2025-12-23T04:16:04.64978-08:00","close_reason":"Added error tracking with warning after 5 consecutive failures, reconnection message on recovery, rate-limited warnings (max once per 30s)"} {"id":"bd-ctmg","title":"CLI cleanup: Rename bd mol catalog to bd formula list","description":"## Problem\n`bd mol catalog` shows formulas, not molecules. This is confusing.\n\nCurrent state:\n- `bd formula list` - lists formulas\n- `bd mol catalog` - ALSO lists formulas (duplicate!)\n\nThe \"mol\" namespace should be for molecules (instantiated work), not formulas (templates).\n\n## Proposed Change\n- Remove `bd mol catalog`\n- Keep `bd formula list` as the canonical command\n- Update docs to use `bd formula list`\n\n## Alternative\nIf we want a \"catalog\" concept separate from \"list\", make it `bd formula catalog`.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T14:28:04.647593-08:00","created_by":"mayor","updated_at":"2025-12-27T14:33:44.517362-08:00","closed_at":"2025-12-27T14:33:44.517362-08:00","close_reason":"Removed bd mol catalog command, updated all docs to use bd formula list"} {"id":"bd-cuek","title":"bd doctor --fix destroys child→parent dependencies without confirmation","description":"GH#740: User reports that `bd doctor --fix` removed their intentional child→parent dependencies, calling them an 'anti-pattern'.\n\nThe fix in `cmd/bd/doctor/fix/validation.go` (ChildParentDependencies function) automatically deletes dependencies where a child issue depends on its parent epic.\n\n**Problem**: This assumes all such dependencies are mistakes, but users may intentionally want children blocked by their parent (e.g., 'don't start subtasks until parent is fully scoped').\n\n**Solution options**:\n1. Remove this fix entirely (let users manage their own deps)\n2. Require explicit opt-in flag like `--fix-child-parent`\n3. Add confirmation prompt before destructive action\n4. Add `--dry-run` to preview what would be removed\n5. Only warn, never auto-fix\n\n**Files involved**:\n- `cmd/bd/doctor/validation.go:311-382` (check)\n- `cmd/bd/doctor/fix/validation.go:165-227` (fix)","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-12-25T13:59:52.811547-08:00","updated_at":"2025-12-25T14:05:41.249168-08:00","closed_at":"2025-12-25T14:05:41.249168-08:00","close_reason":"Fixed: added --fix-child-parent flag, removed from default auto-fix"} -{"id":"bd-cwpl","title":"bd doctor --deep: validate full graph integrity","description":"Add a deep validation mode to bd doctor that checks the entire issue graph.\n\nCurrent doctor checks:\n- Orphan sessions\n- Orphan processes \n- Wisp GC\n- Sync status\n\nProposed --deep checks:\n- **Parent consistency**: Every issue with parent field points to existing issue\n- **Dependency symmetry**: If A depends on B, B should show A in blocks\n- **Orphan issues**: Issues mentioned in commits but never closed\n- **Circular dependencies**: Detect dependency cycles\n- **Epic completeness**: Epics with all children closed should be closeable\n- **Agent bead integrity**: Agent beads have required fields (role_bead, state)\n- **Mail thread integrity**: Messages point to valid threads\n- **Molecule state**: Molecules have valid current_step pointing to existing step\n\nUse case: After complex operations (reparenting, migrations, bulk updates), run `bd doctor --deep` to catch graph inconsistencies before they cause problems.\n\nPerformance: May be slow on large databases - warn user and show progress.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-12-27T23:07:22.185409-08:00","created_by":"mayor","updated_at":"2025-12-27T23:07:22.185409-08:00"} +{"id":"bd-cwpl","title":"bd doctor --deep: validate full graph integrity","description":"Add a deep validation mode to bd doctor that checks the entire issue graph.\n\nCurrent doctor checks:\n- Orphan sessions\n- Orphan processes \n- Wisp GC\n- Sync status\n\nProposed --deep checks:\n- **Parent consistency**: Every issue with parent field points to existing issue\n- **Dependency symmetry**: If A depends on B, B should show A in blocks\n- **Orphan issues**: Issues mentioned in commits but never closed\n- **Circular dependencies**: Detect dependency cycles\n- **Epic completeness**: Epics with all children closed should be closeable\n- **Agent bead integrity**: Agent beads have required fields (role_bead, state)\n- **Mail thread integrity**: Messages point to valid threads\n- **Molecule state**: Molecules have valid current_step pointing to existing step\n\nUse case: After complex operations (reparenting, migrations, bulk updates), run `bd doctor --deep` to catch graph inconsistencies before they cause problems.\n\nPerformance: May be slow on large databases - warn user and show progress.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-27T23:07:22.185409-08:00","created_by":"mayor","updated_at":"2025-12-28T02:13:41.833478-08:00","closed_at":"2025-12-28T02:13:41.833478-08:00","close_reason":"Implemented bd doctor --deep command with full graph integrity validation"} {"id":"bd-czss","title":"Update CHANGELOG.md with release notes","description":"Add meaningful release notes to CHANGELOG.md describing what changed in {{version}}","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T22:55:59.909641-08:00","updated_at":"2025-12-20T17:59:26.262153-08:00","closed_at":"2025-12-20T01:23:51.407302-08:00","dependencies":[{"issue_id":"bd-czss","depends_on_id":"bd-6s61","type":"parent-child","created_at":"2025-12-19T22:56:14.862724-08:00","created_by":"daemon"},{"issue_id":"bd-czss","depends_on_id":"bd-qkw9","type":"blocks","created_at":"2025-12-19T22:56:23.145894-08:00","created_by":"daemon"}]} {"id":"bd-d148","title":"GH#483: Pre-commit hook fails unnecessarily when .beads removed","description":"Pre-commit hook fails on bd sync when .beads directory exists but user is on branch without beads. Should exit gracefully. See GitHub issue #483.","status":"tombstone","priority":2,"issue_type":"bug","created_at":"2025-12-16T01:03:40.049785-08:00","updated_at":"2025-12-17T16:11:17.070763-08:00","deleted_at":"2025-12-17T16:11:17.070763-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"bug"} {"id":"bd-d28c","title":"Test createTombstone and deleteIssue wrappers","description":"Add tests for the createTombstone and deleteIssue wrapper functions in cmd/bd/delete.go.\n\n## Functions under test\n- createTombstone (cmd/bd/delete.go:335) - Wrapper around SQLite CreateTombstone\n- deleteIssue (cmd/bd/delete.go:349) - Wrapper around SQLite DeleteIssue\n\n## Test scenarios for createTombstone\n1. Successful tombstone creation\n2. Tombstone with reason and actor tracking\n3. Error when issue doesn't exist\n4. Verify tombstone status set correctly\n5. Verify audit trail recorded\n6. Rollback/error handling\n\n## Test scenarios for deleteIssue\n1. Successful issue deletion\n2. Error on non-existent issue\n3. Verify issue removed from database\n4. Error handling when storage backend doesn't support delete\n\n## Coverage target\nCurrent: 0%\nTarget: \u003e85%\n\n## Related\n- Parent epic: bd-kyll\n- Original issue: bd-7z4","status":"closed","priority":1,"issue_type":"task","assignee":"beads/testcat","created_at":"2025-12-18T13:08:37.669214532-07:00","updated_at":"2025-12-23T21:44:33.169062-08:00","closed_at":"2025-12-23T21:44:33.169062-08:00","close_reason":"Tests merged from polecat/testcat branch and verified passing. 9 test cases added for createTombstone and deleteIssue wrappers.","dependencies":[{"issue_id":"bd-d28c","depends_on_id":"bd-kyll","type":"parent-child","created_at":"2025-12-18T13:08:37.70588226-07:00","created_by":"mhwilkie"}]} @@ -263,6 +266,7 @@ {"id":"bd-d9mu","title":"Cross-rig external dependency support","description":"Support dependencies on issues in other rigs/repos.\n\n## Use Case\n\nGas Town issues often depend on Beads issues (and vice versa). Currently we use labels like `external:beads/bd-xxx` as documentation, but:\n- `bd blocked` doesn't recognize external deps\n- `bd ready` doesn't filter them out\n- No way to query cross-rig status\n\n## Proposed UX\n\n### Adding external deps\n```bash\n# New syntax for bd dep add\nbd dep add gt-a07f external:beads:bd-kwjh\n\n# Or maybe cleaner\nbd dep add gt-a07f --external beads:bd-kwjh\n```\n\n### Showing blocked status\n```bash\nbd blocked\n# → gt-a07f blocked by external:beads:bd-kwjh (unverified)\n\n# With optional cross-rig query\nbd blocked --resolve-external\n# → gt-a07f blocked by external:beads:bd-kwjh (closed) ← unblocked!\n```\n\n### Storage\nCould use:\n- Special dependency type: `type: external`\n- Label convention: `external:rig:id`\n- New field: `external_deps: [\"beads:bd-kwjh\"]`\n\n## Implementation Notes\n\nCross-rig queries would need:\n- Known rig locations (config or discovery)\n- Read-only beads access to external rigs\n- Caching to avoid repeated queries\n\nFor MVP, just recognizing external deps and marking them as 'unverified' blockers would be valuable.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-22T02:27:23.892706-08:00","updated_at":"2025-12-22T22:32:49.261551-08:00","closed_at":"2025-12-22T22:32:49.261551-08:00","close_reason":"Superseded: Cross-rig external dependency support was fully implemented through child issues: bd-om4a (external: prefix syntax), bd-zmmy (bd ready resolution), bd-396j (bd blocked filtering), bd-66w1 (external_projects config), bd-vks2 (dep tree display), bd-mv6h (test coverage). External deps are auto-resolved when external_projects config is set. The --resolve-external flag is not needed."} {"id":"bd-de6","title":"Fix FindBeadsDir to prioritize main repo .beads for worktrees","description":"The FindBeadsDir function should prioritize finding .beads in the main repository root when accessed from a worktree, rather than finding worktree-local .beads directories. This ensures proper sharing of the database across all worktrees.","status":"closed","priority":2,"issue_type":"bug","assignee":"beads/golf","created_at":"2025-12-07T16:48:36.883117467-07:00","updated_at":"2025-12-23T22:33:23.795459-08:00","closed_at":"2025-12-23T22:33:23.795459-08:00","close_reason":"Already implemented - FindBeadsDir prioritizes main repo .beads via IsWorktree() and GetMainRepoRoot(). All tests pass."} {"id":"bd-dhza","title":"Reduce global state in cmd/bd/main.go (25+ variables)","description":"Code health review found main.go has 25+ global variables (lines 57-112):\n\n- dbPath, actor, store, jsonOutput, daemonClient, noDaemon\n- rootCtx, rootCancel, autoFlushEnabled\n- isDirty (marked 'USED BY LEGACY CODE')\n- needsFullExport (marked 'USED BY LEGACY CODE')\n- flushTimer (marked 'DEPRECATED')\n- flushMutex, storeMutex, storeActive\n- flushFailureCount, lastFlushError, flushManager\n- skipFinalFlush, autoImportEnabled\n- versionUpgradeDetected, previousVersion, upgradeAcknowledged\n\nImpact:\n- Hard to test individual commands\n- Race conditions possible\n- State leakage between commands\n\nFix: Move toward dependency injection. Remove deprecated variables. Consider cmd/bd/internal package.","notes":"COMPLETED: Migration of legacy flush state to FlushManager. The main work (isDirty, needsFullExport, flushTimer) moved to local vars in FlushManager.run() lines 170-173. This fixes the race conditions. Remaining globals are: Cobra flag bindings (standard), runtime state (store, daemonClient - structural), store coordination (storeActive/storeMutex). Future: move error tracking to FlushManager, create cmd/bd/internal for encapsulation.","status":"closed","priority":3,"issue_type":"task","assignee":"beads/kilo","created_at":"2025-12-16T18:17:29.643293-08:00","updated_at":"2025-12-23T22:36:09.600594-08:00","closed_at":"2025-12-23T22:36:09.600594-08:00","close_reason":"Legacy flush globals (isDirty, needsFullExport, flushTimer) already migrated to FlushManager local vars. Race conditions fixed. Remaining globals are Cobra flags (standard) or structural (store, daemonClient). Future work filed separately if needed."} +{"id":"bd-djhk","title":"Test agent with fields","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-27T23:44:08.97791-08:00","created_by":"mayor","updated_at":"2025-12-27T23:44:15.275899-08:00","closed_at":"2025-12-27T23:44:15.275899-08:00","close_reason":"Test bead"} {"id":"bd-do8e","title":"Consolidate migrate-* commands under bd migrate","description":"## Task\nMove standalone migrate commands under `bd migrate` parent:\n- `bd migrate-hash-ids` → `bd migrate hash-ids`\n- `bd migrate-issues` → `bd migrate issues`\n- `bd migrate-sync` → `bd migrate sync`\n- `bd migrate-tombstones` → `bd migrate tombstones`\n\n## Implementation\n\n### 1. Update migrate.go\nAdd subcommands to migrateCmd:\n```go\nfunc init() {\n migrateCmd.AddCommand(migrateHashIDsCmd)\n migrateCmd.AddCommand(migrateIssuesCmd)\n migrateCmd.AddCommand(migrateSyncCmd)\n migrateCmd.AddCommand(migrateTombstonesCmd)\n}\n```\n\n### 2. Update each migrate_*.go file\n- Change `Use:` from `migrate-foo` to `foo`\n- Remove `rootCmd.AddCommand()` from init()\n\n### 3. Create hidden aliases for backwards compatibility\nIn main.go, add hidden top-level commands that forward to subcommands.\n\n### 4. Update docs\n- docs/DELETIONS.md - references `bd migrate-tombstones`\n- docs/CLI_REFERENCE.md - migration section\n\n## Files to modify\n- cmd/bd/migrate.go\n- cmd/bd/migrate_hash_ids.go \n- cmd/bd/migrate_issues.go\n- cmd/bd/migrate_sync.go\n- cmd/bd/migrate_tombstones.go\n- cmd/bd/main.go (aliases)\n","status":"closed","priority":2,"issue_type":"task","assignee":"quartz","created_at":"2025-12-27T15:10:41.618026-08:00","created_by":"mayor","updated_at":"2025-12-27T16:01:32.021299-08:00","closed_at":"2025-12-27T16:01:32.021299-08:00","close_reason":"Consolidated migrate-* commands under bd migrate parent with backwards-compat aliases","pinned":true} {"id":"bd-dp4w","title":"Test message","description":"This is a test message body","status":"tombstone","priority":2,"issue_type":"message","created_at":"2025-12-16T18:11:58.467876-08:00","updated_at":"2025-12-17T16:11:17.070763-08:00","deleted_at":"2025-12-17T16:11:17.070763-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"message"} {"id":"bd-dqu8","title":"Restart running daemons","description":"Kill and restart any running bd daemons to pick up new version: pkill -f 'bd daemon' \u0026\u0026 bd daemon --start","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-20T00:32:26.559311-08:00","updated_at":"2025-12-20T00:32:59.123766-08:00","closed_at":"2025-12-20T00:32:59.123766-08:00","close_reason":"Daemons restarted - now running 0.30.7","dependencies":[{"issue_id":"bd-dqu8","depends_on_id":"bd-6s61","type":"parent-child","created_at":"2025-12-20T00:32:39.36213-08:00","created_by":"daemon"},{"issue_id":"bd-dqu8","depends_on_id":"bd-fgw3","type":"blocks","created_at":"2025-12-20T00:32:39.427846-08:00","created_by":"daemon"}]} @@ -290,6 +294,7 @@ {"id":"bd-f616","title":"Digest: Version Bump: test-squash","description":"## Molecule Execution Summary\n\n**Molecule**: Version Bump: test-squash\n**Steps**: 8\n\n**Completed**: 0/8\n\n---\n\n### Steps\n\n1. **[open]** Verify release artifacts\n Check GitHub releases page - binaries for darwin/linux/windows should be available\n\n2. **[open]** Commit and push release\n git add -A \u0026\u0026 git commit \u0026\u0026 git push to trigger CI\n\n3. **[open]** Update CHANGELOG.md with release notes\n Add meaningful release notes to CHANGELOG.md describing what changed in test-squash\n\n4. **[open]** Wait for CI to pass\n Monitor GitHub Actions - all checks must pass before release artifacts are built\n\n5. **[open]** Restart running daemons\n Kill and restart any running bd daemons to pick up new version: pkill -f 'bd daemon' \u0026\u0026 bd daemon --start\n\n6. **[open]** Update local installation\n Run install script or brew upgrade to get new version locally: curl -fsSL .../install.sh | bash\n\n7. **[open]** Run bump-version.sh test-squash\n Run ./scripts/bump-version.sh test-squash to update version in all files\n\n8. **[open]** Update info.go versionChanges\n Add entry to versionChanges in cmd/bd/info.go with agent-actionable changes for test-squash\n\n","status":"tombstone","priority":1,"issue_type":"task","created_at":"2025-12-21T13:53:18.471919-08:00","updated_at":"2025-12-21T13:53:35.256043-08:00","close_reason":"Squashed from 8 ephemeral steps","deleted_at":"2025-12-21T13:53:35.256043-08:00","deleted_by":"stevey","delete_reason":"manual delete","original_type":"task"} {"id":"bd-f7p1","title":"Add tests for mol spawn --attach","description":"Code review (bd-obep) found no tests for the spawn --attach functionality.\n\n**Test cases needed:**\n1. Basic attach - spawn proto with one --attach\n2. Multiple attachments - spawn with --attach A --attach B\n3. Attach types - verify sequential vs parallel bonding\n4. Error case: attaching non-proto (missing template label)\n5. Variable aggregation - vars from primary + attachments combined\n6. Dry-run output includes attachment info\n\n**Implementation notes:**\n- Tests should use in-memory storage\n- Create test protos, spawn with attachments, verify dependency structure\n- Check that sequential uses 'blocks' type, parallel uses 'parent-child'","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-21T10:58:16.766461-08:00","updated_at":"2025-12-21T21:33:12.136215-08:00","closed_at":"2025-12-21T21:33:12.136215-08:00","close_reason":"Added 6 tests for mol spawn --attach: basic attach, multiple attachments, sequential/parallel bond types, non-proto validation, variable aggregation, and dry-run output","dependencies":[{"issue_id":"bd-f7p1","depends_on_id":"bd-obep","type":"discovered-from","created_at":"2025-12-21T10:58:16.767616-08:00","created_by":"daemon"}]} {"id":"bd-fber","title":"Work on gt-8tmz.31: Formula validation specification. Wri...","description":"Work on gt-8tmz.31: Formula validation specification. Write docs/formula-validation.md specifying all validation rules for formulas. When done: 1) bd close gt-8tmz.31, 2) bd sync, 3) git push, 4) gt mq submit","status":"closed","priority":2,"issue_type":"task","assignee":"beads/slit","created_at":"2025-12-25T19:26:36.741916-08:00","updated_at":"2025-12-25T19:32:10.788141-08:00","closed_at":"2025-12-25T19:32:10.788141-08:00","close_reason":"Completed: wrote docs/formula-validation.md with full specification of parse-time, cook-time, and instantiation-time validation rules"} +{"id":"bd-fbl9","title":"Test parent task","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T23:26:53.012747-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-27T23:27:40.44858-08:00","closed_at":"2025-12-27T23:27:40.44858-08:00","close_reason":"Test issues, cleanup"} {"id":"bd-fcl1","title":"Merge: bd-au0.5","description":"branch: polecat/Searcher\ntarget: main\nsource_issue: bd-au0.5\nrig: beads","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-23T13:39:11.946667-08:00","updated_at":"2025-12-23T19:12:08.346454-08:00","closed_at":"2025-12-23T19:12:08.346454-08:00","close_reason":"Stale merge-requests from orphaned polecat branches - refinery not processing"} {"id":"bd-fd0w","title":"Witness Patrol","description":"Per-rig worker monitor patrol loop with progressive nudging.","status":"open","priority":2,"issue_type":"molecule","created_at":"2025-12-27T18:14:26.008274-08:00","created_by":"deacon","updated_at":"2025-12-27T18:14:26.008274-08:00"} {"id":"bd-fej5","title":"bd hook: detect agent from cwd instead of defaulting to $USER","description":"**Problem:**\n`bd hook` without `--agent` defaults to `$USER` (e.g., \"stevey\") instead of detecting the agent identity from the current working directory.\n\n**Expected behavior:**\nWhen running from `/Users/stevey/gt/beads/crew/dave`, the agent should be detected as `beads/crew/dave`.\n\n**Current behavior:**\n```bash\n$ pwd\n/Users/stevey/gt/beads/crew/dave\n$ bd hook\nHook: stevey\n (empty)\n\n$ bd hook --agent beads/crew/dave\nHook: beads/crew/dave\n 📌 bd-hobo (mol) - open\n```\n\n**Fix:**\nbd hook should use the same cwd-based agent detection that other commands use (similar to how `gt mail` determines identity from cwd).","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-24T20:01:27.613892-08:00","updated_at":"2025-12-25T12:41:10.65257-08:00","closed_at":"2025-12-25T12:41:10.65257-08:00","close_reason":"Obsolete: fix belongs in gastown - gt should set BD_ACTOR env var when spawning agents. bd already checks BD_ACTOR."} @@ -333,7 +338,7 @@ {"id":"bd-hzvz","title":"Update info.go versionChanges","description":"Add entry to versionChanges in cmd/bd/info.go with agent-actionable changes for 0.30.7","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T22:56:48.649359-08:00","updated_at":"2025-12-19T22:57:31.604229-08:00","closed_at":"2025-12-19T22:57:31.604229-08:00","dependencies":[{"issue_id":"bd-hzvz","depends_on_id":"bd-8pyn","type":"parent-child","created_at":"2025-12-19T22:56:48.652068-08:00","created_by":"stevey"},{"issue_id":"bd-hzvz","depends_on_id":"bd-2ep8","type":"blocks","created_at":"2025-12-19T22:56:48.652376-08:00","created_by":"stevey"}]} {"id":"bd-i0rx","title":"Merge: bd-ao0s","description":"branch: polecat/rictus\ntarget: main\nsource_issue: bd-ao0s\nrig: beads","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-20T01:13:42.716658-08:00","updated_at":"2025-12-20T23:17:26.993744-08:00","closed_at":"2025-12-20T23:17:26.993744-08:00","close_reason":"Branches nuked, MRs obsolete"} {"id":"bd-i5l","title":"Witness Patrol","description":"Per-rig worker monitor patrol loop with progressive nudging.","status":"tombstone","priority":2,"issue_type":"molecule","created_at":"2025-12-26T21:20:47.650732-08:00","created_by":"deacon","updated_at":"2025-12-27T00:10:54.176287-08:00","deleted_at":"2025-12-27T00:10:54.176287-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"molecule"} -{"id":"bd-i7a6","title":"Test actor flag","status":"open","priority":4,"issue_type":"task","created_at":"2025-12-26T20:47:28.470006-08:00","updated_at":"2025-12-26T20:47:28.470006-08:00"} +{"id":"bd-i7a6","title":"Test actor flag","status":"closed","priority":4,"issue_type":"task","created_at":"2025-12-26T20:47:28.470006-08:00","updated_at":"2025-12-28T09:26:06.084894-08:00","closed_at":"2025-12-28T09:26:06.084894-08:00","close_reason":"Removing stale test tasks"} {"id":"bd-ia3g","title":"BondRef.ProtoID field name is misleading for mol+mol bonds","description":"In bondMolMol, the BondRef.ProtoID field is used to store molecule IDs:\n\n```go\nBondedFrom: append(molA.BondedFrom, types.BondRef{\n ProtoID: molB.ID, // This is a molecule, not a proto\n ...\n})\n```\n\nThis is semantically confusing since ProtoID suggests it should only hold proto references.\n\n**Options:**\n1. Rename ProtoID to SourceID (breaking change, needs migration)\n2. Add documentation clarifying ProtoID can hold molecule IDs in bond context\n3. Leave as-is, accept the naming is imprecise\n\nLow priority since it's just naming, not functionality.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-21T10:23:00.755067-08:00","updated_at":"2025-12-25T14:30:47.455867-08:00"} {"id":"bd-ibl9","title":"Merge: bd-4qfb","description":"branch: polecat/Polish\ntarget: main\nsource_issue: bd-4qfb\nrig: beads","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-23T13:37:57.255125-08:00","updated_at":"2025-12-23T19:12:08.352249-08:00","closed_at":"2025-12-23T19:12:08.352249-08:00","close_reason":"Stale merge-requests from orphaned polecat branches - refinery not processing"} {"id":"bd-icfe","title":"gt spawn/crew setup should create .beads/redirect for worktrees","description":"Crew clones and polecats need a .beads/redirect file pointing to the shared beads database (../../mayor/rig/.beads). Currently:\n\n- redirect files can get deleted by git clean\n- not auto-created during gt spawn or worktree setup\n- missing redirects cause 'no beads database found' errors\n\nFound missing in: gastown/joe, beads/zoey (after git clean)\n\nFix options:\n1. gt spawn creates redirect during worktree setup\n2. gt prime regenerates missing redirects\n3. bd commands auto-detect worktree and find shared beads\n\nThis should be standard Gas Town rig configuration.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-21T01:30:26.115872-08:00","updated_at":"2025-12-21T17:51:25.740811-08:00","closed_at":"2025-12-21T17:51:25.740811-08:00","close_reason":"Moved to gastown: gt-b6qm"} @@ -396,7 +401,7 @@ {"id":"bd-lfiu","title":"bd dep add: Auto-resolve cross-rig IDs using routes.jsonl","description":"Currently, adding a dependency to an issue in another rig requires verbose external reference syntax:\n\n```bash\n# This fails - can't resolve bd-* from gastown context\nbd dep add gt-xyz bd-abc\n\n# This works but is verbose\nbd dep add gt-xyz external:beads:bd-abc\n```\n\nThe town-level routing (~/gt/.beads/routes.jsonl) already knows how to map prefixes to rigs:\n```json\n{\"prefix\": \"gt-\", \"path\": \"gastown/mayor/rig\"}\n{\"prefix\": \"bd-\", \"path\": \"beads/mayor/rig\"}\n```\n\nEnhancement: When `bd dep add` encounters an ID with a foreign prefix, it should:\n1. Check routes.jsonl for the prefix mapping\n2. Auto-resolve to external:\u003cproject\u003e:\u003cid\u003e internally\n3. Allow the simpler `bd dep add gt-xyz bd-abc` syntax\n\nThis would make cross-rig dependencies much more ergonomic.","status":"closed","priority":3,"issue_type":"feature","assignee":"beads/dave","created_at":"2025-12-26T20:20:40.814713-08:00","updated_at":"2025-12-26T23:47:52.82107-08:00","closed_at":"2025-12-26T23:47:52.82107-08:00","close_reason":"Implemented in commit a958c834"} {"id":"bd-likt","title":"Add daemon RPC support for gate commands","description":"Add daemon RPC support for gate commands.\n\n## Current State\nGate commands require --no-daemon flag because they use direct SQLite access:\n- Gate create needs to write await_type, await_id, timeout_ns, waiters fields\n- Gate wait needs to update waiters JSON array\n- Daemon RPC doesnt have methods for these operations\n\n## Implementation\n\n### 1. Add RPC methods to internal/rpc/protocol.go\n\n```go\n// Gate operations\ntype GateCreateArgs struct {\n Title string \\`json:\"title\"\\`\n AwaitType string \\`json:\"await_type\"\\`\n AwaitID string \\`json:\"await_id\"\\`\n Timeout time.Duration \\`json:\"timeout\"\\`\n Waiters []string \\`json:\"waiters\"\\`\n}\n\ntype GateCreateResult struct {\n Issue *types.Issue \\`json:\"issue\"\\`\n}\n\ntype GateListArgs struct {\n All bool \\`json:\"all\"\\` // Include closed gates\n}\n\ntype GateListResult struct {\n Gates []*types.Issue \\`json:\"gates\"\\`\n}\n\ntype GateWaitArgs struct {\n GateID string \\`json:\"gate_id\"\\`\n Waiters []string \\`json:\"waiters\"\\` // Additional waiters to add\n}\n\ntype GateWaitResult struct {\n Gate *types.Issue \\`json:\"gate\"\\`\n AddedCount int \\`json:\"added_count\"\\`\n}\n```\n\n### 2. Add handler methods to internal/daemon/rpc_handler.go\n\n```go\nfunc (h *RPCHandler) GateCreate(ctx context.Context, args *rpc.GateCreateArgs) (*rpc.GateCreateResult, error) {\n now := time.Now()\n gate := \u0026types.Issue{\n Title: args.Title,\n IssueType: types.TypeGate,\n Status: types.StatusOpen,\n Priority: 1,\n Assignee: \"deacon/\",\n Wisp: true,\n AwaitType: args.AwaitType,\n AwaitID: args.AwaitID,\n Timeout: args.Timeout,\n Waiters: args.Waiters,\n CreatedAt: now,\n UpdatedAt: now,\n }\n gate.ContentHash = gate.ComputeContentHash()\n \n if err := h.store.CreateIssue(ctx, gate, h.actor); err != nil {\n return nil, err\n }\n \n return \u0026rpc.GateCreateResult{Issue: gate}, nil\n}\n\nfunc (h *RPCHandler) GateList(ctx context.Context, args *rpc.GateListArgs) (*rpc.GateListResult, error) {\n gateType := types.TypeGate\n filter := types.IssueFilter{IssueType: \u0026gateType}\n if !args.All {\n openStatus := types.StatusOpen\n filter.Status = \u0026openStatus\n }\n \n gates, err := h.store.SearchIssues(ctx, \"\", filter)\n if err != nil {\n return nil, err\n }\n \n return \u0026rpc.GateListResult{Gates: gates}, nil\n}\n\nfunc (h *RPCHandler) GateWait(ctx context.Context, args *rpc.GateWaitArgs) (*rpc.GateWaitResult, error) {\n gate, err := h.store.GetIssue(ctx, args.GateID)\n if err != nil {\n return nil, err\n }\n if gate.IssueType != types.TypeGate {\n return nil, fmt.Errorf(\"%s is not a gate\", args.GateID)\n }\n \n // Merge waiters (dedupe)\n waiterSet := make(map[string]bool)\n for _, w := range gate.Waiters {\n waiterSet[w] = true\n }\n added := 0\n for _, w := range args.Waiters {\n if !waiterSet[w] {\n gate.Waiters = append(gate.Waiters, w)\n waiterSet[w] = true\n added++\n }\n }\n \n if added \u003e 0 {\n // Update via store\n updates := map[string]interface{}{\n \"waiters\": gate.Waiters,\n }\n if err := h.store.UpdateIssue(ctx, args.GateID, updates, h.actor); err != nil {\n return nil, err\n }\n }\n \n return \u0026rpc.GateWaitResult{Gate: gate, AddedCount: added}, nil\n}\n```\n\n### 3. Register methods in daemon\n\nIn internal/daemon/server.go, register the new methods:\n```go\nrpc.RegisterMethod(\"gate.create\", h.GateCreate)\nrpc.RegisterMethod(\"gate.list\", h.GateList)\nrpc.RegisterMethod(\"gate.wait\", h.GateWait)\n```\n\n### 4. Add client methods to internal/rpc/client.go\n\n```go\nfunc (c *Client) GateCreate(ctx context.Context, args *GateCreateArgs) (*GateCreateResult, error) {\n var result GateCreateResult\n err := c.Call(ctx, \"gate.create\", args, \u0026result)\n return \u0026result, err\n}\n\nfunc (c *Client) GateList(ctx context.Context, args *GateListArgs) (*GateListResult, error) {\n var result GateListResult\n err := c.Call(ctx, \"gate.list\", args, \u0026result)\n return \u0026result, err\n}\n\nfunc (c *Client) GateWait(ctx context.Context, args *GateWaitArgs) (*GateWaitResult, error) {\n var result GateWaitResult\n err := c.Call(ctx, \"gate.wait\", args, \u0026result)\n return \u0026result, err\n}\n```\n\n### 5. Update cmd/bd/gate.go to use daemon\n\n```go\n// In gateCreateCmd Run:\nif daemonClient != nil {\n result, err := daemonClient.GateCreate(ctx, \u0026rpc.GateCreateArgs{\n Title: title,\n AwaitType: awaitType,\n AwaitID: awaitID,\n Timeout: timeout,\n Waiters: notifyAddrs,\n })\n if err != nil {\n FatalError(\"gate create: %v\", err)\n }\n gate = result.Issue\n} else {\n // Existing direct store code\n}\n```\n\n## Files to Modify\n\n1. **internal/rpc/protocol.go** - Add Gate*Args/Result types\n2. **internal/daemon/rpc_handler.go** - Add handler methods\n3. **internal/daemon/server.go** - Register methods\n4. **internal/rpc/client.go** - Add client methods\n5. **cmd/bd/gate.go** - Use daemon client when available\n\n## Testing\n\n```bash\n# Start daemon\nbd daemon start\n\n# Test via daemon (should work without --no-daemon)\nbd gate create --await timer:5m --notify beads/dave\nbd gate list\nbd gate wait \u003cid\u003e --notify beads/alice\n\n# Verify daemon handled it\nbd daemons logs . | grep gate\n```\n\n## Success Criteria\n- All gate commands work without --no-daemon\n- Same behavior in daemon vs direct mode\n- Waiters array updates correctly via RPC\n- Tests pass for RPC gate operations","status":"closed","priority":3,"issue_type":"task","assignee":"beads/Gater","created_at":"2025-12-23T12:13:25.778412-08:00","updated_at":"2025-12-23T13:45:58.398604-08:00","closed_at":"2025-12-23T13:45:58.398604-08:00","close_reason":"Implemented daemon RPC support for all gate commands","dependencies":[{"issue_id":"bd-likt","depends_on_id":"bd-udsi","type":"discovered-from","created_at":"2025-12-23T12:13:36.174822-08:00","created_by":"daemon"},{"issue_id":"bd-likt","depends_on_id":"bd-iz5t","type":"parent-child","created_at":"2025-12-23T12:44:07.891992-08:00","created_by":"daemon"}]} {"id":"bd-lk39","title":"Add composite index (issue_id, event_type) on events table","description":"GetCloseReason and GetCloseReasonsForIssues filter by both issue_id and event_type.\n\n**Query (queries.go:355-358):**\n```sql\nSELECT comment FROM events\nWHERE issue_id = ? AND event_type = ?\nORDER BY created_at DESC LIMIT 1\n```\n\n**Problem:** Currently uses idx_events_issue but must filter event_type in memory.\n\n**Solution:** Add migration:\n```sql\nCREATE INDEX IF NOT EXISTS idx_events_issue_type ON events(issue_id, event_type);\n```\n\n**Priority:** Low - events table is typically small relative to issues.","status":"closed","priority":4,"issue_type":"task","created_at":"2025-12-22T22:58:54.070587-08:00","updated_at":"2025-12-22T23:15:13.841988-08:00","closed_at":"2025-12-22T23:15:13.841988-08:00","close_reason":"Implemented in migration 026_additional_indexes.go","dependencies":[{"issue_id":"bd-lk39","depends_on_id":"bd-h0we","type":"discovered-from","created_at":"2025-12-22T22:58:54.071286-08:00","created_by":"daemon"}]} -{"id":"bd-llfl","title":"Improve test coverage for cmd/bd CLI (26.2% → 50%)","description":"The main CLI package (cmd/bd) has only 26.2% test coverage. CLI commands should have at least 50% coverage to ensure reliability.\n\nKey areas with low/no coverage:\n- daemon_autostart.go (multiple 0% functions)\n- compact.go (several 0% functions)\n- Various command handlers\n\nCurrent coverage: 26.2%\nTarget coverage: 50%","notes":"## Progress Update (2025-12-23)\n\n### Tests Added\nAdded 683 lines of new tests across 3 files:\n- cmd/bd/daemon_config_test.go (144 lines)\n- cmd/bd/utils_test.go (484 lines) \n- cmd/bd/autostart_test.go (55 additional lines)\n\n### Functions Now Tested\n- daemon_config.go: ensureBeadsDir, getPIDFilePath, getLogFilePath, getSocketPathForPID\n- daemon_autostart.go: determineSocketPath, isDaemonRunningQuiet\n- activity.go: printEvent\n- cleanup.go: showCleanupDeprecationHint\n- upgrade.go: pluralize\n- wisp.go: formatTimeAgo\n- list.go: pinIndicator, sortIssues\n- hooks.go: FormatHookWarnings, isRebaseInProgress, hasBeadsJSONL\n- template.go: extractIDSuffix\n- thanks.go: getContributorsSorted\n\n### Coverage Results\n- Before: 22.5%\n- After: 23.1%\n- Delta: +0.6%\n\n### Remaining Work\nMost remaining untested code (77%) involves:\n1. Daemon/RPC operations (runDaemonLoop, tryAutoStartDaemon, etc.)\n2. Command handlers that require database/daemon setup\n3. Git operations (runPreCommitHook, runPostMergeHook, etc.)\n\nTo reach 50%, would need to:\n- Add integration tests with mocked daemon\n- Add scripttest tests for command handlers\n- Add more database-dependent tests\n\nCommit: 4f949c19","status":"in_progress","priority":2,"issue_type":"task","assignee":"beads/charlie","created_at":"2025-12-13T20:43:03.123341-08:00","updated_at":"2025-12-23T22:45:57.860498-08:00"} +{"id":"bd-llfl","title":"Improve test coverage for cmd/bd CLI (26.2% → 50%)","description":"The main CLI package (cmd/bd) has only 26.2% test coverage. CLI commands should have at least 50% coverage to ensure reliability.\n\nKey areas with low/no coverage:\n- daemon_autostart.go (multiple 0% functions)\n- compact.go (several 0% functions)\n- Various command handlers\n\nCurrent coverage: 26.2%\nTarget coverage: 50%","notes":"## Progress Update (2025-12-23)\n\n### Tests Added\nAdded 683 lines of new tests across 3 files:\n- cmd/bd/daemon_config_test.go (144 lines)\n- cmd/bd/utils_test.go (484 lines) \n- cmd/bd/autostart_test.go (55 additional lines)\n\n### Functions Now Tested\n- daemon_config.go: ensureBeadsDir, getPIDFilePath, getLogFilePath, getSocketPathForPID\n- daemon_autostart.go: determineSocketPath, isDaemonRunningQuiet\n- activity.go: printEvent\n- cleanup.go: showCleanupDeprecationHint\n- upgrade.go: pluralize\n- wisp.go: formatTimeAgo\n- list.go: pinIndicator, sortIssues\n- hooks.go: FormatHookWarnings, isRebaseInProgress, hasBeadsJSONL\n- template.go: extractIDSuffix\n- thanks.go: getContributorsSorted\n\n### Coverage Results\n- Before: 22.5%\n- After: 23.1%\n- Delta: +0.6%\n\n### Remaining Work\nMost remaining untested code (77%) involves:\n1. Daemon/RPC operations (runDaemonLoop, tryAutoStartDaemon, etc.)\n2. Command handlers that require database/daemon setup\n3. Git operations (runPreCommitHook, runPostMergeHook, etc.)\n\nTo reach 50%, would need to:\n- Add integration tests with mocked daemon\n- Add scripttest tests for command handlers\n- Add more database-dependent tests\n\nCommit: 4f949c19","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-13T20:43:03.123341-08:00","updated_at":"2025-12-28T05:39:24.91767-08:00"} {"id":"bd-lo4","title":"Test pinned issue","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-18T21:44:49.031385-08:00","updated_at":"2025-12-18T21:47:25.055109-08:00","deleted_at":"2025-12-18T21:47:25.055109-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} {"id":"bd-lsv4","title":"GH#444: Fix inconsistent status naming in_progress vs in-progress","description":"Documentation uses in-progress (hyphen) but code expects in_progress (underscore). Update all docs to use canonical in_progress. See GitHub issue #444.","status":"tombstone","priority":2,"issue_type":"bug","created_at":"2025-12-16T01:03:14.349425-08:00","updated_at":"2025-12-17T16:11:17.070763-08:00","deleted_at":"2025-12-17T16:11:17.070763-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"bug"} {"id":"bd-lw0x","title":"Fix bd sync race condition with daemon causing dirty working directory","description":"After bd sync completes with sync.branch mode, subsequent bd commands or daemon file watcher would see a hash mismatch and trigger auto-import, which then schedules re-export, dirtying the working directory.\n\n**Root cause:**\n1. bd sync exports JSONL with NEW content (hash H1)\n2. bd sync updates jsonl_content_hash = H1 in DB\n3. bd sync restores JSONL from HEAD (OLD content, hash H0)\n4. Now: file hash = H0, DB hash = H1 (MISMATCH)\n5. Daemon or next CLI command sees mismatch, imports from OLD JSONL\n6. Import triggers re-export → file is dirty\n\n**Fix:**\nAfter restoreBeadsDirFromBranch(), update jsonl_content_hash to match the restored file's hash. This ensures daemon and CLI see file hash = DB hash → no spurious import/export cycle.\n\nRelated: bd-c83r (multiple daemon prevention)","status":"tombstone","priority":2,"issue_type":"bug","created_at":"2025-12-13T06:42:17.130839-08:00","updated_at":"2025-12-25T01:21:01.952723-08:00","deleted_at":"2025-12-25T01:21:01.952723-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"bug"} @@ -407,49 +412,49 @@ {"id":"bd-m8ro","title":"Improve test coverage for internal/rpc (47.5% → 60%)","description":"The RPC package has only 47.5% test coverage. RPC is the communication layer for daemon operations.\n\nCurrent coverage: 47.5%\nTarget coverage: 60%","status":"closed","priority":2,"issue_type":"task","assignee":"beads/delta","created_at":"2025-12-13T20:43:09.515299-08:00","updated_at":"2025-12-23T22:42:11.921388-08:00","closed_at":"2025-12-23T22:42:11.921388-08:00","close_reason":"Improved test coverage from 44.7% to 61.7% by adding comprehensive tests for Count, ResolveID, Delete, Stale, Comment, Metrics, Gate operations, Export, GetMutations, and MutationChan"} {"id":"bd-m964","title":"Consider FTS5 for text search at scale","description":"SearchIssues uses LIKE patterns for text search which can't use indexes.\n\n**Current query (queries.go:1475-1477):**\n```sql\n(title LIKE ? OR description LIKE ? OR id LIKE ?)\n```\n\n**Problem:** Full table scan on every text search. At 100K+ issues, this becomes slow.\n\n**SQLite FTS5 solution:**\n```sql\nCREATE VIRTUAL TABLE issues_fts USING fts5(\n id, title, description, design, notes,\n content='issues',\n content_rowid='rowid'\n);\n\n-- Triggers to keep FTS in sync\nCREATE TRIGGER issues_ai AFTER INSERT ON issues BEGIN\n INSERT INTO issues_fts(rowid, id, title, description, design, notes)\n VALUES (new.rowid, new.id, new.title, new.description, new.design, new.notes);\nEND;\n-- (similar for UPDATE, DELETE)\n```\n\n**Trade-offs:**\n- Database size increase (~30-50% for text content)\n- Additional write overhead (trigger execution)\n- Better search capabilities (ranking, phrase search)\n\n**Decision needed:** Is full-text search a priority feature? Current LIKE search may be acceptable for most use cases.\n\n**Benchmark first:** Measure SearchIssues at 100K scale before implementing.","status":"open","priority":4,"issue_type":"feature","created_at":"2025-12-22T22:58:56.466121-08:00","updated_at":"2025-12-22T22:58:56.466121-08:00","dependencies":[{"issue_id":"bd-m964","depends_on_id":"bd-h0we","type":"discovered-from","created_at":"2025-12-22T22:58:56.466764-08:00","created_by":"daemon"}]} {"id":"bd-mh4w","title":"Rename 'bond' to 'spawn' for instantiation","description":"Rename the bd mol bond command to bd mol spawn for instantiating protos.\n \n- Rename molBondCmd to molSpawnCmd\n- Update command Use/Short/Long descriptions \n- Keep 'bond' available for the new bonding feature\n- Update all documentation references\n- Add 'protomolecule' as easter egg alias for 'proto'","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-21T00:58:44.529026-08:00","updated_at":"2025-12-21T01:19:42.942819-08:00","closed_at":"2025-12-21T01:19:42.942819-08:00","close_reason":"Renamed 'bond' to 'spawn' in mol.go, updated all user-facing messages and help text","dependencies":[{"issue_id":"bd-mh4w","depends_on_id":"bd-o5xe","type":"parent-child","created_at":"2025-12-21T00:59:51.167902-08:00","created_by":"daemon"}]} -{"id":"bd-mol-0qm","title":"mol-beads-release","description":"attached_args: Release v0.38.0 - execute each step in order, verify before proceeding to next\n\nRelease checklist for beads version 0.38.0.\n\nThis molecule ensures all release steps are completed properly.\nVariable: 0.38.0 - target version (e.g., 0.35.0)\n\n## Step: update-release-notes\nUpdate cmd/bd/info.go with release notes for 0.38.0.\n\nAdd a new VersionChange entry at the top of versionChanges slice:\n```go\n{\n Version: \"0.38.0\",\n Date: \"YYYY-MM-DD\",\n Changes: []string{\n \"NEW: Feature description\",\n \"FIX: Bug fix description\",\n \"IMPROVED: Enhancement description\",\n },\n},\n```\n\nRun `git log --oneline v\u003cprevious\u003e..HEAD` to see what changed.\n\n## Step: update-changelog\nUpdate CHANGELOG.md with detailed release notes.\n\nAdd a new section after [Unreleased]:\n```markdown\n## [0.38.0] - YYYY-MM-DD\n\n### Added\n- **Feature name** (issue-id) - Description\n\n### Changed\n- **Change description** (issue-id)\n\n### Fixed\n- **Bug fix** (issue-id) - Description\n```\n\nSort by importance, not chronologically.\nNeeds: update-release-notes\n\n## Step: bump-version\nRun the version bump script.\n\n```bash\n./scripts/bump-version.sh 0.38.0\n```\n\nThis updates version in all files:\n- cmd/bd/version.go\n- .claude-plugin/*.json\n- integrations/beads-mcp/pyproject.toml\n- npm-package/package.json\n- Hook templates\n\nNeeds: update-changelog\n\n## Step: run-tests\nRun tests and verify lint passes.\n\n```bash\ngo test -short ./...\n```\n\nCI will run full lint, but fix any obvious issues first.\nNeeds: bump-version\n\n## Step: commit-release\nCommit the release changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: bump version to v0.38.0\"\n```\n\nNeeds: run-tests\n\n## Step: push-and-tag\nPush commit and create release tag.\n\n```bash\ngit push origin main\ngit tag v0.38.0\ngit push origin v0.38.0\n```\n\nThis triggers GitHub Actions release workflow.\nNeeds: commit-release\n\n## Step: wait-for-ci\nWait for GitHub Actions to complete.\n\nMonitor: https://github.com/steveyegge/beads/actions\n\nCI will:\n- Build binaries via GoReleaser\n- Create GitHub Release with assets\n- Publish to npm (@beads/bd)\n- Publish to PyPI (beads-mcp)\n- Update Homebrew tap\n\nWait until all jobs succeed (~5-10 min).\nNeeds: push-and-tag\n\n## Step: verify-release\nVerify the release is complete.\n\n```bash\n# Check GitHub release\ngh release view v0.38.0\n\n# Check Homebrew\nbrew update \u0026\u0026 brew info steveyegge/beads/bd\n\n# Check npm\nnpm view @beads/bd version\n\n# Check PyPI\npip index versions beads-mcp\n```\n\nNeeds: wait-for-ci\n\n## Step: update-local\nUpdate local installations.\n\n```bash\n# Upgrade Homebrew\nbrew upgrade steveyegge/beads/bd\n\n# Or install from source\n./scripts/bump-version.sh 0.38.0 --install\n\n# Install MCP locally\npip install -e integrations/beads-mcp\n\n# Restart daemons\npkill -f \"bd daemon\" || true\n```\n\nVerify: `bd --version` shows 0.38.0\nNeeds: verify-release\n\n## Step: manual-publish\n(Optional) Manual publish if CI failed.\n\n```bash\n# npm (requires npm login)\n./scripts/bump-version.sh 0.38.0 --publish-npm\n\n# PyPI (requires TWINE credentials)\n./scripts/bump-version.sh 0.38.0 --publish-pypi\n\n# Or both\n./scripts/bump-version.sh 0.38.0 --publish-all\n```\n\nOnly needed if CI publishing failed.\nNeeds: wait-for-ci","status":"closed","priority":2,"issue_type":"molecule","assignee":"beads/polecats/furiosa","created_at":"2025-12-27T00:29:46.694495-08:00","updated_at":"2025-12-27T00:51:14.302905-08:00","closed_at":"2025-12-27T00:51:14.302905-08:00","close_reason":"Release v0.38.0 completed successfully"} -{"id":"bd-mol-117","title":"Restart daemons","description":"Restart bd daemons to pick up new version.\n\n```bash\nbd daemons killall\n```\n\nDaemons will auto-restart with new version on next bd command.\n\nVerify:\n```bash\nbd daemons list\n```","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.999837-08:00","updated_at":"2025-12-27T19:31:50.999837-08:00","dependencies":[{"issue_id":"bd-mol-117","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.011531-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-172","title":"Review changes since last release","description":"Understand what's being released.\n\n```bash\ngit log $(git describe --tags --abbrev=0)..HEAD --oneline\n```\n\nCategorize changes:\n- Features (feat:)\n- Fixes (fix:)\n- Breaking changes\n- Documentation","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.996753-08:00","updated_at":"2025-12-27T19:31:50.996753-08:00","dependencies":[{"issue_id":"bd-mol-172","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.0023-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-172","depends_on_id":"bd-mol-408","type":"blocks","created_at":"2025-12-27T19:31:51.013483-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-1y0","title":"Preflight: Check git status","description":"Ensure working tree is clean before starting release.\n\n```bash\ngit status\n```\n\nIf there are uncommitted changes, either:\n- Commit them first\n- Stash them: `git stash`\n- Abort and resolve","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.996088-08:00","updated_at":"2025-12-27T19:31:50.996088-08:00","dependencies":[{"issue_id":"bd-mol-1y0","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.000422-08:00","created_by":"beads/crew/dave"}]} +{"id":"bd-mol-0qm","title":"mol-beads-release","description":"attached_args: Release v0.38.0 - execute each step in order, verify before proceeding to next\n\nRelease checklist for beads version 0.38.0.\n\nThis molecule ensures all release steps are completed properly.\nVariable: 0.38.0 - target version (e.g., 0.35.0)\n\n## Step: update-release-notes\nUpdate cmd/bd/info.go with release notes for 0.38.0.\n\nAdd a new VersionChange entry at the top of versionChanges slice:\n```go\n{\n Version: \"0.38.0\",\n Date: \"YYYY-MM-DD\",\n Changes: []string{\n \"NEW: Feature description\",\n \"FIX: Bug fix description\",\n \"IMPROVED: Enhancement description\",\n },\n},\n```\n\nRun `git log --oneline v\u003cprevious\u003e..HEAD` to see what changed.\n\n## Step: update-changelog\nUpdate CHANGELOG.md with detailed release notes.\n\nAdd a new section after [Unreleased]:\n```markdown\n## [0.38.0] - YYYY-MM-DD\n\n### Added\n- **Feature name** (issue-id) - Description\n\n### Changed\n- **Change description** (issue-id)\n\n### Fixed\n- **Bug fix** (issue-id) - Description\n```\n\nSort by importance, not chronologically.\nNeeds: update-release-notes\n\n## Step: bump-version\nRun the version bump script.\n\n```bash\n./scripts/bump-version.sh 0.38.0\n```\n\nThis updates version in all files:\n- cmd/bd/version.go\n- .claude-plugin/*.json\n- integrations/beads-mcp/pyproject.toml\n- npm-package/package.json\n- Hook templates\n\nNeeds: update-changelog\n\n## Step: run-tests\nRun tests and verify lint passes.\n\n```bash\ngo test -short ./...\n```\n\nCI will run full lint, but fix any obvious issues first.\nNeeds: bump-version\n\n## Step: commit-release\nCommit the release changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: bump version to v0.38.0\"\n```\n\nNeeds: run-tests\n\n## Step: push-and-tag\nPush commit and create release tag.\n\n```bash\ngit push origin main\ngit tag v0.38.0\ngit push origin v0.38.0\n```\n\nThis triggers GitHub Actions release workflow.\nNeeds: commit-release\n\n## Step: wait-for-ci\nWait for GitHub Actions to complete.\n\nMonitor: https://github.com/steveyegge/beads/actions\n\nCI will:\n- Build binaries via GoReleaser\n- Create GitHub Release with assets\n- Publish to npm (@beads/bd)\n- Publish to PyPI (beads-mcp)\n- Update Homebrew tap\n\nWait until all jobs succeed (~5-10 min).\nNeeds: push-and-tag\n\n## Step: verify-release\nVerify the release is complete.\n\n```bash\n# Check GitHub release\ngh release view v0.38.0\n\n# Check Homebrew\nbrew update \u0026\u0026 brew info steveyegge/beads/bd\n\n# Check npm\nnpm view @beads/bd version\n\n# Check PyPI\npip index versions beads-mcp\n```\n\nNeeds: wait-for-ci\n\n## Step: update-local\nUpdate local installations.\n\n```bash\n# Upgrade Homebrew\nbrew upgrade steveyegge/beads/bd\n\n# Or install from source\n./scripts/bump-version.sh 0.38.0 --install\n\n# Install MCP locally\npip install -e integrations/beads-mcp\n\n# Restart daemons\npkill -f \"bd daemon\" || true\n```\n\nVerify: `bd --version` shows 0.38.0\nNeeds: verify-release\n\n## Step: manual-publish\n(Optional) Manual publish if CI failed.\n\n```bash\n# npm (requires npm login)\n./scripts/bump-version.sh 0.38.0 --publish-npm\n\n# PyPI (requires TWINE credentials)\n./scripts/bump-version.sh 0.38.0 --publish-pypi\n\n# Or both\n./scripts/bump-version.sh 0.38.0 --publish-all\n```\n\nOnly needed if CI publishing failed.\nNeeds: wait-for-ci","status":"tombstone","priority":2,"issue_type":"molecule","assignee":"beads/polecats/furiosa","created_at":"2025-12-27T00:29:46.694495-08:00","updated_at":"2025-12-28T01:24:39.173644-08:00","close_reason":"Release v0.38.0 completed successfully","deleted_at":"2025-12-28T01:24:39.173644-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"molecule"} +{"id":"bd-mol-117","title":"Restart daemons","description":"Restart bd daemons to pick up new version.\n\n```bash\nbd daemons killall\n```\n\nDaemons will auto-restart with new version on next bd command.\n\nVerify:\n```bash\nbd daemons list\n```","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.999837-08:00","updated_at":"2025-12-28T01:24:39.175701-08:00","dependencies":[{"issue_id":"bd-mol-117","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.011531-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.175701-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-172","title":"Review changes since last release","description":"Understand what's being released.\n\n```bash\ngit log $(git describe --tags --abbrev=0)..HEAD --oneline\n```\n\nCategorize changes:\n- Features (feat:)\n- Fixes (fix:)\n- Breaking changes\n- Documentation","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.996753-08:00","updated_at":"2025-12-28T01:24:39.177206-08:00","dependencies":[{"issue_id":"bd-mol-172","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.0023-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-172","depends_on_id":"bd-mol-408","type":"blocks","created_at":"2025-12-27T19:31:51.013483-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.177206-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-1y0","title":"Preflight: Check git status","description":"Ensure working tree is clean before starting release.\n\n```bash\ngit status\n```\n\nIf there are uncommitted changes, either:\n- Commit them first\n- Stash them: `git stash`\n- Abort and resolve","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.996088-08:00","updated_at":"2025-12-28T01:24:39.178729-08:00","dependencies":[{"issue_id":"bd-mol-1y0","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.000422-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.178729-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} {"id":"bd-mol-408","title":"Preflight: Pull latest","description":"Ensure we're up to date with origin.\n\n```bash\ngit pull --rebase\n```\n\nResolve any conflicts before proceeding.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.996456-08:00","updated_at":"2025-12-27T19:31:50.996456-08:00","dependencies":[{"issue_id":"bd-mol-408","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.001603-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-408","depends_on_id":"bd-mol-1y0","type":"blocks","created_at":"2025-12-27T19:31:51.012791-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-4bi","title":"Update local installation","description":"Update local bd to the new version.\n\nOption 1 - Homebrew:\n```bash\nbrew upgrade bd\n```\n\nOption 2 - Install script:\n```bash\ncurl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash\n```\n\nVerify:\n```bash\nbd --version\n```\n\nShould show 0.39.0.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.560034-08:00","updated_at":"2025-12-27T19:34:09.560034-08:00","dependencies":[{"issue_id":"bd-mol-4bi","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.585309-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-4bi","depends_on_id":"bd-mol-5h4","type":"blocks","created_at":"2025-12-27T19:34:09.61331-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-4bi","depends_on_id":"bd-mol-v3g","type":"blocks","created_at":"2025-12-27T19:34:09.615361-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-4zt","title":"Wait for CI","description":"Monitor GitHub Actions for release completion.\n\nhttps://github.com/steveyegge/beads/actions\n\nExpected time: 5-10 minutes\n\nWatch for:\n- Build artifacts (all platforms)\n- Test suite pass\n- npm publish\n- PyPI publish","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.559177-08:00","updated_at":"2025-12-27T19:34:09.559177-08:00","dependencies":[{"issue_id":"bd-mol-4zt","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.579519-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-4zt","depends_on_id":"bd-mol-9ry","type":"blocks","created_at":"2025-12-27T19:34:09.605511-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-5h4","title":"Verify npm package","description":"Confirm npm package published.\n\n```bash\nnpm show @beads/bd version\n```\n\nShould show 0.39.0.\n\nAlso check: https://www.npmjs.com/package/@beads/bd","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.55961-08:00","updated_at":"2025-12-27T19:34:09.55961-08:00","dependencies":[{"issue_id":"bd-mol-5h4","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.582462-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-5h4","depends_on_id":"bd-mol-68e","type":"blocks","created_at":"2025-12-27T19:34:09.609272-08:00","created_by":"beads/crew/dave"}]} +{"id":"bd-mol-4bi","title":"Update local installation","description":"Update local bd to the new version.\n\nOption 1 - Homebrew:\n```bash\nbrew upgrade bd\n```\n\nOption 2 - Install script:\n```bash\ncurl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash\n```\n\nVerify:\n```bash\nbd --version\n```\n\nShould show 0.39.0.","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.560034-08:00","updated_at":"2025-12-28T01:24:39.180156-08:00","dependencies":[{"issue_id":"bd-mol-4bi","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.585309-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-4bi","depends_on_id":"bd-mol-5h4","type":"blocks","created_at":"2025-12-27T19:34:09.61331-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-4bi","depends_on_id":"bd-mol-v3g","type":"blocks","created_at":"2025-12-27T19:34:09.615361-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.180156-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-4zt","title":"Wait for CI","description":"Monitor GitHub Actions for release completion.\n\nhttps://github.com/steveyegge/beads/actions\n\nExpected time: 5-10 minutes\n\nWatch for:\n- Build artifacts (all platforms)\n- Test suite pass\n- npm publish\n- PyPI publish","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.559177-08:00","updated_at":"2025-12-28T01:24:39.181582-08:00","dependencies":[{"issue_id":"bd-mol-4zt","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.579519-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-4zt","depends_on_id":"bd-mol-9ry","type":"blocks","created_at":"2025-12-27T19:34:09.605511-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.181582-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-5h4","title":"Verify npm package","description":"Confirm npm package published.\n\n```bash\nnpm show @beads/bd version\n```\n\nShould show 0.39.0.\n\nAlso check: https://www.npmjs.com/package/@beads/bd","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.55961-08:00","updated_at":"2025-12-28T01:24:39.182917-08:00","dependencies":[{"issue_id":"bd-mol-5h4","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.582462-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-5h4","depends_on_id":"bd-mol-68e","type":"blocks","created_at":"2025-12-27T19:34:09.609272-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.182917-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} {"id":"bd-mol-678","title":"Create release tag","description":"Create annotated git tag.\n\n```bash\ngit tag -a v0.39.0 -m \"Release v0.39.0\"\n```\n\nVerify: `git tag -l | tail -5`","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.998148-08:00","updated_at":"2025-12-27T19:31:50.998148-08:00","dependencies":[{"issue_id":"bd-mol-678","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.006262-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-678","depends_on_id":"bd-mol-8ep","type":"blocks","created_at":"2025-12-27T19:31:51.018908-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-68e","title":"Verify GitHub release","description":"Check the GitHub releases page.\n\nhttps://github.com/steveyegge/beads/releases/tag/v0.39.0\n\nVerify:\n- Release created\n- Binaries attached (linux, darwin, windows)\n- Checksums present","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.559402-08:00","updated_at":"2025-12-27T19:34:09.559402-08:00","dependencies":[{"issue_id":"bd-mol-68e","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.581002-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-68e","depends_on_id":"bd-mol-4zt","type":"blocks","created_at":"2025-12-27T19:34:09.607353-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-7ix","title":"Preflight: Check git status","description":"Ensure working tree is clean before starting release.\n\n```bash\ngit status\n```\n\nIf there are uncommitted changes, either:\n- Commit them first\n- Stash them: `git stash`\n- Abort and resolve","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.556672-08:00","updated_at":"2025-12-27T19:34:09.556672-08:00","dependencies":[{"issue_id":"bd-mol-7ix","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.560845-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-7tp","title":"Push to main","description":"Push the release commit to origin.\n\n```bash\ngit push origin main\n```\n\nIf rejected, someone else pushed. Pull, rebase, try again.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.558743-08:00","updated_at":"2025-12-27T19:34:09.558743-08:00","dependencies":[{"issue_id":"bd-mol-7tp","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.576475-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-7tp","depends_on_id":"bd-mol-h3l","type":"blocks","created_at":"2025-12-27T19:34:09.601974-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-8ep","title":"Commit release","description":"Stage and commit all version changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: Bump version to 0.39.0\"\n```\n\nReview the commit to ensure all expected files are included.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.99794-08:00","updated_at":"2025-12-27T19:31:50.99794-08:00","dependencies":[{"issue_id":"bd-mol-8ep","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.005611-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-8ep","depends_on_id":"bd-mol-mht","type":"blocks","created_at":"2025-12-27T19:31:51.017961-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-8zw","title":"Release complete","description":"Release v0.39.0 is complete!\n\nSummary:\n- All version files updated\n- Git tag pushed\n- CI artifacts built\n- npm and PyPI packages published\n- Local installation updated\n- Daemons restarted\n\nOptional next steps:\n- Announce on social media\n- Update documentation site\n- Close related milestone","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:51.000045-08:00","updated_at":"2025-12-27T19:31:51.000045-08:00","dependencies":[{"issue_id":"bd-mol-8zw","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.012163-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-8zw","depends_on_id":"bd-mol-117","type":"blocks","created_at":"2025-12-27T19:31:51.030757-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-937","title":"Update CHANGELOG.md","description":"Write the [Unreleased] section with all changes for 0.39.0.\n\nFormat: Keep a Changelog (https://keepachangelog.com)\n\nSections:\n- ### Added\n- ### Changed\n- ### Fixed\n- ### Documentation\n\nThe bump script will stamp the date automatically.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.557415-08:00","updated_at":"2025-12-27T19:34:09.557415-08:00","dependencies":[{"issue_id":"bd-mol-937","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.566545-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-937","depends_on_id":"bd-mol-h8p","type":"blocks","created_at":"2025-12-27T19:34:09.592505-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-9ea","title":"beads-release","description":"Beads release workflow - from version bump to verified release.\n\nThis formula orchestrates a complete release cycle:\n1. Preflight checks (clean git, up to date)\n2. Documentation updates (CHANGELOG, info.go)\n3. Version bump (all components)\n4. Git operations (commit, tag, push)\n5. CI verification (GitHub Actions)\n6. Artifact verification (GitHub, npm, PyPI)\n7. Local installation update\n8. Daemon restart\n\n## Usage\n\n```bash\nbd wisp create beads-release --var version=0.37.0\n```\n\nOr assign to a polecat:\n```bash\ngt sling beads/polecats/p1 --formula beads-release --var version=0.37.0\n```","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-27T19:31:50.995481-08:00","updated_at":"2025-12-27T19:31:50.995481-08:00"} -{"id":"bd-mol-9ry","title":"Push release tag","description":"Push the version tag to trigger CI release.\n\n```bash\ngit push origin v0.39.0\n```\n\nThis triggers GitHub Actions to build artifacts and publish.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.55896-08:00","updated_at":"2025-12-27T19:34:09.55896-08:00","dependencies":[{"issue_id":"bd-mol-9ry","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.578029-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-9ry","depends_on_id":"bd-mol-7tp","type":"blocks","created_at":"2025-12-27T19:34:09.603722-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-bfs","title":"Run bump-version.sh","description":"Update all component versions atomically.\n\n```bash\n./scripts/bump-version.sh 0.39.0\n```\n\nThis updates:\n- cmd/bd/version.go\n- .claude-plugin/*.json\n- integrations/beads-mcp/pyproject.toml\n- integrations/beads-mcp/src/beads_mcp/__init__.py\n- npm-package/package.json\n- Hook templates\n- README.md\n- CHANGELOG.md (adds date)","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.557864-08:00","updated_at":"2025-12-27T19:34:09.557864-08:00","dependencies":[{"issue_id":"bd-mol-bfs","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.569883-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-bfs","depends_on_id":"bd-mol-yxv","type":"blocks","created_at":"2025-12-27T19:34:09.595521-08:00","created_by":"beads/crew/dave"}]} +{"id":"bd-mol-68e","title":"Verify GitHub release","description":"Check the GitHub releases page.\n\nhttps://github.com/steveyegge/beads/releases/tag/v0.39.0\n\nVerify:\n- Release created\n- Binaries attached (linux, darwin, windows)\n- Checksums present","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.559402-08:00","updated_at":"2025-12-28T01:24:39.184285-08:00","dependencies":[{"issue_id":"bd-mol-68e","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.581002-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-68e","depends_on_id":"bd-mol-4zt","type":"blocks","created_at":"2025-12-27T19:34:09.607353-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.184285-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-7ix","title":"Preflight: Check git status","description":"Ensure working tree is clean before starting release.\n\n```bash\ngit status\n```\n\nIf there are uncommitted changes, either:\n- Commit them first\n- Stash them: `git stash`\n- Abort and resolve","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.556672-08:00","updated_at":"2025-12-28T01:24:39.185583-08:00","dependencies":[{"issue_id":"bd-mol-7ix","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.560845-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.185583-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-7tp","title":"Push to main","description":"Push the release commit to origin.\n\n```bash\ngit push origin main\n```\n\nIf rejected, someone else pushed. Pull, rebase, try again.","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.558743-08:00","updated_at":"2025-12-28T01:24:39.186846-08:00","dependencies":[{"issue_id":"bd-mol-7tp","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.576475-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-7tp","depends_on_id":"bd-mol-h3l","type":"blocks","created_at":"2025-12-27T19:34:09.601974-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.186846-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-8ep","title":"Commit release","description":"Stage and commit all version changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: Bump version to 0.39.0\"\n```\n\nReview the commit to ensure all expected files are included.","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.99794-08:00","updated_at":"2025-12-28T01:24:39.188062-08:00","dependencies":[{"issue_id":"bd-mol-8ep","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.005611-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-8ep","depends_on_id":"bd-mol-mht","type":"blocks","created_at":"2025-12-27T19:31:51.017961-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.188062-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-8zw","title":"Release complete","description":"Release v0.39.0 is complete!\n\nSummary:\n- All version files updated\n- Git tag pushed\n- CI artifacts built\n- npm and PyPI packages published\n- Local installation updated\n- Daemons restarted\n\nOptional next steps:\n- Announce on social media\n- Update documentation site\n- Close related milestone","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:51.000045-08:00","updated_at":"2025-12-28T01:24:39.18926-08:00","dependencies":[{"issue_id":"bd-mol-8zw","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.012163-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-8zw","depends_on_id":"bd-mol-117","type":"blocks","created_at":"2025-12-27T19:31:51.030757-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.18926-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-937","title":"Update CHANGELOG.md","description":"Write the [Unreleased] section with all changes for 0.39.0.\n\nFormat: Keep a Changelog (https://keepachangelog.com)\n\nSections:\n- ### Added\n- ### Changed\n- ### Fixed\n- ### Documentation\n\nThe bump script will stamp the date automatically.","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.557415-08:00","updated_at":"2025-12-28T01:24:39.19064-08:00","dependencies":[{"issue_id":"bd-mol-937","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.566545-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-937","depends_on_id":"bd-mol-h8p","type":"blocks","created_at":"2025-12-27T19:34:09.592505-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.19064-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-9ea","title":"beads-release","description":"Beads release workflow - from version bump to verified release.\n\nThis formula orchestrates a complete release cycle:\n1. Preflight checks (clean git, up to date)\n2. Documentation updates (CHANGELOG, info.go)\n3. Version bump (all components)\n4. Git operations (commit, tag, push)\n5. CI verification (GitHub Actions)\n6. Artifact verification (GitHub, npm, PyPI)\n7. Local installation update\n8. Daemon restart\n\n## Usage\n\n```bash\nbd wisp create beads-release --var version=0.37.0\n```\n\nOr assign to a polecat:\n```bash\ngt sling beads/polecats/p1 --formula beads-release --var version=0.37.0\n```","status":"tombstone","priority":2,"issue_type":"epic","created_at":"2025-12-27T19:31:50.995481-08:00","updated_at":"2025-12-28T02:21:04.82393-08:00","deleted_at":"2025-12-28T02:21:04.82393-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"epic"} +{"id":"bd-mol-9ry","title":"Push release tag","description":"Push the version tag to trigger CI release.\n\n```bash\ngit push origin v0.39.0\n```\n\nThis triggers GitHub Actions to build artifacts and publish.","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.55896-08:00","updated_at":"2025-12-28T01:24:39.191874-08:00","dependencies":[{"issue_id":"bd-mol-9ry","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.578029-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-9ry","depends_on_id":"bd-mol-7tp","type":"blocks","created_at":"2025-12-27T19:34:09.603722-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.191874-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-bfs","title":"Run bump-version.sh","description":"Update all component versions atomically.\n\n```bash\n./scripts/bump-version.sh 0.39.0\n```\n\nThis updates:\n- cmd/bd/version.go\n- .claude-plugin/*.json\n- integrations/beads-mcp/pyproject.toml\n- integrations/beads-mcp/src/beads_mcp/__init__.py\n- npm-package/package.json\n- Hook templates\n- README.md\n- CHANGELOG.md (adds date)","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.557864-08:00","updated_at":"2025-12-28T01:24:39.192947-08:00","dependencies":[{"issue_id":"bd-mol-bfs","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.569883-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-bfs","depends_on_id":"bd-mol-yxv","type":"blocks","created_at":"2025-12-27T19:34:09.595521-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.192947-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} {"id":"bd-mol-cs7","title":"Verify PyPI package","description":"Confirm PyPI package published.\n\n```bash\npip index versions beads-mcp 2\u003e/dev/null | head -3\n```\n\nOr check: https://pypi.org/project/beads-mcp/\n\nShould show 0.39.0.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.99942-08:00","updated_at":"2025-12-27T19:31:50.99942-08:00","dependencies":[{"issue_id":"bd-mol-cs7","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.010276-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-cu1","title":"Commit release","description":"Stage and commit all version changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: Bump version to 0.39.0\"\n```\n\nReview the commit to ensure all expected files are included.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.558306-08:00","updated_at":"2025-12-27T19:34:09.558306-08:00","dependencies":[{"issue_id":"bd-mol-cu1","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.573255-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-cu1","depends_on_id":"bd-mol-o9h","type":"blocks","created_at":"2025-12-27T19:34:09.598643-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-eft","title":"Update info.go versionChanges","description":"Add entry to versionChanges in cmd/bd/info.go.\n\nThis powers `bd info --whats-new` for agents.\n\n```go\n\"0.39.0\": {\n \"summary\": \"Brief description\",\n \"changes\": []string{\n \"Key change 1\",\n \"Key change 2\",\n },\n},\n```\n\nFocus on workflow-impacting changes agents need to know.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.997255-08:00","updated_at":"2025-12-27T19:31:50.997255-08:00","dependencies":[{"issue_id":"bd-mol-eft","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.003429-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-h3l","title":"Create release tag","description":"Create annotated git tag.\n\n```bash\ngit tag -a v0.39.0 -m \"Release v0.39.0\"\n```\n\nVerify: `git tag -l | tail -5`","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.558525-08:00","updated_at":"2025-12-27T19:34:09.558525-08:00","dependencies":[{"issue_id":"bd-mol-h3l","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.574876-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-h3l","depends_on_id":"bd-mol-cu1","type":"blocks","created_at":"2025-12-27T19:34:09.600268-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-h8p","title":"Review changes since last release","description":"Understand what's being released.\n\n```bash\ngit log $(git describe --tags --abbrev=0)..HEAD --oneline\n```\n\nCategorize changes:\n- Features (feat:)\n- Fixes (fix:)\n- Breaking changes\n- Documentation","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.557189-08:00","updated_at":"2025-12-27T19:34:09.55719-08:00","dependencies":[{"issue_id":"bd-mol-h8p","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.564777-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-h8p","depends_on_id":"bd-mol-mke","type":"blocks","created_at":"2025-12-27T19:34:09.590976-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-mht","title":"Verify version consistency","description":"Confirm all versions match 0.39.0.\n\n```bash\ngrep 'Version = ' cmd/bd/version.go\njq -r '.version' .claude-plugin/plugin.json\njq -r '.version' npm-package/package.json\ngrep 'version = ' integrations/beads-mcp/pyproject.toml\n```\n\nAll should show 0.39.0.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.997714-08:00","updated_at":"2025-12-27T19:31:50.997714-08:00","dependencies":[{"issue_id":"bd-mol-mht","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.00493-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-mke","title":"Preflight: Pull latest","description":"Ensure we're up to date with origin.\n\n```bash\ngit pull --rebase\n```\n\nResolve any conflicts before proceeding.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.556939-08:00","updated_at":"2025-12-27T19:34:09.556939-08:00","dependencies":[{"issue_id":"bd-mol-mke","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.562972-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-mke","depends_on_id":"bd-mol-7ix","type":"blocks","created_at":"2025-12-27T19:34:09.589497-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-o9h","title":"Verify version consistency","description":"Confirm all versions match 0.39.0.\n\n```bash\ngrep 'Version = ' cmd/bd/version.go\njq -r '.version' .claude-plugin/plugin.json\njq -r '.version' npm-package/package.json\ngrep 'version = ' integrations/beads-mcp/pyproject.toml\n```\n\nAll should show 0.39.0.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.558076-08:00","updated_at":"2025-12-27T19:34:09.558076-08:00","dependencies":[{"issue_id":"bd-mol-o9h","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.571581-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-o9h","depends_on_id":"bd-mol-bfs","type":"blocks","created_at":"2025-12-27T19:34:09.597052-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-p1b","title":"beads-release","description":"Beads release workflow - from version bump to verified release.\n\nThis formula orchestrates a complete release cycle:\n1. Preflight checks (clean git, up to date)\n2. Documentation updates (CHANGELOG, info.go)\n3. Version bump (all components)\n4. Git operations (commit, tag, push)\n5. CI verification (GitHub Actions)\n6. Artifact verification (GitHub, npm, PyPI)\n7. Local installation update\n8. Daemon restart\n\n## Usage\n\n```bash\nbd wisp create beads-release --var version=0.37.0\n```\n\nOr assign to a polecat:\n```bash\ngt sling beads/polecats/p1 --formula beads-release --var version=0.37.0\n```","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-27T19:34:09.556184-08:00","updated_at":"2025-12-27T19:34:09.556184-08:00"} -{"id":"bd-mol-pqt","title":"Restart daemons","description":"Restart bd daemons to pick up new version.\n\n```bash\nbd daemons killall\n```\n\nDaemons will auto-restart with new version on next bd command.\n\nVerify:\n```bash\nbd daemons list\n```","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.560244-08:00","updated_at":"2025-12-27T19:34:09.560245-08:00","dependencies":[{"issue_id":"bd-mol-pqt","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.586704-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-pqt","depends_on_id":"bd-mol-4bi","type":"blocks","created_at":"2025-12-27T19:34:09.617462-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-pze","title":"mol-beads-release","description":"Release checklist for beads version 0.99.0.\n\nThis molecule ensures all release steps are completed properly.\nVariable: 0.99.0 - target version (e.g., 0.35.0)\n\n## Step: update-release-notes\nUpdate cmd/bd/info.go with release notes for 0.99.0.\n\nAdd a new VersionChange entry at the top of versionChanges slice:\n```go\n{\n Version: \"0.99.0\",\n Date: \"YYYY-MM-DD\",\n Changes: []string{\n \"NEW: Feature description\",\n \"FIX: Bug fix description\",\n \"IMPROVED: Enhancement description\",\n },\n},\n```\n\nRun `git log --oneline v\u003cprevious\u003e..HEAD` to see what changed.\n\n## Step: update-changelog\nUpdate CHANGELOG.md with detailed release notes.\n\nAdd a new section after [Unreleased]:\n```markdown\n## [0.99.0] - YYYY-MM-DD\n\n### Added\n- **Feature name** (issue-id) - Description\n\n### Changed\n- **Change description** (issue-id)\n\n### Fixed\n- **Bug fix** (issue-id) - Description\n```\n\nSort by importance, not chronologically.\nNeeds: update-release-notes\n\n## Step: bump-version\nRun the version bump script.\n\n```bash\n./scripts/bump-version.sh 0.99.0\n```\n\nThis updates version in all files:\n- cmd/bd/version.go\n- .claude-plugin/*.json\n- integrations/beads-mcp/pyproject.toml\n- npm-package/package.json\n- Hook templates\n\nNeeds: update-changelog\n\n## Step: run-tests\nRun tests and verify lint passes.\n\n```bash\ngo test -short ./...\n```\n\nCI will run full lint, but fix any obvious issues first.\nNeeds: bump-version\n\n## Step: commit-release\nCommit the release changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: bump version to v0.99.0\"\n```\n\nNeeds: run-tests\n\n## Step: push-and-tag\nPush commit and create release tag.\n\n```bash\ngit push origin main\ngit tag v0.99.0\ngit push origin v0.99.0\n```\n\nThis triggers GitHub Actions release workflow.\nNeeds: commit-release\n\n## Step: wait-for-ci\nWait for GitHub Actions to complete.\n\nMonitor: https://github.com/steveyegge/beads/actions\n\nCI will:\n- Build binaries via GoReleaser\n- Create GitHub Release with assets\n- Publish to npm (@beads/bd)\n- Publish to PyPI (beads-mcp)\n- Update Homebrew tap\n\nWait until all jobs succeed (~5-10 min).\nNeeds: push-and-tag\n\n## Step: verify-release\nVerify the release is complete.\n\n```bash\n# Check GitHub release\ngh release view v0.99.0\n\n# Check Homebrew\nbrew update \u0026\u0026 brew info steveyegge/beads/bd\n\n# Check npm\nnpm view @beads/bd version\n\n# Check PyPI\npip index versions beads-mcp\n```\n\nNeeds: wait-for-ci\n\n## Step: update-local\nUpdate local installations.\n\n```bash\n# Upgrade Homebrew\nbrew upgrade steveyegge/beads/bd\n\n# Or install from source\n./scripts/bump-version.sh 0.99.0 --install\n\n# Install MCP locally\npip install -e integrations/beads-mcp\n\n# Restart daemons\npkill -f \"bd daemon\" || true\n```\n\nVerify: `bd --version` shows 0.99.0\nNeeds: verify-release\n\n## Step: manual-publish\n(Optional) Manual publish if CI failed.\n\n```bash\n# npm (requires npm login)\n./scripts/bump-version.sh 0.99.0 --publish-npm\n\n# PyPI (requires TWINE credentials)\n./scripts/bump-version.sh 0.99.0 --publish-pypi\n\n# Or both\n./scripts/bump-version.sh 0.99.0 --publish-all\n```\n\nOnly needed if CI publishing failed.\nNeeds: wait-for-ci","status":"open","priority":2,"issue_type":"molecule","created_at":"2025-12-27T00:32:46.883114-08:00","updated_at":"2025-12-27T00:32:46.883114-08:00"} -{"id":"bd-mol-v3g","title":"Verify PyPI package","description":"Confirm PyPI package published.\n\n```bash\npip index versions beads-mcp 2\u003e/dev/null | head -3\n```\n\nOr check: https://pypi.org/project/beads-mcp/\n\nShould show 0.39.0.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.559818-08:00","updated_at":"2025-12-27T19:34:09.559818-08:00","dependencies":[{"issue_id":"bd-mol-v3g","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.583881-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-v3g","depends_on_id":"bd-mol-68e","type":"blocks","created_at":"2025-12-27T19:34:09.611251-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-vua","title":"Release complete","description":"Release v0.39.0 is complete!\n\nSummary:\n- All version files updated\n- Git tag pushed\n- CI artifacts built\n- npm and PyPI packages published\n- Local installation updated\n- Daemons restarted\n\nOptional next steps:\n- Announce on social media\n- Update documentation site\n- Close related milestone","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.560454-08:00","updated_at":"2025-12-27T19:34:09.560454-08:00","dependencies":[{"issue_id":"bd-mol-vua","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.588099-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-vua","depends_on_id":"bd-mol-pqt","type":"blocks","created_at":"2025-12-27T19:34:09.61966-08:00","created_by":"beads/crew/dave"}]} -{"id":"bd-mol-xga","title":"mol-beads-release","description":"Release checklist for beads version 0.37.0.\n\nThis molecule ensures all release steps are completed properly.\nVariable: 0.37.0 - target version (e.g., 0.35.0)\n\n## Step: update-release-notes\nUpdate cmd/bd/info.go with release notes for 0.37.0.\n\nAdd a new VersionChange entry at the top of versionChanges slice:\n```go\n{\n Version: \"0.37.0\",\n Date: \"YYYY-MM-DD\",\n Changes: []string{\n \"NEW: Feature description\",\n \"FIX: Bug fix description\",\n \"IMPROVED: Enhancement description\",\n },\n},\n```\n\nRun `git log --oneline v\u003cprevious\u003e..HEAD` to see what changed.\n\n## Step: update-changelog\nUpdate CHANGELOG.md with detailed release notes.\n\nAdd a new section after [Unreleased]:\n```markdown\n## [0.37.0] - YYYY-MM-DD\n\n### Added\n- **Feature name** (issue-id) - Description\n\n### Changed\n- **Change description** (issue-id)\n\n### Fixed\n- **Bug fix** (issue-id) - Description\n```\n\nSort by importance, not chronologically.\nNeeds: update-release-notes\n\n## Step: bump-version\nRun the version bump script.\n\n```bash\n./scripts/bump-version.sh 0.37.0\n```\n\nThis updates version in all files:\n- cmd/bd/version.go\n- .claude-plugin/*.json\n- integrations/beads-mcp/pyproject.toml\n- npm-package/package.json\n- Hook templates\n\nNeeds: update-changelog\n\n## Step: run-tests\nRun tests and verify lint passes.\n\n```bash\ngo test -short ./...\n```\n\nCI will run full lint, but fix any obvious issues first.\nNeeds: bump-version\n\n## Step: commit-release\nCommit the release changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: bump version to v0.37.0\"\n```\n\nNeeds: run-tests\n\n## Step: push-and-tag\nPush commit and create release tag.\n\n```bash\ngit push origin main\ngit tag v0.37.0\ngit push origin v0.37.0\n```\n\nThis triggers GitHub Actions release workflow.\nNeeds: commit-release\n\n## Step: wait-for-ci\nWait for GitHub Actions to complete.\n\nMonitor: https://github.com/steveyegge/beads/actions\n\nCI will:\n- Build binaries via GoReleaser\n- Create GitHub Release with assets\n- Publish to npm (@beads/bd)\n- Publish to PyPI (beads-mcp)\n- Update Homebrew tap\n\nWait until all jobs succeed (~5-10 min).\nNeeds: push-and-tag\n\n## Step: verify-release\nVerify the release is complete.\n\n```bash\n# Check GitHub release\ngh release view v0.37.0\n\n# Check Homebrew\nbrew update \u0026\u0026 brew info steveyegge/beads/bd\n\n# Check npm\nnpm view @beads/bd version\n\n# Check PyPI\npip index versions beads-mcp\n```\n\nNeeds: wait-for-ci\n\n## Step: update-local\nUpdate local installations.\n\n```bash\n# Upgrade Homebrew\nbrew upgrade steveyegge/beads/bd\n\n# Or install from source\n./scripts/bump-version.sh 0.37.0 --install\n\n# Install MCP locally\npip install -e integrations/beads-mcp\n\n# Restart daemons\npkill -f \"bd daemon\" || true\n```\n\nVerify: `bd --version` shows 0.37.0\nNeeds: verify-release\n\n## Step: manual-publish\n(Optional) Manual publish if CI failed.\n\n```bash\n# npm (requires npm login)\n./scripts/bump-version.sh 0.37.0 --publish-npm\n\n# PyPI (requires TWINE credentials)\n./scripts/bump-version.sh 0.37.0 --publish-pypi\n\n# Or both\n./scripts/bump-version.sh 0.37.0 --publish-all\n```\n\nOnly needed if CI publishing failed.\nNeeds: wait-for-ci","status":"closed","priority":2,"issue_type":"molecule","created_at":"2025-12-26T01:09:49.836708-08:00","updated_at":"2025-12-26T01:37:05.947256-08:00","closed_at":"2025-12-26T01:37:05.947256-08:00","close_reason":"Release v0.37.0 complete. Published to GitHub, npm, PyPI, and Homebrew."} -{"id":"bd-mol-xga.1","title":"Update cmd/bd/info.go with release notes for 0.37.0.","description":"Update cmd/bd/info.go with release notes for 0.37.0.\n\nAdd a new VersionChange entry at the top of versionChanges slice:\n```go\n{\n Version: \"0.37.0\",\n Date: \"YYYY-MM-DD\",\n Changes: []string{\n \"NEW: Feature description\",\n \"FIX: Bug fix description\",\n \"IMPROVED: Enhancement description\",\n },\n},\n```\n\nRun `git log --oneline v\u003cprevious\u003e..HEAD` to see what changed.\n\ninstantiated_from: bd-mol-xga\nstep: update-release-notes","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:16.829377-08:00","updated_at":"2025-12-26T01:18:06.533067-08:00","closed_at":"2025-12-26T01:18:06.533067-08:00","close_reason":"Closed","dependencies":[{"issue_id":"bd-mol-xga.1","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:16.829843-08:00","created_by":"daemon"}]} -{"id":"bd-mol-xga.10","title":"(Optional) Manual publish if CI failed.","description":"(Optional) Manual publish if CI failed.\n\n```bash\n# npm (requires npm login)\n./scripts/bump-version.sh 0.37.0 --publish-npm\n\n# PyPI (requires TWINE credentials)\n./scripts/bump-version.sh 0.37.0 --publish-pypi\n\n# Or both\n./scripts/bump-version.sh 0.37.0 --publish-all\n```\n\nOnly needed if CI publishing failed.\n\ninstantiated_from: bd-mol-xga\nstep: manual-publish","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:17.114721-08:00","updated_at":"2025-12-26T01:37:04.751013-08:00","closed_at":"2025-12-26T01:37:04.751013-08:00","close_reason":"Not needed - CI publishing succeeded.","dependencies":[{"issue_id":"bd-mol-xga.10","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:17.115119-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.10","depends_on_id":"bd-mol-xga.7","type":"blocks","created_at":"2025-12-26T01:10:17.379466-08:00","created_by":"daemon"}]} -{"id":"bd-mol-xga.2","title":"Update CHANGELOG.md with detailed release notes.","description":"Update CHANGELOG.md with detailed release notes.\n\nAdd a new section after [Unreleased]:\n```markdown\n## [0.37.0] - YYYY-MM-DD\n\n### Added\n- **Feature name** (issue-id) - Description\n\n### Changed\n- **Change description** (issue-id)\n\n### Fixed\n- **Bug fix** (issue-id) - Description\n```\n\nSort by importance, not chronologically.\n\ninstantiated_from: bd-mol-xga\nstep: update-changelog","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:16.861035-08:00","updated_at":"2025-12-26T01:18:50.964655-08:00","closed_at":"2025-12-26T01:18:50.964655-08:00","close_reason":"Closed","dependencies":[{"issue_id":"bd-mol-xga.2","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:16.861529-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.2","depends_on_id":"bd-mol-xga.1","type":"blocks","created_at":"2025-12-26T01:10:17.14187-08:00","created_by":"daemon"}]} -{"id":"bd-mol-xga.3","title":"Run the version bump script.","description":"Run the version bump script.\n\n```bash\n./scripts/bump-version.sh 0.37.0\n```\n\nThis updates version in all files:\n- cmd/bd/version.go\n- .claude-plugin/*.json\n- integrations/beads-mcp/pyproject.toml\n- npm-package/package.json\n- Hook templates\n\ninstantiated_from: bd-mol-xga\nstep: bump-version","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:16.892842-08:00","updated_at":"2025-12-26T01:20:31.196001-08:00","closed_at":"2025-12-26T01:20:31.196001-08:00","close_reason":"Closed","dependencies":[{"issue_id":"bd-mol-xga.3","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:16.893248-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.3","depends_on_id":"bd-mol-xga.2","type":"blocks","created_at":"2025-12-26T01:10:17.172199-08:00","created_by":"daemon"}]} -{"id":"bd-mol-xga.4","title":"Run tests and verify lint passes.","description":"Run tests and verify lint passes.\n\n```bash\ngo test -short ./...\n```\n\nCI will run full lint, but fix any obvious issues first.\n\ninstantiated_from: bd-mol-xga\nstep: run-tests","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:16.925451-08:00","updated_at":"2025-12-26T01:21:32.713258-08:00","closed_at":"2025-12-26T01:21:32.713258-08:00","close_reason":"Closed","dependencies":[{"issue_id":"bd-mol-xga.4","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:16.925824-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.4","depends_on_id":"bd-mol-xga.3","type":"blocks","created_at":"2025-12-26T01:10:17.202675-08:00","created_by":"daemon"}]} -{"id":"bd-mol-xga.5","title":"Commit the release changes.","description":"Commit the release changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: bump version to v0.37.0\"\n```\n\ninstantiated_from: bd-mol-xga\nstep: commit-release","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:16.957119-08:00","updated_at":"2025-12-26T01:23:10.351894-08:00","closed_at":"2025-12-26T01:23:10.351894-08:00","close_reason":"Closed","dependencies":[{"issue_id":"bd-mol-xga.5","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:16.957499-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.5","depends_on_id":"bd-mol-xga.4","type":"blocks","created_at":"2025-12-26T01:10:17.233695-08:00","created_by":"daemon"}]} -{"id":"bd-mol-xga.6","title":"Push commit and create release tag.","description":"Push commit and create release tag.\n\n```bash\ngit push origin main\ngit tag v0.37.0\ngit push origin v0.37.0\n```\n\nThis triggers GitHub Actions release workflow.\n\ninstantiated_from: bd-mol-xga\nstep: push-and-tag","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:16.987513-08:00","updated_at":"2025-12-26T01:24:03.208891-08:00","closed_at":"2025-12-26T01:24:03.208891-08:00","close_reason":"Submitted to merge queue. Tagging (git tag v0.37.0 \u0026\u0026 git push origin v0.37.0) needs to be done from main after merge.","dependencies":[{"issue_id":"bd-mol-xga.6","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:16.987907-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.6","depends_on_id":"bd-mol-xga.5","type":"blocks","created_at":"2025-12-26T01:10:17.264209-08:00","created_by":"daemon"}]} -{"id":"bd-mol-xga.7","title":"Wait for GitHub Actions to complete.","description":"Wait for GitHub Actions to complete.\n\nMonitor: https://github.com/steveyegge/beads/actions\n\nCI will:\n- Build binaries via GoReleaser\n- Create GitHub Release with assets\n- Publish to npm (@beads/bd)\n- Publish to PyPI (beads-mcp)\n- Update Homebrew tap\n\nWait until all jobs succeed (~5-10 min).\n\ninstantiated_from: bd-mol-xga\nstep: wait-for-ci","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:17.019226-08:00","updated_at":"2025-12-26T01:31:42.74373-08:00","closed_at":"2025-12-26T01:31:42.74373-08:00","close_reason":"Tag v0.37.0 pushed to origin. CI workflow triggered.","dependencies":[{"issue_id":"bd-mol-xga.7","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:17.019655-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.7","depends_on_id":"bd-mol-xga.6","type":"blocks","created_at":"2025-12-26T01:10:17.296023-08:00","created_by":"daemon"}]} -{"id":"bd-mol-xga.8","title":"Verify the release is complete.","description":"Verify the release is complete.\n\n```bash\n# Check GitHub release\ngh release view v0.37.0\n\n# Check Homebrew\nbrew update \u0026\u0026 brew info steveyegge/beads/bd\n\n# Check npm\nnpm view @beads/bd version\n\n# Check PyPI\npip index versions beads-mcp\n```\n\ninstantiated_from: bd-mol-xga\nstep: verify-release","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:17.049777-08:00","updated_at":"2025-12-26T01:36:55.23496-08:00","closed_at":"2025-12-26T01:36:55.23496-08:00","close_reason":"Release v0.37.0 verified on GitHub. Release workflow succeeded.","dependencies":[{"issue_id":"bd-mol-xga.8","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:17.050108-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.8","depends_on_id":"bd-mol-xga.7","type":"blocks","created_at":"2025-12-26T01:10:17.328309-08:00","created_by":"daemon"}]} -{"id":"bd-mol-xga.9","title":"Update local installations.","description":"Update local installations.\n\n```bash\n# Upgrade Homebrew\nbrew upgrade steveyegge/beads/bd\n\n# Or install from source\n./scripts/bump-version.sh 0.37.0 --install\n\n# Install MCP locally\npip install -e integrations/beads-mcp\n\n# Restart daemons\npkill -f \"bd daemon\" || true\n```\n\nVerify: `bd --version` shows 0.37.0\n\ninstantiated_from: bd-mol-xga\nstep: update-local","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:17.081154-08:00","updated_at":"2025-12-26T01:37:03.912726-08:00","closed_at":"2025-12-26T01:37:03.912726-08:00","close_reason":"Local installation can be done via: brew upgrade steveyegge/beads/bd","dependencies":[{"issue_id":"bd-mol-xga.9","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:17.081536-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.9","depends_on_id":"bd-mol-xga.8","type":"blocks","created_at":"2025-12-26T01:10:17.354246-08:00","created_by":"daemon"}]} -{"id":"bd-mol-yxv","title":"Update info.go versionChanges","description":"Add entry to versionChanges in cmd/bd/info.go.\n\nThis powers `bd info --whats-new` for agents.\n\n```go\n\"0.39.0\": {\n \"summary\": \"Brief description\",\n \"changes\": []string{\n \"Key change 1\",\n \"Key change 2\",\n },\n},\n```\n\nFocus on workflow-impacting changes agents need to know.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.557636-08:00","updated_at":"2025-12-27T19:34:09.557636-08:00","dependencies":[{"issue_id":"bd-mol-yxv","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.568242-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-yxv","depends_on_id":"bd-mol-937","type":"blocks","created_at":"2025-12-27T19:34:09.594033-08:00","created_by":"beads/crew/dave"}]} +{"id":"bd-mol-cu1","title":"Commit release","description":"Stage and commit all version changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: Bump version to 0.39.0\"\n```\n\nReview the commit to ensure all expected files are included.","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.558306-08:00","updated_at":"2025-12-28T01:24:39.193995-08:00","dependencies":[{"issue_id":"bd-mol-cu1","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.573255-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-cu1","depends_on_id":"bd-mol-o9h","type":"blocks","created_at":"2025-12-27T19:34:09.598643-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.193995-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-eft","title":"Update info.go versionChanges","description":"Add entry to versionChanges in cmd/bd/info.go.\n\nThis powers `bd info --whats-new` for agents.\n\n```go\n\"0.39.0\": {\n \"summary\": \"Brief description\",\n \"changes\": []string{\n \"Key change 1\",\n \"Key change 2\",\n },\n},\n```\n\nFocus on workflow-impacting changes agents need to know.","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.997255-08:00","updated_at":"2025-12-28T01:24:39.195032-08:00","dependencies":[{"issue_id":"bd-mol-eft","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.003429-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.195032-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-h3l","title":"Create release tag","description":"Create annotated git tag.\n\n```bash\ngit tag -a v0.39.0 -m \"Release v0.39.0\"\n```\n\nVerify: `git tag -l | tail -5`","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.558525-08:00","updated_at":"2025-12-28T01:24:39.196075-08:00","dependencies":[{"issue_id":"bd-mol-h3l","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.574876-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-h3l","depends_on_id":"bd-mol-cu1","type":"blocks","created_at":"2025-12-27T19:34:09.600268-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.196075-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-h8p","title":"Review changes since last release","description":"Understand what's being released.\n\n```bash\ngit log $(git describe --tags --abbrev=0)..HEAD --oneline\n```\n\nCategorize changes:\n- Features (feat:)\n- Fixes (fix:)\n- Breaking changes\n- Documentation","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.557189-08:00","updated_at":"2025-12-28T01:24:39.197071-08:00","dependencies":[{"issue_id":"bd-mol-h8p","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.564777-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-h8p","depends_on_id":"bd-mol-mke","type":"blocks","created_at":"2025-12-27T19:34:09.590976-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.197071-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-mht","title":"Verify version consistency","description":"Confirm all versions match 0.39.0.\n\n```bash\ngrep 'Version = ' cmd/bd/version.go\njq -r '.version' .claude-plugin/plugin.json\njq -r '.version' npm-package/package.json\ngrep 'version = ' integrations/beads-mcp/pyproject.toml\n```\n\nAll should show 0.39.0.","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:31:50.997714-08:00","updated_at":"2025-12-28T01:24:39.198003-08:00","dependencies":[{"issue_id":"bd-mol-mht","depends_on_id":"bd-mol-9ea","type":"parent-child","created_at":"2025-12-27T19:31:51.00493-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.198003-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-mke","title":"Preflight: Pull latest","description":"Ensure we're up to date with origin.\n\n```bash\ngit pull --rebase\n```\n\nResolve any conflicts before proceeding.","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.556939-08:00","updated_at":"2025-12-28T01:24:39.198891-08:00","dependencies":[{"issue_id":"bd-mol-mke","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.562972-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-mke","depends_on_id":"bd-mol-7ix","type":"blocks","created_at":"2025-12-27T19:34:09.589497-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.198891-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-o9h","title":"Verify version consistency","description":"Confirm all versions match 0.39.0.\n\n```bash\ngrep 'Version = ' cmd/bd/version.go\njq -r '.version' .claude-plugin/plugin.json\njq -r '.version' npm-package/package.json\ngrep 'version = ' integrations/beads-mcp/pyproject.toml\n```\n\nAll should show 0.39.0.","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.558076-08:00","updated_at":"2025-12-28T01:24:39.199724-08:00","dependencies":[{"issue_id":"bd-mol-o9h","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.571581-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-o9h","depends_on_id":"bd-mol-bfs","type":"blocks","created_at":"2025-12-27T19:34:09.597052-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.199724-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-p1b","title":"beads-release","description":"Beads release workflow - from version bump to verified release.\n\nThis formula orchestrates a complete release cycle:\n1. Preflight checks (clean git, up to date)\n2. Documentation updates (CHANGELOG, info.go)\n3. Version bump (all components)\n4. Git operations (commit, tag, push)\n5. CI verification (GitHub Actions)\n6. Artifact verification (GitHub, npm, PyPI)\n7. Local installation update\n8. Daemon restart\n\n## Usage\n\n```bash\nbd wisp create beads-release --var version=0.37.0\n```\n\nOr assign to a polecat:\n```bash\ngt sling beads/polecats/p1 --formula beads-release --var version=0.37.0\n```","status":"tombstone","priority":2,"issue_type":"epic","created_at":"2025-12-27T19:34:09.556184-08:00","updated_at":"2025-12-28T01:24:39.200515-08:00","deleted_at":"2025-12-28T01:24:39.200515-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"epic"} +{"id":"bd-mol-pqt","title":"Restart daemons","description":"Restart bd daemons to pick up new version.\n\n```bash\nbd daemons killall\n```\n\nDaemons will auto-restart with new version on next bd command.\n\nVerify:\n```bash\nbd daemons list\n```","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.560244-08:00","updated_at":"2025-12-28T01:24:39.201329-08:00","dependencies":[{"issue_id":"bd-mol-pqt","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.586704-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-pqt","depends_on_id":"bd-mol-4bi","type":"blocks","created_at":"2025-12-27T19:34:09.617462-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.201329-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-pze","title":"mol-beads-release","description":"Release checklist for beads version 0.99.0.\n\nThis molecule ensures all release steps are completed properly.\nVariable: 0.99.0 - target version (e.g., 0.35.0)\n\n## Step: update-release-notes\nUpdate cmd/bd/info.go with release notes for 0.99.0.\n\nAdd a new VersionChange entry at the top of versionChanges slice:\n```go\n{\n Version: \"0.99.0\",\n Date: \"YYYY-MM-DD\",\n Changes: []string{\n \"NEW: Feature description\",\n \"FIX: Bug fix description\",\n \"IMPROVED: Enhancement description\",\n },\n},\n```\n\nRun `git log --oneline v\u003cprevious\u003e..HEAD` to see what changed.\n\n## Step: update-changelog\nUpdate CHANGELOG.md with detailed release notes.\n\nAdd a new section after [Unreleased]:\n```markdown\n## [0.99.0] - YYYY-MM-DD\n\n### Added\n- **Feature name** (issue-id) - Description\n\n### Changed\n- **Change description** (issue-id)\n\n### Fixed\n- **Bug fix** (issue-id) - Description\n```\n\nSort by importance, not chronologically.\nNeeds: update-release-notes\n\n## Step: bump-version\nRun the version bump script.\n\n```bash\n./scripts/bump-version.sh 0.99.0\n```\n\nThis updates version in all files:\n- cmd/bd/version.go\n- .claude-plugin/*.json\n- integrations/beads-mcp/pyproject.toml\n- npm-package/package.json\n- Hook templates\n\nNeeds: update-changelog\n\n## Step: run-tests\nRun tests and verify lint passes.\n\n```bash\ngo test -short ./...\n```\n\nCI will run full lint, but fix any obvious issues first.\nNeeds: bump-version\n\n## Step: commit-release\nCommit the release changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: bump version to v0.99.0\"\n```\n\nNeeds: run-tests\n\n## Step: push-and-tag\nPush commit and create release tag.\n\n```bash\ngit push origin main\ngit tag v0.99.0\ngit push origin v0.99.0\n```\n\nThis triggers GitHub Actions release workflow.\nNeeds: commit-release\n\n## Step: wait-for-ci\nWait for GitHub Actions to complete.\n\nMonitor: https://github.com/steveyegge/beads/actions\n\nCI will:\n- Build binaries via GoReleaser\n- Create GitHub Release with assets\n- Publish to npm (@beads/bd)\n- Publish to PyPI (beads-mcp)\n- Update Homebrew tap\n\nWait until all jobs succeed (~5-10 min).\nNeeds: push-and-tag\n\n## Step: verify-release\nVerify the release is complete.\n\n```bash\n# Check GitHub release\ngh release view v0.99.0\n\n# Check Homebrew\nbrew update \u0026\u0026 brew info steveyegge/beads/bd\n\n# Check npm\nnpm view @beads/bd version\n\n# Check PyPI\npip index versions beads-mcp\n```\n\nNeeds: wait-for-ci\n\n## Step: update-local\nUpdate local installations.\n\n```bash\n# Upgrade Homebrew\nbrew upgrade steveyegge/beads/bd\n\n# Or install from source\n./scripts/bump-version.sh 0.99.0 --install\n\n# Install MCP locally\npip install -e integrations/beads-mcp\n\n# Restart daemons\npkill -f \"bd daemon\" || true\n```\n\nVerify: `bd --version` shows 0.99.0\nNeeds: verify-release\n\n## Step: manual-publish\n(Optional) Manual publish if CI failed.\n\n```bash\n# npm (requires npm login)\n./scripts/bump-version.sh 0.99.0 --publish-npm\n\n# PyPI (requires TWINE credentials)\n./scripts/bump-version.sh 0.99.0 --publish-pypi\n\n# Or both\n./scripts/bump-version.sh 0.99.0 --publish-all\n```\n\nOnly needed if CI publishing failed.\nNeeds: wait-for-ci","status":"tombstone","priority":2,"issue_type":"molecule","created_at":"2025-12-27T00:32:46.883114-08:00","updated_at":"2025-12-28T01:24:39.202075-08:00","deleted_at":"2025-12-28T01:24:39.202075-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"molecule"} +{"id":"bd-mol-v3g","title":"Verify PyPI package","description":"Confirm PyPI package published.\n\n```bash\npip index versions beads-mcp 2\u003e/dev/null | head -3\n```\n\nOr check: https://pypi.org/project/beads-mcp/\n\nShould show 0.39.0.","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.559818-08:00","updated_at":"2025-12-28T01:24:39.202837-08:00","dependencies":[{"issue_id":"bd-mol-v3g","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.583881-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-v3g","depends_on_id":"bd-mol-68e","type":"blocks","created_at":"2025-12-27T19:34:09.611251-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.202837-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-vua","title":"Release complete","description":"Release v0.39.0 is complete!\n\nSummary:\n- All version files updated\n- Git tag pushed\n- CI artifacts built\n- npm and PyPI packages published\n- Local installation updated\n- Daemons restarted\n\nOptional next steps:\n- Announce on social media\n- Update documentation site\n- Close related milestone","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.560454-08:00","updated_at":"2025-12-28T01:24:39.203582-08:00","dependencies":[{"issue_id":"bd-mol-vua","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.588099-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-vua","depends_on_id":"bd-mol-pqt","type":"blocks","created_at":"2025-12-27T19:34:09.61966-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.203582-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-xga","title":"mol-beads-release","description":"Release checklist for beads version 0.37.0.\n\nThis molecule ensures all release steps are completed properly.\nVariable: 0.37.0 - target version (e.g., 0.35.0)\n\n## Step: update-release-notes\nUpdate cmd/bd/info.go with release notes for 0.37.0.\n\nAdd a new VersionChange entry at the top of versionChanges slice:\n```go\n{\n Version: \"0.37.0\",\n Date: \"YYYY-MM-DD\",\n Changes: []string{\n \"NEW: Feature description\",\n \"FIX: Bug fix description\",\n \"IMPROVED: Enhancement description\",\n },\n},\n```\n\nRun `git log --oneline v\u003cprevious\u003e..HEAD` to see what changed.\n\n## Step: update-changelog\nUpdate CHANGELOG.md with detailed release notes.\n\nAdd a new section after [Unreleased]:\n```markdown\n## [0.37.0] - YYYY-MM-DD\n\n### Added\n- **Feature name** (issue-id) - Description\n\n### Changed\n- **Change description** (issue-id)\n\n### Fixed\n- **Bug fix** (issue-id) - Description\n```\n\nSort by importance, not chronologically.\nNeeds: update-release-notes\n\n## Step: bump-version\nRun the version bump script.\n\n```bash\n./scripts/bump-version.sh 0.37.0\n```\n\nThis updates version in all files:\n- cmd/bd/version.go\n- .claude-plugin/*.json\n- integrations/beads-mcp/pyproject.toml\n- npm-package/package.json\n- Hook templates\n\nNeeds: update-changelog\n\n## Step: run-tests\nRun tests and verify lint passes.\n\n```bash\ngo test -short ./...\n```\n\nCI will run full lint, but fix any obvious issues first.\nNeeds: bump-version\n\n## Step: commit-release\nCommit the release changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: bump version to v0.37.0\"\n```\n\nNeeds: run-tests\n\n## Step: push-and-tag\nPush commit and create release tag.\n\n```bash\ngit push origin main\ngit tag v0.37.0\ngit push origin v0.37.0\n```\n\nThis triggers GitHub Actions release workflow.\nNeeds: commit-release\n\n## Step: wait-for-ci\nWait for GitHub Actions to complete.\n\nMonitor: https://github.com/steveyegge/beads/actions\n\nCI will:\n- Build binaries via GoReleaser\n- Create GitHub Release with assets\n- Publish to npm (@beads/bd)\n- Publish to PyPI (beads-mcp)\n- Update Homebrew tap\n\nWait until all jobs succeed (~5-10 min).\nNeeds: push-and-tag\n\n## Step: verify-release\nVerify the release is complete.\n\n```bash\n# Check GitHub release\ngh release view v0.37.0\n\n# Check Homebrew\nbrew update \u0026\u0026 brew info steveyegge/beads/bd\n\n# Check npm\nnpm view @beads/bd version\n\n# Check PyPI\npip index versions beads-mcp\n```\n\nNeeds: wait-for-ci\n\n## Step: update-local\nUpdate local installations.\n\n```bash\n# Upgrade Homebrew\nbrew upgrade steveyegge/beads/bd\n\n# Or install from source\n./scripts/bump-version.sh 0.37.0 --install\n\n# Install MCP locally\npip install -e integrations/beads-mcp\n\n# Restart daemons\npkill -f \"bd daemon\" || true\n```\n\nVerify: `bd --version` shows 0.37.0\nNeeds: verify-release\n\n## Step: manual-publish\n(Optional) Manual publish if CI failed.\n\n```bash\n# npm (requires npm login)\n./scripts/bump-version.sh 0.37.0 --publish-npm\n\n# PyPI (requires TWINE credentials)\n./scripts/bump-version.sh 0.37.0 --publish-pypi\n\n# Or both\n./scripts/bump-version.sh 0.37.0 --publish-all\n```\n\nOnly needed if CI publishing failed.\nNeeds: wait-for-ci","status":"tombstone","priority":2,"issue_type":"molecule","created_at":"2025-12-26T01:09:49.836708-08:00","updated_at":"2025-12-28T01:24:39.204268-08:00","close_reason":"Release v0.37.0 complete. Published to GitHub, npm, PyPI, and Homebrew.","deleted_at":"2025-12-28T01:24:39.204268-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"molecule"} +{"id":"bd-mol-xga.1","title":"Update cmd/bd/info.go with release notes for 0.37.0.","description":"Update cmd/bd/info.go with release notes for 0.37.0.\n\nAdd a new VersionChange entry at the top of versionChanges slice:\n```go\n{\n Version: \"0.37.0\",\n Date: \"YYYY-MM-DD\",\n Changes: []string{\n \"NEW: Feature description\",\n \"FIX: Bug fix description\",\n \"IMPROVED: Enhancement description\",\n },\n},\n```\n\nRun `git log --oneline v\u003cprevious\u003e..HEAD` to see what changed.\n\ninstantiated_from: bd-mol-xga\nstep: update-release-notes","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:16.829377-08:00","updated_at":"2025-12-28T01:24:39.20498-08:00","close_reason":"Closed","dependencies":[{"issue_id":"bd-mol-xga.1","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:16.829843-08:00","created_by":"daemon"}],"deleted_at":"2025-12-28T01:24:39.20498-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-xga.10","title":"(Optional) Manual publish if CI failed.","description":"(Optional) Manual publish if CI failed.\n\n```bash\n# npm (requires npm login)\n./scripts/bump-version.sh 0.37.0 --publish-npm\n\n# PyPI (requires TWINE credentials)\n./scripts/bump-version.sh 0.37.0 --publish-pypi\n\n# Or both\n./scripts/bump-version.sh 0.37.0 --publish-all\n```\n\nOnly needed if CI publishing failed.\n\ninstantiated_from: bd-mol-xga\nstep: manual-publish","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:17.114721-08:00","updated_at":"2025-12-28T01:24:39.20568-08:00","close_reason":"Not needed - CI publishing succeeded.","dependencies":[{"issue_id":"bd-mol-xga.10","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:17.115119-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.10","depends_on_id":"bd-mol-xga.7","type":"blocks","created_at":"2025-12-26T01:10:17.379466-08:00","created_by":"daemon"}],"deleted_at":"2025-12-28T01:24:39.20568-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-xga.2","title":"Update CHANGELOG.md with detailed release notes.","description":"Update CHANGELOG.md with detailed release notes.\n\nAdd a new section after [Unreleased]:\n```markdown\n## [0.37.0] - YYYY-MM-DD\n\n### Added\n- **Feature name** (issue-id) - Description\n\n### Changed\n- **Change description** (issue-id)\n\n### Fixed\n- **Bug fix** (issue-id) - Description\n```\n\nSort by importance, not chronologically.\n\ninstantiated_from: bd-mol-xga\nstep: update-changelog","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:16.861035-08:00","updated_at":"2025-12-28T01:24:39.20639-08:00","close_reason":"Closed","dependencies":[{"issue_id":"bd-mol-xga.2","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:16.861529-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.2","depends_on_id":"bd-mol-xga.1","type":"blocks","created_at":"2025-12-26T01:10:17.14187-08:00","created_by":"daemon"}],"deleted_at":"2025-12-28T01:24:39.20639-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-xga.3","title":"Run the version bump script.","description":"Run the version bump script.\n\n```bash\n./scripts/bump-version.sh 0.37.0\n```\n\nThis updates version in all files:\n- cmd/bd/version.go\n- .claude-plugin/*.json\n- integrations/beads-mcp/pyproject.toml\n- npm-package/package.json\n- Hook templates\n\ninstantiated_from: bd-mol-xga\nstep: bump-version","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:16.892842-08:00","updated_at":"2025-12-28T01:24:39.207108-08:00","close_reason":"Closed","dependencies":[{"issue_id":"bd-mol-xga.3","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:16.893248-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.3","depends_on_id":"bd-mol-xga.2","type":"blocks","created_at":"2025-12-26T01:10:17.172199-08:00","created_by":"daemon"}],"deleted_at":"2025-12-28T01:24:39.207108-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-xga.4","title":"Run tests and verify lint passes.","description":"Run tests and verify lint passes.\n\n```bash\ngo test -short ./...\n```\n\nCI will run full lint, but fix any obvious issues first.\n\ninstantiated_from: bd-mol-xga\nstep: run-tests","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:16.925451-08:00","updated_at":"2025-12-28T01:24:39.207831-08:00","close_reason":"Closed","dependencies":[{"issue_id":"bd-mol-xga.4","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:16.925824-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.4","depends_on_id":"bd-mol-xga.3","type":"blocks","created_at":"2025-12-26T01:10:17.202675-08:00","created_by":"daemon"}],"deleted_at":"2025-12-28T01:24:39.207831-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-xga.5","title":"Commit the release changes.","description":"Commit the release changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: bump version to v0.37.0\"\n```\n\ninstantiated_from: bd-mol-xga\nstep: commit-release","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:16.957119-08:00","updated_at":"2025-12-28T01:24:39.208512-08:00","close_reason":"Closed","dependencies":[{"issue_id":"bd-mol-xga.5","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:16.957499-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.5","depends_on_id":"bd-mol-xga.4","type":"blocks","created_at":"2025-12-26T01:10:17.233695-08:00","created_by":"daemon"}],"deleted_at":"2025-12-28T01:24:39.208512-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-xga.6","title":"Push commit and create release tag.","description":"Push commit and create release tag.\n\n```bash\ngit push origin main\ngit tag v0.37.0\ngit push origin v0.37.0\n```\n\nThis triggers GitHub Actions release workflow.\n\ninstantiated_from: bd-mol-xga\nstep: push-and-tag","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:16.987513-08:00","updated_at":"2025-12-28T01:24:39.209193-08:00","close_reason":"Submitted to merge queue. Tagging (git tag v0.37.0 \u0026\u0026 git push origin v0.37.0) needs to be done from main after merge.","dependencies":[{"issue_id":"bd-mol-xga.6","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:16.987907-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.6","depends_on_id":"bd-mol-xga.5","type":"blocks","created_at":"2025-12-26T01:10:17.264209-08:00","created_by":"daemon"}],"deleted_at":"2025-12-28T01:24:39.209193-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-xga.7","title":"Wait for GitHub Actions to complete.","description":"Wait for GitHub Actions to complete.\n\nMonitor: https://github.com/steveyegge/beads/actions\n\nCI will:\n- Build binaries via GoReleaser\n- Create GitHub Release with assets\n- Publish to npm (@beads/bd)\n- Publish to PyPI (beads-mcp)\n- Update Homebrew tap\n\nWait until all jobs succeed (~5-10 min).\n\ninstantiated_from: bd-mol-xga\nstep: wait-for-ci","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:17.019226-08:00","updated_at":"2025-12-28T01:24:39.20993-08:00","close_reason":"Tag v0.37.0 pushed to origin. CI workflow triggered.","dependencies":[{"issue_id":"bd-mol-xga.7","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:17.019655-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.7","depends_on_id":"bd-mol-xga.6","type":"blocks","created_at":"2025-12-26T01:10:17.296023-08:00","created_by":"daemon"}],"deleted_at":"2025-12-28T01:24:39.20993-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-xga.8","title":"Verify the release is complete.","description":"Verify the release is complete.\n\n```bash\n# Check GitHub release\ngh release view v0.37.0\n\n# Check Homebrew\nbrew update \u0026\u0026 brew info steveyegge/beads/bd\n\n# Check npm\nnpm view @beads/bd version\n\n# Check PyPI\npip index versions beads-mcp\n```\n\ninstantiated_from: bd-mol-xga\nstep: verify-release","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:17.049777-08:00","updated_at":"2025-12-28T01:24:39.210624-08:00","close_reason":"Release v0.37.0 verified on GitHub. Release workflow succeeded.","dependencies":[{"issue_id":"bd-mol-xga.8","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:17.050108-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.8","depends_on_id":"bd-mol-xga.7","type":"blocks","created_at":"2025-12-26T01:10:17.328309-08:00","created_by":"daemon"}],"deleted_at":"2025-12-28T01:24:39.210624-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-xga.9","title":"Update local installations.","description":"Update local installations.\n\n```bash\n# Upgrade Homebrew\nbrew upgrade steveyegge/beads/bd\n\n# Or install from source\n./scripts/bump-version.sh 0.37.0 --install\n\n# Install MCP locally\npip install -e integrations/beads-mcp\n\n# Restart daemons\npkill -f \"bd daemon\" || true\n```\n\nVerify: `bd --version` shows 0.37.0\n\ninstantiated_from: bd-mol-xga\nstep: update-local","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-26T01:10:17.081154-08:00","updated_at":"2025-12-28T01:24:39.21136-08:00","close_reason":"Local installation can be done via: brew upgrade steveyegge/beads/bd","dependencies":[{"issue_id":"bd-mol-xga.9","depends_on_id":"bd-mol-xga","type":"parent-child","created_at":"2025-12-26T01:10:17.081536-08:00","created_by":"daemon"},{"issue_id":"bd-mol-xga.9","depends_on_id":"bd-mol-xga.8","type":"blocks","created_at":"2025-12-26T01:10:17.354246-08:00","created_by":"daemon"}],"deleted_at":"2025-12-28T01:24:39.21136-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} +{"id":"bd-mol-yxv","title":"Update info.go versionChanges","description":"Add entry to versionChanges in cmd/bd/info.go.\n\nThis powers `bd info --whats-new` for agents.\n\n```go\n\"0.39.0\": {\n \"summary\": \"Brief description\",\n \"changes\": []string{\n \"Key change 1\",\n \"Key change 2\",\n },\n},\n```\n\nFocus on workflow-impacting changes agents need to know.","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T19:34:09.557636-08:00","updated_at":"2025-12-28T01:24:39.212106-08:00","dependencies":[{"issue_id":"bd-mol-yxv","depends_on_id":"bd-mol-p1b","type":"parent-child","created_at":"2025-12-27T19:34:09.568242-08:00","created_by":"beads/crew/dave"},{"issue_id":"bd-mol-yxv","depends_on_id":"bd-mol-937","type":"blocks","created_at":"2025-12-27T19:34:09.594033-08:00","created_by":"beads/crew/dave"}],"deleted_at":"2025-12-28T01:24:39.212106-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} {"id":"bd-mql4","title":"getLocalSyncBranch silently ignores YAML parse errors","description":"In autoimport.go:170-172, YAML parsing errors are silently ignored. If a user has malformed YAML in config.yaml, sync-branch will just silently be empty with no feedback.\n\nRecommendation: Add debug logging since this function is only called during auto-import, and debugging silent failures is painful.\n\nAdd: debug.Logf(\"Warning: failed to parse config.yaml: %v\", err)","status":"open","priority":4,"issue_type":"task","created_at":"2025-12-07T02:03:44.217728-08:00","updated_at":"2025-12-07T02:03:44.217728-08:00"} {"id":"bd-muw","title":"Add empty tasks validation in workflow create","description":"workflow.go:321 will panic if wf.Tasks is empty. Add validation that len(wf.Tasks) \u003e 0 before accessing wf.Tasks[0].","status":"tombstone","priority":3,"issue_type":"bug","created_at":"2025-12-17T22:23:00.75707-08:00","updated_at":"2025-12-25T01:21:01.952723-08:00","deleted_at":"2025-12-25T01:21:01.952723-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"bug"} {"id":"bd-mv6h","title":"Add test coverage for external dep edge cases","description":"During code review of bd-zmmy, identified missing test coverage:\n\n1. RemoveDependency with external ref target (will fail - see bd-a3sj)\n2. GetBlockedIssues with mix of local and external blockers\n3. GetDependencyTree with external deps\n4. AddDependency cycle detection with external refs (should be skipped?)\n5. External dep resolution with WAL mode database\n6. External dep resolution when target project has no .beads directory\n7. External dep resolution with invalid external: format variations\n\nPriority 2 because bd-a3sj is a real bug that tests would catch.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-21T23:45:37.50093-08:00","updated_at":"2025-12-22T22:32:09.515096-08:00","closed_at":"2025-12-22T22:32:09.515096-08:00","close_reason":"Added test coverage: TestGetDependencyTreeExternalDeps (dep tree shows external deps), TestCycleDetectionWithExternalRefs (cycle detection ignores external refs), TestCheckExternalDepNoBeadsDirectory (handles missing .beads dir), TestCheckExternalDepInvalidFormats (handles various invalid formats). All edge cases from bd-mv6h description now covered.","dependencies":[{"issue_id":"bd-mv6h","depends_on_id":"bd-zmmy","type":"discovered-from","created_at":"2025-12-21T23:45:37.501495-08:00","created_by":"daemon"}]} @@ -460,7 +465,7 @@ {"id":"bd-n5ug","title":"Merge: bd-au0.7","description":"branch: polecat/dementus\ntarget: main\nsource_issue: bd-au0.7\nrig: beads","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-23T20:43:36.024341-08:00","updated_at":"2025-12-23T21:21:57.692158-08:00","closed_at":"2025-12-23T21:21:57.692158-08:00","close_reason":"stale - no code pushed"} {"id":"bd-n6fm","title":"witness Handoff","status":"pinned","priority":2,"issue_type":"task","created_at":"2025-12-23T04:35:02.675024-08:00","updated_at":"2025-12-24T17:38:31.554705-08:00"} {"id":"bd-n777","title":"Timer beads for scheduled agent callbacks","description":"## Problem\n\nAgents frequently need to wait for external events (CI completion, PR reviews, artifact builds) but have no good mechanism:\n- `sleep N` blocks and is unreliable (often times out at 8+ minutes)\n- Polling wastes context and is easy to forget\n- No way to survive session restarts\n\n## Proposal: Timer Beads\n\nA new bead type or field that represents a scheduled callback:\n\n### Creating timers\n```bash\nbd timer create --in 30s --callback \"Check CI run 12345\" --issue bd-xyz\nbd timer create --at \"2025-12-20T08:00:00\" --callback \"Morning standup\"\nbd timer create --in 5m --on-expire \"tmux send-keys -t dave 'bd show bd-xyz'\"\n```\n\n### Timer storage\n- Store in beads (survives restarts)\n- Fields: `expires_at`, `callback_description`, `on_expire_command`, `linked_issue`\n- Status: pending, fired, cancelled\n\n### Deacon integration\nThe Deacon daemon monitors timer beads:\n1. Wakes on next timer expiry\n2. Executes `on_expire` command (e.g., tmux send-keys to interrupt agent)\n3. Marks timer as fired\n4. Optionally updates linked issue\n\n### Use cases\n- CI monitoring: \"ping me when build completes\"\n- PR reviews: \"check back in 1 hour\"\n- Scheduled tasks: \"remind me at EOD to sync\"\n- Blocking waits: agent registers callback instead of sleeping\n\n## Acceptance criteria\n- [ ] Timer bead type or field design\n- [ ] `bd timer create/list/cancel` commands\n- [ ] Deacon timer monitoring loop\n- [ ] tmux integration for agent interrupts\n- [ ] Survives daemon restarts","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-19T23:05:33.051861-08:00","updated_at":"2025-12-21T17:19:48.087482-08:00","closed_at":"2025-12-21T17:19:48.087482-08:00","close_reason":"Will not implement - Gas Town uses a different approach for timed events"} -{"id":"bd-n97g","title":"bump-version.sh should detect pre-staged release notes","description":"When running the release workflow, I staged CHANGELOG.md and info.go changes before running bump-version.sh. The script:\n\n1. Warned about uncommitted changes (correct)\n2. Required stash/pop to proceed\n3. After pop, the [Unreleased] header wasn't converted to version/date\n\nThe script could be smarter:\n- Detect if staged changes are to CHANGELOG.md/info.go (expected for releases)\n- Or provide a --allow-staged flag\n- Or at minimum, re-apply the [Unreleased] → [X.Y.Z] transformation after detecting manual edits\n\nWorkaround: manually edit [Unreleased] to [0.39.1] - 2025-12-27 after stash pop.","status":"open","priority":3,"issue_type":"bug","created_at":"2025-12-27T22:51:23.239642-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-27T22:51:23.239642-08:00"} +{"id":"bd-n97g","title":"bump-version.sh should detect pre-staged release notes","description":"When running the release workflow, I staged CHANGELOG.md and info.go changes before running bump-version.sh. The script:\n\n1. Warned about uncommitted changes (correct)\n2. Required stash/pop to proceed\n3. After pop, the [Unreleased] header wasn't converted to version/date\n\nThe script could be smarter:\n- Detect if staged changes are to CHANGELOG.md/info.go (expected for releases)\n- Or provide a --allow-staged flag\n- Or at minimum, re-apply the [Unreleased] → [X.Y.Z] transformation after detecting manual edits\n\nWorkaround: manually edit [Unreleased] to [0.39.1] - 2025-12-27 after stash pop.","status":"closed","priority":3,"issue_type":"bug","created_at":"2025-12-27T22:51:23.239642-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-27T23:36:47.949197-08:00","closed_at":"2025-12-27T23:36:47.949197-08:00","close_reason":"Added --allow-staged flag to detect pre-staged CHANGELOG.md/info.go and include them in auto-commit"} {"id":"bd-ncwo","title":"Ghost resurrection: remote status:closed wins during git merge","description":"During bd sync, the 3-way git merge sometimes keeps remote's status:closed instead of local's status:tombstone. This causes ghost issues to resurrect even when tombstones exist.\n\nRoot cause: Git 3-way merge doesn't understand tombstone semantics. If base had closed, local changed to tombstone, and remote has closed, git might keep remote's version.\n\nThe early tombstone check in importer.go only prevents CREATION when tombstones exist in DB. But if applyDeletionsFromMerge hard-deletes the tombstones before import runs (because they're not in the merged result), the check doesn't help.\n\nPotential fixes:\n1. Make tombstones 'win' in the beads merge driver (internal/merge/merge.go)\n2. Don't hard-delete tombstones in applyDeletionsFromMerge if they're in the DB\n3. Export tombstones to a separate file that's not subject to merge\n\nGhost issues: bd-cb64c226.*, bd-cbed9619.*","status":"tombstone","priority":1,"issue_type":"bug","created_at":"2025-12-16T22:01:03.56423-08:00","updated_at":"2025-12-17T16:11:17.070763-08:00","deleted_at":"2025-12-17T16:11:17.070763-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"bug"} {"id":"bd-ndye","title":"mergeDependencies uses union instead of 3-way merge","description":"## Critical Bug\n\nThe `mergeDependencies` function in internal/merge/merge.go performs a UNION of left and right dependencies instead of a proper 3-way merge. This causes removed dependencies to be resurrected.\n\n### Root Cause\n\n```go\n// Current code (lines 795-816):\nfunc mergeDependencies(left, right []Dependency) []Dependency {\n // Just unions left + right\n // NEVER REMOVES anything\n // Doesn't even look at base!\n}\n```\n\nAnd `mergeIssue` (line 579) doesn't pass `base`:\n```go\nresult.Dependencies = mergeDependencies(left.Dependencies, right.Dependencies)\n```\n\n### Impact\n\nIf:\n- Base has dependency D\n- Left removes D (intentional)\n- Right still has D (stale)\n\nCurrent: D is in result (resurrection!)\nCorrect: Left removed it, D should NOT be in result\n\nThis breaks Gas Town's workflow and data integrity. Closed means closed.\n\n### Fix\n\nChange `mergeDependencies` to take `base` and do proper 3-way merge:\n- If dep was in base and removed by left → exclude (left wins)\n- If dep was in base and removed by right → exclude (right wins)\n- If dep wasn't in base and added by either → include\n- If dep was in base and both still have it → include\n\nKey principle: **REMOVALS ARE AUTHORITATIVE**\n\n### Files to Change\n\n1. internal/merge/merge.go:\n - `mergeDependencies(left, right)` → `mergeDependencies(base, left, right)`\n - `mergeIssue` line 579: pass `base.Dependencies`\n\n### Related\n\nThis also explains why `ProtectLocalExportIDs` in importer is defined but never used - the protection was never actually implemented.","status":"closed","priority":0,"issue_type":"bug","created_at":"2025-12-18T23:15:54.475872-08:00","updated_at":"2025-12-18T23:21:10.709571-08:00","closed_at":"2025-12-18T23:21:10.709571-08:00"} {"id":"bd-nim5","title":"Detect/prevent child→parent dependency anti-pattern","description":"## Problem\n\nWhen filing issues with dependencies, it's easy to fall into the \"temporal trap\":\n- Thinking \"Phase 1 comes before Phase 2\"\n- Writing `bd dep add phase1 phase2`\n- But that means \"phase1 depends on phase2\" (backwards!)\n\nA specific variant: children depending on their parent epic. This is ALWAYS wrong because:\n1. Parent-child relationship already captures the dependency (parent closes when children done)\n2. Child→parent dep creates a block: child can't start because parent is \"open\"\n3. Parent can't close because children aren't done\n4. Deadlock\n\n## Solution\n\n### 1. Prevent at creation (`bd dep add`)\n\nWhen user runs `bd dep add X Y`:\n- Check if X is a child of Y (X.id starts with Y.id + \".\")\n- If so, error: \"Cannot add dependency: X is already a child of Y. Children inherit dependency on parent completion via hierarchy.\"\n\n### 2. Detect in `bd doctor`\n\nAdd a check that finds all cases where:\n- Issue A depends on Issue B\n- A.id matches pattern B.id + \".*\" (A is child of B)\n\nReport as: \"Child→parent dependency detected (anti-pattern)\"\nOffer repair: \"Remove N backwards dependencies? [y/N]\"\n\n## Implementation\n\n- `dep_add.go`: Add parent-child check before adding dependency\n- `doctor.go`: Add backwards-dep detection to health checks\n","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-12-24T12:51:15.788796-08:00","updated_at":"2025-12-24T13:02:44.079093-08:00","closed_at":"2025-12-24T13:02:44.079093-08:00","close_reason":"Implemented child→parent dependency detection and prevention"} @@ -468,7 +473,7 @@ {"id":"bd-nl2","title":"No logging/debugging for tombstone resurrection events","description":"Per the design document bd-zvg Open Question 1: Should resurrection log a warning? Recommendation was Yes. Currently, when an expired tombstone loses to a live issue (resurrection), there is no logging or debugging output. This makes it hard to understand why an issue reappeared. Recommendation: Add optional debug logging when resurrection occurs, e.g., Issue bd-abc resurrected (tombstone expired). Files: internal/merge/merge.go:359-366, 371-378, 400-405, 410-415","status":"open","priority":4,"issue_type":"feature","created_at":"2025-12-05T16:36:52.27525-08:00","updated_at":"2025-12-05T16:36:52.27525-08:00"} {"id":"bd-nmch","title":"Add EntityRef type for structured entity references","description":"Create EntityRef struct with Name, Platform, Org, ID fields. This is the foundation for HOP entity tracking. Can render as entity://hop/\u003cplatform\u003e/\u003corg\u003e/\u003cid\u003e when needed. Add to internal/types/types.go.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-22T17:53:25.104328-08:00","updated_at":"2025-12-22T17:58:00.014103-08:00","closed_at":"2025-12-22T17:58:00.014103-08:00","close_reason":"Implemented EntityRef type with Name, Platform, Org, ID fields. Added URI(), IsEmpty(), String() methods and ParseEntityURI() function. Full test coverage.","dependencies":[{"issue_id":"bd-nmch","depends_on_id":"bd-7pwh","type":"parent-child","created_at":"2025-12-22T17:53:43.325405-08:00","created_by":"daemon"}]} {"id":"bd-nppb","title":"Refinery Patrol","description":"Merge queue processor patrol loop with verification gates.","status":"tombstone","priority":2,"issue_type":"molecule","created_at":"2025-12-26T13:08:21.308272-08:00","updated_at":"2025-12-27T00:10:54.177947-08:00","deleted_at":"2025-12-27T00:10:54.177947-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"molecule"} -{"id":"bd-nqyp","title":"mol-beads-release","description":"Release checklist for beads version {{version}}.\n\nThis molecule ensures all release steps are completed properly.\nVariable: {{version}} - target version (e.g., 0.35.0)\n\n## Step: update-release-notes\nUpdate cmd/bd/info.go with release notes for {{version}}.\n\nAdd a new VersionChange entry at the top of versionChanges slice:\n```go\n{\n Version: \"{{version}}\",\n Date: \"YYYY-MM-DD\",\n Changes: []string{\n \"NEW: Feature description\",\n \"FIX: Bug fix description\",\n \"IMPROVED: Enhancement description\",\n },\n},\n```\n\nRun `git log --oneline v\u003cprevious\u003e..HEAD` to see what changed.\n\n## Step: update-changelog\nUpdate CHANGELOG.md with detailed release notes.\n\nAdd a new section after [Unreleased]:\n```markdown\n## [{{version}}] - YYYY-MM-DD\n\n### Added\n- **Feature name** (issue-id) - Description\n\n### Changed\n- **Change description** (issue-id)\n\n### Fixed\n- **Bug fix** (issue-id) - Description\n```\n\nSort by importance, not chronologically.\nNeeds: update-release-notes\n\n## Step: bump-version\nRun the version bump script.\n\n```bash\n./scripts/bump-version.sh {{version}}\n```\n\nThis updates version in all files:\n- cmd/bd/version.go\n- .claude-plugin/*.json\n- integrations/beads-mcp/pyproject.toml\n- npm-package/package.json\n- Hook templates\n\nNeeds: update-changelog\n\n## Step: run-tests\nRun tests and verify lint passes.\n\n```bash\ngo test -short ./...\n```\n\nCI will run full lint, but fix any obvious issues first.\nNeeds: bump-version\n\n## Step: commit-release\nCommit the release changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: bump version to v{{version}}\"\n```\n\nNeeds: run-tests\n\n## Step: push-and-tag\nPush commit and create release tag.\n\n```bash\ngit push origin main\ngit tag v{{version}}\ngit push origin v{{version}}\n```\n\nThis triggers GitHub Actions release workflow.\nNeeds: commit-release\n\n## Step: wait-for-ci\nWait for GitHub Actions to complete.\n\nMonitor: https://github.com/steveyegge/beads/actions\n\nCI will:\n- Build binaries via GoReleaser\n- Create GitHub Release with assets\n- Publish to npm (@beads/bd)\n- Publish to PyPI (beads-mcp)\n- Update Homebrew tap\n\nWait until all jobs succeed (~5-10 min).\nNeeds: push-and-tag\n\n## Step: verify-release\nVerify the release is complete.\n\n```bash\n# Check GitHub release\ngh release view v{{version}}\n\n# Check Homebrew\nbrew update \u0026\u0026 brew info steveyegge/beads/bd\n\n# Check npm\nnpm view @beads/bd version\n\n# Check PyPI\npip index versions beads-mcp\n```\n\nNeeds: wait-for-ci\n\n## Step: update-local\nUpdate local installations with proper codesigning (macOS).\n\n```bash\n# Build from source in mayor/rig (canonical build location)\ncd ~/gt/beads/mayor/rig\ngit pull\ngo build -o bd ./cmd/bd\n\n# Sign and install (macOS requires codesigning to avoid \"Killed: 9\")\n# Uses fix-gt script which handles both gt and bd binaries\nfix-gt\n\n# Or manually sign if fix-gt not available:\n# xattr -cr bd \u0026\u0026 codesign -f -s - bd\n# cp bd ~/go/bin/bd \u0026\u0026 codesign -f -s - ~/go/bin/bd\n# cp bd ~/.local/bin/bd \u0026\u0026 codesign -f -s - ~/.local/bin/bd\n\n# Install MCP locally\npip install -e integrations/beads-mcp\n\n# Restart daemons\npkill -f \"bd daemon\" || true\n```\n\nVerify: `bd --version` shows {{version}}\nNeeds: verify-release\n\n## Step: manual-publish\n(Optional) Manual publish if CI failed.\n\n```bash\n# npm (requires npm login)\n./scripts/bump-version.sh {{version}} --publish-npm\n\n# PyPI (requires TWINE credentials)\n./scripts/bump-version.sh {{version}} --publish-pypi\n\n# Or both\n./scripts/bump-version.sh {{version}} --publish-all\n```\n\nOnly needed if CI publishing failed.\nNeeds: wait-for-ci","status":"open","priority":2,"issue_type":"molecule","created_at":"2025-12-23T11:29:39.087936-08:00","updated_at":"2025-12-27T00:58:15.998699-08:00","labels":["template"]} +{"id":"bd-nqyp","title":"mol-beads-release","description":"Release checklist for beads version {{version}}.\n\nThis molecule ensures all release steps are completed properly.\nVariable: {{version}} - target version (e.g., 0.35.0)\n\n## Step: update-release-notes\nUpdate cmd/bd/info.go with release notes for {{version}}.\n\nAdd a new VersionChange entry at the top of versionChanges slice:\n```go\n{\n Version: \"{{version}}\",\n Date: \"YYYY-MM-DD\",\n Changes: []string{\n \"NEW: Feature description\",\n \"FIX: Bug fix description\",\n \"IMPROVED: Enhancement description\",\n },\n},\n```\n\nRun `git log --oneline v\u003cprevious\u003e..HEAD` to see what changed.\n\n## Step: update-changelog\nUpdate CHANGELOG.md with detailed release notes.\n\nAdd a new section after [Unreleased]:\n```markdown\n## [{{version}}] - YYYY-MM-DD\n\n### Added\n- **Feature name** (issue-id) - Description\n\n### Changed\n- **Change description** (issue-id)\n\n### Fixed\n- **Bug fix** (issue-id) - Description\n```\n\nSort by importance, not chronologically.\nNeeds: update-release-notes\n\n## Step: bump-version\nRun the version bump script.\n\n```bash\n./scripts/bump-version.sh {{version}}\n```\n\nThis updates version in all files:\n- cmd/bd/version.go\n- .claude-plugin/*.json\n- integrations/beads-mcp/pyproject.toml\n- npm-package/package.json\n- Hook templates\n\nNeeds: update-changelog\n\n## Step: run-tests\nRun tests and verify lint passes.\n\n```bash\ngo test -short ./...\n```\n\nCI will run full lint, but fix any obvious issues first.\nNeeds: bump-version\n\n## Step: commit-release\nCommit the release changes.\n\n```bash\ngit add -A\ngit commit -m \"chore: bump version to v{{version}}\"\n```\n\nNeeds: run-tests\n\n## Step: push-and-tag\nPush commit and create release tag.\n\n```bash\ngit push origin main\ngit tag v{{version}}\ngit push origin v{{version}}\n```\n\nThis triggers GitHub Actions release workflow.\nNeeds: commit-release\n\n## Step: wait-for-ci\nWait for GitHub Actions to complete.\n\nMonitor: https://github.com/steveyegge/beads/actions\n\nCI will:\n- Build binaries via GoReleaser\n- Create GitHub Release with assets\n- Publish to npm (@beads/bd)\n- Publish to PyPI (beads-mcp)\n- Update Homebrew tap\n\nWait until all jobs succeed (~5-10 min).\nNeeds: push-and-tag\n\n## Step: verify-release\nVerify the release is complete.\n\n```bash\n# Check GitHub release\ngh release view v{{version}}\n\n# Check Homebrew\nbrew update \u0026\u0026 brew info steveyegge/beads/bd\n\n# Check npm\nnpm view @beads/bd version\n\n# Check PyPI\npip index versions beads-mcp\n```\n\nNeeds: wait-for-ci\n\n## Step: update-local\nUpdate local installations with proper codesigning (macOS).\n\n```bash\n# Build from source in mayor/rig (canonical build location)\ncd ~/gt/beads/mayor/rig\ngit pull\ngo build -o bd ./cmd/bd\n\n# Sign and install (macOS requires codesigning to avoid \"Killed: 9\")\n# Uses fix-gt script which handles both gt and bd binaries\nfix-gt\n\n# Or manually sign if fix-gt not available:\n# xattr -cr bd \u0026\u0026 codesign -f -s - bd\n# cp bd ~/go/bin/bd \u0026\u0026 codesign -f -s - ~/go/bin/bd\n# cp bd ~/.local/bin/bd \u0026\u0026 codesign -f -s - ~/.local/bin/bd\n\n# Install MCP locally\npip install -e integrations/beads-mcp\n\n# Restart daemons\npkill -f \"bd daemon\" || true\n```\n\nVerify: `bd --version` shows {{version}}\nNeeds: verify-release\n\n## Step: manual-publish\n(Optional) Manual publish if CI failed.\n\n```bash\n# npm (requires npm login)\n./scripts/bump-version.sh {{version}} --publish-npm\n\n# PyPI (requires TWINE credentials)\n./scripts/bump-version.sh {{version}} --publish-pypi\n\n# Or both\n./scripts/bump-version.sh {{version}} --publish-all\n```\n\nOnly needed if CI publishing failed.\nNeeds: wait-for-ci","status":"tombstone","priority":2,"issue_type":"molecule","created_at":"2025-12-23T11:29:39.087936-08:00","updated_at":"2025-12-28T01:26:51.06645-08:00","labels":["template"],"deleted_at":"2025-12-28T01:26:51.06645-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"molecule"} {"id":"bd-nuh1","title":"GH#403: bd doctor --fix circular error message","description":"bd doctor --fix suggests running bd doctor --fix for deletions manifest issue. Fix to provide actual resolution. See GitHub issue #403.","status":"tombstone","priority":2,"issue_type":"bug","created_at":"2025-12-16T01:03:16.290018-08:00","updated_at":"2025-12-17T16:11:17.070763-08:00","deleted_at":"2025-12-17T16:11:17.070763-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"bug"} {"id":"bd-nurq","title":"Implement bd mol current command","description":"Show what molecule the agent should currently be working on. Referenced by gt-um6q, gt-lz13. Needed for molecule navigation workflow in templates.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-12-23T00:17:54.069983-08:00","updated_at":"2025-12-23T01:23:59.523404-08:00","closed_at":"2025-12-23T01:23:59.523404-08:00","close_reason":"Implementation already existed, added tests (TestGetMoleculeProgress, TestFindParentMolecule, TestAdvanceToNextStep*), rebuilt and installed binary"} {"id":"bd-o18s","title":"Rename 'wisp' back to 'ephemeral' in beads API","description":"The beads API uses 'wisp' terminology (Wisp field, bd wisp command) but the underlying SQLite column is 'ephemeral'. \n\nThis creates cognitive overhead since wisp is a Gas Town concept.\n\nRename to use 'ephemeral' consistently:\n- types.Issue.Wisp → types.Issue.Ephemeral\n- JSON field: wisp → ephemeral \n- CLI: bd wisp → bd ephemeral (or just use flags on existing commands)\n\nThe SQLite column already uses 'ephemeral' so no schema migration needed.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T20:16:36.627876-08:00","updated_at":"2025-12-26T21:04:10.212439-08:00","closed_at":"2025-12-26T21:04:10.212439-08:00","close_reason":"Renamed 'wisp' to 'ephemeral' throughout the codebase"} @@ -523,6 +528,7 @@ {"id":"bd-pvu0","title":"Merge: bd-4opy","description":"branch: polecat/angharad\ntarget: main\nsource_issue: bd-4opy\nrig: beads","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-23T00:24:44.057267-08:00","updated_at":"2025-12-23T01:33:25.730271-08:00","closed_at":"2025-12-23T01:33:25.730271-08:00","close_reason":"Merged to main"} {"id":"bd-pzw7","title":"gt handoff deadlock at handoff.go:125","notes":"When running 'gt handoff -m \"message\"' after successful MR submit, go panics with 'fatal error: all goroutines are asleep - deadlock\\!' at handoff.go:125. The shutdown request still appears to be sent successfully but the command crashes. Stack trace shows issue is in runHandoff select statement.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-19T23:22:12.46315-08:00","updated_at":"2025-12-21T17:51:25.817355-08:00","closed_at":"2025-12-21T17:51:25.817355-08:00","close_reason":"Moved to gastown: gt-dich"} {"id":"bd-qioh","title":"Standardize error handling: replace direct fmt.Fprintf+os.Exit with FatalError","description":"Standardize error handling in cmd/bd/ using FatalError pattern.\n\n## Current State\n~200+ instances of direct `fmt.Fprintf(os.Stderr, ...) + os.Exit(1)` pattern scattered across cmd/bd/*.go files.\n\n## Target Pattern\n\nUse existing FatalError helper (or create if missing):\n\n```go\n// In cmd/bd/helpers.go or similar\nfunc FatalError(format string, args ...interface{}) {\n fmt.Fprintf(os.Stderr, \"Error: \"+format+\"\\n\", args...)\n os.Exit(1)\n}\n\nfunc FatalErrorf(err error, context string) {\n fmt.Fprintf(os.Stderr, \"Error: %s: %v\\n\", context, err)\n os.Exit(1)\n}\n```\n\n## Transformation\n\n```go\n// Before\nfmt.Fprintf(os.Stderr, \"Error: %v\\n\", err)\nos.Exit(1)\n\n// After\nFatalError(\"%v\", err)\n\n// Before\nfmt.Fprintf(os.Stderr, \"Error: invalid --since duration: %v\\n\", err)\nos.Exit(1)\n\n// After\nFatalError(\"invalid --since duration: %v\", err)\n```\n\n## Files to Update (by occurrence count)\nRun: `grep -c \"os.Exit(1)\" cmd/bd/*.go | sort -t: -k2 -rn | head -20`\n\nPriority files (highest occurrence):\n- close.go\n- show.go\n- sync.go\n- init.go\n- list.go\n- create.go\n- update.go\n\n## Implementation Steps\n\n1. **Check if FatalError exists** in cmd/bd/helpers.go or create it\n2. **Create migration script** or use sed:\n ```bash\n # Find patterns to replace\n grep -rn \"fmt.Fprintf(os.Stderr.*Error.*\\n.*os.Exit(1)\" cmd/bd/\n ```\n3. **Replace systematically** file by file\n4. **Run tests** after each file to verify behavior unchanged\n5. **Run linter** to catch any missed patterns\n\n## Verification\n```bash\n# Count remaining direct exits (should be near zero)\ngrep -c \"os.Exit(1)\" cmd/bd/*.go | awk -F: \"{sum+=\\$2} END {print sum}\"\n\n# Run tests\ngo test -short ./cmd/bd/...\n```\n\n## Success Criteria\n- All error exits use FatalError/FatalErrorf\n- Consistent \"Error: \" prefix on all error messages\n- Tests pass\n- No behavior changes (exit codes remain 1)","notes":"## Progress (Dec 2025)\n\nStandardized error handling in 3 major files:\n- compact.go: All 48 os.Exit(1) calls converted to FatalError\n- sync.go: All error patterns converted (kept 1 valid summary exit)\n- migrate.go: 4 patterns converted\n\n## Remaining Work\n~326 fmt.Fprintf(os.Stderr, \"Error:\") patterns remain across ~30 files.\nHigh-count files remaining: show.go (16), dep.go (14), gate.go (28), init.go (11).\n\n## Verification\n- Build compiles successfully\n- Tests pass","status":"closed","priority":2,"issue_type":"task","assignee":"beads/Errata","created_at":"2025-12-16T18:17:19.309394-08:00","updated_at":"2025-12-23T14:14:37.939802-08:00","closed_at":"2025-12-23T14:14:37.939802-08:00","close_reason":"Error handling standardization - polecat completed, MR submitted","dependencies":[{"issue_id":"bd-qioh","depends_on_id":"bd-iz5t","type":"parent-child","created_at":"2025-12-23T12:44:07.43514-08:00","created_by":"daemon"}]} +{"id":"bd-qket","title":"Add computed .parent field to JSON output for convenience","description":"Currently parent is only in dependencies[]. Add a top-level .parent field to JSON/JSONL output that extracts the parent-child dependency for easier querying.\n\nExample:\n```bash\n# Current (works but verbose):\nbd show \u003cid\u003e --json | jq '.[0].dependencies[] | select(.dependency_type == \"parent-child\") | .id'\n\n# Desired:\nbd show \u003cid\u003e --json | jq '.[0].parent'\n```\n\nLow priority enhancement.","status":"closed","priority":4,"issue_type":"feature","created_at":"2025-12-27T23:32:44.24217-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-28T02:24:31.453442-08:00","closed_at":"2025-12-28T02:24:31.453442-08:00","close_reason":"Added computed .parent field to JSON output"} {"id":"bd-qkw9","title":"Run bump-version.sh {{version}}","description":"Run ./scripts/bump-version.sh {{version}} to update version in all files","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T22:55:58.841424-08:00","updated_at":"2025-12-20T17:59:26.262877-08:00","closed_at":"2025-12-20T01:18:48.99813-08:00","dependencies":[{"issue_id":"bd-qkw9","depends_on_id":"bd-6s61","type":"parent-child","created_at":"2025-12-19T22:56:14.786027-08:00","created_by":"daemon"}]} {"id":"bd-qph3","title":"Consolidate git context into single cached struct","description":"Code review finding from bd-7di fix.\n\nCurrently there are 3 separate caches:\n- isWorktreeOnce/isWorktreeResult\n- mainRepoRootOnce/mainRepoRootResult/mainRepoRootErr \n- repoRootOnce/repoRootResult\n\nThese have redundant git calls - e.g. both isWorktreeUncached() and getMainRepoRootUncached() call getGitDirNoError(\"--git-common-dir\").\n\nCould consolidate into a single cached struct:\n```go\ntype gitContext struct {\n gitDir string\n commonDir string\n repoRoot string\n isWorktree bool\n}\n```\n\nThis would reduce git calls further and simplify ResetCaches().\n\nFile: internal/git/gitdir.go","status":"closed","priority":4,"issue_type":"task","assignee":"beads/crew/dave","created_at":"2025-12-25T22:08:53.829215-08:00","updated_at":"2025-12-27T21:49:38.611332-08:00","closed_at":"2025-12-27T21:49:38.611332-08:00","close_reason":"Consolidated into single gitContext struct with one git call"} {"id":"bd-qqc","title":"Release v{{version}}","description":"SUPERSEDED by bd-7bs4. Use the new proto for releases.\n\n","status":"tombstone","priority":1,"issue_type":"epic","created_at":"2025-12-18T12:59:00.610371-08:00","updated_at":"2025-12-24T16:25:31.181723-08:00","labels":["template"],"deleted_at":"2025-12-24T16:25:31.181723-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"epic"} @@ -560,6 +566,7 @@ {"id":"bd-rl5t","title":"Integration test: agent waits for CI via gate","description":"End-to-end test of the gate workflow.\n\n## Test Scenario\n1. Agent creates gate: bd gate create --await gh:run:123 --timeout 5m --notify beads/dave\n2. Agent writes handoff and exits\n3. Deacon patrol checks gate condition\n4. (Mock) GitHub run completes\n5. Deacon notifies waiter and closes gate\n6. New agent session reads mail and resumes\n\n## Test Requirements\n- Mock GitHub API responses\n- Test timeout path\n- Test multiple waiters\n- Verify mail notifications sent","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-23T11:44:41.725752-08:00","updated_at":"2025-12-23T12:24:08.346347-08:00","closed_at":"2025-12-23T12:24:08.346347-08:00","close_reason":"Moved to gastown: gt-gswn","dependencies":[{"issue_id":"bd-rl5t","depends_on_id":"bd-udsi","type":"parent-child","created_at":"2025-12-23T11:44:53.157037-08:00","created_by":"daemon"},{"issue_id":"bd-rl5t","depends_on_id":"bd-2l03","type":"blocks","created_at":"2025-12-23T11:44:56.674866-08:00","created_by":"daemon"},{"issue_id":"bd-rl5t","depends_on_id":"bd-ykqu","type":"blocks","created_at":"2025-12-23T11:44:56.753264-08:00","created_by":"daemon"}]} {"id":"bd-rnnr","title":"BondRef data model for compound lineage","description":"Add data model support for tracking compound molecule lineage.\n\nNEW FIELDS on Issue:\n bonded_from: []BondRef // For compounds: constituent protos\n\nNEW TYPE:\n type BondRef struct {\n ProtoID string // Source proto ID\n BondType string // sequential, parallel, conditional\n BondPoint string // Attachment site (issue ID or empty for root)\n }\n\nJSONL SERIALIZATION:\n {\n \"id\": \"proto-feature-tested\",\n \"title\": \"Feature with tests\",\n \"bonded_from\": [\n {\"proto_id\": \"proto-feature\", \"bond_type\": \"root\"},\n {\"proto_id\": \"proto-testing\", \"bond_type\": \"sequential\"}\n ],\n ...\n }\n\nQUERIES:\n- GetCompoundConstituents(id) → []BondRef\n- IsCompound(id) → bool\n- GetCompoundsUsing(protoID) → []Issue // Reverse lookup","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-21T00:59:38.582509-08:00","updated_at":"2025-12-21T01:19:43.922416-08:00","closed_at":"2025-12-21T01:19:43.922416-08:00","close_reason":"Added BondRef type to types.go with ProtoID, BondType, BondPoint fields; added BondedFrom field to Issue; added IsCompound() and GetConstituents() helpers; added BondType constants","dependencies":[{"issue_id":"bd-rnnr","depends_on_id":"bd-o5xe","type":"parent-child","created_at":"2025-12-21T00:59:51.234246-08:00","created_by":"daemon"}]} {"id":"bd-rp4o","title":"Deleted issues resurrect during bd sync (tombstones not propagating)","description":"## Problem\n\nWhen issues are deleted with bd delete --force, they get deleted from the local DB but resurrect during the next bd sync.\n\n## Reproduction\n\n1. Observe orphan warnings (bd-cb64c226.*, bd-cbed9619.*)\n2. Delete them: bd delete bd-cb64c226.1 ... --force\n3. Run bd sync\n4. Orphan warnings reappear - issues were resurrected!\n\n## Root Cause Hypothesis\n\nThe sync branch workflow (beads-sync) has the old state before deletions. When bd sync pulls from beads-sync and copies JSONL to main, the deleted issues are re-imported.\n\nTombstones may not be properly:\n1. Written to beads-sync during export\n2. Propagated during pull/merge\n3. Honored during import\n\n## Related\n\n- bd-7b7h: chicken-and-egg sync.branch bug (same workflow)\n- bd-ncwo: ID-based fallback matching to prevent ghost resurrection\n\n## Files to Investigate\n\n- cmd/bd/sync.go (export/import flow)\n- internal/syncbranch/worktree.go (PullFromSyncBranch, copyJSONLToMainRepo)\n- internal/importer/ (tombstone handling)","status":"tombstone","priority":1,"issue_type":"bug","created_at":"2025-12-16T23:09:43.072696-08:00","updated_at":"2025-12-17T16:11:17.070763-08:00","deleted_at":"2025-12-17T16:11:17.070763-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"bug"} +{"id":"bd-rs5a","title":"Test agent bead","description":"Testing new agent type","status":"closed","priority":2,"issue_type":"agent","created_at":"2025-12-27T23:36:57.594945-08:00","created_by":"mayor","updated_at":"2025-12-27T23:37:15.583616-08:00","closed_at":"2025-12-27T23:37:15.583616-08:00","close_reason":"Test beads for schema change"} {"id":"bd-rupw","title":"Run bump-version.sh 0.30.7","description":"Run ./scripts/bump-version.sh 0.30.7 to update version in all files","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T22:56:48.649647-08:00","updated_at":"2025-12-19T22:57:31.512956-08:00","closed_at":"2025-12-19T22:57:31.512956-08:00","dependencies":[{"issue_id":"bd-rupw","depends_on_id":"bd-8pyn","type":"parent-child","created_at":"2025-12-19T22:56:48.653475-08:00","created_by":"stevey"}]} {"id":"bd-rx6o","title":"Test Child Task","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T22:15:23.27506-08:00","created_by":"beads/crew/dave","updated_at":"2025-12-27T22:16:35.925357-08:00","deleted_at":"2025-12-27T22:16:35.925357-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"task"} {"id":"bd-rze6","title":"Digest: Release v0.34.0 @ 2025-12-22 12:16","description":"Released v0.34.0: wisp commands, chemistry UX, cross-project deps","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-22T12:16:53.033119-08:00","updated_at":"2025-12-22T12:16:53.033119-08:00","closed_at":"2025-12-22T12:16:53.033025-08:00","close_reason":"Squashed from wisp bd-25c (20 issues)"} @@ -578,7 +585,7 @@ {"id":"bd-t3en","title":"Merge: bd-d28c","description":"branch: polecat/capable\ntarget: main\nsource_issue: bd-d28c\nrig: beads","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-23T20:43:16.997802-08:00","updated_at":"2025-12-23T21:21:57.694201-08:00","closed_at":"2025-12-23T21:21:57.694201-08:00","close_reason":"stale - no code pushed"} {"id":"bd-t4sb","title":"Work on beads-d8h: Fix prefix mismatch false positive wit...","description":"Work on beads-d8h: Fix prefix mismatch false positive with multi-hyphen prefixes like 'asianops-audit-' (GH#422). When done, submit MR (not PR) to integration branch for Refinery.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-19T22:56:19.545069-08:00","updated_at":"2025-12-19T23:28:32.429127-08:00","closed_at":"2025-12-19T23:21:45.471711-08:00","close_reason":"Fixed multi-hyphen prefix false positive in ValidateIDFormat (GH#422)"} {"id":"bd-t4u1","title":"False positive detection by Kaspersky Antivirus (Trojan)","description":"Kaspersky Antivirus falsely detects beads (bd.exe v0.23.1) as a Trojan (PDM:Trojan.Win32.Generic) and removes it.\nEvent: Malicious object detected\nComponent: System Watcher\nObject name: bd.exe\n","status":"closed","priority":1,"issue_type":"task","assignee":"beads/capable","created_at":"2025-11-20T18:56:12.498187-05:00","updated_at":"2025-12-23T23:47:23.182018-08:00","closed_at":"2025-12-23T23:47:23.182018-08:00","close_reason":"Documentation already comprehensive in docs/ANTIVIRUS.md and docs/TROUBLESHOOTING.md. Added TROUBLESHOOTING.md link to README for discoverability. Created follow-up issue bd-14v0 to track Windows code signing implementation as a long-term solution."} -{"id":"bd-ta4r","title":"Wisp operations should auto-bypass daemon","description":"During the v0.39.1 release, every wisp operation required --no-daemon flag:\n\nbd --no-daemon mol wisp create beads-release --var version=0.39.1\nbd --no-daemon close bd-eph-xxx\nbd --no-daemon mol burn bd-eph-bv2\n\nSince wisps are ephemeral (Ephemeral=true) and never exported to JSONL, they are inherently local-only. The daemon cannot help with them anyway.\n\nProposal: When operating on bd-eph-* issues or wisp subcommands, auto-detect and bypass the daemon. This would:\n- Reduce friction in wisp workflows\n- Prevent accidental daemon use that would fail anyway\n- Make the ephemeral nature more obvious","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-27T22:51:24.409066-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-27T22:51:24.409066-08:00"} +{"id":"bd-ta4r","title":"Wisp operations should auto-bypass daemon","description":"During the v0.39.1 release, every wisp operation required --no-daemon flag:\n\nbd --no-daemon mol wisp create beads-release --var version=0.39.1\nbd --no-daemon close bd-eph-xxx\nbd --no-daemon mol burn bd-eph-bv2\n\nSince wisps are ephemeral (Ephemeral=true) and never exported to JSONL, they are inherently local-only. The daemon cannot help with them anyway.\n\nProposal: When operating on bd-eph-* issues or wisp subcommands, auto-detect and bypass the daemon. This would:\n- Reduce friction in wisp workflows\n- Prevent accidental daemon use that would fail anyway\n- Make the ephemeral nature more obvious","status":"closed","priority":3,"issue_type":"feature","created_at":"2025-12-27T22:51:24.409066-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-28T02:10:30.123755-08:00","closed_at":"2025-12-28T02:10:30.123755-08:00","close_reason":"Implemented auto-daemon-bypass for wisp operations"} {"id":"bd-tbz3","title":"bd init UX Improvements","description":"bd init leaves users with incomplete setup, requiring manual bd doctor --fix. Issues found: (1) git hooks not installed if user declines prompt, (2) no auto-migration when CLI is upgraded, (3) stale merge driver configs from old versions. Fix by making bd init more robust with better defaults and auto-migration.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-11-21T23:16:00.333543-08:00","updated_at":"2025-12-23T04:20:51.88847-08:00","closed_at":"2025-12-23T04:20:51.88847-08:00","close_reason":"Already implemented in commits ec4117d0 and 3a36d0b9 - hooks/merge driver install by default, doctor runs at end of init"} {"id":"bd-tcvh","title":"Test prefix beads","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-27T14:24:41.707092-08:00","created_by":"stevey","updated_at":"2025-12-27T14:24:50.421598-08:00","deleted_at":"2025-12-27T14:24:50.421598-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} {"id":"bd-tggf","title":"Code Health Review Dec 2025: Technical Debt Cleanup","description":"Epic grouping technical debt identified in the Dec 16, 2025 code health review.\n\n## Overall Health Grade: B (Solid foundation, needs cleanup)\n\n### P1 (High Priority):\n- bd-74w1: Consolidate duplicate path-finding utilities\n- [deleted:bd-b6xo]: Remove/fix ClearDirtyIssues() race condition\n- [deleted:bd-b3og]: Fix TestImportBugIntegration deadlock\n\n### P2 (Medium Priority):\n- bd-05a8: Split large files (doctor.go, sync.go)\n- bd-qioh: Standardize error handling patterns\n- bd-rgyd: Split queries.go (1586 lines)\n- bd-9g1z: Fix/remove TestFindJSONLPathDefault\n\n### P3 (Low Priority):\n- bd-ork0: Add comments to 30+ ignored errors\n- bd-4nqq: Remove dead test code in info_test.go\n- bd-dhza: Reduce global state in main.go\n\n## Key Areas:\n1. Code duplication in path utilities\n2. Large monolithic files (5 files \u003e1000 lines)\n3. Global state (25+ variables, 3 deprecated)\n4. Silent error suppression (30+ instances)\n5. Test gaps and dead test code\n6. Atomicity risks in batch operations","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-16T18:18:58.115507-08:00","updated_at":"2025-12-25T01:21:01.961139-08:00","dependencies":[{"issue_id":"bd-tggf","depends_on_id":"bd-74w1","type":"blocks","created_at":"2025-12-22T21:00:21.429274-08:00","created_by":"daemon"},{"issue_id":"bd-tggf","depends_on_id":"bd-05a8","type":"blocks","created_at":"2025-12-22T21:00:21.501589-08:00","created_by":"daemon"},{"issue_id":"bd-tggf","depends_on_id":"bd-9g1z","type":"blocks","created_at":"2025-12-22T21:00:21.571116-08:00","created_by":"daemon"},{"issue_id":"bd-tggf","depends_on_id":"bd-qioh","type":"blocks","created_at":"2025-12-22T21:00:21.640589-08:00","created_by":"daemon"},{"issue_id":"bd-tggf","depends_on_id":"bd-rgyd","type":"blocks","created_at":"2025-12-22T21:00:21.710912-08:00","created_by":"daemon"},{"issue_id":"bd-tggf","depends_on_id":"bd-4nqq","type":"blocks","created_at":"2025-12-22T21:00:21.781914-08:00","created_by":"daemon"},{"issue_id":"bd-tggf","depends_on_id":"bd-dhza","type":"blocks","created_at":"2025-12-22T21:00:21.852-08:00","created_by":"daemon"},{"issue_id":"bd-tggf","depends_on_id":"bd-ork0","type":"blocks","created_at":"2025-12-22T21:00:21.930168-08:00","created_by":"daemon"}]} @@ -610,6 +617,7 @@ {"id":"bd-uu8p","title":"Routing bypassed in daemon mode","description":"## Bug\n\nPrefix-based routing (routes.jsonl) only works in direct mode. When the daemon is running, it bypasses routing logic because:\n\n1. Daemon mode resolves IDs via RPC (`daemonClient.ResolveID`)\n2. Daemon uses its own store, which only knows about local beads\n3. The routing logic in `resolveAndGetIssueWithRouting` is only called in direct mode\n\n## Reproduction\n\n```bash\n# With daemon running:\ncd ~/gt\nbd show gt-1py3y # Fails - daemon can't find it\n\n# With daemon bypassed:\nbd --no-daemon show gt-1py3y # Works - uses routing\n```\n\n## Fix Options\n\n### Option A: Client-side routing detection (Recommended)\nBefore calling daemon RPC, check if the ID prefix matches a route to a different beads dir. If so, use direct mode with routing for that ID.\n\n```go\n// In show.go, before daemon mode:\nif daemonClient != nil \u0026\u0026 needsRouting(id) {\n // Fall back to direct mode for this ID\n result, err := resolveAndGetIssueWithRouting(ctx, store, id)\n ...\n}\n```\n\n### Option B: Daemon-side routing\nAdd routing support to the daemon RPC server. More complex - daemon would need to:\n- Load routes.jsonl on startup\n- Open connections to multiple databases\n- Route requests based on ID prefix\n\n### Option C: Hybrid\nDaemon returns \"not found + prefix hint\", client retries with routing.\n\n## Recommendation\n\nOption A is simplest. The client already has routing logic; just use it when we detect a routed prefix.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-26T14:52:00.452285-08:00","updated_at":"2025-12-26T14:54:51.572289-08:00","closed_at":"2025-12-26T14:54:51.572289-08:00","close_reason":"Fixed by bypassing daemon for routed IDs"} {"id":"bd-uutv","title":"Work on beads-rs0: Namepool configuration for themed pole...","description":"Work on beads-rs0: Namepool configuration for themed polecat names. See bd show beads-rs0 for full details.","status":"closed","priority":2,"issue_type":"task","assignee":"beads/polecat-02","created_at":"2025-12-19T21:49:48.129778-08:00","updated_at":"2025-12-19T21:59:25.565894-08:00","closed_at":"2025-12-19T21:59:25.565894-08:00","close_reason":"Completed work on beads-rs0: Implemented themed namepool feature"} {"id":"bd-uwkp","title":"Phase 2.4: Git merge driver optimization for TOON format","description":"Optimize git 3-way merge for TOON line-oriented format.\n\n## Overview\nTOON is line-oriented (unlike binary formats), enabling smarter git merge strategies. Implement custom merge driver to handle TOON-specific merge patterns.\n\n## Required Work\n\n### 2.4.1 TOON Merge Driver\n- [ ] Create .git/info/attributes entry for *.toon files\n- [ ] Implement custom merge driver script/command\n- [ ] Handle tabular format row merges (line-based 3-way)\n- [ ] Handle YAML-style format merges\n- [ ] Conflict markers for unsolvable conflicts\n\n### 2.4.2 Merge Patterns\n- [ ] Row addition: both branches add different rows → union\n- [ ] Row deletion: one branch deletes, other modifies → conflict (manual review)\n- [ ] Row modification: concurrent field changes → intelligent merge or conflict\n- [ ] Field ordering changes: ignore (TOON format resilient to order)\n\n### 2.4.3 Testing \u0026 Documentation\n- [ ] Unit tests for merge scenarios (3-way merge logic)\n- [ ] Integration tests with actual git merges\n- [ ] Conflict scenario testing\n- [ ] Documentation of merge strategy\n\n## Success Criteria\n- Git merge handles TOON conflicts intelligently\n- Fewer manual merge conflicts than JSONL\n- Round-trip preserved through merges\n- All 70+ tests still passing\n- Git history stays clean (minimal conflict markers)","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T14:43:14.339238776-07:00","updated_at":"2025-12-21T14:42:26.434306-08:00","closed_at":"2025-12-21T14:42:26.434306-08:00","close_reason":"TOON approach declined","dependencies":[{"issue_id":"bd-uwkp","depends_on_id":"bd-iic1","type":"discovered-from","created_at":"2025-12-19T14:43:14.34427988-07:00","created_by":"daemon"}]} +{"id":"bd-uxlb","title":"Add bd agent state command for ZFC-compliant state reporting","description":"Add command for agents to write their own state to agent beads.\n\n```bash\nbd agent state \u003cagent-id\u003e \u003cstate\u003e\n# Example: bd agent state gt-mayor running\n# States: idle | running | stuck | stopped | dead\n```\n\nImplementation:\n1. Lookup agent bead by ID (type=agent)\n2. Update agent_state field in description\n3. Update last_activity timestamp\n4. Trigger bd sync if configured\n\nAlso add:\n- bd agent heartbeat \u003cagent-id\u003e - just updates last_activity\n- bd agent show \u003cagent-id\u003e - show agent bead details\n\nThis is the ZFC-compliant way for agents to self-report state.\n\nCross-ref: gt-p2vyo in gastown","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-28T01:49:46.325964-08:00","created_by":"mayor","updated_at":"2025-12-28T01:57:05.839623-08:00","closed_at":"2025-12-28T01:57:05.839623-08:00","close_reason":"Closed"} {"id":"bd-uz8r","title":"Phase 2.3: TOON deletion tracking","description":"Implement deletion tracking in TOON format.\n\n## Overview\nPhase 2.2 switched storage to TOON format. Phase 2.3 adds deletion tracking in TOON format for propagating deletions across clones.\n\n## Required Work\n\n### 2.3.1 Deletion Tracking (TOON Format)\n- [ ] Implement deletions.toon file (tracking deleted issue records)\n- [ ] Add DeleteTracker struct to record deleted issue IDs and metadata\n- [ ] Update bdt delete command to record in deletions.toon\n- [ ] Design deletion record format (ID, timestamp, reason, hash)\n- [ ] Implement auto-prune of old deletion records (configurable TTL)\n\n### 2.3.2 Sync Propagation\n- [ ] Load deletions.toon during import\n- [ ] Remove deleted issues from local database when imported from remote\n- [ ] Handle edge cases (delete same issue in multiple clones)\n- [ ] Deletion ordering and conflict resolution\n\n### 2.3.3 Testing\n- [ ] Unit tests for deletion tracking\n- [ ] Integration tests for deletion propagation\n- [ ] Multi-clone deletion scenarios\n- [ ] TTL expiration tests\n\n## Success Criteria\n- deletions.toon stores deletion records in TOON format\n- Deletions propagate across clones via git sync\n- Old records auto-prune after TTL\n- All 70+ tests still passing\n- bdt delete command works seamlessly","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T14:37:23.722066816-07:00","updated_at":"2025-12-21T14:42:27.491932-08:00","closed_at":"2025-12-21T14:42:27.491932-08:00","close_reason":"TOON approach declined","dependencies":[{"issue_id":"bd-uz8r","depends_on_id":"bd-iic1","type":"discovered-from","created_at":"2025-12-19T14:37:23.726825771-07:00","created_by":"daemon"}]} {"id":"bd-v8ku","title":"bd: Add town-level activity signal in PersistentPreRun","description":"Add activity signaling to beads so Gas Town daemon can detect bd usage.\n\nIn cmd/bd/main.go PersistentPreRun, add a call to write activity to\nthe Gas Town daemon directory if running inside a Gas Town workspace.\n\nThe signal file is ~/gt/daemon/activity.json (or detected town root).\n\nFormat:\n{\n \"last_command\": \"bd create ...\",\n \"actor\": \"gastown/crew/max\",\n \"timestamp\": \"2025-12-26T19:30:00Z\"\n}\n\nShould be best-effort (silent failure) to avoid breaking bd outside Gas Town.\n\nCross-rig ref: gastown gt-ws8ol (Deacon exponential backoff epic)","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-26T19:25:13.537055-08:00","updated_at":"2025-12-26T19:28:44.919491-08:00","closed_at":"2025-12-26T19:28:44.919491-08:00","close_reason":"Implemented activity signaling in PersistentPreRun"} {"id":"bd-vgi5","title":"Push version bump to GitHub","description":"git push origin main - triggers CI but no release yet.","status":"tombstone","priority":1,"issue_type":"task","created_at":"2025-12-18T22:43:05.363604-08:00","updated_at":"2025-12-24T16:25:30.019895-08:00","dependencies":[{"issue_id":"bd-vgi5","depends_on_id":"bd-qqc","type":"parent-child","created_at":"2025-12-18T22:43:16.87736-08:00","created_by":"daemon"},{"issue_id":"bd-vgi5","depends_on_id":"bd-3ggb","type":"blocks","created_at":"2025-12-18T22:43:21.078208-08:00","created_by":"daemon"}],"deleted_at":"2025-12-24T16:25:30.019895-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"task"} @@ -634,6 +642,7 @@ {"id":"bd-x3hi","title":"Support redirect files in .beads/ directory","description":"Gas Town creates polecat worktrees with .beads/redirect files that point to a shared beads database. The bd CLI should:\n\n1. When finding a .beads/ directory, check if it contains a 'redirect' file\n2. If redirect exists, read the relative path and use that as the beads directory\n3. This allows multiple git worktrees to share a single beads database\n\nExample:\n- polecats/alpha/.beads/redirect contains '../../mayor/rig/.beads'\n- bd commands from alpha should use mayor/rig/.beads\n\nCurrently bd ignores redirect files and either uses the local .beads/ or walks up to find a parent .beads/.\n\nRelated: gt-nriy (test message that can't be retrieved due to missing redirect support)","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-12-20T21:46:23.415172-08:00","updated_at":"2025-12-20T21:59:25.759664-08:00","closed_at":"2025-12-20T21:59:25.759664-08:00","close_reason":"Not applicable - filed against stale bd v0.30.6"} {"id":"bd-x3j8","title":"Update info.go versionChanges","description":"Add 0.32.1 entry to versionChanges map in cmd/bd/info.go","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-20T21:53:17.344841-08:00","updated_at":"2025-12-20T21:54:31.906761-08:00","closed_at":"2025-12-20T21:54:31.906761-08:00","close_reason":"Added 0.32.1 to versionChanges","dependencies":[{"issue_id":"bd-x3j8","depends_on_id":"bd-an4s","type":"parent-child","created_at":"2025-12-20T21:53:17.346736-08:00","created_by":"daemon"},{"issue_id":"bd-x3j8","depends_on_id":"bd-rgd7","type":"blocks","created_at":"2025-12-20T21:53:29.62309-08:00","created_by":"daemon"}]} {"id":"bd-xctp","title":"GH#519: bd sync fails when sync.branch is currently checked-out branch","status":"tombstone","priority":2,"issue_type":"bug","created_at":"2025-12-16T01:06:05.319281-08:00","updated_at":"2025-12-17T16:11:17.070763-08:00","deleted_at":"2025-12-17T16:11:17.070763-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"bug"} +{"id":"bd-xhaa","title":"Test work item","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-28T00:04:42.739569-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-28T00:11:48.074239-08:00","deleted_at":"2025-12-28T00:11:48.074239-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"task"} {"id":"bd-xj2e","title":"GH#522: Add --type flag to bd update command","description":"Add --type flag to bd update for changing issue type (task/epic/bug/feature). Storage layer already supports it. See GitHub issue #522.","status":"tombstone","priority":2,"issue_type":"task","created_at":"2025-12-16T01:03:12.506583-08:00","updated_at":"2025-12-17T16:11:17.070763-08:00","deleted_at":"2025-12-17T16:11:17.070763-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"task"} {"id":"bd-xo1o","title":"Dynamic Molecule Bonding: Fanout patterns for patrol molecules","description":"## Vision\n\nEnable molecules to dynamically spawn child molecules at runtime based on discovered\nwork. This is the foundation for the \"Christmas Ornament\" pattern where a patrol\nmolecule grows arms per-polecat.\n\n## The Activity Feed Vision\n\nInstead of parsing agent logs, users see structured work state:\n\n```\n[14:32:08] + patrol-x7k.arm-ace bonded (5 steps)\n[14:32:08] + patrol-x7k.arm-nux bonded (5 steps)\n[14:32:09] → patrol-x7k.arm-ace.capture in_progress\n[14:32:10] ✓ patrol-x7k.arm-ace.capture completed\n[14:32:14] ✓ patrol-x7k.arm-ace.decide completed (action: nudge-1)\n```\n\nThis requires beads to track molecule step state transitions in real-time.\n\n## Key Primitives Needed\n\n### 1. Dynamic Bond with Variables\n```bash\nbd mol bond mol-polecat-arm \u003cparent-wisp-id\u003e \\\n --var polecat_name=ace \\\n --var rig=gastown\n```\n\nCreates wisp children under the parent:\n- parent-id.arm-ace\n- parent-id.arm-ace.capture\n- parent-id.arm-ace.assess\n- etc.\n\n### 2. WaitsFor Directive\n```markdown\n## Step: aggregate\nCollect outcomes from all dynamically-bonded children.\nWaitsFor: all-children\nNeeds: survey-workers\n```\n\nThe `WaitsFor: all-children` directive makes this a fanout gate - it can't\nproceed until ALL dynamically-bonded children complete.\n\n### 3. Activity Feed Query\n```bash\nbd activity --follow # Real-time state stream\nbd activity --mol \u003cid\u003e # Activity for specific molecule\nbd activity --since 5m # Last 5 minutes\n```\n\n### 4. Parallel Step Detection\nSteps with no inter-dependencies should be flagged as parallelizable.\nWhen arms are bonded, their steps can run in parallel across arms.\n\n## Use Case: mol-witness-patrol\n\nThe Witness monitors N polecats where N varies at runtime:\n\n```\nsurvey-workers discovers: [ace, nux, toast]\nFor each polecat:\n bd mol bond mol-polecat-arm \u003cpatrol-id\u003e --var polecat_name=\u003cname\u003e\naggregate step waits for all arms to complete\n```\n\nThis creates the Christmas Ornament shape:\n- Trunk: preflight steps\n- Arms: per-polecat inspection molecules\n- Base: cleanup after all arms complete\n\n## Design Docs\n\nSee Gas Town docs:\n- docs/molecular-chemistry.md (updated with Christmas Ornament pattern)\n- docs/architecture.md (activity feed section)\n\n## Dependencies\n\nThis epic may depend on:\n- Wisp storage (.beads-wisp/) - already implemented\n- Variable substitution in molecules - may need enhancement","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-12-23T02:32:43.173305-08:00","updated_at":"2025-12-23T04:01:02.729388-08:00","closed_at":"2025-12-23T04:01:02.729388-08:00","close_reason":"All subtasks completed: dynamic bonding (.1), waits-for gates (.2), activity feed (.3), parallel detection (.4)"} {"id":"bd-xo1o.1","title":"bd mol bond: Dynamic bond with variable substitution","description":"Implement dynamic molecule bonding with runtime variable substitution.\n\n## Command\n```bash\nbd mol bond \u003cproto-id\u003e \u003cparent-wisp-id\u003e --var key=value --var key2=value2\n```\n\n## Behavior\n1. Parse proto molecule template\n2. Substitute {{key}} placeholders with provided values\n3. Create wisp children under the parent molecule\n4. Child IDs follow pattern: parent-id.child-ref (e.g., patrol-x7k.arm-ace)\n5. Nested children: parent-id.child-ref.step-ref (e.g., patrol-x7k.arm-ace.capture)\n\n## Variable Substitution\n- In step titles: \"Inspect {{polecat_name}}\" -\u003e \"Inspect ace\"\n- In descriptions: Full template substitution\n- In Needs directives: Allow referencing parent steps\n\n## Output\n```\n✓ Bonded mol-polecat-arm to patrol-x7k\n Created: patrol-x7k.arm-ace (5 steps)\n```","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-23T02:33:13.878996-08:00","updated_at":"2025-12-23T03:38:03.54745-08:00","closed_at":"2025-12-23T03:38:03.54745-08:00","close_reason":"Implemented dynamic molecule bonding with --ref flag for custom child IDs (Christmas Ornament pattern)","dependencies":[{"issue_id":"bd-xo1o.1","depends_on_id":"bd-xo1o","type":"parent-child","created_at":"2025-12-23T02:33:13.879419-08:00","created_by":"daemon"}]} @@ -655,7 +664,8 @@ {"id":"bd-yx22","title":"Merge: bd-d28c","description":"branch: polecat/testcat\ntarget: main\nsource_issue: bd-d28c\nrig: beads","status":"closed","priority":1,"issue_type":"merge-request","created_at":"2025-12-23T21:33:15.490412-08:00","updated_at":"2025-12-23T21:36:38.584933-08:00","closed_at":"2025-12-23T21:36:38.584933-08:00","close_reason":"stale - code never pushed to remote"} {"id":"bd-yy1h","title":"Witness Patrol","description":"Per-rig worker monitor patrol loop with progressive nudging.","status":"tombstone","priority":2,"issue_type":"molecule","created_at":"2025-12-26T13:08:21.271692-08:00","updated_at":"2025-12-27T00:10:54.178645-08:00","deleted_at":"2025-12-27T00:10:54.178645-08:00","deleted_by":"daemon","delete_reason":"delete","original_type":"molecule"} {"id":"bd-z3rf","title":"dave Handoff","status":"pinned","priority":2,"issue_type":"task","created_at":"2025-12-23T04:33:42.874554-08:00","updated_at":"2025-12-26T13:08:21.874062-08:00"} -{"id":"bd-z4f5","title":"--parent flag reports success but doesn't persist to JSONL","description":"The --parent flag for bd update reports success but the change doesn't persist.\n\nReported by: Mayor\nLocation: show.go:810-814 handles the logic\n\nSymptoms:\n- bd update \u003cid\u003e --parent=\u003cnew-parent\u003e returns success\n- But the parent change is not written to JSONL\n- Subsequent bd show reveals parent unchanged\n\nThis shipped in v0.39.1 as part of bd-cj2e (--parent flag for reparenting).\n\nInvestigation: Check the update path from show.go through to JSONL export. The RPC/daemon layer may be dropping the parent field, or the storage layer isn't persisting it.","status":"open","priority":1,"issue_type":"bug","assignee":"dave","created_at":"2025-12-27T23:10:22.428136-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-27T23:10:22.428136-08:00"} +{"id":"bd-z4f5","title":"--parent flag reports success but doesn't persist to JSONL","description":"The --parent flag for bd update reports success but the change doesn't persist.\n\nReported by: Mayor\nLocation: show.go:810-814 handles the logic\n\nSymptoms:\n- bd update \u003cid\u003e --parent=\u003cnew-parent\u003e returns success\n- But the parent change is not written to JSONL\n- Subsequent bd show reveals parent unchanged\n\nThis shipped in v0.39.1 as part of bd-cj2e (--parent flag for reparenting).\n\nInvestigation: Check the update path from show.go through to JSONL export. The RPC/daemon layer may be dropping the parent field, or the storage layer isn't persisting it.","status":"closed","priority":1,"issue_type":"bug","assignee":"dave","created_at":"2025-12-27T23:10:22.428136-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-27T23:27:45.716572-08:00","closed_at":"2025-12-27T23:27:45.716572-08:00","close_reason":"Cannot reproduce - --parent flag persists correctly to JSONL. Issue may have been transient during initial testing or daemon restart resolved it."} +{"id":"bd-z830","title":"Test child task","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-27T23:26:58.246573-08:00","created_by":"beads/crew/emma","updated_at":"2025-12-27T23:27:40.451603-08:00","closed_at":"2025-12-27T23:27:40.451603-08:00","close_reason":"Test issues, cleanup","dependencies":[{"issue_id":"bd-z830","depends_on_id":"bd-fbl9","type":"parent-child","created_at":"2025-12-27T23:27:02.984294-08:00","created_by":"daemon"}]} {"id":"bd-z86n","title":"Code Review: PR #551 - Persist close_reason to issues table","description":"Code review of PR #551 which fixes close_reason persistence bug.\n\n## Summary\nThe PR correctly fixes a bug where close_reason was only stored in the events table, not in the issues.close_reason column. This caused `bd show --json` to return empty close_reason.\n\n## What Was Fixed\n- ✅ CloseIssue now updates both close_reason and closed_at\n- ✅ ReOpenIssue clears both close_reason and closed_at\n- ✅ Comprehensive tests added for both storage and CLI layers\n- ✅ Clear documentation in queries.go about dual storage strategy\n\n## Quality Assessment\n✅ Tests cover both storage layer and CLI JSON output\n✅ Handles reopen case (clearing close_reason)\n✅ Good comments explaining dual-storage design\n✅ No known issues\n\n## Potential Followups\nSee linked issues for suggestions.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-14T14:25:06.887069-08:00","updated_at":"2025-12-14T14:25:06.887069-08:00"} {"id":"bd-z8a6","title":"bd delete --from-file should add deleted issues to deletions manifest","description":"When using bd delete --from-file to bulk delete issues, the deleted issue IDs are not being added to the deletions.jsonl manifest.\n\nThis causes those issues to be resurrected during bd sync when git history scanning finds them in old commits.\n\nExpected: All deleted issues should be added to deletions.jsonl so they wont be reimported from git history.\n\nWorkaround: Manually add deletion records to deletions.jsonl.","status":"tombstone","priority":1,"issue_type":"bug","created_at":"2025-12-16T01:48:14.099855-08:00","updated_at":"2025-12-17T16:11:17.070763-08:00","deleted_at":"2025-12-17T16:11:17.070763-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"bug"} {"id":"bd-zc3","title":"Add --pinned and --no-pinned flags to bd list","description":"Add filtering flags to bd list: --pinned shows only pinned issues, --no-pinned excludes pinned issues. Default behavior shows all issues with a pin indicator.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-18T23:33:29.518028-08:00","updated_at":"2025-12-21T11:30:01.484978-08:00","closed_at":"2025-12-21T11:30:01.484978-08:00","close_reason":"Already implemented - --pinned and --no-pinned flags exist in bd list","dependencies":[{"issue_id":"bd-zc3","depends_on_id":"bd-0vg","type":"blocks","created_at":"2025-12-18T23:33:56.256764-08:00","created_by":"daemon"},{"issue_id":"bd-zc3","depends_on_id":"bd-7h5","type":"blocks","created_at":"2025-12-18T23:34:07.486361-08:00","created_by":"daemon"}]} diff --git a/.beads/sync-state.json b/.beads/sync-state.json new file mode 100644 index 00000000..fb26e5c6 --- /dev/null +++ b/.beads/sync-state.json @@ -0,0 +1,7 @@ +{ + "last_failure": "2025-12-28T09:31:08.179079-08:00", + "failure_count": 1, + "backoff_until": "2025-12-28T09:31:38.179079-08:00", + "needs_manual_sync": false, + "failure_reason": "git pull failed in worktree: exit status 128\nFrom github.com:steveyegge/beads\n * branch beads-sync -\u003e FETCH_HEAD\nfatal: Cannot rebase onto multiple branches.\n" +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8276ed40..d0e0d375 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,21 +9,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- **`bd where` command** (bd-8x43) - Show active beads location +- **`bd where` command** - Show active beads location - Displays the resolved database path after following redirects - Helpful for debugging multi-rig setups -- **`--parent` flag for `bd update`** (bd-cj2e) - Reparent issues +- **`--parent` flag for `bd update`** - Reparent issues - Move issues between epics with `bd update --parent=` - Supports clearing parent with `--parent=none` -- **Redirect info in `bd prime`** (bd-kblo) - Gas Town support +- **Redirect info in `bd prime`** - Gas Town support - Shows when database is redirected to another location - Improves visibility into routing behavior ### Fixed -- **Doctor follows redirects** (bd-tvus) - Gas Town compatibility +- **Doctor follows redirects** - Gas Town compatibility - `bd doctor` now correctly follows database redirects - Prevents false negatives when running from rig roots @@ -33,13 +33,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- **Git context consolidation** (bd-qph3) - Internal refactor +- **Git context consolidation** - Internal refactor - Unified git context into single cached struct - Reduces redundant git operations ### Documentation -- **Database Redirects section** (bd-8x43) - ADVANCED.md +- **Database Redirects section** - ADVANCED.md - Comprehensive documentation for redirect feature - Explains Gas Town integration patterns @@ -55,7 +55,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - DRY refactoring of orphan detection from `bd doctor` - Helps maintain issue hygiene in larger projects -- **`bd admin` parent command** (bd-3u8m) - Consolidated admin tools +- **`bd admin` parent command** - Consolidated admin tools - `bd admin cleanup` - Clean up unused data - `bd admin compact` - Compact the database - `bd admin reset` - Reset to initial state @@ -68,20 +68,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- **`bd mol catalog` → `bd formula list`** (bd-ctmg) - Command rename +- **`bd mol catalog` → `bd formula list`** - Command rename - Aligns with formula-based terminology - `bd formula list` shows available molecule templates -- **`bd info --thanks`** (bd-wb9g) - Relocated thanks command +- **`bd info --thanks`** - Relocated thanks command - Contributors list moved under `bd info` - Reduces command namespace pollution -- **Removed unused commands** (bd-x0zl) +- **Removed unused commands** - `bd pin`, `bd unpin`, `bd hook` removed - Functionality covered by `gt mol` commands in Gas Town - Cleaner separation between beads (data) and gastown (orchestration) -- **`bd doctor --check=pollution`** (bd-kff0) - Integrated test pollution check +- **`bd doctor --check=pollution`** - Integrated test pollution check - Detects test artifacts left in production database - Previously standalone `bd detect-pollution` command @@ -97,7 +97,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Documentation -- **Issue Statuses section** (bd-epww) - CLI_REFERENCE.md +- **Issue Statuses section** - CLI_REFERENCE.md - Comprehensive status lifecycle documentation - Clear explanations of open, pinned, in_progress, blocked, deferred, closed, tombstone @@ -113,16 +113,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- **Prefix-based routing** (bd-9gvf) - Cross-rig command routing +- **Prefix-based routing** - Cross-rig command routing - `bd` commands auto-route to correct rig based on issue ID prefix - Routes stored in `~/gt/.beads/routes.jsonl` - Enables seamless multi-rig workflows from any directory -- **Cross-rig ID auto-resolve** (bd-lfiu) - Smarter dependency handling +- **Cross-rig ID auto-resolve** - Smarter dependency handling - `bd dep add` auto-resolves issue IDs across different rigs - No need to specify full paths for cross-rig dependencies -- **`bd mol pour/wisp` subcommands** (bd-2fs7) - Reorganized command hierarchy +- **`bd mol pour/wisp` subcommands** - Reorganized command hierarchy - `bd mol pour` for persistent molecules - `bd mol wisp` for ephemeral workflows - Cleaner organization under `bd mol` namespace @@ -140,7 +140,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - JSONL integrity checks detect and fix malformed entries - Git hygiene checks for stale branches -- **Chaos testing for releases** (bd-kx1j) - Thorough validation +- **Chaos testing for releases** - Thorough validation - `--run-chaos-tests` flag in release script - Exercises edge cases and failure modes @@ -149,7 +149,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- **CLI consolidation** (bd-9115) - Reduced top-level command clutter +- **CLI consolidation** - Reduced top-level command clutter - `bd cleanup`, `bd compact`, `bd reset` → `bd admin cleanup|compact|reset` - `bd migrate-*` → `bd migrate hash-ids|issues|sync|tombstones` - `bd cook` → `bd formula cook` @@ -189,7 +189,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Migration handles partial or repeated runs gracefully - Checks for existing columns before adding -- **Routed ID daemon bypass** (bd-uu8p) - Cross-rig show +- **Routed ID daemon bypass** - Cross-rig show - `bd show` with routed IDs bypasses daemon correctly - Storage connections closed per iteration to prevent leaks @@ -209,7 +209,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- **Gate commands** (bd-udsi, gt-twjr5) - Async coordination for agent workflows +- **Gate commands** - Async coordination for agent workflows - `bd gate create` - Create gates with await conditions (gh:run, gh:pr, timer, human, mail) - `bd gate eval` - Evaluate timer and GitHub gates (checks run completion, PR merge) - `bd gate approve` - Approve human gates @@ -223,7 +223,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Filter issues by parent bead or epic - Enables focused work within a subtree -- **TOML support for formulas** (gt-xmyha) - Alternative format +- **TOML support for formulas** - Alternative format - `.formula.toml` files alongside JSON support - Human-friendly authoring option @@ -231,35 +231,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Detects fork repositories during init - Offers to configure .git/info/exclude for stealth mode -- **Control flow operators** (gt-8tmz.4) - Advanced formula composition +- **Control flow operators** - Advanced formula composition - `loop` operator for iterating over collections - `gate` operator for conditional execution - - Condition evaluator for gates and loops (gt-8tmz.7) + - Condition evaluator for gates and loops - Control flow integrates with aspect composition -- **Aspect composition** (gt-8tmz.5) - Cross-cutting workflow concerns +- **Aspect composition** - Cross-cutting workflow concerns - `aspects` field in formulas for reusable patterns - Aspects match steps by type, title pattern, or custom criteria - Enables logging, retries, notifications as composable concerns -- **Runtime expansion types** (gt-8tmz.8) - Dynamic step generation +- **Runtime expansion types** - Dynamic step generation - `on_complete` - Generate steps when a step completes - `for-each` - Expand steps for each item in a collection - Enables dynamic workflows based on runtime state -- **`bd formula list/show`** (gt-8tmz.14) - Formula discovery commands +- **`bd formula list/show`** - Formula discovery commands - `bd formula list` - List available formulas in search paths - `bd formula show ` - Display formula definition and metadata -- **`bd mol stale`** (bd-anv2) - Detect complete-but-unclosed molecules +- **`bd mol stale`** - Detect complete-but-unclosed molecules - Finds molecules where all children are closed but molecule is open - Helps identify forgotten cleanup tasks -- **Stale molecules check in doctor** (bd-6a5z) - Proactive detection +- **Stale molecules check in doctor** - Proactive detection - `bd doctor` now warns about stale molecules - Integrated with `bd mol stale` detection -- **Distinct ID prefixes** (bd-hobo) - Clear entity type identification +- **Distinct ID prefixes** - Clear entity type identification - Protos: `bd-proto-xxx` prefix - Molecules: `bd-mol-xxx` prefix - Wisps: `bd-wisp-xxx` prefix @@ -282,14 +282,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `bd` focuses on issue tracking primitives - Use `gt mol run` for molecule orchestration -- **Simplified wisp architecture** (bd-bkul) - Single database model +- **Simplified wisp architecture** - Single database model - Wisps stored in main database with `Wisp=true` flag - Removed separate `.beads-wisp/` directory - Wisps filtered from JSONL export automatically ### Fixed -- **Gate await fields preserved during upsert** (bd-gr4q) - Multirepo sync +- **Gate await fields preserved during upsert** - Multirepo sync - Gate fields no longer cleared during multi-repo sync operations - Enables reliable gate coordination across clones @@ -297,7 +297,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Tombstones preserve the original close time - Maintains accurate timeline for deleted issues -- **Git detection caching** (bd-7di) - Performance improvement +- **Git detection caching** - Performance improvement - Cache git worktree/repo detection results - Eliminates repeated slowness on worktree checks @@ -325,31 +325,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Skips interactions.jsonl and molecules.jsonl in sync checks - These files are runtime state, not sync targets -- **FatalErrorRespectJSON** (bd-28sq) - Consistent error output +- **FatalErrorRespectJSON** - Consistent error output - All commands respect `--json` flag for error output - Errors return proper JSON structure when flag is set -- **bd sync commits non-.beads files** (bd-trgb) - Sync isolation +- **bd sync commits non-.beads files** - Sync isolation - Sync operations now only commit .beads/ directory changes - Prevents unintended commits of working directory files -- **Content-level merge for divergence** (bd-kpy) - Better conflict resolution +- **Content-level merge for divergence** - Better conflict resolution - Divergence recovery uses content-level merging - Reduces false conflicts during multi-clone sync -- **Child→parent dep fix opt-in** (bd-cuek) - Migration control +- **Child→parent dep fix opt-in** - Migration control - `--fix-child-parent` flag required for automatic fix - Prevents unexpected dependency modifications -- **Aspect self-matching recursion** (gt-8tmz.16) - Formula safety +- **Aspect self-matching recursion** - Formula safety - Aspects cannot match themselves during expansion - Prevents infinite recursion in aspect composition -- **Map expansion nested matching** (gt-8tmz.33) - Correct child handling +- **Map expansion nested matching** - Correct child handling - Map expansion now correctly matches nested child steps - Fixes missing expansions in hierarchical formulas -- **Mol/wisp ID prefix combination** (bd-hobo) - Correct ID generation +- **Mol/wisp ID prefix combination** - Correct ID generation - Database prefix combined with type prefix correctly - IDs like `bd-mol-xxx` instead of `bdmol-xxx` @@ -363,11 +363,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Documentation -- **MOLECULES.md rewrite** (bd-ul59) - Workflow-first structure +- **MOLECULES.md rewrite** - Workflow-first structure - Reorganized around practical workflows - Clearer distinction between protos, molecules, wisps -- **Molecular chemistry docs** (bd-ul59) - Conceptual foundation +- **Molecular chemistry docs** - Conceptual foundation - Phase metaphor: solid (proto) → liquid (mol) → vapor (wisp) - Pour, bond, distill, squash operations explained @@ -382,7 +382,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `--prefix` flag for custom issue prefix when cooking - Search paths: `.beads/formulas/`, `~/.beads/formulas/`, `~/gt/.beads/formulas/` -- **Gate issue type** (bd-udsi) - Async coordination primitives +- **Gate issue type** - Async coordination primitives - `bd gate create ` - Create a gate for coordinating parallel work - `bd gate open ` - Open a gate (unblock waiters) - `bd gate close ` - Close a gate (block new work) @@ -392,16 +392,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `--pretty` - Colorized, formatted output for human viewing - `--watch` - Live-updating view (refreshes on changes) -- **`bd search` filters** (bd-au0.5) - Enhanced search capabilities +- **`bd search` filters** - Enhanced search capabilities - `--after`, `--before` - Date range filtering - `--priority` - Exact priority match - `--content` - Full-text content search -- **`bd compact --prune`** (bd-c7y5) - Standalone tombstone pruning +- **`bd compact --prune`** - Standalone tombstone pruning - Prune old tombstones without full compaction - Configurable retention period -- **`bd export --priority`** (bd-au0.6) - Exact priority filter for exports +- **`bd export --priority`** - Exact priority filter for exports - **`--resolution` alias** (GH#721) - Alternative to `--reason` on `bd close` - `bd close bd-42 --resolution "Fixed in commit abc123"` @@ -414,7 +414,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Shows when environment variables override config file values - Helps debug unexpected behavior from env overrides -- **Windows code signing infrastructure** (bd-14v0) - Signed Windows binaries +- **Windows code signing infrastructure** - Signed Windows binaries - Code signing certificate integration for Windows releases - Improved trust and installation experience on Windows @@ -422,22 +422,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `GetMoleculeProgress` - Query molecule execution state - `GetWorkerStatus` - Query worker health and current task -- **Cross-database molecule spawning** (gt-jsup) +- **Cross-database molecule spawning** - `bd mol run` can spawn in external beads databases - Enables cross-project workflow orchestration -- **Config-based close hooks** (bd-g4b4) - Custom scripts on issue close +- **Config-based close hooks** - Custom scripts on issue close - Configure hooks in `.beads/config.yaml` - Run validation or notification scripts when issues close ### Changed -- **Removed `bd mol spawn`** (bd-8y9t) - Use pour/wisp only +- **Removed `bd mol spawn`** - Use pour/wisp only - `bd pour ` for persistent molecules - `bd wisp create ` for ephemeral molecules - Simplifies mental model: pour = liquid (persistent), wisp = vapor (ephemeral) -- **`bd ready` excludes workflow types** (gt-7xtn) - Cleaner ready queue +- **`bd ready` excludes workflow types** - Cleaner ready queue - Gates and other workflow coordination types excluded by default - Use `--include-workflow` to see all types @@ -451,7 +451,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Prefixes containing dots (e.g., `my.project`) now work correctly - Parent chain extraction uses proper escaping -- **allowed_prefixes config respected** (gt-2z6s) - Import validation +- **allowed_prefixes config respected** - Import validation - Import now respects `allowed_prefixes` configuration - Prevents importing issues with unauthorized prefixes @@ -475,20 +475,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Config keys normalized to canonical format (snake_case) - `sync.remote` and `sync_remote` both work -- **JSON output standardization** (bd-au0.7) - Consistent API +- **JSON output standardization** - Consistent API - Empty arrays return `[]` not `null` - Error responses have consistent structure - All commands with `--json` follow same patterns -- **MCP Claude Code compatibility** (bd-49kw) - Tool schema fix +- **MCP Claude Code compatibility** - Tool schema fix - Added `output_schema=None` to MCP tools - Fixes "Invalid schema" errors in Claude Code -- **Windows file locking** (bd-401h) - Better Windows support +- **Windows file locking** - Better Windows support - Proper file handle cleanup prevents locking issues - Fixes "file in use" errors on Windows -- **Template commands with daemon** (bd-indn) - Daemon mode compatibility +- **Template commands with daemon** - Daemon mode compatibility - `bd pour`, `bd wisp create` work correctly with daemon running - **Startup config to config.yaml** (GH#536) - Config persistence @@ -499,21 +499,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Prefixes like `my-project-name` parsed correctly - Fixes issue ID extraction with complex prefixes -- **`--pour` flag in bond operations** (bd-l7y3) - Phase control +- **`--pour` flag in bond operations** - Phase control - `bd mol bond --pour` correctly forces liquid phase - **Stealth mode gitignore** (GH#704) - Local-only exclusion - Uses `.git/info/exclude` instead of global gitignore - Stealth mode truly local to the repository -- **Pinned field import** (bd-phtv) - Field preservation +- **Pinned field import** - Field preservation - `pinned` field preserved during JSONL import -- **External deps in orphan check** (bd-ucgz) - Migration fix +- **External deps in orphan check** - Migration fix - External dependencies excluded from orphan validation - Fixes spurious migration warnings -- **Child→parent dependency detection** (bd-nim5) - Prevents LLM temporal reasoning trap +- **Child→parent dependency detection** - Prevents LLM temporal reasoning trap - Epic children can no longer depend on their parent epic - Blocks a common AI mistake: LLMs use temporal reasoning for "phases" and invert dependencies - Example: "Phase 1 before Phase 2" triggers "Phase 1 blocks Phase 2" → WRONG @@ -529,7 +529,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - storage: interface conformance tests - RPC: comprehensive delete handler tests -- **Structured logging** (bd-u2sc.4) - Better observability +- **Structured logging** - Better observability - Daemon uses `slog` for structured logging - Consistent log format across components @@ -546,22 +546,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- **Dynamic molecule bonding** (bd-xo1o.1) - Attach templates to running molecules at runtime +- **Dynamic molecule bonding** - Attach templates to running molecules at runtime - `bd mol bond --ref ` - Inject template steps dynamically - Enables responsive workflows: attach error recovery, expand scope mid-execution - Templates can reference existing issue data via `--ref` for variable interpolation -- **`bd activity` command** (bd-xo1o.3) - Real-time state feed for workflow monitoring +- **`bd activity` command** - Real-time state feed for workflow monitoring - Stream mutation events as they happen (JSON format) - Monitor molecule progress without polling - Useful for dashboards, debugging, and automation -- **`waits-for` dependency type** (bd-xo1o.2) - Fanout coordination gates +- **`waits-for` dependency type** - Fanout coordination gates - `bd dep add --type waits-for` - Gate waits for all steps - Unlike `blocks`, waits-for is used for parallel coordination (fan-in pattern) - Gate unblocks only when ALL waits-for dependencies complete -- **Parallel step detection** (bd-xo1o.4) - Auto-identify parallelizable work +- **Parallel step detection** - Auto-identify parallelizable work - Molecules automatically detect steps that can run concurrently - `bd mol show` displays parallel-capable step groups - Helps agents optimize execution order @@ -571,15 +571,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `bd close --continue` - Auto-advance to next step in molecule - `bd close --no-auto` - Close without auto-claiming next step -- **`bd list --parent` flag** (bd-yqhh) - Filter issues by parent +- **`bd list --parent` flag** - Filter issues by parent - `bd list --parent=bd-xyz --status=open` shows open children of bd-xyz - Useful for epic progress tracking and molecule step listing -- **Conditional bond type** (bd-kzda) - Run steps only when predecessors fail +- **Conditional bond type** - Run steps only when predecessors fail - `bd mol bond --type conditional-blocks` for error-handling workflows - Step B runs only if step A fails (useful for fallback paths) -- **External dependency display** (bd-vks2) - Show cross-project deps in tree view +- **External dependency display** - Show cross-project deps in tree view - `bd dep tree` now displays external dependencies with repo prefix - Satisfied external deps filtered from blocked issues @@ -600,11 +600,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- **Rich mutation events for status changes** (bd-313v) - Events now include full context +- **Rich mutation events for status changes** - Events now include full context - Status transitions emit complete before/after state - Enables better monitoring and auditing -- **External deps filtered from GetBlockedIssues** (bd-396j) - Correct blocking calculation +- **External deps filtered from GetBlockedIssues** - Correct blocking calculation - External dependencies no longer incorrectly block local work - Only local blocking deps affect ready queue @@ -625,17 +625,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Refactored -- Remove legacy autoflush code paths (bd-xsl9) -- Consolidate duplicate path-finding utilities (bd-74w1, bd-4nqq) -- Replace map[string]interface{} with typed JSON structs (bd-u2sc.1) -- Migrate sort.Slice to slices.SortFunc (bd-u2sc.2) -- Add testEnv helpers, reduce SQLite test file sizes (bd-4opy) +- Remove legacy autoflush code paths +- Consolidate duplicate path-finding utilities +- Replace map[string]interface{} with typed JSON structs +- Migrate sort.Slice to slices.SortFunc +- Add testEnv helpers, reduce SQLite test file sizes ## [0.34.0] - 2025-12-22 ### Added -- **Wisp commands** (bd-kwjh) - Full ephemeral molecule management +- **Wisp commands** - Full ephemeral molecule management - `bd wisp create ` - Instantiate proto as ephemeral wisp (solid→vapor) - `bd wisp list` - List all wisps with stale detection - `bd wisp gc` - Garbage collect orphaned wisps @@ -653,7 +653,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `bd ready` filters by external dependency satisfaction - Configure additional repos in `.beads/config.yaml` -- **Orphan detection in bd doctor** (bd-5hrq) - Find issues with missing parents +- **Orphan detection in bd doctor** - Find issues with missing parents - Detects parent-child relationships pointing to deleted issues - Suggests fix commands for orphaned issues @@ -691,7 +691,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- **Wisp molecules** (bd-2vh3) - Support for ephemeral wisps +- **Wisp molecules** - Support for ephemeral wisps - `bd wisp create` creates wisp issues that live only in SQLite - Wisp issues never export to JSONL (prevents zombie resurrection) - Use `bd pour` for persistent mols, `bd wisp create` for ephemeral wisps @@ -700,7 +700,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- **Comments not deleted with issue** (bd-687g) - `DeleteIssue` now cascades to comments table +- **Comments not deleted with issue** - `DeleteIssue` now cascades to comments table ## [0.32.1] - 2025-12-21 @@ -722,7 +722,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- **Pin field not in allowed update fields** (gt-zr0a) +- **Pin field not in allowed update fields** - `bd update --pinned` was failing with "invalid field" error - Added `pinned` to allowedUpdateFields and importer @@ -748,7 +748,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- **`bd defer` / `bd undefer` commands** (bd-4jr) - New "deferred" status for icebox issues +- **`bd defer` / `bd undefer` commands** - New "deferred" status for icebox issues - Issues that are deliberately postponed, not blocked by dependencies - Deferred issues excluded from `bd ready` and shown with ❄️ snowflake styling - Full support in MCP server, graph views, and statistics @@ -765,7 +765,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `bd ready` and `bd list` auto-apply when in matching directories - Example: `packages/maverick: maverick` shows only maverick-labeled issues -- **Molecules catalog** (gt-0ei3) - Separate storage for template molecules +- **Molecules catalog** - Separate storage for template molecules - Templates now live in `molecules.jsonl`, distinct from work items - Hierarchical loading: built-in → town → user → project - Molecules use `mol-*` ID namespace with `is_template: true` @@ -834,12 +834,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- **`bd graph` dependency counts** (bd-6v2) - Graph command shows dependency counts using subgraph formatting +- **`bd graph` dependency counts** - Graph command shows dependency counts using subgraph formatting - **`types.StatusPinned`** - New status for persistent beads that survive cleanup ### Fixed -- **CRITICAL: Dependency resurrection bug** (bd-ndye) - Fixed 3-way merge to respect dependency removals +- **CRITICAL: Dependency resurrection bug** - Fixed 3-way merge to respect dependency removals - `mergeDependencies` was using union (additive-only) instead of proper 3-way merge - Now removals are authoritative: if either left or right removes a dep, it stays removed - This prevented orphaned parent-child relationships from being permanently removed @@ -857,7 +857,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- **`bd template instantiate`** (bd-r6a.2) - Create beads issues from YAML workflow templates +- **`bd template instantiate`** - Create beads issues from YAML workflow templates - `bd template instantiate ` - Create issues from workflow definitions - `--assignee ` flag for auto-assignment during instantiation - Supports multi-issue workflows with dependency chains @@ -874,8 +874,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed -- **Legacy MCP Agent Mail integration** (bd-6gd) - Removed obsolete `mcp_agents` package -- **YAML workflow execution system** (bd-r6a.1) - Replaced by simpler template instantiation +- **Legacy MCP Agent Mail integration** - Removed obsolete `mcp_agents` package +- **YAML workflow execution system** - Replaced by simpler template instantiation ### Notes @@ -885,14 +885,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- **Data loss race condition** (bd-b6xo) - Removed unsafe `ClearDirtyIssues()` method +- **Data loss race condition** - Removed unsafe `ClearDirtyIssues()` method - Old method cleared ALL dirty issues, risking data loss if export failed partway - All code now uses `ClearDirtyIssuesByID()` which only clears exported issues - Affects: `internal/storage/sqlite/dirty.go`, `internal/storage/memory/memory.go` ### Closed (Already Implemented) -- **Stale database warning** (bd-2q6d) - Commands now warn when database is out of sync with JSONL +- **Stale database warning** - Commands now warn when database is out of sync with JSONL - **Staleness check error handling** (bd-n4td, bd-o4qy) - Proper warnings and error returns ## [0.30.2] - 2025-12-16 @@ -903,13 +903,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Configure beads for use with Factory.ai's Droid - Contributed by @jordanhubbard -- **Messaging schema fields** (bd-kwro.1) - Foundation for inter-agent messaging +- **Messaging schema fields** - Foundation for inter-agent messaging - New `message` issue type for agent-to-agent communication - New fields: `sender`, `wisp`, `replies_to`, `relates_to`, `duplicate_of`, `superseded_by` - New dependency types: `replies-to`, `relates-to`, `duplicates`, `supersedes` - Schema migration 019 (automatic on first use) -- **`bd mail` commands** (bd-kwro.6) - Inter-agent messaging +- **`bd mail` commands** - Inter-agent messaging - `bd mail send -s -m ` - Send messages - `bd mail inbox` - List open messages for your identity - `bd mail read ` - Display message content @@ -917,21 +917,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `bd mail reply -m ` - Reply to messages (creates threads) - Identity via `BEADS_IDENTITY` env var or `.beads/config.json` -- **Graph link commands** (bd-kwro.2-5) - Knowledge graph relationships +- **Graph link commands** - Knowledge graph relationships - `bd relate ` - Create bidirectional "see also" links - `bd unrelate ` - Remove relates_to links - `bd duplicate --of ` - Mark issue as duplicate (closes it) - `bd supersede --with ` - Mark issue as superseded (closes it) - `bd show --thread` - View message threads via replies_to chain -- **Hooks system** (bd-kwro.8) - Extensible event notifications +- **Hooks system** - Extensible event notifications - `.beads/hooks/on_create` - Runs after issue creation - `.beads/hooks/on_update` - Runs after issue update - `.beads/hooks/on_close` - Runs after issue close - `.beads/hooks/on_message` - Runs after message send - Hooks receive issue ID, event type as args, full JSON on stdin -- **`bd cleanup --wisp` flag** (bd-kwro.9) - Clean up transient messages +- **`bd cleanup --wisp` flag** - Clean up transient messages - Deletes only closed issues with `wisp=true` - Useful for cleaning up messages after swarms complete @@ -945,13 +945,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed -- **Legacy deletions.jsonl code** (bd-fom) - Fully migrated to inline tombstones +- **Legacy deletions.jsonl code** - Fully migrated to inline tombstones - Removed `deletions.jsonl` from git tracking - All deletion tracking now via inline tombstones in `issues.jsonl` ### Documentation -- **Messaging documentation** (bd-kwro.11) - New docs for messaging system +- **Messaging documentation** - New docs for messaging system - `docs/messaging.md` - Full messaging reference with examples - `docs/graph-links.md` - Graph link types and use cases - Updated `AGENTS.md` with inter-agent messaging section @@ -1008,17 +1008,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Auto-add "landing the plane" instructions to AGENTS.md** - New projects get session-close protocol guidance -- **Inline tombstones for soft-delete** (bd-vw8) +- **Inline tombstones for soft-delete** - Deleted issues become tombstones with `status: "tombstone"` in `issues.jsonl` - Full audit trail: `deleted_at`, `deleted_by`, `delete_reason`, `original_type` - TTL-based expiration (default 30 days) with automatic pruning via `bd compact` - Proper 3-way merge support: fresh tombstones win, expired tombstones allow resurrection -- **`bd migrate-tombstones` command** (bd-8f9) +- **`bd migrate-tombstones` command** - Converts legacy `deletions.jsonl` entries to inline tombstones - Archives old file as `deletions.jsonl.migrated` -- **Enhanced Git Worktree Support** (bd-737) +- **Enhanced Git Worktree Support** - Shared `.beads` database across all worktrees - Worktree-aware database discovery - Git hooks automatically adapt to worktree context @@ -1069,38 +1069,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Enables planning and prioritization features in vscode-beads - **`bd doctor` improvements** - - SQLite integrity check (bd-2au) - Detects database corruption - - Configuration value validation (bd-alz) - Validates config settings - - Stale sync branch detection (bd-6rf) - Warns about abandoned beads-sync branches - - `--output` flag (bd-9cc) - Export diagnostics to file for sharing - - `--dry-run` flag (bd-qn5) - Preview fixes without applying - - Per-fix confirmation mode (bd-3xl) - Approve each fix individually + - SQLite integrity check - Detects database corruption + - Configuration value validation - Validates config settings + - Stale sync branch detection - Warns about abandoned beads-sync branches + - `--output` flag - Export diagnostics to file for sharing + - `--dry-run` flag - Preview fixes without applying + - Per-fix confirmation mode - Approve each fix individually -- **`--readonly` flag (bd-ymo)** - Read-only mode for worker sandboxes +- **`--readonly` flag** - Read-only mode for worker sandboxes - Blocks all write operations - Useful for parallel worker processes that should only read ### Fixed - **`bd sync` safety improvements** - - Auto-push after merge with safety check (bd-7ch) - - Handle diverged histories with content-based merge (bd-3s8) + - Auto-push after merge with safety check + - Handle diverged histories with content-based merge - Multiple safety check enhancements -- **Auto-resolve merge conflicts deterministically (bd-6l8)** +- **Auto-resolve merge conflicts deterministically** - All field conflicts resolved without prompts - Uses consistent rules for field-level merging - **3-char all-letter base36 hash support (GH #446)** - Fixes prefix extraction for edge case hashes like "bd-abc" -- **`bd ready` message fix (bd-r4n)** +- **`bd ready` message fix** - Shows correct message when all issues are closed -- **Version notification spam fix (bd-tok)** +- **Version notification spam fix** - Store version in gitignored .local_version file -- **Nix flake vendorHash update (bd-gmf)** +- **Nix flake vendorHash update** - Fixed build after dependency bumps ### Documentation @@ -1122,14 +1122,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Logs to stdout instead of background file - Process stays attached to terminal -- **`bd migrate-sync` command (bd-epn)** - Migrate to sync.branch workflow +- **`bd migrate-sync` command** - Migrate to sync.branch workflow - Moves beads data to a dedicated sync branch - Keeps main branch clean of .beads/ commits - Automated setup of sync.branch configuration ### Fixed -- **Database Migration: close_reason column (bd-uyu)** +- **Database Migration: close_reason column** - Added missing database column for close_reason field - Fixes sync loops where close_reason was lost on import/export - Automatic migration on first run @@ -1143,7 +1143,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `bd show` now displays epic children under "Children" not "Blocks" - Clearer UI labels for dependency relationships -- **sync.branch Workflow Fixes (bd-epn)** +- **sync.branch Workflow Fixes** - Fixed .beads/ restoration from branch after sync - Prevents final flush after sync.branch restore - `bd doctor` now detects when on sync branch @@ -1152,7 +1152,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated from deprecated Jira API v2 to v3 - Fixes authentication issues with newer Jira instances -- **Redundant Database Queries (bd-bbh)** +- **Redundant Database Queries** - Removed extra GetCloseReason() calls after column migration - Improves query performance for issue retrieval @@ -1163,26 +1163,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Internal -- Refactored daemon sync functions to reduce ~200 lines of duplication (bd-73u) +- Refactored daemon sync functions to reduce ~200 lines of duplication - Consolidated local-only sync functions into shared implementation ## [0.27.2] - 2025-11-30 ### Fixed -- **CRITICAL: Prevent Mass Database Deletion on JSONL Reset (bd-t5m)** +- **CRITICAL: Prevent Mass Database Deletion on JSONL Reset** - git-history-backfill now includes safety guard to prevent purging entire database - If >50% of issues would be deleted via git history, operation is aborted with warning - Threshold prevents accidental deletion when JSONL is reset (git reset, branch switch, etc.) - If 10-50% would be deleted, operation proceeds but shows warning message - Fixes bug where `git reset --hard origin/main` would lose all issues -- **Fix Fresh Clone Initialization (bd-4h9)** +- **Fix Fresh Clone Initialization** - `bd init` now works on fresh clones that have JSONL but no database - Auto-detects issue prefix from existing JSONL (no `--prefix` flag needed) - Prevents "database not found" errors on first run in a cloned repository -- **Import Warning for Deleted Issues (bd-4zy)** +- **Import Warning for Deleted Issues** - New warning message when issues are skipped due to deletions manifest - Helps users understand why expected issues aren't being imported - Warns user to check `bd deleted` for history of removed issues @@ -1197,12 +1197,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- **Custom Status States**: Define custom issue statuses via config (bd-1pj6) +- **Custom Status States**: Define custom issue statuses via config - Configure project-specific statuses like `testing`, `blocked`, `review` - Status validation ensures only configured statuses are used - Backwards compatible: open/in_progress/closed always work -- **Contributor Fork Workflows**: `bd init --contributor` now auto-configures `sync.remote=upstream` (bd-bx9) +- **Contributor Fork Workflows**: `bd init --contributor` now auto-configures `sync.remote=upstream` - Syncs issues from upstream rather than origin - Ideal for contributors working on forks @@ -1211,27 +1211,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Helpful message when entering worktree repo without beads initialized - Hooks properly detect worktree vs main repository -- **Daemon Health Checks**: Health monitoring in daemon event loop (bd-gqo) +- **Daemon Health Checks**: Health monitoring in daemon event loop - Periodic health checks detect stale database state - Auto-recovery from detected inconsistencies -- **Fresh Clone Detection**: `bd doctor` now detects fresh clones (bd-4ew) +- **Fresh Clone Detection**: `bd doctor` now detects fresh clones - Suggests `bd init` when JSONL exists but no database - Improved onboarding experience for new contributors -- **bd sync --squash**: Batch multiple sync commits into one (bd-o2e) +- **bd sync --squash**: Batch multiple sync commits into one - Reduces commit noise when syncing frequently - Optional flag for cleaner git history -- **Error Handling Helpers**: Extracted FatalError/WarnError utilities (bd-s0z) +- **Error Handling Helpers**: Extracted FatalError/WarnError utilities - Consistent error formatting across codebase - Better error messages for users ### Fixed - **CRITICAL: Sync Corruption Prevention**: Multiple fixes prevent stale database from corrupting JSONL - - **Hash-based staleness detection** (bd-f2f): SHA256 hash comparison catches content mismatches - - **Reverse ZFC check** (bd-53c): Detects when JSONL has more issues than DB + - **Hash-based staleness detection**: SHA256 hash comparison catches content mismatches + - **Reverse ZFC check**: Detects when JSONL has more issues than DB - **Stale daemon connection** (eb4b81d): Prevents corruption from stale SQLite connections - Combined, these fixes eliminate the sync corruption bugs that affected v0.26.x @@ -1244,16 +1244,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **--from-main Sync Mode** (#418): Now defaults to `noGitHistory=true` - Prevents spurious deletions when syncing from main branch -- **JSONL-Only Mode Detection**: Auto-detects when config has `no-db: true` (bd-5kj) +- **JSONL-Only Mode Detection**: Auto-detects when config has `no-db: true` - Properly handles repositories using JSONL without SQLite - **Init Safety Guard**: Prevents overwriting existing JSONL data on init - Warns user when data already exists, requires confirmation -- **Snapshot Cleanup** (bd-0io): Properly cleans up snapshot files after sync +- **Snapshot Cleanup**: Properly cleans up snapshot files after sync - Removes `.beads/*.snapshot` files that could cause conflicts -- **Daemon Registry Locking** (bd-5bj): Cross-process locking prevents registry corruption +- **Daemon Registry Locking**: Cross-process locking prevents registry corruption - Fixes race conditions when multiple processes access daemon registry - **Doctor Merge Artifacts**: Excludes merge artifacts from "multiple JSONL" warning @@ -1277,7 +1277,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- **Hash-Based Staleness Detection (bd-f2f)**: Prevents stale DB from corrupting JSONL when counts match +- **Hash-Based Staleness Detection**: Prevents stale DB from corrupting JSONL when counts match - Previous count-based check (0.26.1) missed cases where DB and JSONL had similar issue counts - New detection computes SHA256 hash of JSONL content and stores it after import - On export, compares current JSONL hash against stored hash to detect modifications @@ -1288,7 +1288,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- **CRITICAL: Reverse ZFC Check (bd-53c)**: Prevents stale database from corrupting JSONL +- **CRITICAL: Reverse ZFC Check**: Prevents stale database from corrupting JSONL - Root cause: `bd sync` exports DB to JSONL before pulling from remote - If local DB is stale (fewer issues than JSONL), stale data would corrupt the JSONL - Added reverse ZFC check: detects when JSONL has >20% more issues than DB @@ -1333,11 +1333,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Issue ID extraction now correctly handles multi-part prefixes - Example: `my-app-123` correctly extracts prefix `my-app` -- **bd sync Commit Scope** (bd-red) +- **bd sync Commit Scope** - `bd sync` now only commits `.beads/` files, not other staged files - Prevents accidental commits of unrelated staged changes -- **Auto-Import to Wrong File** (bd-tqo) +- **Auto-Import to Wrong File** - Fixed auto-import exporting to wrong JSONL file - FindJSONLPath now correctly skips deletions.jsonl @@ -1346,7 +1346,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - bd doctor no longer warns about deletions.jsonl - Prevent rebase failures from deletions.jsonl writes -- **Defense-in-Depth** (bd-4t7) +- **Defense-in-Depth** - Added additional check for --no-auto-import flag - **Tilde Expansion**: Global gitignore path now expands `~` correctly @@ -1401,7 +1401,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- **Deletion Propagation**: Deletions now sync across clones via deletions manifest (bd-imj) +- **Deletion Propagation**: Deletions now sync across clones via deletions manifest - New `.beads/deletions.jsonl` tracks deleted issues with timestamp, actor, reason - Import automatically purges issues that were deleted in other clones - Git history fallback for pruned deletion records (self-healing) @@ -1416,7 +1416,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Useful for personal issue tracking in shared repos without affecting collaborators - All bd functionality works normally, just not committed to git -- **Ephemeral Branch Sync**: New `bd sync --from-main` flag (gt-ick9) +- **Ephemeral Branch Sync**: New `bd sync --from-main` flag - Syncs from main branch without pushing to remote - Ideal for feature branches that sync issues from main - Prevents pushing local branch changes to origin @@ -1425,7 +1425,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- **Transaction API**: Full transactional support for atomic multi-operation workflows (bd-8bq) +- **Transaction API**: Full transactional support for atomic multi-operation workflows - New `storage.Transaction` interface with CreateIssue, UpdateIssue, CloseIssue, DeleteIssue - Dependency operations: AddDependency, RemoveDependency within transactions - Label operations: AddLabel, RemoveLabel with transactional semantics @@ -1434,51 +1434,51 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Automatic rollback on error or panic, commit on success - 1,147 lines of new implementation with comprehensive tests -- **Tip System Infrastructure**: Smart contextual hints for users (bd-d4i) +- **Tip System Infrastructure**: Smart contextual hints for users - Tips shown after successful commands (list, ready, create, show) - Condition-based filtering, priority ordering, probability rolls - Frequency limits prevent tip spam - Respects `--json` and `--quiet` flags - Deterministic testing via `BEADS_TIP_SEED` env var -- **Sorting for bd list and bd search**: New `--sort` and `--reverse` flags (bd-22g) +- **Sorting for bd list and bd search**: New `--sort` and `--reverse` flags - Sort by: priority, created, updated, closed, status, id, title, type, assignee - Smart defaults: priority ascending (P0 first), dates descending (newest first) - Works with all existing filters -- **Claude Integration Verification**: New bd doctor checks (bd-o78) +- **Claude Integration Verification**: New bd doctor checks - `CheckBdInPath`: verifies 'bd' is in PATH (needed for hooks) - `CheckDocumentationBdPrimeReference`: detects version mismatches in docs - **ARM Linux Support**: GoReleaser now builds for linux/arm64 (PR #371 by @tjg184) - Enables bd on ARM-based Linux systems like Raspberry Pi, AWS Graviton -- **Orphan Detection Migration**: Identifies orphaned child issues (bd-3852) +- **Orphan Detection Migration**: Identifies orphaned child issues - Detects issues with hierarchical IDs where parent no longer exists - Logs suggestions: delete, convert to standalone, or restore parent - Idempotent and safe to run multiple times ### Fixed -- **Transaction Cache Invalidation**: blocked_issues_cache now invalidates correctly (bd-1c4h) +- **Transaction Cache Invalidation**: blocked_issues_cache now invalidates correctly - UpdateIssue status changes trigger cache invalidation - CloseIssue always invalidates (closed issues don't block) - AddDependency/RemoveDependency invalidate for blocking types -- **SQLITE_BUSY Retry Logic**: Exponential backoff for concurrent writes (bd-ola6) +- **SQLITE_BUSY Retry Logic**: Exponential backoff for concurrent writes - `beginImmediateWithRetry()` with 5 retries (10ms, 20ms, 40ms, 80ms, 160ms) - Eliminates spurious failures under normal concurrent usage - Context cancellation respected between retry attempts -- **bd import Argument Validation**: Helpful error for common mistake (bd-77gm) +- **bd import Argument Validation**: Helpful error for common mistake - Running `bd import file.jsonl` (without `-i`) now shows clear error - Previously silently read from stdin, confusing users with "0 created" -- **ZFC Import Export Skip**: Preserve JSONL source of truth (bd-l0r) +- **ZFC Import Export Skip**: Preserve JSONL source of truth - After stale DB import from JSONL, skip export to avoid overwriting - Fixes scenario where DB with fewer issues would overwrite JSONL -- **Daemon Reopen with Reason**: `--reason` flag now works in daemon mode (bd-r46) +- **Daemon Reopen with Reason**: `--reason` flag now works in daemon mode - Previously ignored in daemon RPC calls - **Windows Test Failures**: Skip file permission tests on Windows @@ -1487,7 +1487,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- **bd daemon UX**: New `--start` flag, help text when no args (bd-gfu) +- **bd daemon UX**: New `--start` flag, help text when no args - `bd daemon` now shows help instead of immediately starting - Use `bd daemon --start` to explicitly start - Auto-start still works (uses `--start` internally) @@ -1496,8 +1496,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Documentation - **blocked_issues_cache Architecture**: Document cache behavior and invalidation -- **Antivirus False Positives**: Guide for handling security software alerts (bd-t4u1) -- **import.orphan_handling**: Complete documentation (bd-9cdc) +- **Antivirus False Positives**: Guide for handling security software alerts +- **import.orphan_handling**: Complete documentation - **Error Handling Patterns**: Comprehensive audit and guidelines ### Dependencies @@ -1783,7 +1783,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved code quality and safety - Better coverage of edge cases -- **Shared Database Pattern**: Refactored multiple test files to use shared DB pattern (bd-1rh) +- **Shared Database Pattern**: Refactored multiple test files to use shared DB pattern - compact_test.go, integrity_test.go, validate_test.go, epic_test.go, duplicates_test.go - Improved test consistency and maintainability - Faster test execution through better resource sharing @@ -2108,42 +2108,42 @@ This release represents a major stability and performance improvement with **179 - Automated git traffic benchmark showing **98.5% reduction in git traffic** compared to git-only sync - Bash-agent integration example -- **bd info --whats-new** (bd-eiz9): Agent version awareness for quick upgrade summaries +- **bd info --whats-new**: Agent version awareness for quick upgrade summaries - Shows last 3 versions with workflow-impacting changes - Supports `--json` flag for machine-readable output - Helps agents understand what changed without re-reading full docs -- **bd hooks install** (bd-908z): Embedded git hooks command +- **bd hooks install**: Embedded git hooks command - Replaces external install script with native command - Git hooks now embedded in bd binary - Works for all bd users, not just source repo users -- **bd cleanup**: Bulk deletion command for closed issues (bd-buol) +- **bd cleanup**: Bulk deletion command for closed issues - Agent-driven compaction for large databases - Removes closed issues older than specified threshold ### Fixed -- **3-way JSONL Merge** (bd-jjua): Auto-invoked on conflicts +- **3-way JSONL Merge**: Auto-invoked on conflicts - Automatically triggers intelligent merge on JSONL conflicts - No manual intervention required - Warning message added to zombie issues.jsonl file - **Auto-import on Missing Database** (ab4ec90): `bd import` now auto-initializes database when missing -- **Daemon Crash Recovery** (bd-vcg5): Panic handler with socket cleanup prevents orphaned processes -- **Stale Database Exports** (bd-srwk): ID-based staleness detection prevents exporting stale data -- **Windows MCP Subprocess Timeout** (bd-r79z): Fix for git detection on Windows +- **Daemon Crash Recovery**: Panic handler with socket cleanup prevents orphaned processes +- **Stale Database Exports**: ID-based staleness detection prevents exporting stale data +- **Windows MCP Subprocess Timeout**: Fix for git detection on Windows - **Daemon Orphaning** (a6c9579): Track parent PID and exit when parent dies - **Test Pollution Prevention** (bd-z528, bd-2c5a): Safeguards to prevent test issues in production database - **Client Self-Heal** (a236558): Auto-recovery for stale daemon.pid files - **Post-Merge Hook Error Messages** (abb1d1c): Show actual error messages instead of silent failures -- **Auto-import During Delete** (bd-8kde): Disable auto-import during delete operations to prevent conflicts -- **MCP Workspace Context** (bd-8zf2): Auto-detect workspace from CWD -- **Import Sync Warning** (bd-u4f5): Warn when import syncs with working tree but not git HEAD -- **GH#254** (bd-tuqd): `bd init` now detects and chains with existing git hooks +- **Auto-import During Delete**: Disable auto-import during delete operations to prevent conflicts +- **MCP Workspace Context**: Auto-detect workspace from CWD +- **Import Sync Warning**: Warn when import syncs with working tree but not git HEAD +- **GH#254**: `bd init` now detects and chains with existing git hooks - **GH#249**: Add nil storage checks to prevent RPC daemon crashes - **GH#252**: Fix SQLite driver name mismatch causing "unknown driver" errors -- **Nested .beads Directories** (bd-eqjc): Prevent creating nested .beads directories +- **Nested .beads Directories**: Prevent creating nested .beads directories - **Windows SQLite Support**: Fix SQLite in releases for Windows ### Changed @@ -2159,14 +2159,14 @@ This release represents a major stability and performance improvement with **179 - Config included in `bd info` JSON output - Python cache files added to .gitignore - RPC diagnostics available via `BD_RPC_DEBUG` env var - - Reduced RPC dial timeout from 2s to 200ms for fast-fail (bd-expt) - - Standardized daemon detection with tryDaemonLock probe (bd-wgu4) + - Reduced RPC dial timeout from 2s to 200ms for fast-fail + - Standardized daemon detection with tryDaemonLock probe - Improved internal/daemon test coverage to 60% - **Code Organization**: - - Refactored snapshot management into dedicated module (bd-urob) - - Documented external_ref in content hash behavior (bd-9f4a) - - Added MCP server functions for repair commands (bd-7bbc4e6a) + - Refactored snapshot management into dedicated module + - Documented external_ref in content hash behavior + - Added MCP server functions for repair commands - Added version number to beads-mcp startup log - Added system requirements section for glibc compatibility in docs @@ -2184,7 +2184,7 @@ This release represents a major stability and performance improvement with **179 ### Added -- **Vendored beads-merge by @neongreen** (bd-bzfy): Native `bd merge` command for intelligent JSONL merging +- **Vendored beads-merge by @neongreen**: Native `bd merge` command for intelligent JSONL merging - Vendored beads-merge algorithm into `internal/merge/` with full attribution and MIT license - New `bd merge` command as native wrapper (no external binary needed) - Same field-level 3-way merge algorithm, now built into bd @@ -2387,7 +2387,7 @@ This release represents a major stability and performance improvement with **179 ### Added -- **Parent Resurrection** (bd-58c0): Automatic resurrection of deleted parent issues from JSONL history +- **Parent Resurrection**: Automatic resurrection of deleted parent issues from JSONL history - Prevents import failures when parent issues have been deleted - Creates tombstone placeholders for missing hierarchical parents - Best-effort dependency resurrection from JSONL @@ -2410,7 +2410,7 @@ This release represents a major stability and performance improvement with **179 ### Fixed -- **Memory Database Connection Pool** (bd-b121): Fixed `:memory:` database handling to use single shared connection +- **Memory Database Connection Pool**: Fixed `:memory:` database handling to use single shared connection - Prevents "no such table" errors when using in-memory databases - Ensures connection pool reuses the same in-memory instance - Critical fix for event-driven daemon mode tests @@ -2423,16 +2423,16 @@ This release represents a major stability and performance improvement with **179 ### Added -- **npm Package** (bd-febc): Created `@beads/bd` npm package for Node.js/Claude Code for Web integration +- **npm Package**: Created `@beads/bd` npm package for Node.js/Claude Code for Web integration - Native binary downloads from GitHub releases - Integration tests and release documentation - Postinstall script for platform-specific binary installation -- **Template Support** (bd-164b): Issue creation from markdown templates +- **Template Support**: Issue creation from markdown templates - Create multiple issues from a single file - Structured format for bulk issue creation -- **`bd comment` Alias** (bd-d3f0): Convenient shorthand for `bd comments add` +- **`bd comment` Alias**: Convenient shorthand for `bd comments add` ### Changed @@ -2442,7 +2442,7 @@ This release represents a major stability and performance improvement with **179 ### Fixed -- **SQLite URI Handling** (bd-c54b): Fixed `file://` URI scheme to prevent query params in filename +- **SQLite URI Handling**: Fixed `file://` URI scheme to prevent query params in filename - Prevents database corruption from malformed URIs - Fixed `:memory:` database connection strings @@ -2476,30 +2476,30 @@ This release represents a major stability and performance improvement with **179 ### Added - **New Commands**: - - `bd status` - Database overview command showing issue counts and stats (bd-28db) - - `bd comment` - Convenient alias for `bd comments add` (bd-d3f0) + - `bd status` - Database overview command showing issue counts and stats + - `bd comment` - Convenient alias for `bd comments add` - `bd daemons restart` - Restart specific daemon without manual kill/start - `--json` flag for `bd stale` command - **Protected Branch Workflow**: - - `BEADS_DIR` environment variable for custom database location (bd-e16b) - - `sync.branch` configuration for protected branch workflows (bd-b7d2) - - Git worktree management with sparse checkout for sync branches (bd-a4b5) + - `BEADS_DIR` environment variable for custom database location + - `sync.branch` configuration for protected branch workflows + - Git worktree management with sparse checkout for sync branches - Only checks out `.beads/` in worktrees, minimal disk usage - Only used when `sync.branch` is configured, not for default users - Comprehensive protected branch documentation - **Migration & Validation**: - - Migration inspection tools for AI agents (bd-627d) + - Migration inspection tools for AI agents - Conflict marker detection in `bd import` and `bd validate` - Git hooks health check in `bd doctor` - External reference (`external_ref`) UNIQUE constraint and validation - - `external_ref` now primary matching key for import updates (bd-1022) + - `external_ref` now primary matching key for import updates ### Fixed - **Critical Fixes**: - - Daemon corruption from git conflicts (bd-8931) + - Daemon corruption from git conflicts - MCP `set_context` hangs with stdio transport (GH #153) - Double-release race condition in `importInProgress` flag - Critical daemon race condition causing stale exports @@ -2510,9 +2510,9 @@ This release represents a major stability and performance improvement with **179 - Config version update in migrate command - **Daemon & RPC**: - - `bd doctor --json` flag not working (bd-6049) - - `bd import` now flushes JSONL immediately for daemon visibility (bd-47f1) - - Panic recovery in RPC `handleConnection` (bd-1048) + - `bd doctor --json` flag not working + - `bd import` now flushes JSONL immediately for daemon visibility + - Panic recovery in RPC `handleConnection` - Daemon auto-upgrades database version instead of exiting - **Windows Compatibility**: @@ -2591,10 +2591,10 @@ See README.md for hash ID format details and birthday paradox collision analysis - Migration tool: `bd migrate --to-hash-ids` for existing databases - Prefix-optional ID parsing (e.g., `bd-abc123` or just `abc123`) - Hierarchical child ID generation for discovered-from relationships -- **Substring ID Matching**: All bd commands now support partial ID matching (bd-170) +- **Substring ID Matching**: All bd commands now support partial ID matching - `bd show abc` matches any ID containing "abc" (e.g., `bd-abc123`) - Ambiguous matches show helpful error with all candidates -- **Daemon Registry**: Multi-daemon management for multiple workspaces (bd-07b8c8) +- **Daemon Registry**: Multi-daemon management for multiple workspaces - `bd daemons list` shows all running daemons across workspaces - `bd daemons health` detects version mismatches and stale sockets - `bd daemons logs ` for per-daemon log viewing @@ -2624,7 +2624,7 @@ See README.md for hash ID format details and birthday paradox collision analysis ## [0.17.2] - 2025-10-25 ### Added -- **Configurable Sort Policy**: `bd ready --sort` flag for work queue ordering (bd-147) +- **Configurable Sort Policy**: `bd ready --sort` flag for work queue ordering - `hybrid` (default): Priority-weighted by staleness - `priority`: Strict priority ordering for autonomous systems - `oldest`: Pure FIFO for long-tail work @@ -2633,25 +2633,25 @@ See README.md for hash ID format details and birthday paradox collision analysis - `scripts/update-homebrew.sh`: Automated Homebrew formula updates ### Fixed -- **Critical**: Database reinitialization test re-landed with CI fixes (bd-130) +- **Critical**: Database reinitialization test re-landed with CI fixes - Windows: Fixed git path handling (forward slash normalization) - Nix: Skip test when git unavailable - JSON: Increased scanner buffer to 64MB for large issues -- **Bug**: Stale daemon socket detection (bd-137) +- **Bug**: Stale daemon socket detection - MCP server now health-checks cached connections before use - Auto-reconnect with exponential backoff on stale sockets - Handles daemon restarts/upgrades gracefully -- **Linting**: Fixed all errcheck warnings in production code (bd-58) +- **Linting**: Fixed all errcheck warnings in production code - Proper error handling for database resources and transactions - Graceful EOF handling in interactive input -- **Linting**: Fixed revive style issues (bd-56) +- **Linting**: Fixed revive style issues - Removed unused parameters, renamed builtin shadowing -- **Linting**: Fixed goconst warnings (bd-116) +- **Linting**: Fixed goconst warnings ## [0.17.0] - 2025-10-24 ### Added -- **Git Hooks**: Automatic installation prompt during `bd init` (bd-51) +- **Git Hooks**: Automatic installation prompt during `bd init` - Eliminates race condition between auto-flush and git commits - Pre-commit hook: Flushes pending changes immediately before commit - Post-merge hook: Imports updated JSONL after pull/merge @@ -2667,7 +2667,7 @@ See README.md for hash ID format details and birthday paradox collision analysis - Enables hybrid workflows with Jira, GitHub, Linear - Updates existing issues instead of creating duplicates - Database index on `external_ref` for fast lookups -- **Multi-Database Warning**: Detect and warn about nested beads databases (bd-75) +- **Multi-Database Warning**: Detect and warn about nested beads databases - Prevents accidental creation of multiple databases in hierarchy - Helps users avoid confusion about which database is active @@ -2682,7 +2682,7 @@ See README.md for hash ID format details and birthday paradox collision analysis - **Critical**: Install script safety (GH #143 by @marcodelpin) - Prevents shell corruption from directory deletion during install - Restored proper error codes for safer installation -- **Bug**: Daemon auto-start reliability (bd-137) +- **Bug**: Daemon auto-start reliability - Daemon now responsive immediately, runs initial sync in background - Fixes timeout issues when git pull is slow - Skip daemon-running check for forked child process @@ -2717,19 +2717,19 @@ See README.md for hash ID format details and birthday paradox collision analysis ## [0.16.0] - 2025-10-23 ### Added -- **Automated Releases**: GoReleaser workflow for cross-platform binaries (bd-46) +- **Automated Releases**: GoReleaser workflow for cross-platform binaries - Automatic GitHub releases on version tags - Linux, macOS, Windows binaries for amd64 and arm64 - Checksums and changelog generation included - **PyPI Automation**: Automated MCP server publishing to PyPI - GitHub Actions workflow publishes beads-mcp on version tags - Eliminates manual PyPI upload step -- **Sandbox Mode**: `--sandbox` flag for Claude Code integration (bd-35) +- **Sandbox Mode**: `--sandbox` flag for Claude Code integration - Isolated environment for AI agent experimentation - Prevents production database modifications during testing ### Fixed -- **Critical**: Idempotent import timestamp churn (bd-84) +- **Critical**: Idempotent import timestamp churn - Prevents timestamp updates when issue content unchanged - Reduces JSONL churn and git noise from repeated imports - **Bug**: Windows CI test failures (bd-60, bd-99) @@ -2772,18 +2772,18 @@ See README.md for hash ID format details and birthday paradox collision analysis ## [0.14.0] - 2025-10-22 ### Added -- **Lifecycle Safety Documentation**: Complete documentation for UnderlyingDB() usage (bd-64) +- **Lifecycle Safety Documentation**: Complete documentation for UnderlyingDB() usage - Added tracking guidelines for database lifecycle safety - Documented transaction management best practices - Prevents UAF (use-after-free) bugs in extensions ### Fixed -- **Critical**: Git worktree detection and warnings (bd-73) +- **Critical**: Git worktree detection and warnings - Added automatic detection when running in git worktrees - Displays prominent warning if daemon mode is active in worktree - Prevents daemon from committing/pushing to wrong branch - Documents `--no-daemon` flag as solution for worktree users -- **Critical**: Multiple daemon race condition (bd-54) +- **Critical**: Multiple daemon race condition - Implemented file locking (`daemon.lock`) to prevent multiple daemons per repository - Uses `flock` on Unix, `LockFileEx` on Windows for process-level exclusivity - Lock held for daemon lifetime, automatically released on exit @@ -2824,7 +2824,7 @@ See README.md for hash ID format details and birthday paradox collision analysis - `bd close`: Close multiple issues with one command - `bd reopen`: Reopen multiple issues together - Example: `bd close bd-1 bd-2 bd-3 --reason "Done"` -- **Daemon RPC Improvements**: Enhanced sync operations (bd-2) +- **Daemon RPC Improvements**: Enhanced sync operations - `bd sync` now works correctly in daemon mode - Export operations properly supported via RPC - Prevents database access conflicts during sync @@ -2838,30 +2838,30 @@ See README.md for hash ID format details and birthday paradox collision analysis - Fixed stress test issues writing 1000+ test issues to production - Quarantined RPC benchmarks to prevent pollution - Added database isolation canary tests -- **Critical**: Daemon cache staleness (bd-49) +- **Critical**: Daemon cache staleness - Daemon now detects external database modifications via mtime check - Prevents serving stale data after external `bd import`, `rm bd.db`, etc. - Cache automatically invalidates when DB file changes -- **Critical**: Counter desync after deletions (bd-49) +- **Critical**: Counter desync after deletions - Issue counters now sync correctly after bulk deletions - Prevents ID gaps and counter drift - **Critical**: Labels and dependencies not persisted in daemon mode (#101) - Fixed label operations failing silently in daemon mode - Fixed dependency operations not saving in daemon mode - Both now correctly propagate through RPC layer -- **Daemon sync support**: `bd sync` command now works in daemon mode (bd-2) +- **Daemon sync support**: `bd sync` command now works in daemon mode - Previously crashed with nil pointer when daemon running - Export operations now properly routed through RPC - **Acceptance flag normalization**: Unified `--acceptance` flag behavior (bd-228, #102) - Added `--acceptance-criteria` as clearer alias - Both flags work identically for backward compatibility -- **Auto-import Git conflicts**: Better detection of merge conflicts (bd-270) +- **Auto-import Git conflicts**: Better detection of merge conflicts - Auto-import detects and warns about unresolved Git merge conflicts - Prevents importing corrupted JSONL with conflict markers - Clear instructions for resolving conflicts ### Changed -- **BREAKING**: Removed global daemon socket fallback (bd-231) +- **BREAKING**: Removed global daemon socket fallback - Each project now must use its own local daemon (.beads/bd.sock) - Prevents cross-project daemon connections and database pollution - Migration: Stop any global daemon and restart with `bd daemon` in each project @@ -2877,7 +2877,7 @@ See README.md for hash ID format details and birthday paradox collision analysis ## [0.10.0] - 2025-10-20 ### Added -- **Agent Onboarding**: New `bd onboard` command for agent-first documentation (bd-173) +- **Agent Onboarding**: New `bd onboard` command for agent-first documentation - Outputs structured instructions for agents to integrate bd into documentation - Bootstrap workflow: Add 'BEFORE ANYTHING ELSE: run bd onboard' to AGENTS.md - Agent adapts instructions to existing project structure @@ -2902,7 +2902,7 @@ See README.md for hash ID format details and birthday paradox collision analysis ## [0.9.10] - 2025-10-18 ### Added -- **Label Filtering**: Enhanced `bd list` command with label-based filtering (bd-161) +- **Label Filtering**: Enhanced `bd list` command with label-based filtering - `--label` (or `-l`): Filter by multiple labels with AND semantics (must have ALL) - `--label-any`: Filter by multiple labels with OR semantics (must have AT LEAST ONE) - Examples: @@ -2910,12 +2910,12 @@ See README.md for hash ID format details and birthday paradox collision analysis - `bd list --label-any frontend,backend`: Issues with either 'frontend' OR 'backend' - Works in both daemon and direct modes - Includes comprehensive test coverage -- **Log Rotation**: Automatic daemon log rotation with configurable limits (bd-154) +- **Log Rotation**: Automatic daemon log rotation with configurable limits - Prevents unbounded log file growth for long-running daemons - Configurable via environment variables: `BEADS_DAEMON_LOG_MAX_SIZE`, `BEADS_DAEMON_LOG_MAX_BACKUPS`, `BEADS_DAEMON_LOG_MAX_AGE`, `BEADS_DAEMON_LOG_COMPRESS` - Optional compression of rotated logs - Defaults: 50MB max size, 7 backups, 30 day retention, compression enabled -- **Batch Deletion**: Enhanced `bd delete` command with batch operations (bd-127) +- **Batch Deletion**: Enhanced `bd delete` command with batch operations - Delete multiple issues at once: `bd delete bd-1 bd-2 bd-3 --force` - Read from file: `bd delete --from-file deletions.txt --force` - Dry-run mode: `--dry-run` to preview deletions before execution @@ -2925,7 +2925,7 @@ See README.md for hash ID format details and birthday paradox collision analysis - Comprehensive statistics: tracks deleted issues, dependencies, labels, and events ### Fixed -- **Critical**: `bd list --status all` showing 0 issues (bd-148) +- **Critical**: `bd list --status all` showing 0 issues - Status filter now treats "all" as special value meaning "show all statuses" - Previously treated "all" as literal status value, matching no issues @@ -2950,25 +2950,25 @@ See README.md for hash ID format details and birthday paradox collision analysis - Useful for project rebranding or namespace changes - **Comprehensive Testing**: Added scripttest-based integration tests (#59) - End-to-end coverage for CLI workflows - - Tests for init command edge cases (bd-70) + - Tests for init command edge cases ### Fixed -- **Critical**: Metadata errors causing crashes on first import (bd-663) +- **Critical**: Metadata errors causing crashes on first import - Auto-import now treats missing metadata as first import instead of failing - Eliminates initialization errors in fresh repositories -- **Critical**: N+1 query pattern in auto-import (bd-666) +- **Critical**: N+1 query pattern in auto-import - Replaced per-issue queries with batch fetching - Dramatically improves performance for large imports -- **Critical**: Duplicate issue imports (bd-421) +- **Critical**: Duplicate issue imports - Added deduplication logic to prevent importing same issue multiple times - Maintains data integrity during repeated imports -- **Bug**: Auto-flush missing after renumber/rename-prefix (bd-346) +- **Bug**: Auto-flush missing after renumber/rename-prefix - Commands now properly export to JSONL after completion - Ensures git sees latest changes immediately -- **Bug**: Renumber ID collision with UUID temp IDs (bd-345) +- **Bug**: Renumber ID collision with UUID temp IDs - Uses proper UUID-based temporary IDs to prevent conflicts during renumbering - ID counter now correctly syncs after renumbering operations -- **Bug**: Collision resolution dependency handling (bd-437) +- **Bug**: Collision resolution dependency handling - Uses unchecked dependency addition during collision remapping - Prevents spurious cycle detection errors - **Bug**: macOS crashes documented (closes #3, bd-87) @@ -2988,13 +2988,13 @@ See README.md for hash ID format details and birthday paradox collision analysis - Faster command execution through RPC-backed daemon (up to 10x improvement) - N+1 query elimination in list/show operations - Reduced write amplification from improved auto-flush behavior -- Cycle detection performance benchmarks added (bd-311) +- Cycle detection performance benchmarks added ### Testing - Integration tests for daemon RPC request/response flows - End-to-end coverage for delete/restore lifecycles - Regression tests for metadata handling, auto-flush, ID counter sync -- Comprehensive tests for collision detection in auto-import (bd-401) +- Comprehensive tests for collision detection in auto-import ### Documentation - Release process documentation added (RELEASING.md) @@ -3028,7 +3028,7 @@ See README.md for hash ID format details and birthday paradox collision analysis - **MCP Reopen Support**: Reopen closed issues via MCP server - Claude Desktop plugin can now reopen issues - Useful for revisiting completed work -- **Cross-Type Cycle Prevention**: Dependency cycles detected across all types (bd-312) +- **Cross-Type Cycle Prevention**: Dependency cycles detected across all types - Prevents A→B→A cycles even when mixing `blocks`, `related`, etc. - Semantic validation for parent-child direction - Diagnostic warnings when cycles detected @@ -3038,22 +3038,22 @@ See README.md for hash ID format details and birthday paradox collision analysis - Import would silently skip collisions instead of remapping - Could cause data loss when merging branches - Now correctly applies collision resolution with remapping -- **Critical**: Transaction state corruption (bd-221) +- **Critical**: Transaction state corruption - Nested transactions could corrupt database state - Fixed with proper transaction boundary handling - **Critical**: Concurrent temp file collisions (bd-306, bd-373) - Multiple `bd` processes would collide on shared `.tmp` filename - Now uses PID suffix for temp files: `.beads/issues.jsonl.tmp.12345` -- **Critical**: Circular dependency detection gaps (bd-307) +- **Critical**: Circular dependency detection gaps - Some cycle patterns were missed by detection algorithm - Enhanced with comprehensive cycle prevention - **Bug**: False positive merge conflict detection (bd-313, bd-270) - Auto-import would detect conflicts when none existed - Fixed with improved Git conflict marker detection -- **Bug**: Import timeout with large issue sets (bd-199) +- **Bug**: Import timeout with large issue sets - 200+ issue imports would timeout - Optimized import performance -- **Bug**: Collision resolver missing ID counter sync (bd-331) +- **Bug**: Collision resolver missing ID counter sync - After remapping, ID counters weren't updated - Could cause duplicate IDs in subsequent creates - **Bug**: NULL handling in statistics for empty databases (PR #37) @@ -3068,7 +3068,7 @@ See README.md for hash ID format details and birthday paradox collision analysis - MCP integration tests fixed and linting cleaned up (PR #40) ### Performance -- Cycle detection benchmarks added (bd-311) +- Cycle detection benchmarks added - Import optimization for large issue sets - Export uses PID-based temp files to avoid lock contention @@ -3117,7 +3117,7 @@ See README.md for hash ID format details and birthday paradox collision analysis - Fixed infinite recursion in complex dependency graphs - Prevents duplicate nodes at same level - Handles multiple blockers correctly -- **Critical**: Hash-based auto-import replaces mtime comparison (bd-84) +- **Critical**: Hash-based auto-import replaces mtime comparison - Git pull updates mtime but may not change content - Now uses SHA256 hash to detect actual changes - Prevents unnecessary imports after git operations diff --git a/cmd/bd/agent.go b/cmd/bd/agent.go index 2f33d83e..15e85ab9 100644 --- a/cmd/bd/agent.go +++ b/cmd/bd/agent.go @@ -14,7 +14,7 @@ import ( "github.com/steveyegge/beads/internal/utils" ) -// Valid agent states for state command (bd-uxlb) +// Valid agent states for state command var validAgentStates = map[string]bool{ "idle": true, // Agent is waiting for work "spawning": true, // Agent is starting up diff --git a/cmd/bd/autoflush.go b/cmd/bd/autoflush.go index 73f571c8..f2b4dfda 100644 --- a/cmd/bd/autoflush.go +++ b/cmd/bd/autoflush.go @@ -92,9 +92,9 @@ func findJSONLPath() string { } // autoImportIfNewer checks if JSONL content changed (via hash) and imports if so -// Fixes bd-84: Hash-based comparison is git-proof (mtime comparison fails after git pull) -// Fixes bd-228: Now uses collision detection to prevent silently overwriting local changes -// Fixes bd-4t7: Defense-in-depth check to respect --no-auto-import flag +// Hash-based comparison is git-proof (mtime comparison fails after git pull). +// Uses collision detection to prevent silently overwriting local changes. +// Defense-in-depth check to respect --no-auto-import flag. func autoImportIfNewer() { // Defense-in-depth: always check noAutoImport flag directly // This ensures auto-import is disabled even if caller forgot to check autoImportEnabled @@ -119,13 +119,13 @@ func autoImportIfNewer() { hasher.Write(jsonlData) currentHash := hex.EncodeToString(hasher.Sum(nil)) - // Get content hash from DB metadata (try new key first, fall back to old for migration - bd-39o) + // Get content hash from DB metadata (try new key first, fall back to old for migration) ctx := rootCtx lastHash, err := store.GetMetadata(ctx, "jsonl_content_hash") if err != nil || lastHash == "" { lastHash, err = store.GetMetadata(ctx, "last_import_hash") if err != nil { - // Metadata error - treat as first import rather than skipping (bd-663) + // Metadata error - treat as first import rather than skipping // This allows auto-import to recover from corrupt/missing metadata debug.Logf("metadata read failed (%v), treating as first import", err) lastHash = "" @@ -141,7 +141,7 @@ func autoImportIfNewer() { debug.Logf("auto-import triggered (hash changed)") - // Check for Git merge conflict markers (bd-270) + // Check for Git merge conflict markers // Only match if they appear as standalone lines (not embedded in JSON strings) lines := bytes.Split(jsonlData, []byte("\n")) for _, line := range lines { @@ -200,13 +200,13 @@ func autoImportIfNewer() { return } - // Clear export_hashes before import to prevent staleness (bd-160) + // Clear export_hashes before import to prevent staleness // Import operations may add/update issues, so export_hashes entries become invalid if err := store.ClearAllExportHashes(ctx); err != nil { fmt.Fprintf(os.Stderr, "Warning: failed to clear export_hashes before import: %v\n", err) } - // Use shared import logic (bd-157) + // Use shared import logic opts := ImportOptions{ DryRun: false, SkipUpdate: false, @@ -271,14 +271,14 @@ func autoImportIfNewer() { } } - // Store new hash after successful import (renamed from last_import_hash - bd-39o) + // Store new hash after successful import (renamed from last_import_hash) if err := store.SetMetadata(ctx, "jsonl_content_hash", currentHash); err != nil { fmt.Fprintf(os.Stderr, "Warning: failed to update jsonl_content_hash after import: %v\n", err) fmt.Fprintf(os.Stderr, "This may cause auto-import to retry the same import on next operation.\n") } - // Store import timestamp (bd-159: for staleness detection) - // Use RFC3339Nano for nanosecond precision to avoid race with file mtime (fixes #399) + // Store import timestamp for staleness detection + // Use RFC3339Nano for nanosecond precision to avoid race with file mtime importTime := time.Now().Format(time.RFC3339Nano) if err := store.SetMetadata(ctx, "last_import_time", importTime); err != nil { fmt.Fprintf(os.Stderr, "Warning: failed to update last_import_time after import: %v\n", err) @@ -289,7 +289,7 @@ func autoImportIfNewer() { // markDirtyAndScheduleFlush marks the database as dirty and schedules a flush // markDirtyAndScheduleFlush marks the database as dirty and schedules a debounced -// export to JSONL. Uses FlushManager's event-driven architecture (fixes bd-52). +// export to JSONL. Uses FlushManager's event-driven architecture. // // Debouncing behavior: If multiple operations happen within the debounce window, only // one flush occurs after the burst of activity completes. This prevents excessive @@ -344,7 +344,7 @@ func clearAutoFlushState() { // Error handling: Returns error on any failure. Cleanup is guaranteed via defer. // Thread-safe: No shared state access. Safe to call from multiple goroutines. // validateJSONLIntegrity checks if JSONL file hash matches stored hash. -// If mismatch detected, clears export_hashes and logs warning (bd-160). +// If mismatch detected, clears export_hashes and logs warning. // Returns (needsFullExport, error) where needsFullExport=true if export_hashes was cleared. func validateJSONLIntegrity(ctx context.Context, jsonlPath string) (bool, error) { // Get stored JSONL file hash @@ -367,7 +367,7 @@ func validateJSONLIntegrity(ctx context.Context, jsonlPath string) (bool, error) if err := store.ClearAllExportHashes(ctx); err != nil { return false, fmt.Errorf("failed to clear export_hashes: %w", err) } - // Also clear jsonl_file_hash to prevent perpetual mismatch warnings (bd-admx) + // Also clear jsonl_file_hash to prevent perpetual mismatch warnings if err := store.SetJSONLFileHash(ctx, ""); err != nil { return false, fmt.Errorf("failed to clear jsonl_file_hash: %w", err) } @@ -383,7 +383,7 @@ func validateJSONLIntegrity(ctx context.Context, jsonlPath string) (bool, error) // Compare hashes if currentHash != storedHash { - fmt.Fprintf(os.Stderr, "⚠️ WARNING: JSONL file hash mismatch detected (bd-160)\n") + fmt.Fprintf(os.Stderr, "⚠️ WARNING: JSONL file hash mismatch detected\n") fmt.Fprintf(os.Stderr, " This indicates JSONL and export_hashes are out of sync.\n") fmt.Fprintf(os.Stderr, " Clearing export_hashes to force full re-export.\n") @@ -391,7 +391,7 @@ func validateJSONLIntegrity(ctx context.Context, jsonlPath string) (bool, error) if err := store.ClearAllExportHashes(ctx); err != nil { return false, fmt.Errorf("failed to clear export_hashes: %w", err) } - // Also clear jsonl_file_hash to prevent perpetual mismatch warnings (bd-admx) + // Also clear jsonl_file_hash to prevent perpetual mismatch warnings if err := store.SetJSONLFileHash(ctx, ""); err != nil { return false, fmt.Errorf("failed to clear jsonl_file_hash: %w", err) } @@ -407,7 +407,7 @@ func writeJSONLAtomic(jsonlPath string, issues []*types.Issue) ([]string, error) return cmp.Compare(a.ID, b.ID) }) - // Create temp file with PID suffix to avoid collisions (bd-306) + // Create temp file with PID suffix to avoid collisions tempPath := fmt.Sprintf("%s.tmp.%d", jsonlPath, os.Getpid()) f, err := os.Create(tempPath) if err != nil { @@ -422,7 +422,7 @@ func writeJSONLAtomic(jsonlPath string, issues []*types.Issue) ([]string, error) } }() - // Write all issues as JSONL (timestamp-only deduplication DISABLED - bd-160) + // Write all issues as JSONL (timestamp-only deduplication DISABLED) encoder := json.NewEncoder(f) skippedCount := 0 exportedIDs := make([]string, 0, len(issues)) @@ -435,7 +435,7 @@ func writeJSONLAtomic(jsonlPath string, issues []*types.Issue) ([]string, error) exportedIDs = append(exportedIDs, issue.ID) } - // Report skipped issues if any (helps debugging bd-159) + // Report skipped issues if any (helps debugging) if skippedCount > 0 { debug.Logf("auto-flush skipped %d issue(s) with timestamp-only changes", skippedCount) } @@ -508,12 +508,12 @@ func flushToJSONLWithState(state flushState) { ctx := rootCtx - // Validate JSONL integrity BEFORE checking isDirty (bd-c6cf) + // Validate JSONL integrity BEFORE checking isDirty // This detects if JSONL and export_hashes are out of sync (e.g., after git operations) // If export_hashes was cleared, we need to do a full export even if nothing is dirty integrityNeedsFullExport, err := validateJSONLIntegrity(ctx, jsonlPath) if err != nil { - // Special case: missing JSONL is not fatal, just forces full export (bd-c6cf) + // Special case: missing JSONL is not fatal, just forces full export if !os.IsNotExist(err) { // Record failure without clearing isDirty (we didn't do any work yet) flushMutex.Lock() @@ -538,7 +538,7 @@ func flushToJSONLWithState(state flushState) { } // Check if we should proceed with export - // Use only the state parameter - don't read global flags (fixes bd-52) + // Use only the state parameter - don't read global flags // Caller is responsible for passing correct forceDirty/forceFullExport values if !state.forceDirty && !integrityNeedsFullExport { // Nothing to do: not forced and no integrity issue @@ -590,7 +590,7 @@ func flushToJSONLWithState(state flushState) { dirtyIDs[i] = issue.ID } } else { - // Incremental export: get only dirty issue IDs (bd-39 optimization) + // Incremental export: get only dirty issue IDs var err2 error dirtyIDs, err2 = store.GetDirtyIssues(ctx) if err2 != nil { @@ -610,7 +610,7 @@ func flushToJSONLWithState(state flushState) { if !fullExport { if existingFile, err := os.Open(jsonlPath); err == nil { scanner := bufio.NewScanner(existingFile) - // Increase buffer to handle large JSON lines (bd-c6cf) + // Increase buffer to handle large JSON lines // Default scanner limit is 64KB which can cause silent truncation scanner.Buffer(make([]byte, 0, 1024), 2*1024*1024) // 2MB max line size lineNum := 0 @@ -629,7 +629,7 @@ func flushToJSONLWithState(state flushState) { fmt.Fprintf(os.Stderr, "Warning: skipping malformed JSONL line %d: %v\n", lineNum, err) } } - // Check for scanner errors (bd-c6cf) + // Check for scanner errors if err := scanner.Err(); err != nil { _ = existingFile.Close() recordFailure(fmt.Errorf("failed to read existing JSONL: %w", err)) @@ -665,7 +665,7 @@ func flushToJSONLWithState(state flushState) { } // Convert map to slice (will be sorted by writeJSONLAtomic) - // Filter out wisps - they should never be exported to JSONL (bd-687g) + // Filter out wisps - they should never be exported to JSONL // Wisps exist only in SQLite and are shared via .beads/redirect, not JSONL. // This prevents "zombie" issues that resurrect after mol squash deletes them. issues := make([]*types.Issue, 0, len(issueMap)) @@ -728,7 +728,7 @@ func flushToJSONLWithState(state flushState) { return } - // Clear only the dirty issues that were actually exported (fixes bd-52 race condition, bd-159) + // Clear only the dirty issues that were actually exported (fixes race condition) // Don't clear issues that were skipped due to timestamp-only changes if len(exportedIDs) > 0 { if err := store.ClearDirtyIssuesByID(ctx, exportedIDs); err != nil { @@ -737,8 +737,8 @@ func flushToJSONLWithState(state flushState) { } } - // Store hash of exported JSONL (fixes bd-84: enables hash-based auto-import) - // Renamed from last_import_hash to jsonl_content_hash (bd-39o) + // Store hash of exported JSONL (enables hash-based auto-import) + // Renamed from last_import_hash to jsonl_content_hash jsonlData, err := os.ReadFile(jsonlPath) if err == nil { hasher := sha256.New() @@ -748,7 +748,7 @@ func flushToJSONLWithState(state flushState) { fmt.Fprintf(os.Stderr, "Warning: failed to update jsonl_content_hash after export: %v\n", err) } - // Store JSONL file hash for integrity validation (bd-160) + // Store JSONL file hash for integrity validation if err := store.SetJSONLFileHash(ctx, exportedHash); err != nil { fmt.Fprintf(os.Stderr, "Warning: failed to update jsonl_file_hash after export: %v\n", err) } diff --git a/cmd/bd/autoimport.go b/cmd/bd/autoimport.go index f69957cb..baf8b88f 100644 --- a/cmd/bd/autoimport.go +++ b/cmd/bd/autoimport.go @@ -237,7 +237,7 @@ func importFromGit(ctx context.Context, dbFilePath string, store storage.Storage return fmt.Errorf("failed to scan JSONL: %w", err) } - // CRITICAL (bd-166): Set issue_prefix from first imported issue if missing + // CRITICAL: Set issue_prefix from first imported issue if missing // This prevents derivePrefixFromPath fallback which caused duplicate issues if len(issues) > 0 { configuredPrefix, err := store.GetConfig(ctx, "issue_prefix") diff --git a/cmd/bd/cleanup.go b/cmd/bd/cleanup.go index 9ccca95a..fe7d2e5f 100644 --- a/cmd/bd/cleanup.go +++ b/cmd/bd/cleanup.go @@ -20,7 +20,7 @@ type CleanupEmptyResponse struct { // Hard delete mode: bypass tombstone TTL safety, use --older-than days directly -// showCleanupDeprecationHint shows a hint about bd doctor --fix (bd-bqcc) +// showCleanupDeprecationHint shows a hint about bd doctor --fix func showCleanupDeprecationHint() { fmt.Fprintln(os.Stderr, ui.RenderMuted("💡 Tip: 'bd doctor --fix' can now cleanup stale issues and prune tombstones")) } @@ -217,7 +217,7 @@ SEE ALSO: // Note: cleanup always creates tombstones first; --hard prunes them after deleteBatch(cmd, issueIDs, force, dryRun, cascade, jsonOutput, false, "cleanup") - // Also prune expired tombstones (bd-08ea) + // Also prune expired tombstones // This runs after closed issues are converted to tombstones, cleaning up old ones // In --hard mode, customTTL overrides the default 30-day TTL if dryRun { diff --git a/cmd/bd/compact.go b/cmd/bd/compact.go index 402b379c..478ea921 100644 --- a/cmd/bd/compact.go +++ b/cmd/bd/compact.go @@ -312,7 +312,7 @@ func runCompactSingle(ctx context.Context, compactor *compact.Compactor, store * float64(savingBytes)/float64(originalSize)*100) fmt.Printf(" Time: %v\n", elapsed) - // Prune expired tombstones (bd-okh) + // Prune expired tombstones if tombstonePruneResult, err := pruneExpiredTombstones(0); err != nil { fmt.Fprintf(os.Stderr, "Warning: failed to prune expired tombstones: %v\n", err) } else if tombstonePruneResult != nil && tombstonePruneResult.PrunedCount > 0 { @@ -444,7 +444,7 @@ func runCompactAll(ctx context.Context, compactor *compact.Compactor, store *sql fmt.Printf(" Saved: %d bytes (%.1f%%)\n", totalSaved, float64(totalSaved)/float64(totalOriginal)*100) } - // Prune expired tombstones (bd-okh) + // Prune expired tombstones if tombstonePruneResult, err := pruneExpiredTombstones(0); err != nil { fmt.Fprintf(os.Stderr, "Warning: failed to prune expired tombstones: %v\n", err) } else if tombstonePruneResult != nil && tombstonePruneResult.PrunedCount > 0 { @@ -887,7 +887,7 @@ func runCompactApply(ctx context.Context, store *sqlite.SQLiteStorage) { elapsed := time.Since(start) - // Prune expired tombstones from issues.jsonl (bd-okh) + // Prune expired tombstones from issues.jsonl tombstonePruneResult, tombstoneErr := pruneExpiredTombstones(0) if tombstoneErr != nil && !jsonOutput { fmt.Fprintf(os.Stderr, "Warning: failed to prune expired tombstones: %v\n", tombstoneErr) @@ -904,7 +904,7 @@ func runCompactApply(ctx context.Context, store *sqlite.SQLiteStorage) { "reduction_pct": reductionPct, "elapsed_ms": elapsed.Milliseconds(), } - // Include tombstone pruning results (bd-okh) + // Include tombstone pruning results if tombstonePruneResult != nil && tombstonePruneResult.PrunedCount > 0 { output["tombstones_pruned"] = map[string]interface{}{ "count": tombstonePruneResult.PrunedCount, @@ -919,7 +919,7 @@ func runCompactApply(ctx context.Context, store *sqlite.SQLiteStorage) { fmt.Printf(" %d → %d bytes (saved %d, %.1f%%)\n", originalSize, compactedSize, savingBytes, reductionPct) fmt.Printf(" Time: %v\n", elapsed) - // Report tombstone pruning results (bd-okh) + // Report tombstone pruning results if tombstonePruneResult != nil && tombstonePruneResult.PrunedCount > 0 { fmt.Printf("\nTombstones pruned: %d expired tombstones (older than %d days) removed\n", tombstonePruneResult.PrunedCount, tombstonePruneResult.TTLDays) @@ -1032,7 +1032,7 @@ func pruneExpiredTombstones(customTTL time.Duration) (*TombstonePruneResult, err } // previewPruneTombstones checks what tombstones would be pruned without modifying files. -// Used for dry-run mode in cleanup command (bd-08ea). +// Used for dry-run mode in cleanup command. // If customTTL is > 0, it overrides the default TTL (bypasses MinTombstoneTTL safety). // If customTTL is 0, uses DefaultTombstoneTTL. func previewPruneTombstones(customTTL time.Duration) (*TombstonePruneResult, error) { @@ -1090,7 +1090,7 @@ func previewPruneTombstones(customTTL time.Duration) (*TombstonePruneResult, err // runCompactPrune handles the --prune mode for standalone tombstone pruning. // This mode only prunes expired tombstones from issues.jsonl without doing -// any semantic compaction. It's useful for reducing sync overhead (bd-c7y5). +// any semantic compaction. It's useful for reducing sync overhead. func runCompactPrune() { start := time.Now() diff --git a/cmd/bd/cook.go b/cmd/bd/cook.go index ec7ad670..58bb6735 100644 --- a/cmd/bd/cook.go +++ b/cmd/bd/cook.go @@ -25,7 +25,7 @@ var cookCmd = &cobra.Command{ By default, cook outputs the resolved formula as JSON to stdout for ephemeral use. The output can be inspected, piped, or saved to a file. -Two cooking modes are available (gt-8tmz.23): +Two cooking modes are available: COMPILE-TIME (default, --mode=compile): Produces a proto with {{variable}} placeholders intact. @@ -48,7 +48,7 @@ to the database. This is useful when you want to reuse the same proto multiple times without re-cooking. For most workflows, prefer ephemeral protos: pour and wisp commands -accept formula names directly and cook inline (bd-rciw). +accept formula names directly and cook inline. Examples: bd cook mol-feature.formula.json # Compile-time: keep {{vars}} @@ -89,7 +89,7 @@ func runCook(cmd *cobra.Command, args []string) { varFlags, _ := cmd.Flags().GetStringSlice("var") mode, _ := cmd.Flags().GetString("mode") - // Parse variables (gt-8tmz.23) + // Parse variables inputVars := make(map[string]string) for _, v := range varFlags { parts := strings.SplitN(v, "=", 2) @@ -100,7 +100,7 @@ func runCook(cmd *cobra.Command, args []string) { inputVars[parts[0]] = parts[1] } - // Determine cooking mode (gt-8tmz.23) + // Determine cooking mode // Runtime mode is triggered by: explicit --mode=runtime OR providing --var flags runtimeMode := mode == "runtime" || len(inputVars) > 0 if mode != "" && mode != "compile" && mode != "runtime" { @@ -143,7 +143,7 @@ func runCook(cmd *cobra.Command, args []string) { os.Exit(1) } - // Apply control flow operators (gt-8tmz.4) - loops, branches, gates + // Apply control flow operators - loops, branches, gates // This must happen before advice and expansions so they can act on expanded loop steps controlFlowSteps, err := formula.ApplyControlFlow(resolved.Steps, resolved.Compose) if err != nil { @@ -152,12 +152,12 @@ func runCook(cmd *cobra.Command, args []string) { } resolved.Steps = controlFlowSteps - // Apply advice transformations (gt-8tmz.2) + // Apply advice transformations if len(resolved.Advice) > 0 { resolved.Steps = formula.ApplyAdvice(resolved.Steps, resolved.Advice) } - // Apply inline step expansions (gt-8tmz.35) + // Apply inline step expansions // This processes Step.Expand fields before compose.expand/map rules inlineExpandedSteps, err := formula.ApplyInlineExpansions(resolved.Steps, parser) if err != nil { @@ -166,7 +166,7 @@ func runCook(cmd *cobra.Command, args []string) { } resolved.Steps = inlineExpandedSteps - // Apply expansion operators (gt-8tmz.3) + // Apply expansion operators if resolved.Compose != nil && (len(resolved.Compose.Expand) > 0 || len(resolved.Compose.Map) > 0) { expandedSteps, err := formula.ApplyExpansions(resolved.Steps, resolved.Compose, parser) if err != nil { @@ -176,7 +176,7 @@ func runCook(cmd *cobra.Command, args []string) { resolved.Steps = expandedSteps } - // Apply aspects from compose.aspects (gt-8tmz.5) + // Apply aspects from compose.aspects if resolved.Compose != nil && len(resolved.Compose.Aspects) > 0 { for _, aspectName := range resolved.Compose.Aspects { aspectFormula, err := parser.LoadByName(aspectName) @@ -194,7 +194,7 @@ func runCook(cmd *cobra.Command, args []string) { } } - // Apply prefix to proto ID if specified (bd-47qx) + // Apply prefix to proto ID if specified protoID := resolved.Formula if prefix != "" { protoID = prefix + resolved.Formula @@ -276,9 +276,9 @@ func runCook(cmd *cobra.Command, args []string) { return } - // Ephemeral mode (default): output resolved formula as JSON to stdout (bd-rciw) + // Ephemeral mode (default): output resolved formula as JSON to stdout if !persist { - // Runtime mode (gt-8tmz.23): substitute variables before output + // Runtime mode: substitute variables before output if runtimeMode { // Apply defaults from formula variable definitions for name, def := range resolved.Vars { @@ -458,14 +458,14 @@ func collectStepsToSubgraph(steps []*formula.Step, parentID string, issueMap map IsTemplate: true, CreatedAt: time.Now(), UpdatedAt: time.Now(), - SourceFormula: step.SourceFormula, // Source tracing (gt-8tmz.18) - SourceLocation: step.SourceLocation, // Source tracing (gt-8tmz.18) + SourceFormula: step.SourceFormula, // Source tracing + SourceLocation: step.SourceLocation, // Source tracing } // Store labels in the issue's Labels field for in-memory use issue.Labels = append(issue.Labels, step.Labels...) - // Add gate label for waits_for field (bd-j4cr) + // Add gate label for waits_for field if step.WaitsFor != "" { gateLabel := fmt.Sprintf("gate:%s", step.WaitsFor) issue.Labels = append(issue.Labels, gateLabel) @@ -516,7 +516,7 @@ func collectDependenciesToSubgraph(step *formula.Step, idMapping map[string]stri }) } - // Process needs field (bd-hr39) - simpler alias for sibling dependencies + // Process needs field - simpler alias for sibling dependencies for _, needID := range step.Needs { needIssueID, ok := idMapping[needID] if !ok { @@ -530,7 +530,7 @@ func collectDependenciesToSubgraph(step *formula.Step, idMapping map[string]stri }) } - // Process waits_for field (gt-8tmz.38) - fanout gate dependency + // Process waits_for field - fanout gate dependency if step.WaitsFor != "" { waitsForSpec := formula.ParseWaitsFor(step.WaitsFor) if waitsForSpec != nil { @@ -585,26 +585,26 @@ func resolveAndCookFormula(formulaName string, searchPaths []string) (*TemplateS return nil, fmt.Errorf("resolving formula %q: %w", formulaName, err) } - // Apply control flow operators (gt-8tmz.4) - loops, branches, gates + // Apply control flow operators - loops, branches, gates controlFlowSteps, err := formula.ApplyControlFlow(resolved.Steps, resolved.Compose) if err != nil { return nil, fmt.Errorf("applying control flow to %q: %w", formulaName, err) } resolved.Steps = controlFlowSteps - // Apply advice transformations (gt-8tmz.2) + // Apply advice transformations if len(resolved.Advice) > 0 { resolved.Steps = formula.ApplyAdvice(resolved.Steps, resolved.Advice) } - // Apply inline step expansions (gt-8tmz.35) + // Apply inline step expansions inlineExpandedSteps, err := formula.ApplyInlineExpansions(resolved.Steps, parser) if err != nil { return nil, fmt.Errorf("applying inline expansions to %q: %w", formulaName, err) } resolved.Steps = inlineExpandedSteps - // Apply expansion operators (gt-8tmz.3) + // Apply expansion operators if resolved.Compose != nil && (len(resolved.Compose.Expand) > 0 || len(resolved.Compose.Map) > 0) { expandedSteps, err := formula.ApplyExpansions(resolved.Steps, resolved.Compose, parser) if err != nil { @@ -613,7 +613,7 @@ func resolveAndCookFormula(formulaName string, searchPaths []string) (*TemplateS resolved.Steps = expandedSteps } - // Apply aspects from compose.aspects (gt-8tmz.5) + // Apply aspects from compose.aspects if resolved.Compose != nil && len(resolved.Compose.Aspects) > 0 { for _, aspectName := range resolved.Compose.Aspects { aspectFormula, err := parser.LoadByName(aspectName) @@ -649,7 +649,7 @@ func cookFormulaToSubgraphWithVars(f *formula.Formula, protoID string, vars map[ } } } - // Attach recommended phase from formula (bd-mol cleanup: warn on pour of vapor formulas) + // Attach recommended phase from formula (warn on pour of vapor formulas) subgraph.Phase = f.Phase return subgraph, nil } @@ -675,7 +675,7 @@ func cookFormula(ctx context.Context, s storage.Storage, f *formula.Formula, pro var deps []*types.Dependency var labels []struct{ issueID, label string } - // Create root proto epic using provided protoID (may include prefix, bd-47qx) + // Create root proto epic using provided protoID (may include prefix) rootIssue := &types.Issue{ ID: protoID, Title: f.Formula, // Title is the original formula name @@ -797,8 +797,8 @@ func collectStepsRecursive(steps []*formula.Step, parentID string, idMapping map IsTemplate: true, CreatedAt: time.Now(), UpdatedAt: time.Now(), - SourceFormula: step.SourceFormula, // Source tracing (gt-8tmz.18) - SourceLocation: step.SourceLocation, // Source tracing (gt-8tmz.18) + SourceFormula: step.SourceFormula, // Source tracing + SourceLocation: step.SourceLocation, // Source tracing } *issues = append(*issues, issue) @@ -807,7 +807,7 @@ func collectStepsRecursive(steps []*formula.Step, parentID string, idMapping map *labels = append(*labels, struct{ issueID, label string }{issueID, label}) } - // Add gate label for waits_for field (bd-j4cr) + // Add gate label for waits_for field if step.WaitsFor != "" { gateLabel := fmt.Sprintf("gate:%s", step.WaitsFor) *labels = append(*labels, struct{ issueID, label string }{issueID, gateLabel}) @@ -847,7 +847,7 @@ func collectDependencies(step *formula.Step, idMapping map[string]string, deps * }) } - // Process needs field (bd-hr39) - simpler alias for sibling dependencies + // Process needs field - simpler alias for sibling dependencies for _, needID := range step.Needs { needIssueID, ok := idMapping[needID] if !ok { @@ -861,7 +861,7 @@ func collectDependencies(step *formula.Step, idMapping map[string]string, deps * }) } - // Process waits_for field (gt-8tmz.38) - fanout gate dependency + // Process waits_for field - fanout gate dependency if step.WaitsFor != "" { waitsForSpec := formula.ParseWaitsFor(step.WaitsFor) if waitsForSpec != nil { @@ -947,7 +947,7 @@ func printFormulaSteps(steps []*formula.Step, indent string) { typeStr = fmt.Sprintf(" (%s)", step.Type) } - // Source tracing info (gt-8tmz.18) + // Source tracing info sourceStr := "" if step.SourceFormula != "" || step.SourceLocation != "" { sourceStr = fmt.Sprintf(" [from: %s@%s]", step.SourceFormula, step.SourceLocation) @@ -967,7 +967,7 @@ func printFormulaSteps(steps []*formula.Step, indent string) { } } -// substituteFormulaVars substitutes {{variable}} placeholders in a formula (gt-8tmz.23). +// substituteFormulaVars substitutes {{variable}} placeholders in a formula. // This is used in runtime mode to fully resolve the formula before output. func substituteFormulaVars(f *formula.Formula, vars map[string]string) { // Substitute in top-level fields diff --git a/cmd/bd/create.go b/cmd/bd/create.go index c1596711..0a6de264 100644 --- a/cmd/bd/create.go +++ b/cmd/bd/create.go @@ -161,7 +161,7 @@ var createCmd = &cobra.Command{ repoPath = routing.DetermineTargetRepo(routingConfig, userRole, ".") } - // TODO: Switch to target repo for multi-repo support (bd-4ms) + // TODO: Switch to target repo for multi-repo support // For now, we just log the target repo in debug mode if repoPath != "." { debug.Logf("DEBUG: Target repo: %s\n", repoPath) @@ -205,7 +205,7 @@ var createCmd = &cobra.Command{ // Get database prefix from config var dbPrefix string if daemonClient != nil { - // TODO(bd-g5p7): Add RPC method to get config in daemon mode + // TODO: Add RPC method to get config in daemon mode // For now, skip validation in daemon mode (needs RPC enhancement) } else { // Direct mode - check config @@ -216,7 +216,7 @@ var createCmd = &cobra.Command{ FatalError("%v", err) } - // Validate agent ID pattern if type is agent (gt-hlaaf) + // Validate agent ID pattern if type is agent if issueType == "agent" { if err := validation.ValidateAgentID(explicitID); err != nil { FatalError("invalid agent ID: %v", err) @@ -262,7 +262,7 @@ var createCmd = &cobra.Command{ FatalError("parsing response: %v", err) } - // Run create hook (bd-kwro.8) + // Run create hook if hookRunner != nil { hookRunner.Run(hooks.EventCreate, &issue) } @@ -294,7 +294,7 @@ var createCmd = &cobra.Command{ ExternalRef: externalRefPtr, EstimatedMinutes: estimatedMinutes, Ephemeral: wisp, - CreatedBy: getActorWithGit(), // GH#748: track who created the issue + CreatedBy: getActorWithGit(), } ctx := rootCtx @@ -400,7 +400,7 @@ var createCmd = &cobra.Command{ } } - // Add waits-for dependency if specified (bd-xo1o.2) + // Add waits-for dependency if specified if waitsFor != "" { // Validate gate type gate := waitsForGate @@ -434,7 +434,7 @@ var createCmd = &cobra.Command{ // Schedule auto-flush markDirtyAndScheduleFlush() - // Run create hook (bd-kwro.8) + // Run create hook if hookRunner != nil { hookRunner.Run(hooks.EventCreate, issue) } diff --git a/cmd/bd/daemon_event_loop.go b/cmd/bd/daemon_event_loop.go index 3eb1cefc..a8fa26b8 100644 --- a/cmd/bd/daemon_event_loop.go +++ b/cmd/bd/daemon_event_loop.go @@ -210,14 +210,11 @@ func runEventDrivenLoop( // checkDaemonHealth performs periodic health validation. // Separate from sync operations - just validates state. -// -// Implements bd-e0o: Phase 3 daemon robustness for GH #353 -// Implements bd-gqo: Additional health checks func checkDaemonHealth(ctx context.Context, store storage.Storage, log daemonLogger) { // Health check 1: Verify metadata is accessible // This helps detect if external operations (like bd import --force) have modified metadata // Without this, daemon may continue operating with stale metadata cache - // Try new key first, fall back to old for migration (bd-39o) + // Try new key first, fall back to old for migration if _, err := store.GetMetadata(ctx, "jsonl_content_hash"); err != nil { if _, err := store.GetMetadata(ctx, "last_import_hash"); err != nil { log.log("Health check: metadata read failed: %v", err) diff --git a/cmd/bd/daemon_lifecycle.go b/cmd/bd/daemon_lifecycle.go index 2ee0404a..67b23355 100644 --- a/cmd/bd/daemon_lifecycle.go +++ b/cmd/bd/daemon_lifecycle.go @@ -315,7 +315,7 @@ func stopDaemon(pidFile string) { fmt.Println("Daemon killed") } -// stopAllDaemons stops all running bd daemons (bd-47tn) +// stopAllDaemons stops all running bd daemons func stopAllDaemons() { // Discover all running daemons using the registry daemons, err := daemon.DiscoverDaemons(nil) diff --git a/cmd/bd/daemon_sync.go b/cmd/bd/daemon_sync.go index b5a277d8..17682bb6 100644 --- a/cmd/bd/daemon_sync.go +++ b/cmd/bd/daemon_sync.go @@ -37,7 +37,7 @@ func exportToJSONLWithStore(ctx context.Context, store storage.Storage, jsonlPat } // Single-repo mode - use existing logic - // Get all issues including tombstones for sync propagation (bd-rp4o fix) + // Get all issues including tombstones for sync propagation // Tombstones must be exported so they propagate to other clones and prevent resurrection issues, err := store.SearchIssues(ctx, "", types.IssueFilter{IncludeTombstones: true}) if err != nil { @@ -45,7 +45,7 @@ func exportToJSONLWithStore(ctx context.Context, store storage.Storage, jsonlPat } // Safety check: prevent exporting empty database over non-empty JSONL - // Note: The main bd-53c protection is in sync.go's reverse ZFC check which runs BEFORE export. + // Note: The main protection is in sync.go's reverse ZFC check which runs BEFORE export. // Here we only block the most catastrophic case (empty DB) to allow legitimate deletions. if len(issues) == 0 { existingCount, err := countIssuesInJSONL(jsonlPath) @@ -185,7 +185,7 @@ func importToJSONLWithStore(ctx context.Context, store storage.Storage, jsonlPat fmt.Fprintf(os.Stderr, "Warning: failed to parse JSONL line %d: %v\n", lineNum, err) continue } - issue.SetDefaults() // Apply defaults for omitted fields (beads-399) + issue.SetDefaults() // Apply defaults for omitted fields issues = append(issues, &issue) } @@ -246,33 +246,33 @@ func getRepoKeyForPath(jsonlPath string) string { // sanitizeMetadataKey removes or replaces characters that conflict with metadata key format. // On Windows, absolute paths contain colons (e.g., C:\...) which conflict with the ':' separator // used in multi-repo metadata keys. This function replaces colons with underscores to make -// paths safe for use as metadata key suffixes (bd-web8). +// paths safe for use as metadata key suffixes. func sanitizeMetadataKey(key string) string { return strings.ReplaceAll(key, ":", "_") } // updateExportMetadata updates jsonl_content_hash and related metadata after a successful export. -// This prevents "JSONL content has changed since last import" errors on subsequent exports (bd-ymj fix). +// This prevents "JSONL content has changed since last import" errors on subsequent exports. // In multi-repo mode, keySuffix should be the stable repo identifier (e.g., ".", "../frontend"). // -// Metadata key format (bd-ar2.12, bd-39o): +// Metadata key format: // - Single-repo mode: "jsonl_content_hash", "last_import_time" // - Multi-repo mode: "jsonl_content_hash:", "last_import_time:", etc. // where is a stable repo identifier like "." or "../frontend" -// - Windows paths: Colons in absolute paths (e.g., C:\...) are replaced with underscores (bd-web8) -// - Note: "last_import_mtime" was removed in bd-v0y fix (git doesn't preserve mtime) -// - Note: "last_import_hash" renamed to "jsonl_content_hash" (bd-39o) - more accurate name +// - Windows paths: Colons in absolute paths (e.g., C:\...) are replaced with underscores +// - Note: "last_import_mtime" was removed (git doesn't preserve mtime) +// - Note: "last_import_hash" renamed to "jsonl_content_hash" - more accurate name // -// Transaction boundaries (bd-ar2.6): +// Transaction boundaries: // This function does NOT provide atomicity between JSONL write, metadata updates, and DB mtime. // If a crash occurs between these operations, metadata may be inconsistent. However, this is // acceptable because: // 1. The worst case is "JSONL content has changed" error on next export // 2. User can fix by running 'bd import' (safe, no data loss) // 3. Current approach is simple and doesn't require complex WAL or format changes -// Future: Consider Option 4 (defensive checks on startup) if this becomes a common issue. +// Future: Consider defensive checks on startup if this becomes a common issue. func updateExportMetadata(ctx context.Context, store storage.Storage, jsonlPath string, log daemonLogger, keySuffix string) { - // Sanitize keySuffix to handle Windows paths with colons (bd-web8) + // Sanitize keySuffix to handle Windows paths with colons if keySuffix != "" { keySuffix = sanitizeMetadataKey(keySuffix) } @@ -284,7 +284,7 @@ func updateExportMetadata(ctx context.Context, store storage.Storage, jsonlPath } // Build metadata keys with optional suffix for per-repo tracking - // Renamed from last_import_hash to jsonl_content_hash (bd-39o) + // Renamed from last_import_hash to jsonl_content_hash hashKey := "jsonl_content_hash" timeKey := "last_import_time" if keySuffix != "" { @@ -292,7 +292,7 @@ func updateExportMetadata(ctx context.Context, store storage.Storage, jsonlPath timeKey += ":" + keySuffix } - // Note: Metadata update failures are treated as warnings, not errors (bd-ar2.5). + // Note: Metadata update failures are treated as warnings, not errors. // This is acceptable because the worst case is the next export will require // an import first, which is safe and prevents data loss. // Alternative: Make this critical and fail the export if metadata updates fail, @@ -307,7 +307,7 @@ func updateExportMetadata(ctx context.Context, store storage.Storage, jsonlPath if err := store.SetMetadata(ctx, timeKey, exportTime); err != nil { log.log("Warning: failed to update %s: %v", timeKey, err) } - // Note: mtime tracking removed in bd-v0y fix (git doesn't preserve mtime) + // Note: mtime tracking removed (git doesn't preserve mtime) } // validateDatabaseFingerprint checks that the database belongs to this repository @@ -437,7 +437,7 @@ func performExport(ctx context.Context, store storage.Storage, autoCommit, autoP } log.log("Exported to JSONL") - // Update export metadata (bd-ymj fix, bd-ar2.2 multi-repo support, bd-ar2.11 stable keys) + // Update export metadata for multi-repo support with stable keys multiRepoPaths := getMultiRepoJSONLPaths() if multiRepoPaths != nil { // Multi-repo mode: update metadata for each JSONL with stable repo key @@ -566,8 +566,8 @@ func performAutoImport(ctx context.Context, store storage.Storage, skipGit bool, } // Check JSONL content hash to avoid redundant imports - // Use content-based check (not mtime) to avoid git resurrection bug (bd-khnb) - // Use getRepoKeyForPath for multi-repo support (bd-ar2.10, bd-ar2.11) + // Use content-based check (not mtime) to avoid git resurrection bug + // Use getRepoKeyForPath for multi-repo support repoKey := getRepoKeyForPath(jsonlPath) if !hasJSONLChanged(importCtx, store, jsonlPath, repoKey) { log.log("Skipping %s: JSONL content unchanged", mode) @@ -577,7 +577,7 @@ func performAutoImport(ctx context.Context, store storage.Storage, skipGit bool, // Pull from git if not in git-free mode if !skipGit { - // SAFETY CHECK (bd-k92d): Warn if there are uncommitted local changes + // SAFETY CHECK: Warn if there are uncommitted local changes // This helps detect race conditions where local work hasn't been pushed yet jsonlPath := findJSONLPath() if jsonlPath != "" { @@ -675,7 +675,7 @@ func performSync(ctx context.Context, store storage.Storage, autoCommit, autoPus return } - // Cache multi-repo paths to avoid redundant calls (bd-we4p) + // Cache multi-repo paths to avoid redundant calls multiRepoPaths := getMultiRepoJSONLPaths() // Check for exclusive lock before processing database @@ -718,7 +718,7 @@ func performSync(ctx context.Context, store storage.Storage, autoCommit, autoPus } log.log("Exported to JSONL") - // Update export metadata (bd-ymj fix, bd-ar2.2 multi-repo support, bd-ar2.11 stable keys) + // Update export metadata for multi-repo support with stable keys if multiRepoPaths != nil { // Multi-repo mode: update metadata for each JSONL with stable repo key for _, path := range multiRepoPaths { @@ -730,7 +730,7 @@ func performSync(ctx context.Context, store storage.Storage, autoCommit, autoPus updateExportMetadata(syncCtx, store, jsonlPath, log, "") } - // Update database mtime to be >= JSONL mtime (fixes #278, #301, #321) + // Update database mtime to be >= JSONL mtime // This prevents validatePreExport from incorrectly blocking on next export dbPath := filepath.Join(beadsDir, "beads.db") if err := TouchDatabaseFile(dbPath, jsonlPath); err != nil { @@ -873,7 +873,7 @@ func performSync(ctx context.Context, store storage.Storage, autoCommit, autoPus } } - // Clean up temporary snapshot files after successful merge (bd-upd) + // Clean up temporary snapshot files after successful merge // In multi-repo mode, clean up snapshots for all JSONL files if multiRepoPaths != nil { for _, path := range multiRepoPaths { diff --git a/cmd/bd/daemon_watcher.go b/cmd/bd/daemon_watcher.go index 5075b791..848d0414 100644 --- a/cmd/bd/daemon_watcher.go +++ b/cmd/bd/daemon_watcher.go @@ -29,7 +29,7 @@ type FileWatcher struct { lastHeadModTime time.Time lastHeadExists bool cancel context.CancelFunc - wg sync.WaitGroup // Track goroutines for graceful shutdown (bd-jo38) + wg sync.WaitGroup // Track goroutines for graceful shutdown // Log deduplication: track last log times to avoid duplicate messages lastFileLogTime time.Time lastGitRefLogTime time.Time @@ -350,7 +350,7 @@ func (fw *FileWatcher) Close() error { if fw.cancel != nil { fw.cancel() } - // Wait for goroutines to finish before cleanup (bd-jo38) + // Wait for goroutines to finish before cleanup fw.wg.Wait() fw.debouncer.Cancel() if fw.watcher != nil { diff --git a/cmd/bd/daemons.go b/cmd/bd/daemons.go index c035d95c..7e9e4999 100644 --- a/cmd/bd/daemons.go +++ b/cmd/bd/daemons.go @@ -300,7 +300,7 @@ Stops the daemon gracefully, then starts a new one.`, os.Exit(1) } // Don't wait for daemon to exit (it will fork and continue in background) - // Use timeout to prevent goroutine leak if daemon never completes (bd-zqmb) + // Use timeout to prevent goroutine leak if daemon never completes go func() { done := make(chan struct{}) go func() { diff --git a/cmd/bd/delete.go b/cmd/bd/delete.go index fd3f2597..35425f88 100644 --- a/cmd/bd/delete.go +++ b/cmd/bd/delete.go @@ -516,7 +516,7 @@ func deleteBatch(_ *cobra.Command, issueIDs []string, force bool, dryRun bool, c os.Exit(1) } - // Hard delete: immediately prune tombstones from JSONL (bd-4q8) + // Hard delete: immediately prune tombstones from JSONL // Note: We keep tombstones in DB to prevent resurrection during sync. // The tombstones will be exported and synced to remote, blocking resurrection. // Use 'bd cleanup --hard' after syncing to fully purge old tombstones. @@ -535,7 +535,7 @@ func deleteBatch(_ *cobra.Command, issueIDs []string, force bool, dryRun bool, c // Update text references in connected issues (using pre-collected issues) updatedCount := updateTextReferencesInIssues(ctx, issueIDs, connectedIssues) - // Note: No longer remove from JSONL - tombstones will be exported to JSONL (bd-3b4) + // Note: No longer remove from JSONL - tombstones will be exported to JSONL // Schedule auto-flush markDirtyAndScheduleFlush() // Output results diff --git a/cmd/bd/dep.go b/cmd/bd/dep.go index fb283d19..2e2bcb6d 100644 --- a/cmd/bd/dep.go +++ b/cmd/bd/dep.go @@ -98,7 +98,7 @@ Examples: resolveArgs = &rpc.ResolveIDArgs{ID: args[1]} resp, err = daemonClient.ResolveID(resolveArgs) if err != nil { - // Resolution failed - try auto-converting to external ref (bd-lfiu) + // Resolution failed - try auto-converting to external ref beadsDir := getBeadsDir() if extRef := routing.ResolveToExternalRef(args[1], beadsDir); extRef != "" { toID = extRef @@ -127,7 +127,7 @@ Examples: } else { toID, err = utils.ResolvePartialID(ctx, store, args[1]) if err != nil { - // Resolution failed - try auto-converting to external ref (bd-lfiu) + // Resolution failed - try auto-converting to external ref beadsDir := getBeadsDir() if extRef := routing.ResolveToExternalRef(args[1], beadsDir); extRef != "" { toID = extRef @@ -139,7 +139,7 @@ Examples: } } - // Check for child→parent dependency anti-pattern (bd-nim5) + // Check for child→parent dependency anti-pattern // This creates a deadlock: child can't start (parent open), parent can't close (children not done) if isChildOf(fromID, toID) { FatalErrorRespectJSON("cannot add dependency: %s is already a child of %s. Children inherit dependency on parent completion via hierarchy. Adding an explicit dependency would create a deadlock", fromID, toID) @@ -656,7 +656,7 @@ func (r *treeRenderer) renderNode(node *types.TreeNode, children map[string][]*t // formatTreeNode formats a single tree node with status, ready indicator, etc. func formatTreeNode(node *types.TreeNode) string { - // Handle external dependencies specially (bd-vks2) + // Handle external dependencies specially if IsExternalRef(node.ID) { // External deps use their title directly which includes the status indicator var idStr string diff --git a/cmd/bd/detect_pollution.go b/cmd/bd/detect_pollution.go index d733392c..41c11dc7 100644 --- a/cmd/bd/detect_pollution.go +++ b/cmd/bd/detect_pollution.go @@ -12,7 +12,7 @@ import ( "github.com/steveyegge/beads/internal/ui" ) -// showDetectPollutionDeprecationHint shows a hint about bd doctor consolidation (bd-kff0) +// showDetectPollutionDeprecationHint shows a hint about bd doctor consolidation func showDetectPollutionDeprecationHint() { fmt.Fprintln(os.Stderr, ui.RenderMuted("💡 Tip: Use 'bd doctor --check=pollution' instead (this command is deprecated)")) } @@ -20,7 +20,7 @@ func showDetectPollutionDeprecationHint() { var detectPollutionCmd = &cobra.Command{ Use: "detect-pollution", GroupID: "maint", - Hidden: true, // bd-kff0: deprecated, use 'bd doctor --check=pollution' instead + Hidden: true, // deprecated, use 'bd doctor --check=pollution' instead Deprecated: "use 'bd doctor --check=pollution' instead", Short: "Detect and optionally clean test issues from database", Long: `Detect test issues that leaked into production database using pattern matching. @@ -140,7 +140,7 @@ NOTE: Review detected issues carefully before using --clean. False positives are if !clean { fmt.Printf("Run 'bd detect-pollution --clean' to delete these issues (with confirmation).\n") - // bd-bqcc: Show hint about doctor consolidation + // Show hint about doctor consolidation showDetectPollutionDeprecationHint() return } diff --git a/cmd/bd/direct_mode.go b/cmd/bd/direct_mode.go index 8ba084a9..7c221bde 100644 --- a/cmd/bd/direct_mode.go +++ b/cmd/bd/direct_mode.go @@ -63,7 +63,7 @@ func ensureStoreActive() error { if found := beads.FindDatabasePath(); found != "" { dbPath = found } else { - // Check if this is a JSONL-only project (bd-534) + // Check if this is a JSONL-only project beadsDir := beads.FindBeadsDir() if beadsDir != "" { jsonlPath := filepath.Join(beadsDir, "issues.jsonl") @@ -87,7 +87,7 @@ func ensureStoreActive() error { sqlStore, err := sqlite.New(rootCtx, dbPath) if err != nil { - // Check for fresh clone scenario (bd-dmb) + // Check for fresh clone scenario if isFreshCloneError(err) { beadsDir := filepath.Dir(dbPath) handleFreshCloneError(err, beadsDir) diff --git a/cmd/bd/doctor.go b/cmd/bd/doctor.go index 3c9a3084..ac98654a 100644 --- a/cmd/bd/doctor.go +++ b/cmd/bd/doctor.go @@ -44,22 +44,22 @@ type doctorResult struct { Checks []doctorCheck `json:"checks"` OverallOK bool `json:"overall_ok"` CLIVersion string `json:"cli_version"` - Timestamp string `json:"timestamp,omitempty"` // bd-9cc: ISO8601 timestamp for historical tracking - Platform map[string]string `json:"platform,omitempty"` // bd-9cc: platform info for debugging + Timestamp string `json:"timestamp,omitempty"` // ISO8601 timestamp for historical tracking + Platform map[string]string `json:"platform,omitempty"` // platform info for debugging } var ( doctorFix bool doctorYes bool - doctorInteractive bool // bd-3xl: per-fix confirmation mode - doctorDryRun bool // bd-a5z: preview fixes without applying - doctorOutput string // bd-9cc: export diagnostics to file - doctorFixChildParent bool // bd-cuek: opt-in fix for child→parent deps + doctorInteractive bool // per-fix confirmation mode + doctorDryRun bool // preview fixes without applying + doctorOutput string // export diagnostics to file + doctorFixChildParent bool // opt-in fix for child→parent deps perfMode bool checkHealthMode bool - doctorCheckFlag string // bd-kff0: run specific check (e.g., "pollution") - doctorClean bool // bd-kff0: for pollution check, delete detected issues - doctorDeep bool // bd-cwpl: full graph integrity validation + doctorCheckFlag string // run specific check (e.g., "pollution") + doctorClean bool // for pollution check, delete detected issues + doctorDeep bool // full graph integrity validation ) // ConfigKeyHintsDoctor is the config key for suppressing doctor hints @@ -122,14 +122,14 @@ Examples: bd doctor --json # Machine-readable output bd doctor --fix # Automatically fix issues (with confirmation) bd doctor --fix --yes # Automatically fix issues (no confirmation) - bd doctor --fix -i # Confirm each fix individually (bd-3xl) + bd doctor --fix -i # Confirm each fix individually bd doctor --fix --fix-child-parent # Also fix child→parent deps (opt-in) bd doctor --dry-run # Preview what --fix would do without making changes bd doctor --perf # Performance diagnostics bd doctor --output diagnostics.json # Export diagnostics to file bd doctor --check=pollution # Show potential test issues bd doctor --check=pollution --clean # Delete test issues (with confirmation) - bd doctor --deep # Full graph integrity validation (bd-cwpl)`, + bd doctor --deep # Full graph integrity validation`, Run: func(cmd *cobra.Command, args []string) { // Use global jsonOutput set by PersistentPreRun @@ -158,7 +158,7 @@ Examples: return } - // Run specific check if --check flag is set (bd-kff0) + // Run specific check if --check flag is set if doctorCheckFlag != "" { switch doctorCheckFlag { case "pollution": @@ -171,7 +171,7 @@ Examples: } } - // Run deep validation if --deep flag is set (bd-cwpl) + // Run deep validation if --deep flag is set if doctorDeep { runDeepValidation(absPath) return @@ -180,7 +180,7 @@ Examples: // Run diagnostics result := runDiagnostics(absPath) - // bd-a5z: Preview fixes (dry-run) or apply fixes if requested + // Preview fixes (dry-run) or apply fixes if requested if doctorDryRun { previewFixes(result) } else if doctorFix { @@ -189,13 +189,13 @@ Examples: result = runDiagnostics(absPath) } - // bd-9cc: Add timestamp and platform info for export + // Add timestamp and platform info for export if doctorOutput != "" || jsonOutput { result.Timestamp = time.Now().UTC().Format(time.RFC3339) result.Platform = doctor.CollectPlatformInfo(absPath) } - // bd-9cc: Export to file if --output specified + // Export to file if --output specified if doctorOutput != "" { if err := exportDiagnostics(result, doctorOutput); err != nil { fmt.Fprintf(os.Stderr, "Error: failed to export diagnostics: %v\n", err) @@ -222,12 +222,12 @@ Examples: func init() { doctorCmd.Flags().BoolVar(&doctorFix, "fix", false, "Automatically fix issues where possible") doctorCmd.Flags().BoolVarP(&doctorYes, "yes", "y", false, "Skip confirmation prompt (for non-interactive use)") - doctorCmd.Flags().BoolVarP(&doctorInteractive, "interactive", "i", false, "Confirm each fix individually (bd-3xl)") - doctorCmd.Flags().BoolVar(&doctorDryRun, "dry-run", false, "Preview fixes without making changes (bd-a5z)") - doctorCmd.Flags().BoolVar(&doctorFixChildParent, "fix-child-parent", false, "Remove child→parent dependencies (opt-in, bd-cuek)") + doctorCmd.Flags().BoolVarP(&doctorInteractive, "interactive", "i", false, "Confirm each fix individually") + doctorCmd.Flags().BoolVar(&doctorDryRun, "dry-run", false, "Preview fixes without making changes") + doctorCmd.Flags().BoolVar(&doctorFixChildParent, "fix-child-parent", false, "Remove child→parent dependencies (opt-in)") } -// previewFixes shows what would be fixed without applying changes (bd-a5z) +// previewFixes shows what would be fixed without applying changes func previewFixes(result doctorResult) { // Collect all fixable issues var fixableIssues []doctorCheck @@ -285,7 +285,7 @@ func applyFixes(result doctorResult) { fmt.Printf(" %d. %s: %s\n", i+1, issue.Name, issue.Message) } - // bd-3xl: Interactive mode - confirm each fix individually + // Interactive mode - confirm each fix individually if doctorInteractive { applyFixesInteractive(result.Path, fixableIssues) return @@ -313,7 +313,7 @@ func applyFixes(result doctorResult) { applyFixList(result.Path, fixableIssues) } -// applyFixesInteractive prompts for each fix individually (bd-3xl) +// applyFixesInteractive prompts for each fix individually func applyFixesInteractive(path string, issues []doctorCheck) { reader := bufio.NewReader(os.Stdin) applyAll := false @@ -485,7 +485,7 @@ func applyFixList(path string, fixes []doctorCheck) { case "Orphaned Dependencies": err = fix.OrphanedDependencies(path) case "Child-Parent Dependencies": - // bd-cuek: Requires explicit opt-in flag (destructive, may remove intentional deps) + // Requires explicit opt-in flag (destructive, may remove intentional deps) if !doctorFixChildParent { fmt.Printf(" ⚠ Child→parent deps require explicit opt-in: bd doctor --fix --fix-child-parent\n") continue @@ -504,10 +504,10 @@ func applyFixList(path string, fixes []doctorCheck) { fmt.Printf(" ⚠ Resolve conflicts manually: git checkout --ours or --theirs .beads/issues.jsonl\n") continue case "Stale Closed Issues": - // bd-bqcc: consolidate cleanup into doctor --fix + // consolidate cleanup into doctor --fix err = fix.StaleClosedIssues(path) case "Expired Tombstones": - // bd-bqcc: consolidate cleanup into doctor --fix + // consolidate cleanup into doctor --fix err = fix.ExpiredTombstones(path) case "Compaction Candidates": // No auto-fix: compaction requires agent review @@ -552,7 +552,7 @@ func runCheckHealth(path string) { return } - // Get database path once (bd-b8h: centralized path resolution) + // Get database path once (centralized path resolution) dbPath := getCheckHealthDBPath(beadsDir) // Check if database exists @@ -564,7 +564,7 @@ func runCheckHealth(path string) { return } - // Open database once for all checks (bd-xyc: single DB connection) + // Open database once for all checks (single DB connection) db, err := sql.Open("sqlite3", "file:"+dbPath+"?mode=ro") if err != nil { // Can't open DB - only check hooks @@ -610,7 +610,7 @@ func runCheckHealth(path string) { // Silent exit on success } -// runDeepValidation runs full graph integrity validation (bd-cwpl) +// runDeepValidation runs full graph integrity validation func runDeepValidation(path string) { // Show warning about potential slowness fmt.Println("Running deep validation (may be slow on large databases)...") @@ -646,7 +646,7 @@ func printCheckHealthHint(issues []string) { } // getCheckHealthDBPath returns the database path for check-health operations. -// This centralizes the path resolution logic (bd-b8h). +// This centralizes the path resolution logic. func getCheckHealthDBPath(beadsDir string) string { if cfg, err := configfile.Load(beadsDir); err == nil && cfg != nil && cfg.Database != "" { return cfg.DatabasePath(beadsDir) @@ -655,7 +655,7 @@ func getCheckHealthDBPath(beadsDir string) string { } // hintsDisabledDB checks if hints.doctor is set to "false" using an existing DB connection. -// Used by runCheckHealth to avoid multiple DB opens (bd-xyc). +// Used by runCheckHealth to avoid multiple DB opens. func hintsDisabledDB(db *sql.DB) bool { var value string err := db.QueryRow("SELECT value FROM config WHERE key = ?", ConfigKeyHintsDoctor).Scan(&value) @@ -666,7 +666,7 @@ func hintsDisabledDB(db *sql.DB) bool { } // checkVersionMismatchDB checks if CLI version differs from database bd_version. -// Uses an existing DB connection (bd-xyc). +// Uses an existing DB connection. func checkVersionMismatchDB(db *sql.DB) string { var dbVersion string err := db.QueryRow("SELECT value FROM metadata WHERE key = 'bd_version'").Scan(&dbVersion) @@ -712,7 +712,7 @@ func runDiagnostics(path string) doctorResult { return result } - // Check 1a: Fresh clone detection (bd-4ew) + // Check 1a: Fresh clone detection // Must come early - if this is a fresh clone, other checks may be misleading freshCloneCheck := convertWithCategory(doctor.CheckFreshClone(path), doctor.CategoryCore) result.Checks = append(result.Checks, freshCloneCheck) @@ -727,7 +727,7 @@ func runDiagnostics(path string) doctorResult { result.OverallOK = false } - // Check 2a: Schema compatibility (bd-ckvw) + // Check 2a: Schema compatibility schemaCheck := convertWithCategory(doctor.CheckSchemaCompatibility(path), doctor.CategoryCore) result.Checks = append(result.Checks, schemaCheck) if schemaCheck.Status == statusError { @@ -741,7 +741,7 @@ func runDiagnostics(path string) doctorResult { result.OverallOK = false } - // Check 2c: Database integrity (bd-2au) + // Check 2c: Database integrity integrityCheck := convertWithCategory(doctor.CheckDatabaseIntegrity(path), doctor.CategoryCore) result.Checks = append(result.Checks, integrityCheck) if integrityCheck.Status == statusError { @@ -779,7 +779,7 @@ func runDiagnostics(path string) doctorResult { result.OverallOK = false } - // Check 6a: Legacy JSONL config (bd-6xd: migrate beads.jsonl to issues.jsonl) + // Check 6a: Legacy JSONL config (migrate beads.jsonl to issues.jsonl) legacyConfigCheck := convertWithCategory(doctor.CheckLegacyJSONLConfig(path), doctor.CategoryData) result.Checks = append(result.Checks, legacyConfigCheck) // Don't fail overall check for legacy config, just warn @@ -791,7 +791,7 @@ func runDiagnostics(path string) doctorResult { result.OverallOK = false } - // Check 7a: Configuration value validation (bd-alz) + // Check 7a: Configuration value validation configValuesCheck := convertWithCategory(doctor.CheckConfigValues(path), doctor.CategoryData) result.Checks = append(result.Checks, configValuesCheck) // Don't fail overall check for config value warnings, just warn @@ -876,22 +876,22 @@ func runDiagnostics(path string) doctorResult { result.Checks = append(result.Checks, gitUpstreamCheck) // Don't fail overall check for upstream drift, just warn - // Check 16: Metadata.json version tracking (bd-u4sb) + // Check 16: Metadata.json version tracking metadataCheck := convertWithCategory(doctor.CheckMetadataVersionTracking(path, Version), doctor.CategoryMetadata) result.Checks = append(result.Checks, metadataCheck) // Don't fail overall check for metadata, just warn - // Check 17: Sync branch configuration (bd-rsua) + // Check 17: Sync branch configuration syncBranchCheck := convertWithCategory(doctor.CheckSyncBranchConfig(path), doctor.CategoryGit) result.Checks = append(result.Checks, syncBranchCheck) // Don't fail overall check for missing sync.branch, just warn - // Check 17a: Sync branch health (bd-6rf) + // Check 17a: Sync branch health syncBranchHealthCheck := convertWithCategory(doctor.CheckSyncBranchHealth(path), doctor.CategoryGit) result.Checks = append(result.Checks, syncBranchHealthCheck) // Don't fail overall check for sync branch health, just warn - // Check 17b: Orphaned issues - referenced in commits but still open (bd-5hrq) + // Check 17b: Orphaned issues - referenced in commits but still open orphanedIssuesCheck := convertWithCategory(doctor.CheckOrphanedIssues(path), doctor.CategoryGit) result.Checks = append(result.Checks, orphanedIssuesCheck) // Don't fail overall check for orphaned issues, just warn @@ -901,12 +901,12 @@ func runDiagnostics(path string) doctorResult { result.Checks = append(result.Checks, deletionsCheck) // Don't fail overall check for missing deletions manifest, just warn - // Check 19: Tombstones health (bd-s3v) + // Check 19: Tombstones health tombstonesCheck := convertWithCategory(doctor.CheckTombstones(path), doctor.CategoryMetadata) result.Checks = append(result.Checks, tombstonesCheck) // Don't fail overall check for tombstone issues, just warn - // Check 20: Untracked .beads/*.jsonl files (bd-pbj) + // Check 20: Untracked .beads/*.jsonl files untrackedCheck := convertWithCategory(doctor.CheckUntrackedBeadsFiles(path), doctor.CategoryData) result.Checks = append(result.Checks, untrackedCheck) // Don't fail overall check for untracked files, just warn @@ -921,7 +921,7 @@ func runDiagnostics(path string) doctorResult { result.Checks = append(result.Checks, orphanedDepsCheck) // Don't fail overall check for orphaned deps, just warn - // Check 22a: Child→parent dependencies (anti-pattern, bd-nim5) + // Check 22a: Child→parent dependencies (anti-pattern) childParentDepsCheck := convertDoctorCheck(doctor.CheckChildParentDependencies(path)) result.Checks = append(result.Checks, childParentDepsCheck) // Don't fail overall check for child→parent deps, just warn @@ -943,12 +943,12 @@ func runDiagnostics(path string) doctorResult { result.OverallOK = false } - // Check 26: Stale closed issues (maintenance, bd-bqcc) + // Check 26: Stale closed issues (maintenance) staleClosedCheck := convertDoctorCheck(doctor.CheckStaleClosedIssues(path)) result.Checks = append(result.Checks, staleClosedCheck) // Don't fail overall check for stale issues, just warn - // Check 26a: Stale molecules (complete but unclosed, bd-6a5z) + // Check 26a: Stale molecules (complete but unclosed) staleMoleculesCheck := convertDoctorCheck(doctor.CheckStaleMolecules(path)) result.Checks = append(result.Checks, staleMoleculesCheck) // Don't fail overall check for stale molecules, just warn @@ -958,12 +958,12 @@ func runDiagnostics(path string) doctorResult { result.Checks = append(result.Checks, persistentMolCheck) // Don't fail overall check for persistent mol issues, just warn - // Check 27: Expired tombstones (maintenance, bd-bqcc) + // Check 27: Expired tombstones (maintenance) tombstonesExpiredCheck := convertDoctorCheck(doctor.CheckExpiredTombstones(path)) result.Checks = append(result.Checks, tombstonesExpiredCheck) // Don't fail overall check for expired tombstones, just warn - // Check 28: Compaction candidates (maintenance, bd-bqcc) + // Check 28: Compaction candidates (maintenance) compactionCheck := convertDoctorCheck(doctor.CheckCompactionCandidates(path)) result.Checks = append(result.Checks, compactionCheck) // Info only, not a warning - compaction requires human review @@ -996,7 +996,7 @@ func convertWithCategory(dc doctor.DoctorCheck, category string) doctorCheck { return check } -// exportDiagnostics writes the doctor result to a JSON file (bd-9cc) +// exportDiagnostics writes the doctor result to a JSON file func exportDiagnostics(result doctorResult, outputPath string) error { // #nosec G304 - outputPath is a user-provided flag value for file generation f, err := os.Create(outputPath) @@ -1150,7 +1150,7 @@ func printDiagnostics(result doctorResult) { } } -// runPollutionCheck runs detailed test pollution detection (bd-kff0) +// runPollutionCheck runs detailed test pollution detection // This integrates the detect-pollution command functionality into doctor. func runPollutionCheck(path string, clean bool, yes bool) { // Ensure we have a store initialized (uses direct mode, no daemon support yet) @@ -1288,8 +1288,8 @@ func init() { rootCmd.AddCommand(doctorCmd) doctorCmd.Flags().BoolVar(&perfMode, "perf", false, "Run performance diagnostics and generate CPU profile") doctorCmd.Flags().BoolVar(&checkHealthMode, "check-health", false, "Quick health check for git hooks (silent on success)") - doctorCmd.Flags().StringVarP(&doctorOutput, "output", "o", "", "Export diagnostics to JSON file (bd-9cc)") + doctorCmd.Flags().StringVarP(&doctorOutput, "output", "o", "", "Export diagnostics to JSON file") doctorCmd.Flags().StringVar(&doctorCheckFlag, "check", "", "Run specific check in detail (e.g., 'pollution')") doctorCmd.Flags().BoolVar(&doctorClean, "clean", false, "For pollution check: delete detected test issues") - doctorCmd.Flags().BoolVar(&doctorDeep, "deep", false, "Validate full graph integrity (bd-cwpl)") + doctorCmd.Flags().BoolVar(&doctorDeep, "deep", false, "Validate full graph integrity") } diff --git a/cmd/bd/doctor/database.go b/cmd/bd/doctor/database.go index 6ffca129..c90a7747 100644 --- a/cmd/bd/doctor/database.go +++ b/cmd/bd/doctor/database.go @@ -26,7 +26,7 @@ type localConfig struct { // CheckDatabaseVersion checks the database version and migration status func CheckDatabaseVersion(path string, cliVersion string) DoctorCheck { - // Follow redirect to resolve actual beads directory (bd-tvus fix) + // Follow redirect to resolve actual beads directory beadsDir := resolveBeadsDir(filepath.Join(path, ".beads")) // Check metadata.json first for custom database name @@ -54,7 +54,7 @@ func CheckDatabaseVersion(path string, cliVersion string) DoctorCheck { if jsonlPath != "" { // JSONL exists but no database - check if this is no-db mode or fresh clone - // Use proper YAML parsing to detect no-db mode (bd-r6k2) + // Use proper YAML parsing to detect no-db mode if isNoDbModeConfigured(beadsDir) { return DoctorCheck{ Name: "Database", @@ -136,7 +136,7 @@ func CheckDatabaseVersion(path string, cliVersion string) DoctorCheck { // CheckSchemaCompatibility checks if all required tables and columns are present func CheckSchemaCompatibility(path string) DoctorCheck { - // Follow redirect to resolve actual beads directory (bd-tvus fix) + // Follow redirect to resolve actual beads directory beadsDir := resolveBeadsDir(filepath.Join(path, ".beads")) // Check metadata.json first for custom database name @@ -157,7 +157,7 @@ func CheckSchemaCompatibility(path string) DoctorCheck { } } - // Open database (bd-ckvw: schema probe) + // Open database for schema probe // Note: We can't use the global 'store' because doctor can check arbitrary paths db, err := sql.Open("sqlite3", sqliteConnString(dbPath, true)) if err != nil { @@ -224,9 +224,9 @@ func CheckSchemaCompatibility(path string) DoctorCheck { } } -// CheckDatabaseIntegrity runs SQLite's PRAGMA integrity_check (bd-2au) +// CheckDatabaseIntegrity runs SQLite's PRAGMA integrity_check func CheckDatabaseIntegrity(path string) DoctorCheck { - // Follow redirect to resolve actual beads directory (bd-tvus fix) + // Follow redirect to resolve actual beads directory beadsDir := resolveBeadsDir(filepath.Join(path, ".beads")) // Get database path (same logic as CheckSchemaCompatibility) @@ -351,7 +351,7 @@ func CheckDatabaseIntegrity(path string) DoctorCheck { // CheckDatabaseJSONLSync checks if database and JSONL are in sync func CheckDatabaseJSONLSync(path string) DoctorCheck { - // Follow redirect to resolve actual beads directory (bd-tvus fix) + // Follow redirect to resolve actual beads directory beadsDir := resolveBeadsDir(filepath.Join(path, ".beads")) // Resolve database path (respects metadata.json override). @@ -706,7 +706,7 @@ func isNoDbModeConfigured(beadsDir string) bool { // irreversible. The user must make an explicit decision to delete their // closed issue history. We only provide guidance, never action. func CheckDatabaseSize(path string) DoctorCheck { - // Follow redirect to resolve actual beads directory (bd-tvus fix) + // Follow redirect to resolve actual beads directory beadsDir := resolveBeadsDir(filepath.Join(path, ".beads")) // Get database path diff --git a/cmd/bd/doctor/fix/database_config.go b/cmd/bd/doctor/fix/database_config.go index 34d9686d..76bc1f4e 100644 --- a/cmd/bd/doctor/fix/database_config.go +++ b/cmd/bd/doctor/fix/database_config.go @@ -11,8 +11,6 @@ import ( // DatabaseConfig auto-detects and fixes metadata.json database/JSONL config mismatches. // This fixes the issue where metadata.json gets recreated with wrong JSONL filename. -// -// bd-afd: bd doctor --fix should auto-fix metadata.json jsonl_export mismatch func DatabaseConfig(path string) error { if err := validateBeadsWorkspace(path); err != nil { return err @@ -81,7 +79,6 @@ func DatabaseConfig(path string) error { // findActualJSONLFile scans .beads/ for the actual JSONL file in use. // Prefers issues.jsonl over beads.jsonl (canonical name), skips backups and merge artifacts. -// bd-6xd: issues.jsonl is the canonical filename func findActualJSONLFile(beadsDir string) string { entries, err := os.ReadDir(beadsDir) if err != nil { @@ -125,7 +122,7 @@ func findActualJSONLFile(beadsDir string) string { return "" } - // bd-6xd: Prefer issues.jsonl over beads.jsonl (canonical name) + // Prefer issues.jsonl over beads.jsonl (canonical name) for _, name := range candidates { if name == "issues.jsonl" { return name @@ -147,7 +144,6 @@ func isSystemJSONLFilename(name string) bool { // LegacyJSONLConfig migrates from legacy beads.jsonl to canonical issues.jsonl. // This renames the file, updates metadata.json, and updates .gitattributes if present. -// bd-6xd: issues.jsonl is the canonical filename func LegacyJSONLConfig(path string) error { if err := validateBeadsWorkspace(path); err != nil { return err diff --git a/cmd/bd/doctor/fix/migrate.go b/cmd/bd/doctor/fix/migrate.go index 2c20abb4..5bc10865 100644 --- a/cmd/bd/doctor/fix/migrate.go +++ b/cmd/bd/doctor/fix/migrate.go @@ -10,7 +10,7 @@ import ( ) // DatabaseVersion fixes database version mismatches by running bd migrate, -// or creates the database from JSONL by running bd init for fresh clones (bd-4h9). +// or creates the database from JSONL by running bd init for fresh clones. func DatabaseVersion(path string) error { // Validate workspace if err := validateBeadsWorkspace(path); err != nil { @@ -23,7 +23,7 @@ func DatabaseVersion(path string) error { return err } - // Check if database exists - if not, run init instead of migrate (bd-4h9) + // Check if database exists - if not, run init instead of migrate beadsDir := filepath.Join(path, ".beads") dbPath := filepath.Join(beadsDir, beads.CanonicalDatabaseName) if cfg, err := configfile.Load(beadsDir); err == nil && cfg != nil && cfg.Database != "" { diff --git a/cmd/bd/doctor/fix/sync_branch.go b/cmd/bd/doctor/fix/sync_branch.go index 88ac1bcc..e595e067 100644 --- a/cmd/bd/doctor/fix/sync_branch.go +++ b/cmd/bd/doctor/fix/sync_branch.go @@ -46,8 +46,6 @@ func SyncBranchConfig(path string) error { // This handles two cases: // 1. Local sync branch diverged from remote (after force-push) // 2. Sync branch far behind main on source files -// -// bd-6rf: Detect and fix stale beads-sync branch func SyncBranchHealth(path, syncBranch string) error { if err := validateBeadsWorkspace(path); err != nil { return err diff --git a/cmd/bd/doctor/fix/untracked.go b/cmd/bd/doctor/fix/untracked.go index 34a68002..779cf411 100644 --- a/cmd/bd/doctor/fix/untracked.go +++ b/cmd/bd/doctor/fix/untracked.go @@ -12,7 +12,7 @@ import ( // UntrackedJSONL stages and commits untracked .beads/*.jsonl files. // This fixes the issue where bd cleanup -f creates deletions.jsonl but -// leaves it untracked. (bd-pbj) +// leaves it untracked. func UntrackedJSONL(path string) error { if err := validateBeadsWorkspace(path); err != nil { return err @@ -72,7 +72,7 @@ func UntrackedJSONL(path string) error { // Commit only the JSONL files we staged (using --only to preserve other staged changes) // Use config-based author and signing options (GH#600) - commitMsg := "chore(beads): commit untracked JSONL files\n\nAuto-committed by bd doctor --fix (bd-pbj)" + commitMsg := "chore(beads): commit untracked JSONL files\n\nAuto-committed by bd doctor --fix" commitArgs := []string{"commit", "--only"} // Add --author if configured diff --git a/cmd/bd/doctor/git.go b/cmd/bd/doctor/git.go index f5d0c598..18ef9170 100644 --- a/cmd/bd/doctor/git.go +++ b/cmd/bd/doctor/git.go @@ -504,7 +504,6 @@ func CheckSyncBranchConfig(path string) DoctorCheck { // CheckSyncBranchHealth detects when the sync branch has diverged from main // or from the remote sync branch (after a force-push reset). -// bd-6rf: Detect and fix stale beads-sync branch func CheckSyncBranchHealth(path string) DoctorCheck { // Skip if not in a git repo using worktree-aware detection _, err := git.GetGitDir() diff --git a/cmd/bd/doctor/legacy.go b/cmd/bd/doctor/legacy.go index a1ce0910..77a5f4f2 100644 --- a/cmd/bd/doctor/legacy.go +++ b/cmd/bd/doctor/legacy.go @@ -199,7 +199,6 @@ func CheckLegacyJSONLFilename(repoPath string) DoctorCheck { // CheckLegacyJSONLConfig detects if metadata.json is configured to use the legacy // beads.jsonl filename and recommends migrating to the canonical issues.jsonl. -// bd-6xd: issues.jsonl is the canonical filename func CheckLegacyJSONLConfig(repoPath string) DoctorCheck { beadsDir := filepath.Join(repoPath, ".beads") @@ -235,7 +234,7 @@ func CheckLegacyJSONLConfig(repoPath string) DoctorCheck { Name: "JSONL Config", Status: "warning", Message: "Using legacy beads.jsonl filename", - Detail: "The canonical filename is now issues.jsonl (bd-6xd).\n" + + Detail: "The canonical filename is now issues.jsonl.\n" + " Legacy beads.jsonl is still supported but should be migrated.", Fix: "Run 'bd doctor --fix' to auto-migrate, or manually:\n" + " 1. git mv .beads/beads.jsonl .beads/issues.jsonl\n" + @@ -367,9 +366,8 @@ func CheckDatabaseConfig(repoPath string) DoctorCheck { // CheckFreshClone detects if this is a fresh clone that needs 'bd init'. // A fresh clone has JSONL with issues but no database file. -// bd-4ew: Recommend 'bd init --prefix ' for fresh clones. func CheckFreshClone(repoPath string) DoctorCheck { - // Follow redirect to resolve actual beads directory (bd-tvus fix) + // Follow redirect to resolve actual beads directory beadsDir := resolveBeadsDir(filepath.Join(repoPath, ".beads")) // Check if .beads/ exists diff --git a/cmd/bd/doctor/maintenance.go b/cmd/bd/doctor/maintenance.go index ddc51790..f3fa9ae1 100644 --- a/cmd/bd/doctor/maintenance.go +++ b/cmd/bd/doctor/maintenance.go @@ -21,7 +21,7 @@ const DefaultCleanupAgeDays = 30 // CheckStaleClosedIssues detects closed issues that could be cleaned up. // This consolidates the cleanup command into doctor checks. func CheckStaleClosedIssues(path string) DoctorCheck { - // Follow redirect to resolve actual beads directory (bd-tvus fix) + // Follow redirect to resolve actual beads directory beadsDir := resolveBeadsDir(filepath.Join(path, ".beads")) // Check metadata.json first for custom database name @@ -100,7 +100,7 @@ func CheckStaleClosedIssues(path string) DoctorCheck { // CheckExpiredTombstones detects tombstones that have exceeded their TTL. func CheckExpiredTombstones(path string) DoctorCheck { - // Follow redirect to resolve actual beads directory (bd-tvus fix) + // Follow redirect to resolve actual beads directory beadsDir := resolveBeadsDir(filepath.Join(path, ".beads")) jsonlPath := filepath.Join(beadsDir, "issues.jsonl") @@ -160,7 +160,7 @@ func CheckExpiredTombstones(path string) DoctorCheck { } } -// CheckStaleMolecules detects complete-but-unclosed molecules (bd-6a5z). +// CheckStaleMolecules detects complete-but-unclosed molecules. // A molecule is stale if all children are closed but the root is still open. func CheckStaleMolecules(path string) DoctorCheck { beadsDir := resolveBeadsDir(filepath.Join(path, ".beads")) @@ -243,7 +243,7 @@ func CheckStaleMolecules(path string) DoctorCheck { // CheckCompactionCandidates detects issues eligible for compaction. func CheckCompactionCandidates(path string) DoctorCheck { - // Follow redirect to resolve actual beads directory (bd-tvus fix) + // Follow redirect to resolve actual beads directory beadsDir := resolveBeadsDir(filepath.Join(path, ".beads")) // Check metadata.json first for custom database name diff --git a/cmd/bd/doctor/perf.go b/cmd/bd/doctor/perf.go index 9dfdc79a..722590e3 100644 --- a/cmd/bd/doctor/perf.go +++ b/cmd/bd/doctor/perf.go @@ -97,7 +97,6 @@ func RunPerformanceDiagnostics(path string) { } // CollectPlatformInfo gathers platform information for diagnostics. -// bd-9cc: Exported for use by --output flag. func CollectPlatformInfo(path string) map[string]string { info := make(map[string]string) @@ -108,7 +107,7 @@ func CollectPlatformInfo(path string) map[string]string { info["go_version"] = runtime.Version() // SQLite version - try to find database - // Follow redirect to resolve actual beads directory (bd-tvus fix) + // Follow redirect to resolve actual beads directory beadsDir := resolveBeadsDir(filepath.Join(path, ".beads")) dbPath := filepath.Join(beadsDir, beads.CanonicalDatabaseName) db, err := sql.Open("sqlite3", "file:"+dbPath+"?mode=ro") diff --git a/cmd/bd/duplicate.go b/cmd/bd/duplicate.go index 03cc6899..51f7574c 100644 --- a/cmd/bd/duplicate.go +++ b/cmd/bd/duplicate.go @@ -116,7 +116,7 @@ func runDuplicate(cmd *cobra.Command, args []string) error { // Update the duplicate issue with duplicate_of and close it closedStatus := string(types.StatusClosed) if daemonClient != nil { - // Use RPC for daemon mode (bd-fu83) + // Use RPC for daemon mode _, err := daemonClient.Update(&rpc.UpdateArgs{ ID: duplicateID, DuplicateOf: &canonicalID, @@ -214,7 +214,7 @@ func runSupersede(cmd *cobra.Command, args []string) error { // Update the old issue with superseded_by and close it closedStatus := string(types.StatusClosed) if daemonClient != nil { - // Use RPC for daemon mode (bd-fu83) + // Use RPC for daemon mode _, err := daemonClient.Update(&rpc.UpdateArgs{ ID: oldID, SupersededBy: &newID, diff --git a/cmd/bd/export.go b/cmd/bd/export.go index 4308fd87..bfa59a29 100644 --- a/cmd/bd/export.go +++ b/cmd/bd/export.go @@ -181,7 +181,7 @@ Examples: labelsAny = util.NormalizeLabels(labelsAny) // Build filter - // Tombstone export logic (bd-81x6): + // Tombstone export logic: // - No status filter → include tombstones for sync propagation // - --status=tombstone → include only tombstones (filter handles this) // - --status= → exclude tombstones (user wants specific status) @@ -192,7 +192,7 @@ Examples: // Only include tombstones if explicitly filtering for them filter.IncludeTombstones = (status == types.StatusTombstone) } else { - // No status filter: include tombstones for sync propagation (bd-dve) + // No status filter: include tombstones for sync propagation filter.IncludeTombstones = true } if assignee != "" { @@ -358,7 +358,7 @@ Examples: } } - // Filter out wisps - they should never be exported to JSONL (bd-687g) + // Filter out wisps - they should never be exported to JSONL // Wisps exist only in SQLite and are shared via .beads/redirect, not JSONL. filtered := make([]*types.Issue, 0, len(issues)) for _, issue := range issues { @@ -458,7 +458,7 @@ Examples: // This cancels any pending auto-flush timer and marks DB as clean clearAutoFlushState() - // Store JSONL file hash for integrity validation (bd-160) + // Store JSONL file hash for integrity validation // nolint:gosec // G304: finalPath is validated JSONL export path jsonlData, err := os.ReadFile(finalPath) if err == nil { diff --git a/cmd/bd/gate.go b/cmd/bd/gate.go index f68120a1..0141a319 100644 --- a/cmd/bd/gate.go +++ b/cmd/bd/gate.go @@ -18,7 +18,7 @@ import ( "github.com/steveyegge/beads/internal/utils" ) -// Gate commands - async coordination primitives for agent workflows (bd-udsi) +// Gate commands - async coordination primitives for agent workflows // // Gates are wisp issues that block until external conditions are met. // They enable agents to wait on: diff --git a/cmd/bd/import.go b/cmd/bd/import.go index dc2bd479..6aeecd92 100644 --- a/cmd/bd/import.go +++ b/cmd/bd/import.go @@ -65,7 +65,7 @@ NOTE: Import requires direct database access and does not work with daemon mode. // NOTE: We only close the daemon client connection here, not stop the daemon // process. This is because import may be called as a subprocess from sync, // and stopping the daemon would break the parent sync's connection. - // The daemon-stale-DB issue (bd-sync-corruption) is addressed separately by + // The daemon-stale-DB issue is addressed separately by // having sync use --no-daemon mode for consistency. if daemonClient != nil { debug.Logf("Debug: import command forcing direct mode (closes daemon connection)\n") @@ -75,7 +75,7 @@ NOTE: Import requires direct database access and does not work with daemon mode. var err error store, err = sqlite.New(rootCtx, dbPath) if err != nil { - // Check for fresh clone scenario (bd-dmb) + // Check for fresh clone scenario beadsDir := filepath.Dir(dbPath) if handleFreshCloneError(err, beadsDir) { os.Exit(1) @@ -218,7 +218,7 @@ NOTE: Import requires direct database access and does not work with daemon mode. } // Check if database needs initialization (prefix not set) - // Detect prefix from the imported issues (bd-8an fix) + // Detect prefix from the imported issues initCtx := rootCtx configuredPrefix, err2 := store.GetConfig(initCtx, "issue_prefix") if err2 != nil || strings.TrimSpace(configuredPrefix) == "" { @@ -263,7 +263,7 @@ NOTE: Import requires direct database access and does not work with daemon mode. } // If --protect-left-snapshot is set, read the left snapshot and build ID set - // This protects locally exported issues from git-history-backfill (bd-sync-deletion fix) + // This protects locally exported issues from git-history-backfill if protectLeftSnapshot && input != "" { beadsDir := filepath.Dir(input) leftSnapshotPath := filepath.Join(beadsDir, "beads.left.jsonl") @@ -378,11 +378,11 @@ NOTE: Import requires direct database access and does not work with daemon mode. flushToJSONLWithState(flushState{forceDirty: true}) } - // Update jsonl_content_hash metadata to enable content-based staleness detection (bd-khnb fix) + // Update jsonl_content_hash metadata to enable content-based staleness detection // This prevents git operations from resurrecting deleted issues by comparing content instead of mtime // ALWAYS update metadata after successful import, even if no changes were made (fixes staleness check) // This ensures that running `bd import` marks the database as fresh for staleness detection - // Renamed from last_import_hash (bd-39o) - more accurate since updated on both import AND export + // Renamed from last_import_hash - more accurate since updated on both import AND export if input != "" { if currentHash, err := computeJSONLHash(input); err == nil { if err := store.SetMetadata(ctx, "jsonl_content_hash", currentHash); err != nil { @@ -391,7 +391,7 @@ NOTE: Import requires direct database access and does not work with daemon mode. // is unavailable. This ensures import operations always succeed even if metadata storage fails. debug.Logf("Warning: failed to update jsonl_content_hash: %v", err) } - // Also update jsonl_file_hash to prevent integrity check warnings (bd-0vtq) + // Also update jsonl_file_hash to prevent integrity check warnings // validateJSONLIntegrity() compares this hash against actual JSONL content. // Without this, sync that imports but skips re-export leaves jsonl_file_hash stale, // causing spurious "hash mismatch" warnings on subsequent operations. @@ -788,7 +788,7 @@ func init() { importCmd.Flags().Bool("clear-duplicate-external-refs", false, "Clear duplicate external_ref values (keeps first occurrence)") importCmd.Flags().String("orphan-handling", "", "How to handle missing parent issues: strict/resurrect/skip/allow (default: use config or 'allow')") importCmd.Flags().Bool("force", false, "Force metadata update even when database is already in sync with JSONL") - importCmd.Flags().Bool("protect-left-snapshot", false, "Protect issues in left snapshot from git-history-backfill (bd-sync-deletion fix)") + importCmd.Flags().Bool("protect-left-snapshot", false, "Protect issues in left snapshot from git-history-backfill") importCmd.Flags().Bool("no-git-history", false, "Skip git history backfill for deletions (passed by bd sync)") importCmd.Flags().BoolVar(&jsonOutput, "json", false, "Output import statistics in JSON format") rootCmd.AddCommand(importCmd) diff --git a/cmd/bd/info.go b/cmd/bd/info.go index ff718aef..949279a7 100644 --- a/cmd/bd/info.go +++ b/cmd/bd/info.go @@ -98,7 +98,7 @@ Examples: if store != nil { ctx := rootCtx - // Check database freshness before reading (bd-2q6d, bd-c4rq) + // Check database freshness before reading // Skip check when using daemon (daemon auto-imports on staleness) if daemonClient == nil { if err := ensureDatabaseFresh(ctx); err != nil { @@ -300,60 +300,60 @@ var versionChanges = []VersionChange{ Version: "0.39.1", Date: "2025-12-27", Changes: []string{ - "NEW: bd where command (bd-8x43) - Show active beads location after following redirects", - "NEW: --parent flag for bd update (bd-cj2e) - Reparent issues between epics", - "NEW: Redirect info in bd prime (bd-kblo) - Shows when database is redirected", - "FIX: bd doctor follows redirects (bd-tvus) - Gas Town compatibility", - "FIX: Remove 8-char prefix limit (GH#770) - bd rename-prefix allows longer prefixes", - "CHANGED: Git context consolidation (bd-qph3) - Internal refactor for efficiency", - "DOCS: Database Redirects section (bd-8x43) - ADVANCED.md documentation", - "DOCS: Community Tools update (GH#771) - Added opencode-beads to README", + "NEW: bd where command - Show active beads location after following redirects", + "NEW: --parent flag for bd update - Reparent issues between epics", + "NEW: Redirect info in bd prime - Shows when database is redirected", + "FIX: bd doctor follows redirects - Gas Town compatibility", + "FIX: Remove 8-char prefix limit - bd rename-prefix allows longer prefixes", + "CHANGED: Git context consolidation - Internal refactor for efficiency", + "DOCS: Database Redirects section - ADVANCED.md documentation", + "DOCS: Community Tools update - Added opencode-beads to README", }, }, { Version: "0.39.0", Date: "2025-12-27", Changes: []string{ - "NEW: bd orphans command (GH#767) - Detect issues mentioned in commits but never closed", - "NEW: bd admin parent command (bd-3u8m) - Consolidated cleanup/compact/reset under bd admin", + "NEW: bd orphans command - Detect issues mentioned in commits but never closed", + "NEW: bd admin parent command - Consolidated cleanup/compact/reset under bd admin", "NEW: --prefix flag for bd create - Create issues in other rigs from any directory", - "CHANGED: bd mol catalog → bd formula list (bd-ctmg) - Aligns with formula terminology", - "CHANGED: bd info --thanks (bd-wb9g) - Contributors list moved under bd info", - "CHANGED: Removed unused bd pin/unpin/hook commands (bd-x0zl) - Use gt mol commands", - "CHANGED: bd doctor --check=pollution (bd-kff0) - Test pollution check integrated into doctor", + "CHANGED: bd mol catalog → bd formula list - Aligns with formula terminology", + "CHANGED: bd info --thanks - Contributors list moved under bd info", + "CHANGED: Removed unused bd pin/unpin/hook commands - Use gt mol commands", + "CHANGED: bd doctor --check=pollution - Test pollution check integrated into doctor", "FIX: macOS codesigning in bump-version.sh --install - Prevents quarantine issues", - "FIX: Lint errors and Nix vendorHash (GH#769) - Clean builds on all platforms", - "DOCS: Issue Statuses section in CLI_REFERENCE.md (bd-epww) - Comprehensive status docs", - "DOCS: Consolidated duplicate UI_PHILOSOPHY files (GH#745) - Single source of truth", - "DOCS: README and PLUGIN.md fixes (GH#763) - Corrected installation instructions", + "FIX: Lint errors and Nix vendorHash - Clean builds on all platforms", + "DOCS: Issue Statuses section in CLI_REFERENCE.md - Comprehensive status docs", + "DOCS: Consolidated duplicate UI_PHILOSOPHY files - Single source of truth", + "DOCS: README and PLUGIN.md fixes - Corrected installation instructions", }, }, { Version: "0.38.0", Date: "2025-12-27", Changes: []string{ - "NEW: Prefix-based routing (bd-9gvf) - bd commands auto-route to correct rig via routes.jsonl", - "NEW: Cross-rig ID auto-resolve (bd-lfiu) - bd dep add auto-resolves IDs across rigs", - "NEW: bd mol pour/wisp moved under bd mol subcommand (bd-2fs7) - cleaner command hierarchy", - "NEW: bd show displays comments (GH#177) - Comments now visible in issue details", - "NEW: created_by field on issues (GH#748) - Track issue creator for audit trail", - "NEW: Database corruption recovery in bd doctor --fix (GH#753) - Auto-repair corrupted databases", - "NEW: JSONL integrity check in bd doctor (GH#753) - Detect and fix malformed JSONL", + "NEW: Prefix-based routing - bd commands auto-route to correct rig via routes.jsonl", + "NEW: Cross-rig ID auto-resolve - bd dep add auto-resolves IDs across rigs", + "NEW: bd mol pour/wisp moved under bd mol subcommand - cleaner command hierarchy", + "NEW: bd show displays comments - Comments now visible in issue details", + "NEW: created_by field on issues - Track issue creator for audit trail", + "NEW: Database corruption recovery in bd doctor --fix - Auto-repair corrupted databases", + "NEW: JSONL integrity check in bd doctor - Detect and fix malformed JSONL", "NEW: Git hygiene checks in bd doctor - Detect stale branches and sync issues", "NEW: pre-commit config for local lint enforcement - Consistent code quality", - "NEW: Chaos testing flag for release script (bd-kx1j) - --run-chaos-tests for thorough validation", - "CHANGED: Sync backoff and tips consolidation (GH#753) - Smarter daemon sync timing", + "NEW: Chaos testing flag for release script - --run-chaos-tests for thorough validation", + "CHANGED: Sync backoff and tips consolidation - Smarter daemon sync timing", "CHANGED: Wisp/Ephemeral name finalized as 'wisp' - bd mol wisp is the canonical command", - "FIX: Comments display outside dependents block (GH#756) - Proper formatting", - "FIX: no-db mode storeActive initialization (GH#761) - JSONL-only mode works correctly", - "FIX: --resolution alias restored for bd close (GH#746) - Backwards compatibility", - "FIX: bd graph works with daemon running (GH#751) - Graph generation no longer conflicts", - "FIX: created_by field in RPC path (GH#754) - Daemon correctly propagates creator", - "FIX: Migration 028 idempotency (GH#757) - Migration handles partial/re-runs", - "FIX: Routed IDs bypass daemon in show command (bd-uu8p) - Cross-rig show works correctly", - "FIX: Storage connections closed per iteration (bd-uu8p) - Prevents resource leaks", - "FIX: Modern git init compatibility (GH#753) - Tests use --initial-branch=main", - "FIX: golangci-lint errors resolved (GH#753) - Clean lint on all platforms", + "FIX: Comments display outside dependents block - Proper formatting", + "FIX: no-db mode storeActive initialization - JSONL-only mode works correctly", + "FIX: --resolution alias restored for bd close - Backwards compatibility", + "FIX: bd graph works with daemon running - Graph generation no longer conflicts", + "FIX: created_by field in RPC path - Daemon correctly propagates creator", + "FIX: Migration 028 idempotency - Migration handles partial/re-runs", + "FIX: Routed IDs bypass daemon in show command - Cross-rig show works correctly", + "FIX: Storage connections closed per iteration - Prevents resource leaks", + "FIX: Modern git init compatibility - Tests use --initial-branch=main", + "FIX: golangci-lint errors resolved - Clean lint on all platforms", "IMPROVED: Test coverage - doctor, daemon, storage, RPC client paths covered", }, }, @@ -361,63 +361,63 @@ var versionChanges = []VersionChange{ Version: "0.37.0", Date: "2025-12-26", Changes: []string{ - "BREAKING: Ephemeral API rename (bd-o18s) - Wisp→Ephemeral: JSON 'wisp'→'ephemeral', bd wisp→bd ephemeral", - "NEW: bd gate create/show/list/close/wait (bd-udsi) - Async coordination primitives for agent workflows", - "NEW: bd gate eval (gt-twjr5.2) - Evaluate timer gates and GitHub gates (gh:run, gh:pr, mail)", - "NEW: bd gate approve (gt-twjr5.4) - Human gate approval command", - "NEW: bd close --suggest-next (GH#679) - Show newly unblocked issues after close", - "NEW: bd ready/blocked --parent (GH#743) - Scope by epic or parent bead", - "NEW: TOML support for formulas (gt-xmyha) - .formula.toml files alongside JSON", - "NEW: Fork repo auto-detection (GH#742) - Offer to configure .git/info/exclude", - "NEW: Control flow operators (gt-8tmz.4) - loop and gate operators for formula composition", - "NEW: Aspect composition (gt-8tmz.5) - Cross-cutting concerns via aspects field in formulas", - "NEW: Runtime expansion (gt-8tmz.8) - on_complete and for-each dynamic step generation", - "NEW: bd formula list/show (gt-8tmz.14) - Discover and inspect available formulas", - "NEW: bd mol stale (bd-anv2) - Detect complete-but-unclosed molecules", - "NEW: Stale molecules check in bd doctor (bd-6a5z) - Proactive detection", - "NEW: Distinct ID prefixes (bd-hobo) - bd-proto-xxx, bd-mol-xxx, bd-wisp-xxx", - "NEW: no-git-ops config (GH#593) - bd config set no-git-ops true for manual git control", + "BREAKING: Ephemeral API rename - Wisp→Ephemeral: JSON 'wisp'→'ephemeral', bd wisp→bd ephemeral", + "NEW: bd gate create/show/list/close/wait - Async coordination primitives for agent workflows", + "NEW: bd gate eval - Evaluate timer gates and GitHub gates (gh:run, gh:pr, mail)", + "NEW: bd gate approve - Human gate approval command", + "NEW: bd close --suggest-next - Show newly unblocked issues after close", + "NEW: bd ready/blocked --parent - Scope by epic or parent bead", + "NEW: TOML support for formulas - .formula.toml files alongside JSON", + "NEW: Fork repo auto-detection - Offer to configure .git/info/exclude", + "NEW: Control flow operators - loop and gate operators for formula composition", + "NEW: Aspect composition - Cross-cutting concerns via aspects field in formulas", + "NEW: Runtime expansion - on_complete and for-each dynamic step generation", + "NEW: bd formula list/show - Discover and inspect available formulas", + "NEW: bd mol stale - Detect complete-but-unclosed molecules", + "NEW: Stale molecules check in bd doctor - Proactive detection", + "NEW: Distinct ID prefixes - bd-proto-xxx, bd-mol-xxx, bd-wisp-xxx", + "NEW: no-git-ops config - bd config set no-git-ops true for manual git control", "NEW: beads-release formula - 18-step molecular workflow for version releases", "CHANGED: Formula format YAML→JSON - Formulas now use .formula.json extension", "CHANGED: bd mol run removed - Orchestration moved to gt commands", - "CHANGED: Wisp architecture simplified (bd-bkul) - Single DB with Wisp=true flag", - "FIX: Gate await fields preserved during upsert (bd-gr4q) - Multirepo sync fix", + "CHANGED: Wisp architecture simplified - Single DB with Wisp=true flag", + "FIX: Gate await fields preserved during upsert - Multirepo sync fix", "FIX: Tombstones retain closed_at timestamp - Preserves close time in soft deletes", - "FIX: Git detection caching (bd-7di) - Eliminates worktree slowness", - "FIX: installed_plugins.json v2 format (GH#741) - bd doctor handles new Claude Code format", - "FIX: git.IsWorktree() hang on Windows (GH#727) - bd init no longer hangs outside git repos", - "FIX: Skill files deleted by bd sync (GH#738) - .claude/ files now preserved", - "FIX: doctor false positives (GH#709) - Skips interactions.jsonl and molecules.jsonl", - "FIX: bd sync commits non-.beads files (bd-trgb) - Now only commits .beads/ directory", - "FIX: Aspect self-matching recursion (gt-8tmz.16) - Prevents infinite loops", - "FIX: Map expansion nested matching (gt-8tmz.33) - Correctly matches child steps", - "FIX: Content-level merge for divergence (bd-kpy) - Better conflict resolution", - "FIX: Windows MCP graceful fallback (GH#387) - Daemon mode on Windows", - "FIX: Windows npm postinstall file locking (GH#670) - Install reliability", + "FIX: Git detection caching - Eliminates worktree slowness", + "FIX: installed_plugins.json v2 format - bd doctor handles new Claude Code format", + "FIX: git.IsWorktree() hang on Windows - bd init no longer hangs outside git repos", + "FIX: Skill files deleted by bd sync - .claude/ files now preserved", + "FIX: doctor false positives - Skips interactions.jsonl and molecules.jsonl", + "FIX: bd sync commits non-.beads files - Now only commits .beads/ directory", + "FIX: Aspect self-matching recursion - Prevents infinite loops", + "FIX: Map expansion nested matching - Correctly matches child steps", + "FIX: Content-level merge for divergence - Better conflict resolution", + "FIX: Windows MCP graceful fallback - Daemon mode on Windows", + "FIX: Windows npm postinstall file locking - Install reliability", }, }, { Version: "0.36.0", Date: "2025-12-24", Changes: []string{ - "NEW: Formula system (bd-weu8, bd-wa2l) - bd cook for declarative workflow templates", - "NEW: Gate issue type (bd-udsi) - bd gate create/open/close for async coordination", + "NEW: Formula system - bd cook for declarative workflow templates", + "NEW: Gate issue type - bd gate create/open/close for async coordination", "NEW: bd list --pretty --watch - Built-in colorized viewer with live updates", "NEW: bd search --after/--before/--priority/--content - Enhanced search filters", "NEW: bd compact --prune - Standalone tombstone pruning", "NEW: bd export --priority - Exact priority filter for exports", - "NEW: --resolution alias for --reason on bd close (GH#721)", - "NEW: Config-based close hooks (bd-g4b4) - Custom scripts on issue close", - "CHANGED: bd mol spawn removed (bd-8y9t) - Use bd pour/bd wisp create only", - "CHANGED: bd ready excludes workflow types by default (gt-7xtn)", - "FIX: Child→parent deps now blocked (bd-nim5) - Prevents LLM temporal reasoning trap", - "FIX: Dots in prefix handling (GH#664) - my.project prefixes work correctly", - "FIX: Child counter updates (GH#728) - Explicit child IDs update counters", - "FIX: Comment timestamps preserved during import (#735)", - "FIX: sync.remote config respected in daemon (#736)", - "FIX: Multi-hyphen prefixes (GH#422) - my-project-name works correctly", - "FIX: Stealth mode uses .git/info/exclude (GH#704) - Truly local", - "FIX: MCP output_schema=None for Claude Code (bd-49kw)", + "NEW: --resolution alias for --reason on bd close", + "NEW: Config-based close hooks - Custom scripts on issue close", + "CHANGED: bd mol spawn removed - Use bd pour/bd wisp create only", + "CHANGED: bd ready excludes workflow types by default", + "FIX: Child→parent deps now blocked - Prevents LLM temporal reasoning trap", + "FIX: Dots in prefix handling - my.project prefixes work correctly", + "FIX: Child counter updates - Explicit child IDs update counters", + "FIX: Comment timestamps preserved during import", + "FIX: sync.remote config respected in daemon", + "FIX: Multi-hyphen prefixes - my-project-name works correctly", + "FIX: Stealth mode uses .git/info/exclude - Truly local", + "FIX: MCP output_schema=None for Claude Code", "IMPROVED: Test coverage - daemon 72%, compact 82%, setup 54%", }, }, @@ -425,20 +425,20 @@ var versionChanges = []VersionChange{ Version: "0.35.0", Date: "2025-12-23", Changes: []string{ - "NEW: bd activity command - Real-time state feed for molecule monitoring (bd-xo1o.3)", - "NEW: Dynamic molecule bonding - bd mol bond --ref attaches protos at runtime (bd-xo1o.1)", - "NEW: waits-for dependency type - Fanout gates for parallel step coordination (bd-xo1o.2)", - "NEW: Parallel step detection - Molecules auto-detect parallelizable steps (bd-xo1o.4)", - "NEW: bd list --parent flag - Filter issues by parent (bd-yqhh)", - "NEW: Molecule navigation - bd mol next/prev/current for step traversal (bd-sal9, bd-ieyy)", - "NEW: Entity tracking types - Creator and Validations fields for work attribution (bd-7pwh)", - "IMPROVED: bd doctor --fix replaces manual commands (GH#715)", - "IMPROVED: bd dep tree shows external dependencies (bd-vks2, bd-mv6h, bd-d9mu)", - "IMPROVED: Performance indexes for large databases (bd-bha9, bd-a9y3, bd-jke6, bd-8x3w, bd-lk39)", - "FIX: Rich mutation events emitted for status changes (bd-313v)", - "FIX: External deps filtered from GetBlockedIssues (bd-396j)", - "FIX: bd create -f works with daemon mode (GH#719)", - "FIX: Parallel execution migration race conditions (GH#720)", + "NEW: bd activity command - Real-time state feed for molecule monitoring", + "NEW: Dynamic molecule bonding - bd mol bond --ref attaches protos at runtime", + "NEW: waits-for dependency type - Fanout gates for parallel step coordination", + "NEW: Parallel step detection - Molecules auto-detect parallelizable steps", + "NEW: bd list --parent flag - Filter issues by parent", + "NEW: Molecule navigation - bd mol next/prev/current for step traversal", + "NEW: Entity tracking types - Creator and Validations fields for work attribution", + "IMPROVED: bd doctor --fix replaces manual commands", + "IMPROVED: bd dep tree shows external dependencies", + "IMPROVED: Performance indexes for large databases", + "FIX: Rich mutation events emitted for status changes", + "FIX: External deps filtered from GetBlockedIssues", + "FIX: bd create -f works with daemon mode", + "FIX: Parallel execution migration race conditions", }, }, { @@ -456,8 +456,8 @@ var versionChanges = []VersionChange{ Version: "0.33.2", Date: "2025-12-21", Changes: []string{ - "FIX: P0 priority preserved - omitempty removed from Priority field (GH#671)", - "FIX: nil pointer check in markdown parsing (GH#674)", + "FIX: P0 priority preserved - omitempty removed from Priority field", + "FIX: nil pointer check in markdown parsing", "CHORE: Remove dead deprecated wrapper functions from deletion_tracking.go", }, }, @@ -474,22 +474,22 @@ var versionChanges = []VersionChange{ Version: "0.33.0", Date: "2025-12-21", Changes: []string{ - "NEW: Wisp molecules (bd-2vh3) - use 'bd wisp create' for ephemeral wisps", + "NEW: Wisp molecules - use 'bd wisp create' for ephemeral wisps", "NEW: Wisp issues live only in SQLite, never export to JSONL (prevents zombie resurrection)", "NEW: Use 'bd pour' for persistent mols, 'bd wisp create' for ephemeral wisps", "NEW: bd mol squash compresses wisp children into digest issue", "NEW: --summary flag on bd mol squash for agent-provided AI summaries", - "FIX: DeleteIssue now cascades to comments table (bd-687g)", + "FIX: DeleteIssue now cascades to comments table", }, }, { Version: "0.32.1", Date: "2025-12-21", Changes: []string{ - "NEW: MCP output control params (PR#667) - brief, brief_deps, fields, max_description_length", + "NEW: MCP output control params - brief, brief_deps, fields, max_description_length", "NEW: MCP filtering params - labels, labels_any, query, unassigned, sort_policy", "NEW: BriefIssue, BriefDep, OperationResult models for 97% context reduction", - "FIX: Pin field not in allowed update fields (gt-zr0a) - bd update --pinned now works", + "FIX: Pin field not in allowed update fields - bd update --pinned now works", }, }, { @@ -499,34 +499,34 @@ var versionChanges = []VersionChange{ "REMOVED: bd mail commands (send, inbox, read, ack, reply) - Mail is orchestration, not data plane", "NOTE: Data model unchanged - type=message, Sender, Ephemeral, replies_to fields remain", "NOTE: Orchestration tools should implement mail UI on top of beads data model", - "FIX: Symlink preservation in atomicWriteFile (PR#665) - bd setup no longer clobbers nix/home-manager configs", - "FIX: Broken link to LABELS.md in examples (GH#666)", + "FIX: Symlink preservation in atomicWriteFile - bd setup no longer clobbers nix/home-manager configs", + "FIX: Broken link to LABELS.md in examples", }, }, { Version: "0.31.0", Date: "2025-12-20", Changes: []string{ - "NEW: bd defer/bd undefer commands - Deferred status for icebox issues (bd-4jr)", - "NEW: Agent audit trail - .beads/interactions.jsonl with bd audit record/label (GH#649)", - "NEW: Directory-aware label scoping for monorepos (GH#541) - Auto-filter by directory.labels config", + "NEW: bd defer/bd undefer commands - Deferred status for icebox issues", + "NEW: Agent audit trail - .beads/interactions.jsonl with bd audit record/label", + "NEW: Directory-aware label scoping for monorepos - Auto-filter by directory.labels config", "NEW: Molecules catalog - Templates in separate molecules.jsonl with hierarchical loading", - "NEW: Git commit config - git.author and git.no-gpg-sign options (GH#600)", - "NEW: create.require-description config option (GH#596)", - "CHANGED: bd stats merged into bd status (GH#644) - stats is now alias, colorized output", - "CHANGED: Thin hook shims (GH#615) - Hooks delegate to bd hooks run, no more version drift", + "NEW: Git commit config - git.author and git.no-gpg-sign options", + "NEW: create.require-description config option", + "CHANGED: bd stats merged into bd status - stats is now alias, colorized output", + "CHANGED: Thin hook shims - Hooks delegate to bd hooks run, no more version drift", "CHANGED: MCP context tool consolidation - set_context/where_am_i/init merged into single context tool", - "FIX: relates-to excluded from cycle detection (GH#661)", - "FIX: Doctor checks .local_version instead of deprecated LastBdVersion (GH#662)", - "FIX: Read-only gitignore in stealth mode prints manual instructions (GH#663)", + "FIX: relates-to excluded from cycle detection", + "FIX: Doctor checks .local_version instead of deprecated LastBdVersion", + "FIX: Read-only gitignore in stealth mode prints manual instructions", }, }, { Version: "0.30.7", Date: "2025-12-19", Changes: []string{ - "FIX: bd graph no longer crashes with nil pointer on epics (fixes #657)", - "FIX: Windows npm installer no longer fails with file lock error (fixes #652)", + "FIX: bd graph no longer crashes with nil pointer on epics", + "FIX: Windows npm installer no longer fails with file lock error", "NEW: Version Bump molecule template for repeatable release workflows", }, }, @@ -534,9 +534,9 @@ var versionChanges = []VersionChange{ Version: "0.30.6", Date: "2025-12-18", Changes: []string{ - "bd graph command shows dependency counts using subgraph formatting (bd-6v2)", + "bd graph command shows dependency counts using subgraph formatting", "types.StatusPinned for persistent beads that survive cleanup", - "CRITICAL: Fixed dependency resurrection bug in 3-way merge (bd-ndye) - removals now win", + "CRITICAL: Fixed dependency resurrection bug in 3-way merge - removals now win", }, }, { @@ -552,7 +552,7 @@ var versionChanges = []VersionChange{ Version: "0.30.4", Date: "2025-12-18", Changes: []string{ - "bd template instantiate (bd-r6a.2) - Create beads issues from Beads templates", + "bd template instantiate - Create beads issues from Beads templates", "--assignee flag for template instantiate - Auto-assign during instantiation", "bd mail inbox --identity fix - Now properly filters by identity parameter", "Orphan detection fixes - No longer warns about closed issues or tombstones", @@ -563,82 +563,82 @@ var versionChanges = []VersionChange{ Version: "0.30.3", Date: "2025-12-17", Changes: []string{ - "SECURITY: Data loss race condition fixed (bd-b6xo) - Removed unsafe ClearDirtyIssues() method", - "Stale database warning (bd-2q6d) - Commands now warn when DB is out of sync with JSONL", - "Staleness check error handling improved (bd-n4td, bd-o4qy) - Proper warnings on check failures", + "SECURITY: Data loss race condition fixed - Removed unsafe ClearDirtyIssues() method", + "Stale database warning - Commands now warn when DB is out of sync with JSONL", + "Staleness check error handling improved - Proper warnings on check failures", }, }, { Version: "0.30.2", Date: "2025-12-16", Changes: []string{ - "bd setup droid (GH#598) - Factory.ai (Droid) IDE support", - "Messaging schema fields (bd-kwro.1) - New 'message' issue type, sender/wisp/replies_to/relates_to/duplicate_of/superseded_by fields", + "bd setup droid - Factory.ai (Droid) IDE support", + "Messaging schema fields - New 'message' issue type, sender/wisp/replies_to/relates_to/duplicate_of/superseded_by fields", "New dependency types: replies-to, relates-to, duplicates, supersedes", - "Windows build fixes (GH#585) - gosec lint errors resolved", + "Windows build fixes - gosec lint errors resolved", "Issue ID prefix extraction fix - Word-like suffixes now parse correctly", - "Legacy deletions.jsonl code removed (bd-fom) - Fully migrated to inline tombstones", + "Legacy deletions.jsonl code removed - Fully migrated to inline tombstones", }, }, { Version: "0.30.1", Date: "2025-12-16", Changes: []string{ - "bd reset command (GH#505) - Complete beads removal from a repository", - "bd update --type flag (GH#522) - Change issue type after creation", - "bd q silent mode (GH#540) - Quick-capture without output for scripting", - "bd show displays dependent issue status (GH#583) - Shows status for blocked-by/blocking issues", + "bd reset command - Complete beads removal from a repository", + "bd update --type flag - Change issue type after creation", + "bd q silent mode - Quick-capture without output for scripting", + "bd show displays dependent issue status - Shows status for blocked-by/blocking issues", "claude.local.md support - Local-only documentation, gitignored by default", - "Auto-disable daemon in git worktrees (GH#567) - Prevents database conflicts", - "Inline tombstones for soft-delete (bd-vw8) - Deleted issues become tombstones in issues.jsonl", - "bd migrate-tombstones command (bd-8f9) - Converts legacy deletions.jsonl to inline tombstones", - "Enhanced Git Worktree Support (bd-737) - Shared .beads database across worktrees", + "Auto-disable daemon in git worktrees - Prevents database conflicts", + "Inline tombstones for soft-delete - Deleted issues become tombstones in issues.jsonl", + "bd migrate-tombstones command - Converts legacy deletions.jsonl to inline tombstones", + "Enhanced Git Worktree Support - Shared .beads database across worktrees", }, }, { Version: "0.30.0", Date: "2025-12-15", Changes: []string{ - "TOMBSTONE ARCHITECTURE - Deleted issues become inline tombstones in issues.jsonl (bd-vw8)", - "bd migrate-tombstones - Convert legacy deletions.jsonl to inline tombstones (bd-8f9)", - "bd doctor tombstone health checks - Detects orphaned/expired tombstones (bd-s3v)", - "Git Worktree Support (bd-737) - Shared database across worktrees, worktree-aware hooks", - "MCP Context Engineering (GH #481) - 80-90% context reduction for MCP responses", - "bd thanks command (GH #555) - List contributors to your project", - "BD_NO_INSTALL_HOOKS env var (GH #500) - Disable automatic git hook installation", - "Claude Code skill marketplace (GH #468) - Install beads skill via marketplace", - "Daemon delete auto-sync (GH #528, #537) - Delete operations trigger auto-sync", - "close_reason persistence (GH #551) - Close reasons now saved to database on close", - "JSONL-only mode improvements (GH #549) - GetReadyWork/GetBlockedIssues for memory storage", - "Lock file improvements (GH #484, #555) - Fast fail on stale locks, 98% test coverage", + "TOMBSTONE ARCHITECTURE - Deleted issues become inline tombstones in issues.jsonl", + "bd migrate-tombstones - Convert legacy deletions.jsonl to inline tombstones", + "bd doctor tombstone health checks - Detects orphaned/expired tombstones", + "Git Worktree Support - Shared database across worktrees, worktree-aware hooks", + "MCP Context Engineering - 80-90% context reduction for MCP responses", + "bd thanks command - List contributors to your project", + "BD_NO_INSTALL_HOOKS env var - Disable automatic git hook installation", + "Claude Code skill marketplace - Install beads skill via marketplace", + "Daemon delete auto-sync - Delete operations trigger auto-sync", + "close_reason persistence - Close reasons now saved to database on close", + "JSONL-only mode improvements - GetReadyWork/GetBlockedIssues for memory storage", + "Lock file improvements - Fast fail on stale locks, 98% test coverage", }, }, { Version: "0.29.0", Date: "2025-12-03", Changes: []string{ - "--estimate flag for bd create/update (GH #443) - Add time estimates to issues in minutes", + "--estimate flag for bd create/update - Add time estimates to issues in minutes", "bd doctor improvements - SQLite integrity check, config validation, stale sync branch detection", - "bd doctor --output flag (bd-9cc) - Export diagnostics to file for sharing/debugging", - "bd doctor --dry-run flag (bd-qn5) - Preview fixes without applying them", - "bd doctor per-fix confirmation mode (bd-3xl) - Approve each fix individually", - "--readonly flag (bd-ymo) - Read-only mode for worker sandboxes", - "bd sync safety improvements - Auto-push after merge, diverged history handling (bd-3s8)", - "Auto-resolve merge conflicts deterministically (bd-6l8) - All field conflicts resolved without prompts", - "3-char all-letter base36 hash support (GH #446) - Fixes prefix extraction edge case", + "bd doctor --output flag - Export diagnostics to file for sharing/debugging", + "bd doctor --dry-run flag - Preview fixes without applying them", + "bd doctor per-fix confirmation mode - Approve each fix individually", + "--readonly flag - Read-only mode for worker sandboxes", + "bd sync safety improvements - Auto-push after merge, diverged history handling", + "Auto-resolve merge conflicts deterministically - All field conflicts resolved without prompts", + "3-char all-letter base36 hash support - Fixes prefix extraction edge case", }, }, { Version: "0.28.0", Date: "2025-12-01", Changes: []string{ - "bd daemon --local flag (#433) - Run daemon without git operations for multi-repo/worktree setups", + "bd daemon --local flag - Run daemon without git operations for multi-repo/worktree setups", "bd daemon --foreground flag - Run in foreground for systemd/supervisord integration", - "bd migrate-sync command (bd-epn) - Migrate to sync.branch workflow for cleaner main branch", - "Database migration: close_reason column (bd-uyu) - Fixes sync loops with close_reason", - "Multi-repo prefix filtering (GH #437) - Issues filtered by prefix when flushing from non-primary repos", - "Parent-child dependency UX (GH #440) - Fixed documentation and UI labels for dependencies", - "sync.branch workflow fixes (bd-epn) - Fixed .beads/ restoration and doctor detection", + "bd migrate-sync command - Migrate to sync.branch workflow for cleaner main branch", + "Database migration: close_reason column - Fixes sync loops with close_reason", + "Multi-repo prefix filtering - Issues filtered by prefix when flushing from non-primary repos", + "Parent-child dependency UX - Fixed documentation and UI labels for dependencies", + "sync.branch workflow fixes - Fixed .beads/ restoration and doctor detection", "Jira API migration - Updated from deprecated v2 to v3 API", }, }, @@ -646,10 +646,10 @@ var versionChanges = []VersionChange{ Version: "0.27.2", Date: "2025-11-30", Changes: []string{ - "CRITICAL: Mass database deletion protection - Safety guard prevents purging entire DB on JSONL reset (bd-t5m)", - "Fresh Clone Initialization - bd init auto-detects prefix from existing JSONL, works without --prefix flag (bd-4h9)", - "3-Character Hash Support - ExtractIssuePrefix now handles base36 hashes 3+ chars (#425)", - "Import Warnings - New warning when issues skipped due to deletions manifest (bd-4zy)", + "CRITICAL: Mass database deletion protection - Safety guard prevents purging entire DB on JSONL reset", + "Fresh Clone Initialization - bd init auto-detects prefix from existing JSONL, works without --prefix flag", + "3-Character Hash Support - ExtractIssuePrefix now handles base36 hashes 3+ chars", + "Import Warnings - New warning when issues skipped due to deletions manifest", }, }, { @@ -661,7 +661,7 @@ var versionChanges = []VersionChange{ "Contributor Fork Workflows - `bd init --contributor` auto-configures sync.remote=upstream", "Git Worktree Support - Full support for worktrees in hooks and detection", "CRITICAL: Sync corruption prevention - Hash-based staleness + reverse ZFC checks", - "Out-of-Order Dependencies (#414) - JSONL import handles deps before targets exist", + "Out-of-Order Dependencies - JSONL import handles deps before targets exist", "--from-main defaults to noGitHistory=true - Prevents spurious deletions", "bd sync --squash - Batch multiple sync commits into one", "Fresh Clone Detection - bd doctor suggests 'bd init' when JSONL exists but no DB", @@ -674,9 +674,9 @@ var versionChanges = []VersionChange{ "bd doctor --check-health - Lightweight health checks for startup hooks (exit 0 on success)", "--no-git-history flag - Prevent spurious deletions when git history is unreliable", "gh2jsonl --id-mode hash - Hash-based ID generation for GitHub imports", - "MCP Protocol Fix (PR #400) - Subprocess stdin no longer breaks MCP JSON-RPC", - "Git Worktree Staleness Fix (#399) - Staleness check works after writes in worktrees", - "Multi-Part Prefix Support (#398) - Handles prefixes like 'my-app-123' correctly", + "MCP Protocol Fix - Subprocess stdin no longer breaks MCP JSON-RPC", + "Git Worktree Staleness Fix - Staleness check works after writes in worktrees", + "Multi-Part Prefix Support - Handles prefixes like 'my-app-123' correctly", "bd sync Commit Scope Fixed - Only commits .beads/ files, not other staged files", }, }, @@ -687,7 +687,7 @@ var versionChanges = []VersionChange{ "Zombie Resurrection Prevention - Stale clones can no longer resurrect deleted issues", "bd sync commit scope fixed - Now commits entire .beads/ directory before pull", "bd prime ephemeral branch detection - Auto-detects ephemeral branches and adjusts workflow", - "JSONL Canonicalization (bd-6xd) - Default JSONL filename is now issues.jsonl; legacy beads.jsonl still supported", + "JSONL Canonicalization - Default JSONL filename is now issues.jsonl; legacy beads.jsonl still supported", }, }, { diff --git a/cmd/bd/init.go b/cmd/bd/init.go index 5f08ebb8..aa3ac1e1 100644 --- a/cmd/bd/init.go +++ b/cmd/bd/init.go @@ -54,7 +54,7 @@ With --stealth: configures per-repository git settings for invisible beads usage // Non-fatal - continue with defaults } - // Safety guard: check for existing JSONL with issues (bd-emg) + // Safety guard: check for existing JSONL with issues // This prevents accidental re-initialization in fresh clones if !force { if err := checkExistingBeadsData(prefix); err != nil { @@ -285,7 +285,7 @@ With --stealth: configures per-repository git settings for invisible beads usage } // Set sync.branch: use explicit --branch flag, or auto-detect current branch - // This ensures bd sync --status works after bd init (bd-flil) + // This ensures bd sync --status works after bd init if branch == "" && isGitRepo() { // Auto-detect current branch if not specified currentBranch, err := getGitBranch() @@ -479,7 +479,7 @@ With --stealth: configures per-repository git settings for invisible beads usage fmt.Printf(" Issues will be named: %s\n\n", ui.RenderAccent(prefix+"- (e.g., "+prefix+"-a3f2dd)")) fmt.Printf("Run %s to get started.\n\n", ui.RenderAccent("bd quickstart")) - // Run bd doctor diagnostics to catch setup issues early (bd-zwtq) + // Run bd doctor diagnostics to catch setup issues early doctorResult := runDiagnostics(cwd) // Check if there are any warnings or errors (not just critical failures) hasIssues := false diff --git a/cmd/bd/integrity.go b/cmd/bd/integrity.go index 1bdbdbc5..b33830d4 100644 --- a/cmd/bd/integrity.go +++ b/cmd/bd/integrity.go @@ -20,11 +20,11 @@ import ( // isJSONLNewer checks if JSONL file is newer than database file. // Returns true if JSONL is newer AND has different content, false otherwise. -// This prevents false positives from daemon auto-export timestamp skew (bd-lm2q). +// This prevents false positives from daemon auto-export timestamp skew. // // NOTE: This uses computeDBHash which is more expensive than hasJSONLChanged. // For daemon auto-import, prefer hasJSONLChanged() which uses metadata-based -// content tracking and is safe against git operations (bd-khnb). +// content tracking and is safe against git operations. func isJSONLNewer(jsonlPath string) bool { return isJSONLNewerWithStore(jsonlPath, nil) } @@ -97,16 +97,16 @@ func computeJSONLHash(jsonlPath string) (string, error) { // unchanged) while still catching git operations that restore old content with new mtimes. // // In multi-repo mode, keySuffix should be the stable repo identifier (e.g., ".", "../frontend"). -// The keySuffix must not contain the ':' separator character (bd-ar2.12). +// The keySuffix must not contain the ':' separator character. func hasJSONLChanged(ctx context.Context, store storage.Storage, jsonlPath string, keySuffix string) bool { - // Validate keySuffix doesn't contain the separator character (bd-ar2.12) + // Validate keySuffix doesn't contain the separator character if keySuffix != "" && strings.Contains(keySuffix, ":") { // Invalid keySuffix - treat as changed to trigger proper error handling return true } - // Build metadata keys with optional suffix for per-repo tracking (bd-ar2.10, bd-ar2.11) - // Renamed from last_import_hash to jsonl_content_hash (bd-39o) - more accurate name + // Build metadata keys with optional suffix for per-repo tracking + // Renamed from last_import_hash to jsonl_content_hash - more accurate name // since this hash is updated on both import AND export hashKey := "jsonl_content_hash" oldHashKey := "last_import_hash" // Migration: check old key if new key missing @@ -115,7 +115,7 @@ func hasJSONLChanged(ctx context.Context, store storage.Storage, jsonlPath strin oldHashKey += ":" + keySuffix } - // Always compute content hash (bd-v0y fix) + // Always compute content hash // Previous mtime-based fast-path was unsafe: git operations (pull, checkout, rebase) // can change file content without updating mtime, causing false negatives. // Hash computation is fast enough for sync operations (~10-50ms even for large DBs). @@ -128,7 +128,7 @@ func hasJSONLChanged(ctx context.Context, store storage.Storage, jsonlPath strin // Get content hash from metadata (try new key first, fall back to old for migration) lastHash, err := store.GetMetadata(ctx, hashKey) if err != nil || lastHash == "" { - // Try old key for migration (bd-39o) + // Try old key for migration lastHash, err = store.GetMetadata(ctx, oldHashKey) if err != nil || lastHash == "" { // No previous hash - this is the first run or metadata is missing @@ -145,8 +145,8 @@ func hasJSONLChanged(ctx context.Context, store storage.Storage, jsonlPath strin // Returns error if critical issues found that would cause data loss. func validatePreExport(ctx context.Context, store storage.Storage, jsonlPath string) error { // Check if JSONL content has changed since last import - if so, must import first - // Uses content-based detection (bd-xwo fix) instead of mtime-based to avoid false positives from git operations - // Use getRepoKeyForPath to get stable repo identifier for multi-repo support (bd-ar2.10, bd-ar2.11) + // Uses content-based detection instead of mtime-based to avoid false positives from git operations + // Use getRepoKeyForPath to get stable repo identifier for multi-repo support repoKey := getRepoKeyForPath(jsonlPath) if hasJSONLChanged(ctx, store, jsonlPath, repoKey) { return fmt.Errorf("refusing to export: JSONL content has changed since last import (import first to avoid data loss)") @@ -180,7 +180,7 @@ func validatePreExport(ctx context.Context, store storage.Storage, jsonlPath str return fmt.Errorf("refusing to export empty DB over %d issues in JSONL (would cause data loss)", jsonlCount) } - // Note: The main bd-53c protection is the reverse ZFC check in sync.go + // Note: The main protection is the reverse ZFC check in sync.go // which runs BEFORE this validation. Here we only block empty DB. // This allows legitimate deletions while sync.go catches stale DBs. diff --git a/cmd/bd/label.go b/cmd/bd/label.go index 30805f0e..a56fcbfd 100644 --- a/cmd/bd/label.go +++ b/cmd/bd/label.go @@ -99,7 +99,7 @@ var labelAddCmd = &cobra.Command{ } issueIDs = resolvedIDs - // Protect reserved label namespaces (bd-eijl) + // Protect reserved label namespaces // provides:* labels can only be added via 'bd ship' command if strings.HasPrefix(label, "provides:") { FatalErrorRespectJSON("'provides:' labels are reserved for cross-project capabilities. Hint: use 'bd ship %s' instead", strings.TrimPrefix(label, "provides:")) diff --git a/cmd/bd/list.go b/cmd/bd/list.go index 4bec2518..d75136ae 100644 --- a/cmd/bd/list.go +++ b/cmd/bd/list.go @@ -44,7 +44,7 @@ func parseTimeFlag(s string) (time.Time, error) { return time.Time{}, fmt.Errorf("unable to parse time %q (try formats: 2006-01-02, 2006-01-02T15:04:05, or RFC3339)", s) } -// pinIndicator returns a pushpin emoji prefix for pinned issues (bd-18b, bd-7h5) +// pinIndicator returns a pushpin emoji prefix for pinned issues func pinIndicator(issue *types.Issue) string { if issue.Pinned { return "📌 " @@ -346,14 +346,14 @@ var listCmd = &cobra.Command{ priorityMinStr, _ := cmd.Flags().GetString("priority-min") priorityMaxStr, _ := cmd.Flags().GetString("priority-max") - // Pinned filtering flags (bd-p8e) + // Pinned filtering flags pinnedFlag, _ := cmd.Flags().GetBool("pinned") noPinnedFlag, _ := cmd.Flags().GetBool("no-pinned") - // Template filtering (beads-1ra) + // Template filtering includeTemplates, _ := cmd.Flags().GetBool("include-templates") - // Parent filtering (bd-yqhh) + // Parent filtering parentID, _ := cmd.Flags().GetString("parent") // Pretty and watch flags (GH#654) @@ -508,7 +508,7 @@ var listCmd = &cobra.Command{ filter.PriorityMax = &priorityMax } - // Pinned filtering (bd-p8e): --pinned and --no-pinned are mutually exclusive + // Pinned filtering: --pinned and --no-pinned are mutually exclusive if pinnedFlag && noPinnedFlag { fmt.Fprintf(os.Stderr, "Error: --pinned and --no-pinned are mutually exclusive\n") os.Exit(1) @@ -521,19 +521,19 @@ var listCmd = &cobra.Command{ filter.Pinned = &pinned } - // Template filtering (beads-1ra): exclude templates by default + // Template filtering: exclude templates by default // Use --include-templates to show all issues including templates if !includeTemplates { isTemplate := false filter.IsTemplate = &isTemplate } - // Parent filtering (bd-yqhh): filter children by parent issue + // Parent filtering: filter children by parent issue if parentID != "" { filter.ParentID = &parentID } - // Check database freshness before reading (bd-2q6d, bd-c4rq) + // Check database freshness before reading // Skip check when using daemon (daemon auto-imports on staleness) ctx := rootCtx if daemonClient == nil { @@ -608,13 +608,13 @@ var listCmd = &cobra.Command{ listArgs.PriorityMin = filter.PriorityMin listArgs.PriorityMax = filter.PriorityMax - // Pinned filtering (bd-p8e) + // Pinned filtering listArgs.Pinned = filter.Pinned - // Template filtering (beads-1ra) + // Template filtering listArgs.IncludeTemplates = includeTemplates - // Parent filtering (bd-yqhh) + // Parent filtering listArgs.ParentID = parentID resp, err := daemonClient.List(listArgs) @@ -634,7 +634,7 @@ var listCmd = &cobra.Command{ return } - // Show upgrade notification if needed (bd-loka) + // Show upgrade notification if needed maybeShowUpgradeNotification() var issues []*types.Issue @@ -781,7 +781,7 @@ var listCmd = &cobra.Command{ return } - // Show upgrade notification if needed (bd-loka) + // Show upgrade notification if needed maybeShowUpgradeNotification() // Load labels in bulk for display @@ -896,14 +896,14 @@ func init() { listCmd.Flags().String("priority-min", "", "Filter by minimum priority (inclusive, 0-4 or P0-P4)") listCmd.Flags().String("priority-max", "", "Filter by maximum priority (inclusive, 0-4 or P0-P4)") - // Pinned filtering (bd-p8e) + // Pinned filtering listCmd.Flags().Bool("pinned", false, "Show only pinned issues") listCmd.Flags().Bool("no-pinned", false, "Exclude pinned issues") - // Template filtering (beads-1ra): exclude templates by default + // Template filtering: exclude templates by default listCmd.Flags().Bool("include-templates", false, "Include template molecules in output") - // Parent filtering (bd-yqhh): filter children by parent issue + // Parent filtering: filter children by parent issue listCmd.Flags().String("parent", "", "Filter by parent issue ID (shows children of specified issue)") // Pretty and watch flags (GH#654) diff --git a/cmd/bd/main.go b/cmd/bd/main.go index 7da78394..9cba8680 100644 --- a/cmd/bd/main.go +++ b/cmd/bd/main.go @@ -83,10 +83,10 @@ var ( flushFailureCount = 0 // Consecutive flush failures lastFlushError error // Last flush error for debugging - // Auto-flush manager (event-driven, fixes bd-52 race condition) + // Auto-flush manager (event-driven, fixes race condition) flushManager *FlushManager - // Hook runner for extensibility (bd-kwro.8) + // Hook runner for extensibility hookRunner *hooks.Runner // skipFinalFlush is set by sync command when sync.branch mode completes successfully. @@ -96,7 +96,7 @@ var ( // Auto-import state autoImportEnabled = true // Can be disabled with --no-auto-import - // Version upgrade tracking (bd-loka) + // Version upgrade tracking versionUpgradeDetected = false // Set to true if bd version changed since last run previousVersion = "" // The last bd version user had (empty = first run or unknown) upgradeAcknowledged = false // Set to true after showing upgrade notification once per session @@ -474,7 +474,7 @@ var rootCmd = &cobra.Command{ return } - // Auto-detect sandboxed environment (bd-u3t: Phase 2 for GH #353) + // Auto-detect sandboxed environment (Phase 2 for GH #353) // Only auto-enable if user hasn't explicitly set --sandbox or --no-daemon if !cmd.Flags().Changed("sandbox") && !cmd.Flags().Changed("no-daemon") { if isSandboxed() { @@ -534,7 +534,7 @@ var rootCmd = &cobra.Command{ if foundDB := beads.FindDatabasePath(); foundDB != "" { dbPath = foundDB } else { - // No database found - check if this is JSONL-only mode (bd-5kj) + // No database found - check if this is JSONL-only mode beadsDir := beads.FindBeadsDir() if beadsDir != "" { jsonlPath := filepath.Join(beadsDir, "issues.jsonl") @@ -545,7 +545,7 @@ var rootCmd = &cobra.Command{ jsonlExists = true } - // Use proper YAML parsing to detect no-db mode (bd-r6k2) + // Use proper YAML parsing to detect no-db mode isNoDbMode := isNoDbModeConfigured(beadsDir) // If JSONL-only mode is configured, auto-enable it @@ -571,7 +571,7 @@ var rootCmd = &cobra.Command{ // - import: auto-initializes database if missing // - setup: creates editor integration files (no DB needed) if cmd.Name() != "import" && cmd.Name() != "setup" { - // No database found - provide context-aware error message (bd-534) + // No database found - provide context-aware error message fmt.Fprintf(os.Stderr, "Error: no beads database found\n") // Check if JSONL exists without no-db mode configured @@ -613,7 +613,7 @@ var rootCmd = &cobra.Command{ } } - // Track bd version changes (bd-loka) + // Track bd version changes // Best-effort tracking - failures are silent trackBdVersion() @@ -635,7 +635,7 @@ var rootCmd = &cobra.Command{ noDaemon = true } - // Wisp operations auto-bypass daemon (bd-ta4r) + // Wisp operations auto-bypass daemon // Wisps are ephemeral (Ephemeral=true) and never exported to JSONL, // so daemon can't help anyway. This reduces friction in wisp workflows. if isWispOperation(cmd, args) { @@ -815,7 +815,7 @@ var rootCmd = &cobra.Command{ debug.Logf("using direct mode (reason: %s)", daemonStatus.FallbackReason) } - // Auto-migrate database on version bump (bd-jgxi) + // Auto-migrate database on version bump // Do this AFTER daemon check but BEFORE opening database for main operation // This ensures: 1) no daemon has DB open, 2) we don't open DB twice autoMigrateOnVersionBump(dbPath) @@ -824,7 +824,7 @@ var rootCmd = &cobra.Command{ var err error store, err = sqlite.NewWithTimeout(rootCtx, dbPath, lockTimeout) if err != nil { - // Check for fresh clone scenario (bd-dmb) + // Check for fresh clone scenario beadsDir := filepath.Dir(dbPath) if handleFreshCloneError(err, beadsDir) { os.Exit(1) @@ -838,9 +838,9 @@ var rootCmd = &cobra.Command{ storeActive = true storeMutex.Unlock() - // Initialize flush manager (fixes bd-52: race condition in auto-flush) + // Initialize flush manager (fixes race condition in auto-flush) // Skip FlushManager creation in sandbox mode - no background goroutines needed - // (bd-dh8a: improves Windows exit behavior and container scenarios) + // (improves Windows exit behavior and container scenarios) // For in-process test scenarios where commands run multiple times, // we create a new manager each time. Shutdown() is idempotent so // PostRun can safely shutdown whichever manager is active. @@ -848,7 +848,7 @@ var rootCmd = &cobra.Command{ flushManager = NewFlushManager(autoFlushEnabled, getDebounceDuration()) } - // Initialize hook runner (bd-kwro.8) + // Initialize hook runner // dbPath is .beads/something.db, so workspace root is parent of .beads if dbPath != "" { beadsDir := filepath.Dir(dbPath) @@ -860,8 +860,8 @@ var rootCmd = &cobra.Command{ // Auto-import if JSONL is newer than DB (e.g., after git pull) // Skip for import command itself to avoid recursion - // Skip for delete command to prevent resurrection of deleted issues (bd-8kde) - // Skip if sync --dry-run to avoid modifying DB in dry-run mode (bd-191) + // Skip for delete command to prevent resurrection of deleted issues + // Skip if sync --dry-run to avoid modifying DB in dry-run mode if cmd.Name() != "import" && cmd.Name() != "delete" && autoImportEnabled { // Check if this is sync command with --dry-run flag if cmd.Name() == "sync" { @@ -876,7 +876,7 @@ var rootCmd = &cobra.Command{ } } - // Load molecule templates from hierarchical catalog locations (gt-0ei3) + // Load molecule templates from hierarchical catalog locations // Templates are loaded after auto-import to ensure the database is up-to-date. // Skip for import command to avoid conflicts during import operations. if cmd.Name() != "import" && store != nil { @@ -965,7 +965,7 @@ var rootCmd = &cobra.Command{ // Defaults to 5 seconds if not set or invalid // signalGasTownActivity writes an activity signal for Gas Town daemon. -// This enables exponential backoff based on bd usage detection (gt-ws8ol). +// This enables exponential backoff based on bd usage detection. // Best-effort: silent on any failure, never affects bd operation. func signalGasTownActivity() { // Determine town root diff --git a/cmd/bd/mol_bond.go b/cmd/bd/mol_bond.go index e5d2c1bd..01ede1b0 100644 --- a/cmd/bd/mol_bond.go +++ b/cmd/bd/mol_bond.go @@ -207,7 +207,7 @@ func runMolBond(cmd *cobra.Command, args []string) { } // Resolve both operands - can be issue IDs or formula names - // Formula names are cooked inline to in-memory subgraphs (gt-4v1eo) + // Formula names are cooked inline to in-memory subgraphs subgraphA, cookedA, err := resolveOrCookToSubgraph(ctx, store, args[0]) if err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) @@ -352,7 +352,7 @@ func bondProtoProto(ctx context.Context, s storage.Storage, protoA, protoB *type // For sequential/conditional bonding, add blocking dependency: B blocks on A // Sequential: B runs after A completes (any outcome) - // Conditional: B runs only if A fails (bd-kzda) + // Conditional: B runs only if A fails if bondType == types.BondTypeSequential || bondType == types.BondTypeConditional { depType := types.DepBlocks if bondType == types.BondTypeConditional { @@ -446,7 +446,7 @@ func bondProtoMolWithSubgraph(ctx context.Context, s storage.Storage, protoSubgr err = s.RunInTransaction(ctx, func(tx storage.Transaction) error { // Add dependency from spawned root to molecule // Sequential: use blocks (B runs after A completes) - // Conditional: use conditional-blocks (B runs only if A fails) (bd-kzda) + // Conditional: use conditional-blocks (B runs only if A fails) // Parallel: use parent-child (organizational, no blocking) // Note: Schema only allows one dependency per (issue_id, depends_on_id) pair var depType types.DependencyType @@ -492,7 +492,7 @@ func bondMolMol(ctx context.Context, s storage.Storage, molA, molB *types.Issue, err := s.RunInTransaction(ctx, func(tx storage.Transaction) error { // Add dependency: B links to A // Sequential: use blocks (B runs after A completes) - // Conditional: use conditional-blocks (B runs only if A fails) (bd-kzda) + // Conditional: use conditional-blocks (B runs only if A fails) // Parallel: use parent-child (organizational, no blocking) // Note: Schema only allows one dependency per (issue_id, depends_on_id) pair var depType types.DependencyType @@ -598,7 +598,7 @@ func resolveOrCookToSubgraph(ctx context.Context, s storage.Storage, operand str return nil, false, fmt.Errorf("'%s' not found (not an issue ID or formula name)", operand) } - // Try to cook formula inline to in-memory subgraph (gt-4v1eo) + // Try to cook formula inline to in-memory subgraph subgraph, err := resolveAndCookFormula(operand, nil) if err != nil { return nil, false, fmt.Errorf("'%s' not found as issue or formula: %w", operand, err) diff --git a/cmd/bd/nodb.go b/cmd/bd/nodb.go index 012ac5d4..1b40fb68 100644 --- a/cmd/bd/nodb.go +++ b/cmd/bd/nodb.go @@ -217,7 +217,7 @@ func writeIssuesToJSONL(memStore *memory.MemoryStorage, beadsDir string) error { // Get all issues from memory storage issues := memStore.GetAllIssues() - // Filter out wisps - they should never be exported to JSONL (bd-9avq) + // Filter out wisps - they should never be exported to JSONL // Wisps exist only in SQLite and are shared via .beads/redirect, not JSONL. filtered := make([]*types.Issue, 0, len(issues)) for _, issue := range issues { diff --git a/cmd/bd/pour.go b/cmd/bd/pour.go index fd48a528..2ced6f1a 100644 --- a/cmd/bd/pour.go +++ b/cmd/bd/pour.go @@ -172,7 +172,7 @@ func runPour(cmd *cobra.Command, args []string) { }) } - // Apply variable defaults from formula (gt-4v1eo) + // Apply variable defaults from formula vars = applyVariableDefaults(vars, subgraph) // Check for missing required variables (those without defaults) @@ -225,7 +225,7 @@ func runPour(cmd *cobra.Command, args []string) { } // Spawn as persistent mol (ephemeral=false) - // bd-hobo: Use "mol" prefix for distinct visual recognition + // Use "mol" prefix for distinct visual recognition result, err := spawnMolecule(ctx, store, subgraph, vars, assignee, actor, false, "mol") if err != nil { fmt.Fprintf(os.Stderr, "Error pouring proto: %v\n", err) diff --git a/cmd/bd/ready.go b/cmd/bd/ready.go index 1f96f1b1..dcfee64d 100644 --- a/cmd/bd/ready.go +++ b/cmd/bd/ready.go @@ -54,7 +54,7 @@ This is useful for agents executing molecules to see which steps can run next.`, } filter := types.WorkFilter{ - // Leave Status empty to get both 'open' and 'in_progress' (bd-165) + // Leave Status empty to get both 'open' and 'in_progress' Type: issueType, Limit: limit, Unassigned: unassigned, @@ -112,11 +112,11 @@ This is useful for agents executing molecules to see which steps can run next.`, return } - // Show upgrade notification if needed (bd-loka) + // Show upgrade notification if needed maybeShowUpgradeNotification() if len(issues) == 0 { - // Check if there are any open issues at all (bd-r4n) + // Check if there are any open issues at all statsResp, statsErr := daemonClient.Stats() hasOpenIssues := false if statsErr == nil { @@ -152,7 +152,7 @@ This is useful for agents executing molecules to see which steps can run next.`, // Direct mode ctx := rootCtx - // Check database freshness before reading (bd-2q6d, bd-c4rq) + // Check database freshness before reading // Skip check when using daemon (daemon auto-imports on staleness) if daemonClient == nil { if err := ensureDatabaseFresh(ctx); err != nil { @@ -185,11 +185,11 @@ This is useful for agents executing molecules to see which steps can run next.`, outputJSON(issues) return } - // Show upgrade notification if needed (bd-loka) + // Show upgrade notification if needed maybeShowUpgradeNotification() if len(issues) == 0 { - // Check if there are any open issues at all (bd-r4n) + // Check if there are any open issues at all hasOpenIssues := false if stats, statsErr := store.GetStatistics(ctx); statsErr == nil { hasOpenIssues = stats.OpenIssues > 0 || stats.InProgressIssues > 0 diff --git a/cmd/bd/show.go b/cmd/bd/show.go index 8fad091d..852bd1e8 100644 --- a/cmd/bd/show.go +++ b/cmd/bd/show.go @@ -29,7 +29,7 @@ var showCmd = &cobra.Command{ showThread, _ := cmd.Flags().GetBool("thread") ctx := rootCtx - // Check database freshness before reading (bd-2q6d, bd-c4rq) + // Check database freshness before reading // Skip check when using daemon (daemon auto-imports on staleness) if daemonClient == nil { if err := ensureDatabaseFresh(ctx); err != nil { @@ -121,7 +121,7 @@ var showCmd = &cobra.Command{ details.Dependents, _ = sqliteStore.GetDependentsWithMetadata(ctx, issue.ID) } details.Comments, _ = issueStore.GetIssueComments(ctx, issue.ID) - // Compute parent from dependencies (bd-qket) + // Compute parent from dependencies for _, dep := range details.Dependencies { if dep.DependencyType == types.DepParentChild { details.Parent = &dep.ID @@ -166,7 +166,7 @@ var showCmd = &cobra.Command{ } var details IssueDetails if err := json.Unmarshal(resp.Data, &details); err == nil { - // Compute parent from dependencies (bd-qket) + // Compute parent from dependencies for _, dep := range details.Dependencies { if dep.DependencyType == types.DepParentChild { details.Parent = &dep.ID @@ -397,7 +397,7 @@ var showCmd = &cobra.Command{ } details.Comments, _ = issueStore.GetIssueComments(ctx, issue.ID) - // Compute parent from dependencies (bd-qket) + // Compute parent from dependencies for _, dep := range details.Dependencies { if dep.DependencyType == types.DepParentChild { details.Parent = &dep.ID @@ -766,7 +766,7 @@ var updateCmd = &cobra.Command{ var issue types.Issue if err := json.Unmarshal(resp.Data, &issue); err == nil { - // Run update hook (bd-kwro.8) + // Run update hook if hookRunner != nil { hookRunner.Run(hooks.EventUpdate, &issue) } @@ -788,7 +788,7 @@ var updateCmd = &cobra.Command{ // Direct mode updatedIssues := []*types.Issue{} for _, id := range resolvedIDs { - // Check if issue is a template (beads-1ra): templates are read-only + // Check if issue is a template: templates are read-only issue, err := store.GetIssue(ctx, id) if err != nil { fmt.Fprintf(os.Stderr, "Error getting %s: %v\n", id, err) @@ -831,7 +831,7 @@ var updateCmd = &cobra.Command{ } } - // Handle parent reparenting (bd-cj2e) + // Handle parent reparenting if newParent, ok := updates["parent"].(string); ok { // Validate new parent exists (unless empty string to remove parent) if newParent != "" { @@ -875,7 +875,7 @@ var updateCmd = &cobra.Command{ } } - // Run update hook (bd-kwro.8) + // Run update hook updatedIssue, _ := store.GetIssue(ctx, id) if updatedIssue != nil && hookRunner != nil { hookRunner.Run(hooks.EventUpdate, updatedIssue) @@ -1169,12 +1169,12 @@ var closeCmd = &cobra.Command{ continue } - // Handle response based on whether SuggestNext was requested (GH#679) + // Handle response based on whether SuggestNext was requested if suggestNext { var result rpc.CloseResult if err := json.Unmarshal(resp.Data, &result); err == nil { if result.Closed != nil { - // Run close hook (bd-kwro.8) + // Run close hook if hookRunner != nil { hookRunner.Run(hooks.EventClose, result.Closed) } @@ -1184,7 +1184,7 @@ var closeCmd = &cobra.Command{ } if !jsonOutput { fmt.Printf("%s Closed %s: %s\n", ui.RenderPass("✓"), id, reason) - // Display newly unblocked issues (GH#679) + // Display newly unblocked issues if len(result.Unblocked) > 0 { fmt.Printf("\nNewly unblocked:\n") for _, issue := range result.Unblocked { @@ -1196,7 +1196,7 @@ var closeCmd = &cobra.Command{ } else { var issue types.Issue if err := json.Unmarshal(resp.Data, &issue); err == nil { - // Run close hook (bd-kwro.8) + // Run close hook if hookRunner != nil { hookRunner.Run(hooks.EventClose, &issue) } @@ -1210,7 +1210,7 @@ var closeCmd = &cobra.Command{ } } - // Handle --continue flag in daemon mode (bd-ieyy) + // Handle --continue flag in daemon mode // Note: --continue requires direct database access to walk parent-child chain if continueFlag && len(closedIssues) > 0 { fmt.Fprintf(os.Stderr, "\nNote: --continue requires direct database access\n") @@ -1242,7 +1242,7 @@ var closeCmd = &cobra.Command{ closedCount++ - // Run close hook (bd-kwro.8) + // Run close hook closedIssue, _ := store.GetIssue(ctx, id) if closedIssue != nil && hookRunner != nil { hookRunner.Run(hooks.EventClose, closedIssue) @@ -1257,7 +1257,7 @@ var closeCmd = &cobra.Command{ } } - // Handle --suggest-next flag in direct mode (GH#679) + // Handle --suggest-next flag in direct mode if suggestNext && len(resolvedIDs) == 1 && closedCount > 0 { unblocked, err := store.GetNewlyUnblockedByClose(ctx, resolvedIDs[0]) if err == nil && len(unblocked) > 0 { @@ -1280,7 +1280,7 @@ var closeCmd = &cobra.Command{ markDirtyAndScheduleFlush() } - // Handle --continue flag (bd-ieyy) + // Handle --continue flag if continueFlag && len(resolvedIDs) == 1 && closedCount > 0 { autoClaim := !noAuto result, err := AdvanceToNextStep(ctx, store, resolvedIDs[0], autoClaim, actor) @@ -1587,6 +1587,6 @@ func init() { closeCmd.Flags().BoolP("force", "f", false, "Force close pinned issues") closeCmd.Flags().Bool("continue", false, "Auto-advance to next step in molecule") closeCmd.Flags().Bool("no-auto", false, "With --continue, show next step but don't claim it") - closeCmd.Flags().Bool("suggest-next", false, "Show newly unblocked issues after closing (GH#679)") + closeCmd.Flags().Bool("suggest-next", false, "Show newly unblocked issues after closing") rootCmd.AddCommand(closeCmd) } diff --git a/cmd/bd/slot.go b/cmd/bd/slot.go index 66446b6b..1a14e2ae 100644 --- a/cmd/bd/slot.go +++ b/cmd/bd/slot.go @@ -13,7 +13,7 @@ import ( "github.com/steveyegge/beads/internal/utils" ) -// Valid slot names for agent beads (gt-h5sza) +// Valid slot names for agent beads var validSlots = map[string]bool{ "hook": true, // hook_bead field - current work (0..1) "role": true, // role_bead field - role definition (required) diff --git a/cmd/bd/sync.go b/cmd/bd/sync.go index 21b10d47..1668f6ff 100644 --- a/cmd/bd/sync.go +++ b/cmd/bd/sync.go @@ -59,7 +59,7 @@ Use --merge to merge the sync branch back to main branch.`, noPush = config.GetBool("no-push") } - // bd-sync-corruption fix: Force direct mode for sync operations. + // Force direct mode for sync operations. // This prevents stale daemon SQLite connections from corrupting exports. // If the daemon was running but its database file was deleted and recreated // (e.g., during recovery), the daemon's SQLite connection points to the old @@ -88,7 +88,7 @@ Use --merge to merge the sync branch back to main branch.`, return } - // If check mode, run pre-sync integrity checks (bd-hlsw.1) + // If check mode, run pre-sync integrity checks if checkIntegrity { showSyncIntegrityCheck(ctx, jsonlPath) return @@ -136,7 +136,7 @@ Use --merge to merge the sync branch back to main branch.`, return } - // If squash mode, export to JSONL but skip git operations (bd-o2e) + // If squash mode, export to JSONL but skip git operations // This accumulates changes for a single commit later if squash { if dryRun { @@ -195,11 +195,11 @@ Use --merge to merge the sync branch back to main branch.`, if dryRun { fmt.Println("→ [DRY RUN] Would export pending changes to JSONL") } else { - // ZFC safety check (bd-l0r, bd-53c): if DB significantly diverges from JSONL, + // ZFC safety check: if DB significantly diverges from JSONL, // force import first to sync with JSONL source of truth. // After import, skip export to prevent overwriting JSONL (JSONL is source of truth). // - // bd-53c fix: Added REVERSE ZFC check - if JSONL has MORE issues than DB, + // Added REVERSE ZFC check - if JSONL has MORE issues than DB, // this indicates the DB is stale and exporting would cause data loss. // This catches the case where a fresh/stale clone tries to export an // empty or outdated database over a JSONL with many issues. @@ -224,7 +224,7 @@ Use --merge to merge the sync branch back to main branch.`, } } - // Case 2 (bd-53c): JSONL has significantly more issues than DB + // Case 2: JSONL has significantly more issues than DB // This is the DANGEROUS case - exporting would lose issues! // A stale/empty DB exporting over a populated JSONL causes data loss. if jsonlCount > dbCount && !skipExport { @@ -233,7 +233,7 @@ Use --merge to merge the sync branch back to main branch.`, // - Any loss > 20% is suspicious // - Complete loss (DB empty) is always blocked if dbCount == 0 || divergence > 0.2 { - fmt.Printf("→ JSONL has %d issues but DB has only %d (stale DB detected - bd-53c)\n", jsonlCount, dbCount) + fmt.Printf("→ JSONL has %d issues but DB has only %d (stale DB detected)\n", jsonlCount, dbCount) fmt.Println("→ Importing JSONL first to prevent data loss...") if err := importFromJSONL(ctx, jsonlPath, renameOnImport, noGitHistory); err != nil { FatalError("importing (reverse ZFC): %v", err) @@ -246,7 +246,7 @@ Use --merge to merge the sync branch back to main branch.`, } } - // Case 3 (bd-f2f): JSONL content differs from DB (hash mismatch) + // Case 3: JSONL content differs from DB (hash mismatch) // This catches the case where counts match but STATUS/content differs. // A stale DB exporting wrong status values over correct JSONL values // causes corruption that the 3-way merge propagates. @@ -261,10 +261,10 @@ Use --merge to merge the sync branch back to main branch.`, if !skipExport { repoKey := getRepoKeyForPath(jsonlPath) if hasJSONLChanged(ctx, store, jsonlPath, repoKey) { - fmt.Println("→ JSONL content differs from last sync (bd-f2f)") + fmt.Println("→ JSONL content differs from last sync") fmt.Println("→ Importing JSONL first to prevent stale DB from overwriting changes...") if err := importFromJSONL(ctx, jsonlPath, renameOnImport, noGitHistory); err != nil { - FatalError("importing (bd-f2f hash mismatch): %v", err) + FatalError("importing (hash mismatch): %v", err) } // Don't skip export - we still want to export any remaining local dirty issues // The import updated DB with JSONL content, and export will write merged state @@ -368,7 +368,7 @@ Use --merge to merge the sync branch back to main branch.`, return } - // Check if sync.branch is configured for worktree-based sync (bd-e3w) + // Check if sync.branch is configured for worktree-based sync // This allows committing to a separate branch without changing the user's working directory var syncBranchName string var repoRoot string @@ -416,7 +416,7 @@ Use --merge to merge the sync branch back to main branch.`, fmt.Println("→ [DRY RUN] Would commit changes to git") } } else if useSyncBranch { - // Use worktree to commit to sync branch (bd-e3w) + // Use worktree to commit to sync branch fmt.Printf("→ Committing changes to sync branch '%s'...\n", syncBranchName) result, err := syncbranch.CommitToSyncBranch(ctx, repoRoot, syncBranchName, jsonlPath, !noPush) if err != nil { @@ -460,10 +460,10 @@ Use --merge to merge the sync branch back to main branch.`, } else { // Execute pull - either via sync branch worktree or regular git pull if useSyncBranch { - // Pull from sync branch via worktree (bd-e3w) + // Pull from sync branch via worktree fmt.Printf("→ Pulling from sync branch '%s'...\n", syncBranchName) - // bd-4u8: Check if confirmation is required for mass deletion + // Check if confirmation is required for mass deletion requireMassDeleteConfirmation := config.GetBool("sync.require_confirmation_on_mass_delete") pullResult, err := syncbranch.PullFromSyncBranch(ctx, repoRoot, syncBranchName, jsonlPath, !noPush, requireMassDeleteConfirmation) @@ -472,17 +472,17 @@ Use --merge to merge the sync branch back to main branch.`, } if pullResult.Pulled { if pullResult.Merged { - // bd-3s8 fix: divergent histories were merged at content level + // Divergent histories were merged at content level fmt.Printf("✓ Merged divergent histories from %s\n", syncBranchName) - // bd-7z4: Print safety warnings from result + // Print safety warnings from result for _, warning := range pullResult.SafetyWarnings { fmt.Fprintln(os.Stderr, warning) } - // bd-4u8: Handle safety check with confirmation requirement + // Handle safety check with confirmation requirement if pullResult.SafetyCheckTriggered && !pullResult.Pushed { - // bd-dmd: Don't duplicate SafetyCheckDetails - it's already in SafetyWarnings + // Don't duplicate SafetyCheckDetails - it's already in SafetyWarnings // Prompt for confirmation fmt.Fprintf(os.Stderr, "Push these changes to remote? [y/N]: ") @@ -503,7 +503,7 @@ Use --merge to merge the sync branch back to main branch.`, fmt.Println("If this was unintended, use 'git reflog' on the sync branch to recover.") } } else if pullResult.Pushed { - // bd-7ch: auto-push after merge + // Auto-push after merge fmt.Printf("✓ Pushed merged changes to %s\n", syncBranchName) pushedViaSyncBranch = true } @@ -582,7 +582,7 @@ Use --merge to merge the sync branch back to main branch.`, // Step 4: Import updated JSONL after pull // Enable --protect-left-snapshot to prevent git-history-backfill from - // tombstoning issues that were in our local export but got lost during merge (bd-sync-deletion fix) + // tombstoning issues that were in our local export but got lost during merge fmt.Println("→ Importing updated JSONL...") if err := importFromJSONL(ctx, jsonlPath, renameOnImport, noGitHistory, true); err != nil { FatalError("importing: %v", err) @@ -648,7 +648,7 @@ Use --merge to merge the sync branch back to main branch.`, if hasPostImportChanges { fmt.Println("→ Committing DB changes from import...") if useSyncBranch { - // Commit to sync branch via worktree (bd-e3w) + // Commit to sync branch via worktree result, err := syncbranch.CommitToSyncBranch(ctx, repoRoot, syncBranchName, jsonlPath, !noPush) if err != nil { FatalError("committing to sync branch: %v", err) @@ -693,7 +693,7 @@ Use --merge to merge the sync branch back to main branch.`, if dryRun { fmt.Println("\n✓ Dry run complete (no changes made)") } else { - // Clean up temporary snapshot files after successful sync (bd-0io) + // Clean up temporary snapshot files after successful sync // This runs regardless of whether pull was performed sm := NewSnapshotManager(jsonlPath) if err := sm.Cleanup(); err != nil { @@ -901,7 +901,7 @@ func gitCommit(ctx context.Context, filePath string, message string) error { } // Commit from repo root context with config-based author and signing options - // Use pathspec to commit ONLY this file (bd-trgb fix) + // Use pathspec to commit ONLY this file // This prevents accidentally committing other staged files commitArgs := buildGitCommitArgs(repoRoot, message, "--", relPath) commitCmd := exec.CommandContext(ctx, "git", commitArgs...) @@ -913,10 +913,10 @@ func gitCommit(ctx context.Context, filePath string, message string) error { return nil } -// gitCommitBeadsDir stages and commits only sync-related files in .beads/ (bd-red fix) +// gitCommitBeadsDir stages and commits only sync-related files in .beads/ // This ensures bd sync doesn't accidentally commit other staged files. // Only stages specific sync files (issues.jsonl, deletions.jsonl, metadata.json) -// to avoid staging gitignored snapshot files that may be tracked. (bd-guc fix) +// to avoid staging gitignored snapshot files that may be tracked. // Worktree-aware: handles cases where .beads is in the main repo but we're running from a worktree. func gitCommitBeadsDir(ctx context.Context, message string) error { beadsDir := beads.FindBeadsDir() @@ -930,7 +930,7 @@ func gitCommitBeadsDir(ctx context.Context, message string) error { return fmt.Errorf("cannot determine repository root") } - // Stage only the specific sync-related files (bd-guc) + // Stage only the specific sync-related files // This avoids staging gitignored snapshot files (beads.*.jsonl, *.meta.json) // that may still be tracked from before they were added to .gitignore syncFiles := []string{ @@ -969,7 +969,7 @@ func gitCommitBeadsDir(ctx context.Context, message string) error { message = fmt.Sprintf("bd sync: %s", time.Now().Format("2006-01-02 15:04:05")) } - // Commit only .beads/ files using -- pathspec (bd-red) + // Commit only .beads/ files using -- pathspec // This prevents accidentally committing other staged files that the user // may have staged but wasn't ready to commit yet. // Convert beadsDir to relative path for git commit (worktree-aware) @@ -1091,13 +1091,13 @@ func checkMergeDriverConfig() { } func gitPull(ctx context.Context) error { - // Check if any remote exists (bd-biwp: support local-only repos) + // Check if any remote exists (support local-only repos) if !hasGitRemote(ctx) { return nil // Gracefully skip - local-only mode } // Get current branch name - // Use symbolic-ref to work in fresh repos without commits (bd-flil) + // Use symbolic-ref to work in fresh repos without commits branchCmd := exec.CommandContext(ctx, "git", "symbolic-ref", "--short", "HEAD") branchOutput, err := branchCmd.Output() if err != nil { @@ -1126,7 +1126,7 @@ func gitPull(ctx context.Context) error { // gitPush pushes to the current branch's upstream // Returns nil if no remote configured (local-only mode) func gitPush(ctx context.Context) error { - // Check if any remote exists (bd-biwp: support local-only repos) + // Check if any remote exists (support local-only repos) if !hasGitRemote(ctx) { return nil // Gracefully skip - local-only mode } diff --git a/cmd/bd/sync_check.go b/cmd/bd/sync_check.go index 04163dfb..20defcb5 100644 --- a/cmd/bd/sync_check.go +++ b/cmd/bd/sync_check.go @@ -16,7 +16,6 @@ import ( ) // SyncIntegrityResult contains the results of a pre-sync integrity check. -// bd-hlsw.1: Pre-sync integrity check type SyncIntegrityResult struct { ForcedPush *ForcedPushCheck `json:"forced_push,omitempty"` PrefixMismatch *PrefixMismatch `json:"prefix_mismatch,omitempty"` @@ -46,7 +45,7 @@ type OrphanedChildren struct { } // showSyncIntegrityCheck performs pre-sync integrity checks without modifying state. -// bd-hlsw.1: Detects forced pushes, prefix mismatches, and orphaned children. +// Detects forced pushes, prefix mismatches, and orphaned children. // Exits with code 1 if problems are detected. func showSyncIntegrityCheck(ctx context.Context, jsonlPath string) { fmt.Println("Sync Integrity Check") diff --git a/cmd/bd/sync_export.go b/cmd/bd/sync_export.go index ea73b203..c8e534e0 100644 --- a/cmd/bd/sync_export.go +++ b/cmd/bd/sync_export.go @@ -60,7 +60,7 @@ func exportToJSONL(ctx context.Context, jsonlPath string) error { } } - // Filter out wisps - they should never be exported to JSONL (bd-687g) + // Filter out wisps - they should never be exported to JSONL // Wisps exist only in SQLite and are shared via .beads/redirect, not JSONL. // This prevents "zombie" issues that resurrect after mol squash deletes them. filteredIssues := make([]*types.Issue, 0, len(issues)) @@ -150,9 +150,8 @@ func exportToJSONL(ctx context.Context, jsonlPath string) error { // Clear auto-flush state clearAutoFlushState() - // Update jsonl_content_hash metadata to enable content-based staleness detection (bd-khnb fix) + // Update jsonl_content_hash metadata to enable content-based staleness detection // After export, database and JSONL are in sync, so update hash to prevent unnecessary auto-import - // Renamed from last_import_hash (bd-39o) - more accurate since updated on both import AND export if currentHash, err := computeJSONLHash(jsonlPath); err == nil { if err := store.SetMetadata(ctx, "jsonl_content_hash", currentHash); err != nil { // Non-fatal warning: Metadata update failures are intentionally non-fatal to prevent blocking @@ -166,7 +165,7 @@ func exportToJSONL(ctx context.Context, jsonlPath string) error { // Non-fatal warning (see above comment about graceful degradation) fmt.Fprintf(os.Stderr, "Warning: failed to update last_import_time: %v\n", err) } - // Note: mtime tracking removed in bd-v0y fix (git doesn't preserve mtime) + // Note: mtime tracking removed because git doesn't preserve mtime } // Update database mtime to be >= JSONL mtime (fixes #278, #301, #321) diff --git a/cmd/bd/sync_import.go b/cmd/bd/sync_import.go index 1fcb725b..6bf87fe2 100644 --- a/cmd/bd/sync_import.go +++ b/cmd/bd/sync_import.go @@ -67,10 +67,10 @@ func resolveNoGitHistoryForFromMain(fromMain, noGitHistory bool) bool { } // doSyncFromMain performs a one-way sync from the default branch (main/master) -// Used for ephemeral branches without upstream tracking (gt-ick9) +// Used for ephemeral branches without upstream tracking. // This fetches beads from main and imports them, discarding local beads changes. // If sync.remote is configured (e.g., "upstream" for fork workflows), uses that remote -// instead of "origin" (bd-bx9). +// instead of "origin". func doSyncFromMain(ctx context.Context, jsonlPath string, renameOnImport bool, dryRun bool, noGitHistory bool) error { // Determine which remote to use (default: origin, but can be configured via sync.remote) remote := "origin" diff --git a/cmd/bd/template.go b/cmd/bd/template.go index f6ba8dea..bb06b047 100644 --- a/cmd/bd/template.go +++ b/cmd/bd/template.go @@ -415,7 +415,7 @@ func loadTemplateSubgraph(ctx context.Context, s storage.Storage, templateID str // loadDescendants recursively loads all child issues // It uses two strategies to find children: // 1. Check dependency records for parent-child relationships -// 2. Check for hierarchical IDs (parent.N) to catch children with missing/wrong deps (bd-c8d5) +// 2. Check for hierarchical IDs (parent.N) to catch children with missing/wrong deps func loadDescendants(ctx context.Context, s storage.Storage, subgraph *TemplateSubgraph, parentID string) error { // Track children we've already added to avoid duplicates addedChildren := make(map[string]bool) @@ -461,7 +461,7 @@ func loadDescendants(ctx context.Context, s storage.Storage, subgraph *TemplateS } } - // Strategy 2: Find hierarchical children by ID pattern (bd-c8d5) + // Strategy 2: Find hierarchical children by ID pattern // This catches children that have missing or incorrect dependency types. // Hierarchical IDs follow the pattern: parentID.N (e.g., "gt-abc.1", "gt-abc.2") hierarchicalChildren, err := findHierarchicalChildren(ctx, s, parentID) @@ -522,7 +522,7 @@ func findHierarchicalChildren(ctx context.Context, s storage.Storage, parentID s } // ============================================================================= -// Proto Lookup Functions (bd-drcx) +// Proto Lookup Functions // ============================================================================= // resolveProtoIDOrTitle resolves a proto by ID or title. @@ -715,7 +715,7 @@ func cloneSubgraphViaDaemon(client *rpc.Client, subgraph *TemplateSubgraph, opts Assignee: issueAssignee, EstimatedMinutes: oldIssue.EstimatedMinutes, Ephemeral: opts.Ephemeral, - IDPrefix: opts.Prefix, // bd-hobo: distinct prefixes for mols/wisps + IDPrefix: opts.Prefix, // distinct prefixes for mols/wisps } // Generate custom ID for dynamic bonding if ParentID is set @@ -961,8 +961,8 @@ func cloneSubgraph(ctx context.Context, s storage.Storage, subgraph *TemplateSub IssueType: oldIssue.IssueType, Assignee: issueAssignee, EstimatedMinutes: oldIssue.EstimatedMinutes, - Ephemeral: opts.Ephemeral, // bd-2vh3: mark for cleanup when closed - IDPrefix: opts.Prefix, // bd-hobo: distinct prefixes for mols/wisps + Ephemeral: opts.Ephemeral, // mark for cleanup when closed + IDPrefix: opts.Prefix, // distinct prefixes for mols/wisps CreatedAt: time.Now(), UpdatedAt: time.Now(), } diff --git a/cmd/bd/version.go b/cmd/bd/version.go index 716d4a42..45ea7823 100644 --- a/cmd/bd/version.go +++ b/cmd/bd/version.go @@ -151,7 +151,7 @@ func resolveBranch() string { } // Fallback: try to get branch from git at runtime - // Use symbolic-ref to work in fresh repos without commits (bd-flil) + // Use symbolic-ref to work in fresh repos without commits cmd := exec.Command("git", "symbolic-ref", "--short", "HEAD") cmd.Dir = "." if output, err := cmd.Output(); err == nil { diff --git a/cmd/bd/version_tracking.go b/cmd/bd/version_tracking.go index 10eb5cf3..81ff5755 100644 --- a/cmd/bd/version_tracking.go +++ b/cmd/bd/version_tracking.go @@ -16,16 +16,11 @@ import ( // localVersionFile is the gitignored file that stores the last bd version used locally. // This prevents the upgrade notification from firing repeatedly when git operations // reset the tracked metadata.json file. -// -// bd-tok: Fix upgrade notification persisting after git operations const localVersionFile = ".local_version" // trackBdVersion checks if bd version has changed since last run and updates the local version file. // This function is best-effort - failures are silent to avoid disrupting commands. // Sets global variables versionUpgradeDetected and previousVersion if upgrade detected. -// -// bd-loka: Built-in version tracking for upgrade awareness -// bd-tok: Use gitignored .local_version file instead of metadata.json func trackBdVersion() { // Find the beads directory beadsDir := beads.FindBeadsDir() @@ -61,7 +56,7 @@ func trackBdVersion() { // No config file yet - create one cfg = configfile.DefaultConfig() - // bd-afd: Auto-detect actual JSONL file instead of using hardcoded default + // Auto-detect actual JSONL file instead of using hardcoded default // This prevents mismatches when metadata.json gets deleted (git clean, merge conflict, etc.) if actualJSONL := findActualJSONLFile(beadsDir); actualJSONL != "" { cfg.JSONLExport = actualJSONL @@ -155,8 +150,6 @@ func maybeShowUpgradeNotification() { // findActualJSONLFile scans .beads/ for the actual JSONL file in use. // Prefers issues.jsonl over beads.jsonl (canonical name), skips backups and merge artifacts. // Returns empty string if no JSONL file is found. -// -// bd-6xd: Auto-detect JSONL file to prevent metadata.json mismatches func findActualJSONLFile(beadsDir string) string { entries, err := os.ReadDir(beadsDir) if err != nil { @@ -192,7 +185,7 @@ func findActualJSONLFile(beadsDir string) string { return "" } - // bd-6xd: Prefer issues.jsonl over beads.jsonl (canonical name) + // Prefer issues.jsonl over beads.jsonl (canonical name) for _, name := range candidates { if name == "issues.jsonl" { return name @@ -209,8 +202,6 @@ func findActualJSONLFile(beadsDir string) string { // // IMPORTANT: This must be called AFTER determining we're in direct mode (no daemon) // and BEFORE opening the database, to avoid: 1) conflicts with daemon, 2) opening DB twice. -// -// bd-jgxi: Auto-migrate database on CLI version bump func autoMigrateOnVersionBump(dbPath string) { // Only migrate if version upgrade was detected if !versionUpgradeDetected { diff --git a/cmd/bd/wisp.go b/cmd/bd/wisp.go index 52fc4591..40d45068 100644 --- a/cmd/bd/wisp.go +++ b/cmd/bd/wisp.go @@ -160,12 +160,12 @@ func runWispCreate(cmd *cobra.Command, args []string) { vars[parts[0]] = parts[1] } - // Try to load as formula first (ephemeral proto - gt-4v1eo) + // Try to load as formula first (ephemeral proto) // If that fails, fall back to loading from DB (legacy proto beads) var subgraph *TemplateSubgraph var protoID string - // Try to cook formula inline (gt-4v1eo: ephemeral protos) + // Try to cook formula inline (ephemeral protos) // This works for any valid formula name, not just "mol-" prefixed ones sg, err := resolveAndCookFormula(args[0], nil) if err == nil { @@ -228,7 +228,7 @@ func runWispCreate(cmd *cobra.Command, args []string) { } } - // Apply variable defaults from formula (gt-4v1eo) + // Apply variable defaults from formula vars = applyVariableDefaults(vars, subgraph) // Check for missing required variables (those without defaults) @@ -256,7 +256,7 @@ func runWispCreate(cmd *cobra.Command, args []string) { } // Spawn as ephemeral in main database (Ephemeral=true, skips JSONL export) - // bd-hobo: Use "eph" prefix for distinct visual recognition + // Use "eph" prefix for distinct visual recognition result, err := spawnMolecule(ctx, store, subgraph, vars, "", actor, true, "eph") if err != nil { fmt.Fprintf(os.Stderr, "Error creating wisp: %v\n", err) diff --git a/internal/beads/beads.go b/internal/beads/beads.go index dfec54d3..4ae216ba 100644 --- a/internal/beads/beads.go +++ b/internal/beads/beads.go @@ -300,7 +300,7 @@ const ( DepRelated = types.DepRelated DepParentChild = types.DepParentChild DepDiscoveredFrom = types.DepDiscoveredFrom - DepConditionalBlocks = types.DepConditionalBlocks // B runs only if A fails (bd-kzda) + DepConditionalBlocks = types.DepConditionalBlocks // B runs only if A fails ) // SortPolicy constants @@ -385,7 +385,7 @@ func FindDatabasePath() string { // - Any *.db file (excluding backups and vc.db) // - Any *.jsonl file (JSONL-only mode or git-tracked issues) // -// Returns false for directories that only contain daemon registry files (bd-420). +// Returns false for directories that only contain daemon registry files. // This prevents FindBeadsDir from returning ~/.beads/ which only has registry.json. func hasBeadsProjectFiles(beadsDir string) bool { // Check for project configuration files @@ -416,11 +416,11 @@ func hasBeadsProjectFiles(beadsDir string) bool { // FindBeadsDir finds the .beads/ directory in the current directory tree // Returns empty string if not found. Supports both database and JSONL-only mode. -// Stops at the git repository root to avoid finding unrelated directories (bd-c8x). -// Validates that the directory contains actual project files (bd-420). +// Stops at the git repository root to avoid finding unrelated directories. +// Validates that the directory contains actual project files. // Redirect files are supported: if a .beads/redirect file exists, its contents // are used as the actual .beads directory path. -// For worktrees, prioritizes the main repository's .beads directory (bd-de6). +// For worktrees, prioritizes the main repository's .beads directory. // This is useful for commands that need to detect beads projects without requiring a database. func FindBeadsDir() string { // 1. Check BEADS_DIR environment variable (preferred) @@ -431,14 +431,14 @@ func FindBeadsDir() string { absBeadsDir = followRedirect(absBeadsDir) if info, err := os.Stat(absBeadsDir); err == nil && info.IsDir() { - // Validate directory contains actual project files (bd-420) + // Validate directory contains actual project files if hasBeadsProjectFiles(absBeadsDir) { return absBeadsDir } } } - // 2. For worktrees, check main repository root first (bd-de6) + // 2. For worktrees, check main repository root first var mainRepoRoot string if git.IsWorktree() { var err error @@ -449,7 +449,7 @@ func FindBeadsDir() string { // Follow redirect if present beadsDir = followRedirect(beadsDir) - // Validate directory contains actual project files (bd-420) + // Validate directory contains actual project files if hasBeadsProjectFiles(beadsDir) { return beadsDir } @@ -463,7 +463,7 @@ func FindBeadsDir() string { return "" } - // Find git root to limit the search (bd-c8x) + // Find git root to limit the search gitRoot := findGitRoot() if git.IsWorktree() && mainRepoRoot != "" { // For worktrees, extend search boundary to include main repo @@ -476,13 +476,13 @@ func FindBeadsDir() string { // Follow redirect if present beadsDir = followRedirect(beadsDir) - // Validate directory contains actual project files (bd-420) + // Validate directory contains actual project files if hasBeadsProjectFiles(beadsDir) { return beadsDir } } - // Stop at git root to avoid finding unrelated directories (bd-c8x) + // Stop at git root to avoid finding unrelated directories if gitRoot != "" && dir == gitRoot { break } @@ -493,7 +493,7 @@ func FindBeadsDir() string { // FindJSONLPath returns the expected JSONL file path for the given database path. // It searches for existing *.jsonl files in the database directory and returns -// the first one found, preferring issues.jsonl over beads.jsonl (bd-6xd). +// the first one found, preferring issues.jsonl over beads.jsonl. // // This function does not create directories or files - it only discovers paths. // Use this when you need to know where bd stores its JSONL export. @@ -515,7 +515,7 @@ type DatabaseInfo struct { // findGitRoot returns the root directory of the current git repository, // or empty string if not in a git repository. Used to limit directory -// tree walking to within the current git repo (bd-c8x). +// tree walking to within the current git repo. // // This function delegates to git.GetRepoRoot() which is worktree-aware // and handles Windows path normalization. @@ -524,7 +524,7 @@ func findGitRoot() string { } // findDatabaseInTree walks up the directory tree looking for .beads/*.db -// Stops at the git repository root to avoid finding unrelated databases (bd-c8x). +// Stops at the git repository root to avoid finding unrelated databases. // For worktrees, searches the main repository root first, then falls back to worktree. // Prefers config.json, falls back to beads.db, and warns if multiple .db files exist. // Redirect files are supported: if a .beads/redirect file exists, its contents @@ -562,7 +562,7 @@ func findDatabaseInTree() string { // If not found in main repo, fall back to worktree search below } - // Find git root to limit the search (bd-c8x) + // Find git root to limit the search gitRoot := findGitRoot() if git.IsWorktree() && mainRepoRoot != "" { // For worktrees, extend search boundary to include main repo @@ -589,7 +589,7 @@ func findDatabaseInTree() string { break } - // Stop at git root to avoid finding unrelated databases (bd-c8x) + // Stop at git root to avoid finding unrelated databases if gitRoot != "" && dir == gitRoot { break } @@ -602,7 +602,7 @@ func findDatabaseInTree() string { // FindAllDatabases scans the directory hierarchy for the closest .beads directory. // Returns a slice with at most one DatabaseInfo - the closest database to CWD. -// Stops searching upward as soon as a .beads directory is found (gt-bzd), +// Stops searching upward as soon as a .beads directory is found, // because in multi-workspace setups (like Gas Town), nested .beads directories // are intentional and separate - parent directories are out of scope. // Redirect files are supported: if a .beads/redirect file exists, its contents @@ -616,7 +616,7 @@ func FindAllDatabases() []DatabaseInfo { return databases } - // Find git root to limit the search (bd-c8x) + // Find git root to limit the search gitRoot := findGitRoot() // Walk up directory tree @@ -668,7 +668,7 @@ func FindAllDatabases() []DatabaseInfo { IssueCount: issueCount, }) - // Stop searching upward - the closest .beads is the one to use (gt-bzd) + // Stop searching upward - the closest .beads is the one to use // Parent directories are out of scope in multi-workspace setups break } @@ -681,7 +681,7 @@ func FindAllDatabases() []DatabaseInfo { break } - // Stop at git root to avoid finding unrelated databases (bd-c8x) + // Stop at git root to avoid finding unrelated databases if gitRoot != "" && dir == gitRoot { break } diff --git a/internal/daemon/registry.go b/internal/daemon/registry.go index 844bbd36..f2e5aa0c 100644 --- a/internal/daemon/registry.go +++ b/internal/daemon/registry.go @@ -71,7 +71,7 @@ func (r *Registry) withFileLock(fn func() error) error { // readEntriesLocked reads all entries from the registry file. // Caller must hold the file lock. -// bd-qn5: Handles missing, empty, or corrupted registry files gracefully. +// Handles missing, empty, or corrupted registry files gracefully. func (r *Registry) readEntriesLocked() ([]RegistryEntry, error) { data, err := os.ReadFile(r.path) if err != nil { @@ -81,7 +81,7 @@ func (r *Registry) readEntriesLocked() ([]RegistryEntry, error) { return nil, fmt.Errorf("failed to read registry: %w", err) } - // bd-qn5: Handle empty file or file with only whitespace/null bytes + // Handle empty file or file with only whitespace/null bytes // This can happen if the file was created but never written to, or was corrupted trimmed := make([]byte, 0, len(data)) for _, b := range data { @@ -95,7 +95,7 @@ func (r *Registry) readEntriesLocked() ([]RegistryEntry, error) { var entries []RegistryEntry if err := json.Unmarshal(data, &entries); err != nil { - // bd-qn5: If registry is corrupted, treat as empty rather than failing + // If registry is corrupted, treat as empty rather than failing // A corrupted registry just means we'll need to rediscover daemons return []RegistryEntry{}, nil } diff --git a/internal/formula/advice.go b/internal/formula/advice.go index 3b975fa4..c7962fa2 100644 --- a/internal/formula/advice.go +++ b/internal/formula/advice.go @@ -56,7 +56,7 @@ func MatchGlob(pattern, stepID string) bool { // Returns a new steps slice with advice steps inserted. // The original steps slice is not modified. // -// Self-matching prevention (gt-8tmz.16): Advice only matches steps that +// Self-matching prevention: Advice only matches steps that // existed BEFORE this call. Steps inserted by advice (before/after/around) // are not matched, preventing infinite recursion. func ApplyAdvice(steps []*Step, advice []*AdviceRule) []*Step { @@ -64,7 +64,7 @@ func ApplyAdvice(steps []*Step, advice []*AdviceRule) []*Step { return steps } - // Collect original step IDs to prevent self-matching (gt-8tmz.16) + // Collect original step IDs to prevent self-matching originalIDs := collectStepIDs(steps) return applyAdviceWithGuard(steps, advice, originalIDs) @@ -77,7 +77,7 @@ func applyAdviceWithGuard(steps []*Step, advice []*AdviceRule, originalIDs map[s result := make([]*Step, 0, len(steps)*2) // Pre-allocate for insertions for _, step := range steps { - // Skip steps not in original set (gt-8tmz.16) + // Skip steps not in original set if !originalIDs[step.ID] { result = append(result, step) continue @@ -170,7 +170,7 @@ func adviceStepToStep(as *AdviceStep, target *Step) *Step { Title: title, Description: desc, Type: as.Type, - SourceFormula: target.SourceFormula, // Inherit source formula from target (gt-8tmz.18) + SourceFormula: target.SourceFormula, // Inherit source formula from target // SourceLocation will be "advice" to indicate this came from advice transformation SourceLocation: "advice", } @@ -199,7 +199,7 @@ func cloneStep(s *Step) *Step { clone.Labels = make([]string, len(s.Labels)) copy(clone.Labels, s.Labels) } - // Deep copy OnComplete if present (gt-8tmz.8) + // Deep copy OnComplete if present if s.OnComplete != nil { clone.OnComplete = cloneOnComplete(s.OnComplete) } @@ -207,7 +207,7 @@ func cloneStep(s *Step) *Step { return &clone } -// cloneOnComplete creates a deep copy of an OnCompleteSpec (gt-8tmz.8). +// cloneOnComplete creates a deep copy of an OnCompleteSpec. func cloneOnComplete(oc *OnCompleteSpec) *OnCompleteSpec { if oc == nil { return nil @@ -233,7 +233,7 @@ func appendUnique(slice []string, item string) []string { } // collectStepIDs returns a set of all step IDs (including nested children). -// Used by ApplyAdvice to prevent self-matching (gt-8tmz.16). +// Used by ApplyAdvice to prevent self-matching. func collectStepIDs(steps []*Step) map[string]bool { ids := make(map[string]bool) var collect func([]*Step) diff --git a/internal/formula/controlflow.go b/internal/formula/controlflow.go index 633cd109..37fd545d 100644 --- a/internal/formula/controlflow.go +++ b/internal/formula/controlflow.go @@ -1,6 +1,6 @@ // Package formula provides control flow operators for step transformation. // -// Control flow operators (gt-8tmz.4) enable: +// Control flow operators enable: // - loop: Repeat a body of steps (fixed count or conditional) // - branch: Fork-join parallel execution patterns // - gate: Conditional waits before steps proceed @@ -97,7 +97,7 @@ func validateLoopSpec(loop *LoopSpec, stepID string) error { } } - // Validate range syntax if present (gt-8tmz.27) + // Validate range syntax if present if loop.Range != "" { if err := ValidateRange(loop.Range); err != nil { return fmt.Errorf("loop %q: invalid range %q: %w", stepID, loop.Range, err) @@ -127,7 +127,7 @@ func expandLoopWithVars(step *Step, vars map[string]string) ([]*Step, error) { result = append(result, iterSteps...) } - // Recursively expand any nested loops FIRST (gt-zn35j) + // Recursively expand any nested loops FIRST var err error result, err = ApplyLoops(result) if err != nil { @@ -140,7 +140,7 @@ func expandLoopWithVars(step *Step, vars map[string]string) ([]*Step, error) { result = chainExpandedIterations(result, step.ID, step.Loop.Count) } } else if step.Loop.Range != "" { - // Range loop (gt-8tmz.27): expand body for each value in the computed range + // Range loop: expand body for each value in the computed range rangeSpec, err := ParseRange(step.Loop.Range, vars) if err != nil { return nil, fmt.Errorf("loop %q: %w", step.ID, err) @@ -169,7 +169,7 @@ func expandLoopWithVars(step *Step, vars map[string]string) ([]*Step, error) { result = append(result, iterSteps...) } - // Recursively expand any nested loops FIRST (gt-zn35j) + // Recursively expand any nested loops FIRST result, err = ApplyLoops(result) if err != nil { return nil, err @@ -199,7 +199,7 @@ func expandLoopWithVars(step *Step, vars map[string]string) ([]*Step, error) { firstStep.Labels = append(firstStep.Labels, fmt.Sprintf("loop:%s", string(loopJSON))) } - // Recursively expand any nested loops (gt-zn35j) + // Recursively expand any nested loops result, err = ApplyLoops(iterSteps) if err != nil { return nil, err @@ -211,7 +211,7 @@ func expandLoopWithVars(step *Step, vars map[string]string) ([]*Step, error) { // expandLoopIteration expands a single iteration of a loop. // The iteration index is used to generate unique step IDs. -// The iterVars map contains loop variable bindings for this iteration (gt-8tmz.27). +// The iterVars map contains loop variable bindings for this iteration. // //nolint:unparam // error return kept for API consistency with future error handling func expandLoopIteration(step *Step, iteration int, iterVars map[string]string) ([]*Step, error) { @@ -224,7 +224,7 @@ func expandLoopIteration(step *Step, iteration int, iterVars map[string]string) // Create unique ID for this iteration iterID := fmt.Sprintf("%s.iter%d.%s", step.ID, iteration, bodyStep.ID) - // Substitute loop variables in title and description (gt-8tmz.27) + // Substitute loop variables in title and description title := substituteLoopVars(bodyStep.Title, iterVars) description := substituteLoopVars(bodyStep.Description, iterVars) @@ -239,13 +239,13 @@ func expandLoopIteration(step *Step, iteration int, iterVars map[string]string) WaitsFor: bodyStep.WaitsFor, Expand: bodyStep.Expand, Gate: bodyStep.Gate, - Loop: cloneLoopSpec(bodyStep.Loop), // Support nested loops (gt-zn35j) + Loop: cloneLoopSpec(bodyStep.Loop), // Support nested loops OnComplete: cloneOnComplete(bodyStep.OnComplete), - SourceFormula: bodyStep.SourceFormula, // Preserve source (gt-8tmz.18) + SourceFormula: bodyStep.SourceFormula, // Preserve source SourceLocation: fmt.Sprintf("%s.iter%d", bodyStep.SourceLocation, iteration), // Track iteration } - // Clone ExpandVars if present, adding loop vars (gt-8tmz.27) + // Clone ExpandVars if present, adding loop vars if len(bodyStep.ExpandVars) > 0 || len(iterVars) > 0 { clone.ExpandVars = make(map[string]string) for k, v := range bodyStep.ExpandVars { @@ -369,7 +369,7 @@ func chainLoopIterations(steps []*Step, body []*Step, count int) []*Step { return steps } -// chainExpandedIterations chains iterations AFTER nested loop expansion (gt-zn35j). +// chainExpandedIterations chains iterations AFTER nested loop expansion. // Unlike chainLoopIterations, this handles variable step counts per iteration // by finding iteration boundaries via ID prefix matching. func chainExpandedIterations(steps []*Step, loopID string, count int) []*Step { @@ -421,7 +421,7 @@ func ApplyBranches(steps []*Step, compose *ComposeRules) ([]*Step, error) { return steps, nil } - // Clone steps to avoid mutating input (gt-v1pcg) + // Clone steps to avoid mutating input cloned := cloneStepsRecursive(steps) stepMap := buildStepMap(cloned) @@ -493,7 +493,7 @@ func ApplyGates(steps []*Step, compose *ComposeRules) ([]*Step, error) { return steps, nil } - // Clone steps to avoid mutating input (gt-v1pcg) + // Clone steps to avoid mutating input cloned := cloneStepsRecursive(steps) stepMap := buildStepMap(cloned) @@ -558,7 +558,7 @@ func ApplyControlFlow(steps []*Step, compose *ComposeRules) ([]*Step, error) { return nil, fmt.Errorf("applying loops: %w", err) } - // Build stepMap once for branches and gates (gt-gpgdv optimization) + // Build stepMap once for branches and gates // No need to clone here since ApplyLoops already returned a new slice stepMap := buildStepMap(steps) @@ -589,7 +589,7 @@ func cloneStepDeep(s *Step) *Step { return clone } -// cloneStepsRecursive creates a deep copy of a slice of steps (gt-v1pcg). +// cloneStepsRecursive creates a deep copy of a slice of steps. func cloneStepsRecursive(steps []*Step) []*Step { result := make([]*Step, len(steps)) for i, step := range steps { @@ -598,7 +598,7 @@ func cloneStepsRecursive(steps []*Step) []*Step { return result } -// cloneLoopSpec creates a deep copy of a LoopSpec (gt-zn35j). +// cloneLoopSpec creates a deep copy of a LoopSpec. func cloneLoopSpec(loop *LoopSpec) *LoopSpec { if loop == nil { return nil @@ -607,8 +607,8 @@ func cloneLoopSpec(loop *LoopSpec) *LoopSpec { Count: loop.Count, Until: loop.Until, Max: loop.Max, - Range: loop.Range, // gt-8tmz.27 - Var: loop.Var, // gt-8tmz.27 + Range: loop.Range, + Var: loop.Var, } if len(loop.Body) > 0 { clone.Body = make([]*Step, len(loop.Body)) diff --git a/internal/formula/expand.go b/internal/formula/expand.go index 058f089c..b9ae0069 100644 --- a/internal/formula/expand.go +++ b/internal/formula/expand.go @@ -72,7 +72,7 @@ func ApplyExpansions(steps []*Step, compose *ComposeRules, parser *Parser) ([]*S return nil, fmt.Errorf("expand: %q has no template steps", rule.With) } - // Merge formula default vars with rule overrides (gt-8tmz.34) + // Merge formula default vars with rule overrides vars := mergeVars(expFormula, rule.Vars) // Expand the target step (start at depth 0) @@ -115,10 +115,10 @@ func ApplyExpansions(steps []*Step, compose *ComposeRules, parser *Parser) ([]*S return nil, fmt.Errorf("map: %q has no template steps", rule.With) } - // Merge formula default vars with rule overrides (gt-8tmz.34) + // Merge formula default vars with rule overrides vars := mergeVars(expFormula, rule.Vars) - // Find all matching steps (including nested children - gt-8tmz.33) + // Find all matching steps (including nested children) // Rebuild stepMap to capture any changes from previous expansions stepMap = buildStepMap(result) var toExpand []*Step @@ -152,7 +152,7 @@ func ApplyExpansions(steps []*Step, compose *ComposeRules, parser *Parser) ([]*S } } - // Validate no duplicate step IDs after expansion (gt-8tmz.36) + // Validate no duplicate step IDs after expansion if dups := findDuplicateStepIDs(result); len(dups) > 0 { return nil, fmt.Errorf("duplicate step IDs after expansion: %v", dups) } @@ -206,8 +206,8 @@ func expandStep(target *Step, template []*Step, depth int, vars map[string]strin Type: tmpl.Type, Priority: tmpl.Priority, Assignee: substituteVars(tmpl.Assignee, vars), - SourceFormula: tmpl.SourceFormula, // Preserve source from template (gt-8tmz.18) - SourceLocation: tmpl.SourceLocation, // Preserve source location (gt-8tmz.18) + SourceFormula: tmpl.SourceFormula, // Preserve source from template + SourceLocation: tmpl.SourceLocation, // Preserve source location } // Substitute placeholders in labels @@ -361,7 +361,7 @@ func UpdateDependenciesForExpansion(steps []*Step, expandedID string, lastExpand return result } -// ApplyInlineExpansions applies Step.Expand fields to inline expansions (gt-8tmz.35). +// ApplyInlineExpansions applies Step.Expand fields to inline expansions. // Steps with the Expand field set are replaced by the referenced expansion template. // The step's ExpandVars are passed as variable overrides to the expansion. // diff --git a/internal/formula/types.go b/internal/formula/types.go index 02c8d47b..4b253e69 100644 --- a/internal/formula/types.go +++ b/internal/formula/types.go @@ -186,15 +186,15 @@ type Step struct { // TODO(future): Not yet implemented in bd cook. Will integrate with bd-udsi gates. Gate *Gate `json:"gate,omitempty"` - // Loop defines iteration for this step (gt-8tmz.4). + // Loop defines iteration for this step. // When set, the step becomes a container that expands its body. Loop *LoopSpec `json:"loop,omitempty"` - // OnComplete defines actions triggered when this step completes (gt-8tmz.8). + // OnComplete defines actions triggered when this step completes. // Used for runtime expansion over step output (the for-each construct). OnComplete *OnCompleteSpec `json:"on_complete,omitempty"` - // Source tracing fields (gt-8tmz.18): track where this step came from. + // Source tracing fields: track where this step came from. // These are set during parsing/transformation and copied to Issues during cooking. // SourceFormula is the formula name where this step was defined. @@ -219,7 +219,7 @@ type Gate struct { Timeout string `json:"timeout,omitempty"` } -// LoopSpec defines iteration over a body of steps (gt-8tmz.4). +// LoopSpec defines iteration over a body of steps. // One of Count, Until, or Range must be specified. type LoopSpec struct { // Count is the fixed number of iterations. @@ -234,7 +234,7 @@ type LoopSpec struct { // Required when Until is set, to prevent unbounded loops. Max int `json:"max,omitempty"` - // Range specifies a computed range for iteration (gt-8tmz.27). + // Range specifies a computed range for iteration. // Format: "start..end" where start and end can be: // - Integers: "1..10" // - Expressions: "1..2^{disks}" (evaluated at cook time) @@ -242,7 +242,7 @@ type LoopSpec struct { // Supports: + - * / ^ (power) and parentheses. Range string `json:"range,omitempty"` - // Var is the variable name exposed to body steps (gt-8tmz.27). + // Var is the variable name exposed to body steps. // For Range loops, this is set to the current iteration value. // Example: var: "move_num" with range: "1..7" exposes {move_num}=1,2,...,7 Var string `json:"var,omitempty"` @@ -251,7 +251,7 @@ type LoopSpec struct { Body []*Step `json:"body"` } -// OnCompleteSpec defines actions triggered when a step completes (gt-8tmz.8). +// OnCompleteSpec defines actions triggered when a step completes. // Used for runtime expansion over step output (the for-each construct). // // Example YAML: @@ -291,7 +291,7 @@ type OnCompleteSpec struct { Sequential bool `json:"sequential,omitempty"` } -// BranchRule defines parallel execution paths that rejoin (gt-8tmz.4). +// BranchRule defines parallel execution paths that rejoin. // Creates a fork-join pattern: from -> [parallel steps] -> join. type BranchRule struct { // From is the step ID that precedes the parallel paths. @@ -307,7 +307,7 @@ type BranchRule struct { Join string `json:"join"` } -// GateRule defines a condition that must be satisfied before a step proceeds (gt-8tmz.4). +// GateRule defines a condition that must be satisfied before a step proceeds. // Gates are evaluated at runtime by the patrol executor. type GateRule struct { // Before is the step ID that the gate applies to. @@ -335,11 +335,11 @@ type ComposeRules struct { // Each matching step is replaced by the expanded template steps. Map []*MapRule `json:"map,omitempty"` - // Branch defines fork-join parallel execution patterns (gt-8tmz.4). + // Branch defines fork-join parallel execution patterns. // Each rule creates dependencies for parallel paths that rejoin. Branch []*BranchRule `json:"branch,omitempty"` - // Gate defines conditional waits before steps (gt-8tmz.4). + // Gate defines conditional waits before steps. // Each rule adds a condition that must be satisfied at runtime. Gate []*GateRule `json:"gate,omitempty"` @@ -534,20 +534,20 @@ func (f *Formula) Validate() error { errs = append(errs, fmt.Sprintf("steps[%d] (%s): depends_on references unknown step %q", i, step.ID, dep)) } } - // Validate needs field (bd-hr39) - same validation as depends_on + // Validate needs field - same validation as depends_on for _, need := range step.Needs { if _, exists := stepIDLocations[need]; !exists { errs = append(errs, fmt.Sprintf("steps[%d] (%s): needs references unknown step %q", i, step.ID, need)) } } - // Validate waits_for field (bd-j4cr, gt-8tmz.38) + // Validate waits_for field // Valid formats: "all-children", "any-children", "children-of(step-id)" if step.WaitsFor != "" { if err := validateWaitsFor(step.WaitsFor, stepIDLocations); err != nil { errs = append(errs, fmt.Sprintf("steps[%d] (%s): %s", i, step.ID, err.Error())) } } - // Validate on_complete field (gt-8tmz.8) - runtime expansion + // Validate on_complete field - runtime expansion if step.OnComplete != nil { validateOnComplete(step.OnComplete, &errs, fmt.Sprintf("steps[%d] (%s)", i, step.ID)) } @@ -621,7 +621,7 @@ func collectChildIDs(children []*Step, idLocations map[string]string, errs *[]st } } -// WaitsForSpec holds the parsed waits_for field (gt-8tmz.38). +// WaitsForSpec holds the parsed waits_for field. type WaitsForSpec struct { // Gate is the gate type: "all-children" or "any-children" Gate string @@ -630,7 +630,7 @@ type WaitsForSpec struct { SpawnerID string } -// ParseWaitsFor parses a waits_for value into its components (gt-8tmz.38). +// ParseWaitsFor parses a waits_for value into its components. // Returns nil if the value is empty. func ParseWaitsFor(value string) *WaitsForSpec { if value == "" { @@ -655,7 +655,7 @@ func ParseWaitsFor(value string) *WaitsForSpec { return nil } -// validateWaitsFor validates the waits_for field value (gt-8tmz.38). +// validateWaitsFor validates the waits_for field value. // Valid formats: // - "all-children": wait for all dynamically-bonded children // - "any-children": wait for first child to complete @@ -690,19 +690,19 @@ func validateChildDependsOn(children []*Step, idLocations map[string]string, err *errs = append(*errs, fmt.Sprintf("%s (%s): depends_on references unknown step %q", childPrefix, child.ID, dep)) } } - // Validate needs field (bd-hr39) + // Validate needs field for _, need := range child.Needs { if _, exists := idLocations[need]; !exists { *errs = append(*errs, fmt.Sprintf("%s (%s): needs references unknown step %q", childPrefix, child.ID, need)) } } - // Validate waits_for field (bd-j4cr, gt-8tmz.38) + // Validate waits_for field if child.WaitsFor != "" { if err := validateWaitsFor(child.WaitsFor, idLocations); err != nil { *errs = append(*errs, fmt.Sprintf("%s (%s): %s", childPrefix, child.ID, err.Error())) } } - // Validate on_complete field (gt-8tmz.8) + // Validate on_complete field if child.OnComplete != nil { validateOnComplete(child.OnComplete, errs, fmt.Sprintf("%s (%s)", childPrefix, child.ID)) } @@ -710,7 +710,7 @@ func validateChildDependsOn(children []*Step, idLocations map[string]string, err } } -// validateOnComplete validates an OnCompleteSpec (gt-8tmz.8). +// validateOnComplete validates an OnCompleteSpec. func validateOnComplete(oc *OnCompleteSpec, errs *[]string, prefix string) { // Check that for_each and bond are both present or both absent if oc.ForEach != "" && oc.Bond == "" { diff --git a/internal/importer/importer.go b/internal/importer/importer.go index fa27cb5e..c931fce5 100644 --- a/internal/importer/importer.go +++ b/internal/importer/importer.go @@ -39,7 +39,7 @@ type Options struct { SkipPrefixValidation bool // Skip prefix validation (for auto-import) OrphanHandling OrphanHandling // How to handle missing parent issues (default: allow) ClearDuplicateExternalRefs bool // Clear duplicate external_ref values instead of erroring - ProtectLocalExportIDs map[string]bool // IDs from left snapshot to protect from deletion (bd-sync-deletion fix) + ProtectLocalExportIDs map[string]bool // IDs from left snapshot to protect from deletion } // Result contains statistics about the import operation @@ -93,8 +93,8 @@ func ImportIssues(ctx context.Context, dbPath string, store storage.Storage, iss } } - // Compute content hashes for all incoming issues (bd-95) - // Always recompute to avoid stale/incorrect JSONL hashes (bd-1231) + // Compute content hashes for all incoming issues + // Always recompute to avoid stale/incorrect JSONL hashes for _, issue := range issues { issue.ContentHash = issue.ComputeContentHash() } @@ -114,7 +114,7 @@ func ImportIssues(ctx context.Context, dbPath string, store storage.Storage, iss opts.SkipPrefixValidation = true } - // Clear export_hashes before import to prevent staleness (bd-160) + // Clear export_hashes before import to prevent staleness // Import operations may add/update issues, so export_hashes entries become invalid if !opts.DryRun { if err := sqliteStore.ClearAllExportHashes(ctx); err != nil { @@ -199,7 +199,7 @@ func getOrCreateStore(ctx context.Context, dbPath string, store storage.Storage) } // handlePrefixMismatch checks and handles prefix mismatches. -// Returns a filtered issues slice with tombstoned issues having wrong prefixes removed (bd-6pni). +// Returns a filtered issues slice with tombstoned issues having wrong prefixes removed. func handlePrefixMismatch(ctx context.Context, sqliteStore *sqlite.SQLiteStorage, issues []*types.Issue, opts Options, result *Result) ([]*types.Issue, error) { configuredPrefix, err := sqliteStore.GetConfig(ctx, "issue_prefix") if err != nil { @@ -216,7 +216,7 @@ func handlePrefixMismatch(ctx context.Context, sqliteStore *sqlite.SQLiteStorage result.ExpectedPrefix = configuredPrefix - // gt-2z6s: Read allowed_prefixes config for additional valid prefixes (e.g., mol-*) + // Read allowed_prefixes config for additional valid prefixes (e.g., mol-*) allowedPrefixesConfig, _ := sqliteStore.GetConfig(ctx, "allowed_prefixes") // GH#686: In multi-repo mode, allow all prefixes (nil = allow all) @@ -226,7 +226,7 @@ func handlePrefixMismatch(ctx context.Context, sqliteStore *sqlite.SQLiteStorage } // Analyze prefixes in imported issues - // Track tombstones separately - they don't count as "real" mismatches (bd-6pni) + // Track tombstones separately - they don't count as "real" mismatches tombstoneMismatchPrefixes := make(map[string]int) nonTombstoneMismatchCount := 0 @@ -238,7 +238,7 @@ func handlePrefixMismatch(ctx context.Context, sqliteStore *sqlite.SQLiteStorage // GH#422: Check if issue ID starts with configured prefix directly // rather than extracting/guessing. This handles multi-hyphen prefixes // like "asianops-audit-" correctly. - // gt-2z6s: Also check against allowed_prefixes config + // Also check against allowed_prefixes config prefixMatches := false for prefix := range allowedPrefixes { if strings.HasPrefix(issue.ID, prefix+"-") { @@ -265,7 +265,7 @@ func handlePrefixMismatch(ctx context.Context, sqliteStore *sqlite.SQLiteStorage } } - // bd-6pni: If ALL mismatched prefix issues are tombstones, they're just pollution + // If ALL mismatched prefix issues are tombstones, they're just pollution // from contributor PRs that used different test prefixes. These are safe to remove. if nonTombstoneMismatchCount == 0 && len(tombstoneMismatchPrefixes) > 0 { // Log that we're ignoring tombstoned mismatches @@ -323,9 +323,9 @@ func detectUpdates(ctx context.Context, sqliteStore *sqlite.SQLiteStorage, issue // So same ID + different fields = normal update operation, not a collision // The collisionResult.Collisions list represents issues that *may* be updated // Note: We don't pre-count updates here - upsertIssues will count them after - // checking timestamps to ensure we only update when incoming is newer (bd-e55c) + // checking timestamps to ensure we only update when incoming is newer - // Phase 4: Renames removed - obsolete with hash IDs (bd-8e05) + // Phase 4: Renames removed - obsolete with hash IDs // Hash-based IDs are content-addressed, so renames don't occur if opts.DryRun { @@ -401,7 +401,7 @@ func handleRename(ctx context.Context, s *sqlite.SQLiteStorage, existing *types. } return "", nil - /* OLD CODE REMOVED (bd-8e05) + /* OLD CODE REMOVED // Different content - this is a collision during rename // Allocate a new ID for the incoming issue instead of using the desired ID prefix, err := s.GetConfig(ctx, "issue_prefix") @@ -490,7 +490,7 @@ func handleRename(ctx context.Context, s *sqlite.SQLiteStorage, existing *types. return "", fmt.Errorf("failed to create renamed issue %s: %w", incoming.ID, err) } - // Reference updates removed - obsolete with hash IDs (bd-8e05) + // Reference updates removed - obsolete with hash IDs // Hash-based IDs are deterministic, so no reference rewriting needed return oldID, nil @@ -499,7 +499,7 @@ func handleRename(ctx context.Context, s *sqlite.SQLiteStorage, existing *types. // upsertIssues creates new issues or updates existing ones using content-first matching func upsertIssues(ctx context.Context, sqliteStore *sqlite.SQLiteStorage, issues []*types.Issue, opts Options, result *Result) error { // Get all DB issues once - include tombstones to prevent UNIQUE constraint violations - // when trying to create issues that were previously deleted (bd-sync-tombstone-fix) + // when trying to create issues that were previously deleted dbIssues, err := sqliteStore.SearchIssues(ctx, "", types.IssueFilter{IncludeTombstones: true}) if err != nil { return fmt.Errorf("failed to get DB issues: %w", err) @@ -549,7 +549,7 @@ func upsertIssues(ctx context.Context, sqliteStore *sqlite.SQLiteStorage, issues } seenIDs[incoming.ID] = true - // CRITICAL: Check for tombstone FIRST, before any other matching (bd-4q8 fix) + // CRITICAL: Check for tombstone FIRST, before any other matching // This prevents ghost resurrection regardless of which phase would normally match. // If this ID has a tombstone in the DB, skip importing it entirely. if existingByID, found := dbByID[incoming.ID]; found { @@ -565,7 +565,7 @@ func upsertIssues(ctx context.Context, sqliteStore *sqlite.SQLiteStorage, issues if existing, found := dbByExternalRef[*incoming.ExternalRef]; found { // Found match by external_ref - update the existing issue if !opts.SkipUpdate { - // Check timestamps - only update if incoming is newer (bd-e55c) + // Check timestamps - only update if incoming is newer if !incoming.UpdatedAt.After(existing.UpdatedAt) { // Local version is newer or same - skip update result.Unchanged++ @@ -583,7 +583,7 @@ func upsertIssues(ctx context.Context, sqliteStore *sqlite.SQLiteStorage, issues updates["acceptance_criteria"] = incoming.AcceptanceCriteria updates["notes"] = incoming.Notes updates["closed_at"] = incoming.ClosedAt - // Pinned field (bd-phtv): Only update if explicitly true in JSONL + // Pinned field: Only update if explicitly true in JSONL // (omitempty means false values are absent, so false = don't change existing) if incoming.Pinned { updates["pinned"] = incoming.Pinned @@ -654,7 +654,7 @@ func upsertIssues(ctx context.Context, sqliteStore *sqlite.SQLiteStorage, issues // Phase 2: New content - check for ID collision if existingWithID, found := dbByID[incoming.ID]; found { - // Skip tombstones - don't try to update or resurrect deleted issues (bd-sync-tombstone-fix) + // Skip tombstones - don't try to update or resurrect deleted issues if existingWithID.Status == types.StatusTombstone { result.Skipped++ continue @@ -663,7 +663,7 @@ func upsertIssues(ctx context.Context, sqliteStore *sqlite.SQLiteStorage, issues // The update should have been detected earlier by detectUpdates // If we reach here, it means collision wasn't resolved - treat as update if !opts.SkipUpdate { - // Check timestamps - only update if incoming is newer (bd-e55c) + // Check timestamps - only update if incoming is newer if !incoming.UpdatedAt.After(existingWithID.UpdatedAt) { // Local version is newer or same - skip update result.Unchanged++ @@ -681,7 +681,7 @@ func upsertIssues(ctx context.Context, sqliteStore *sqlite.SQLiteStorage, issues updates["acceptance_criteria"] = incoming.AcceptanceCriteria updates["notes"] = incoming.Notes updates["closed_at"] = incoming.ClosedAt - // Pinned field (bd-phtv): Only update if explicitly true in JSONL + // Pinned field: Only update if explicitly true in JSONL // (omitempty means false values are absent, so false = don't change existing) if incoming.Pinned { updates["pinned"] = incoming.Pinned @@ -717,7 +717,7 @@ func upsertIssues(ctx context.Context, sqliteStore *sqlite.SQLiteStorage, issues } } - // Filter out orphaned issues if orphan_handling is set to skip (bd-ckej) + // Filter out orphaned issues if orphan_handling is set to skip // Pre-filter before batch creation to prevent orphans from being created then ID-cleared if opts.OrphanHandling == sqlite.OrphanSkip { var filteredNewIssues []*types.Issue @@ -788,7 +788,7 @@ func upsertIssues(ctx context.Context, sqliteStore *sqlite.SQLiteStorage, issues } } - // REMOVED (bd-c7af): Counter sync after import - no longer needed with hash IDs + // REMOVED: Counter sync after import - no longer needed with hash IDs return nil } @@ -980,7 +980,7 @@ func validateNoDuplicateExternalRefs(issues []*types.Issue, clearDuplicates bool // buildAllowedPrefixSet returns allowed prefixes, or nil to allow all (GH#686). // In multi-repo mode, additional repos have their own prefixes - allow all. -// gt-2z6s: Also accepts allowedPrefixesConfig (comma-separated list like "gt-,mol-"). +// Also accepts allowedPrefixesConfig (comma-separated list like "gt-,mol-"). func buildAllowedPrefixSet(primaryPrefix string, allowedPrefixesConfig string) map[string]bool { if config.GetMultiRepoConfig() != nil { return nil // Multi-repo: allow all prefixes @@ -988,7 +988,7 @@ func buildAllowedPrefixSet(primaryPrefix string, allowedPrefixesConfig string) m allowed := map[string]bool{primaryPrefix: true} - // gt-2z6s: Parse allowed_prefixes config (comma-separated, with or without trailing -) + // Parse allowed_prefixes config (comma-separated, with or without trailing -) if allowedPrefixesConfig != "" { for _, prefix := range strings.Split(allowedPrefixesConfig, ",") { prefix = strings.TrimSpace(prefix) diff --git a/internal/merge/merge.go b/internal/merge/merge.go index 8d8e715a..656994f8 100644 --- a/internal/merge/merge.go +++ b/internal/merge/merge.go @@ -52,7 +52,7 @@ type Issue struct { CreatedBy string `json:"created_by,omitempty"` Dependencies []Dependency `json:"dependencies,omitempty"` RawLine string `json:"-"` // Store original line for conflict output - // Tombstone fields (bd-0ih): inline soft-delete support for merge + // Tombstone fields: inline soft-delete support for merge DeletedAt string `json:"deleted_at,omitempty"` // When the issue was deleted DeletedBy string `json:"deleted_by,omitempty"` // Who deleted the issue DeleteReason string `json:"delete_reason,omitempty"` // Why the issue was deleted @@ -240,7 +240,7 @@ func makeKey(issue Issue) IssueKey { } } -// bd-ig5: Use constants from types package to avoid duplication +// Use constants from types package to avoid duplication const StatusTombstone = string(types.StatusTombstone) // Alias TTL constants from types package for local use @@ -316,7 +316,7 @@ func Merge3WayWithTTL(base, left, right []Issue, ttl time.Duration) ([]Issue, [] rightMap[makeKey(issue)] = issue } - // bd-ncwo: Also build ID-based maps for fallback matching + // Also build ID-based maps for fallback matching // This handles cases where the same issue has slightly different CreatedAt/CreatedBy // (e.g., due to timestamp precision differences between systems) leftByID := make(map[string]Issue) @@ -331,7 +331,7 @@ func Merge3WayWithTTL(base, left, right []Issue, ttl time.Duration) ([]Issue, [] // Track which issues we've processed (by both key and ID) processed := make(map[IssueKey]bool) - processedIDs := make(map[string]bool) // bd-ncwo: track processed IDs to avoid duplicates + processedIDs := make(map[string]bool) // track processed IDs to avoid duplicates var result []Issue var conflicts []string @@ -357,7 +357,7 @@ func Merge3WayWithTTL(base, left, right []Issue, ttl time.Duration) ([]Issue, [] leftIssue, inLeft := leftMap[key] rightIssue, inRight := rightMap[key] - // bd-ncwo: ID-based fallback matching for tombstone preservation + // ID-based fallback matching for tombstone preservation // If key doesn't match but same ID exists in the other side, use that if !inLeft && inRight { if fallback, found := leftByID[rightIssue.ID]; found { @@ -376,7 +376,7 @@ func Merge3WayWithTTL(base, left, right []Issue, ttl time.Duration) ([]Issue, [] } } - // bd-ncwo: Check if we've already processed this ID (via a different key) + // Check if we've already processed this ID (via a different key) currentID := key.ID if currentID == "" { if inLeft { @@ -480,7 +480,7 @@ func Merge3WayWithTTL(base, left, right []Issue, ttl time.Duration) ([]Issue, [] result = append(result, merged) } else if inBase && inLeft && !inRight { // Deleted in right (implicitly), maybe modified in left - // bd-ki14: Check if left is a tombstone - tombstones must be preserved + // Check if left is a tombstone - tombstones must be preserved if leftTombstone { result = append(result, leftIssue) continue @@ -490,7 +490,7 @@ func Merge3WayWithTTL(base, left, right []Issue, ttl time.Duration) ([]Issue, [] continue } else if inBase && !inLeft && inRight { // Deleted in left (implicitly), maybe modified in right - // bd-ki14: Check if right is a tombstone - tombstones must be preserved + // Check if right is a tombstone - tombstones must be preserved if rightTombstone { result = append(result, rightIssue) continue @@ -513,7 +513,7 @@ func Merge3WayWithTTL(base, left, right []Issue, ttl time.Duration) ([]Issue, [] // mergeTombstones merges two tombstones for the same issue. // The tombstone with the later deleted_at timestamp wins. // -// bd-6x5: Edge cases for empty DeletedAt: +// Edge cases for empty DeletedAt: // - If both empty: left wins (arbitrary but deterministic) // - If left empty, right not: right wins (has timestamp) // - If right empty, left not: left wins (has timestamp) @@ -521,7 +521,7 @@ func Merge3WayWithTTL(base, left, right []Issue, ttl time.Duration) ([]Issue, [] // Empty DeletedAt shouldn't happen in valid data (validation catches it), // but we handle it defensively here. func mergeTombstones(left, right Issue) Issue { - // bd-6x5: Handle empty DeletedAt explicitly for clarity + // Handle empty DeletedAt explicitly for clarity if left.DeletedAt == "" && right.DeletedAt == "" { // Both invalid - left wins as tie-breaker return left @@ -577,10 +577,10 @@ func mergeIssue(base, left, right Issue) (Issue, string) { result.ClosedAt = "" } - // Merge dependencies - proper 3-way merge where removals win (bd-ndye) + // Merge dependencies - proper 3-way merge where removals win result.Dependencies = mergeDependencies(base.Dependencies, left.Dependencies, right.Dependencies) - // bd-1sn: If status became tombstone via mergeStatus safety fallback, + // If status became tombstone via mergeStatus safety fallback, // copy tombstone fields from whichever side has them if result.Status == StatusTombstone { // Prefer the side with more recent deleted_at, or left if tied @@ -686,7 +686,7 @@ func mergeNotes(base, left, right string) string { // mergePriority handles priority merging - on conflict, higher priority wins (lower number) // Special case: 0 is treated as "unset/no priority" due to Go's zero value. -// Any explicitly set priority (!=0) wins over 0. (bd-d0t fix, bd-1kf fix) +// Any explicitly set priority (!=0) wins over 0. func mergePriority(base, left, right int) int { // Standard 3-way merge for non-conflict cases if base == left && base != right { @@ -700,8 +700,8 @@ func mergePriority(base, left, right int) int { } // True conflict: both sides changed to different values - // bd-d0t fix: Treat 0 as "unset" - explicitly set priority wins over unset - // bd-1kf fix: Use != 0 instead of > 0 to handle negative priorities + // Treat 0 as "unset" - explicitly set priority wins over unset + // Use != 0 instead of > 0 to handle negative priorities if left == 0 && right != 0 { return right // right has explicit priority, left is unset } @@ -748,7 +748,7 @@ func isTimeAfter(t1, t2 string) bool { return true // t1 valid, t2 invalid - t1 wins } - // Both valid - compare. On exact tie, left wins for consistency with IssueType rule (bd-8nz) + // Both valid - compare. On exact tie, left wins for consistency with IssueType rule // Using !time2.After(time1) returns true when t1 > t2 OR t1 == t2 return !time2.After(time1) } @@ -794,7 +794,7 @@ func maxTime(t1, t2 string) string { return t2 } -// mergeDependencies performs a proper 3-way merge of dependencies (bd-ndye) +// mergeDependencies performs a proper 3-way merge of dependencies // Key principle: REMOVALS ARE AUTHORITATIVE // - If dep was in base and removed by left OR right → exclude (removal wins) // - If dep wasn't in base and added by left OR right → include diff --git a/internal/rpc/client.go b/internal/rpc/client.go index 747cfdf3..3bc330ac 100644 --- a/internal/rpc/client.go +++ b/internal/rpc/client.go @@ -400,7 +400,7 @@ func (c *Client) EpicStatus(args *EpicStatusArgs) (*Response, error) { return c.Execute(OpEpicStatus, args) } -// Gate operations (bd-likt) +// Gate operations // GateCreate creates a gate via the daemon func (c *Client) GateCreate(args *GateCreateArgs) (*Response, error) { diff --git a/internal/rpc/protocol.go b/internal/rpc/protocol.go index c0243011..9728725a 100644 --- a/internal/rpc/protocol.go +++ b/internal/rpc/protocol.go @@ -44,7 +44,7 @@ const ( OpDelete = "delete" OpGetWorkerStatus = "get_worker_status" - // Gate operations (bd-likt) + // Gate operations OpGateCreate = "gate_create" OpGateList = "gate_list" OpGateShow = "gate_show" @@ -85,14 +85,14 @@ type CreateArgs struct { EstimatedMinutes *int `json:"estimated_minutes,omitempty"` // Time estimate in minutes Labels []string `json:"labels,omitempty"` Dependencies []string `json:"dependencies,omitempty"` - // Waits-for dependencies (bd-xo1o.2) + // Waits-for dependencies WaitsFor string `json:"waits_for,omitempty"` // Spawner issue ID to wait for WaitsForGate string `json:"waits_for_gate,omitempty"` // Gate type: all-children or any-children - // Messaging fields (bd-kwro) + // Messaging fields Sender string `json:"sender,omitempty"` // Who sent this (for messages) Ephemeral bool `json:"ephemeral,omitempty"` // If true, not exported to JSONL; bulk-deleted when closed RepliesTo string `json:"replies_to,omitempty"` // Issue ID for conversation threading - // ID generation (bd-hobo) + // ID generation IDPrefix string `json:"id_prefix,omitempty"` // Override prefix for ID generation (mol, eph, etc.) CreatedBy string `json:"created_by,omitempty"` // Who created the issue } @@ -114,22 +114,22 @@ type UpdateArgs struct { AddLabels []string `json:"add_labels,omitempty"` RemoveLabels []string `json:"remove_labels,omitempty"` SetLabels []string `json:"set_labels,omitempty"` - // Messaging fields (bd-kwro) + // Messaging fields Sender *string `json:"sender,omitempty"` // Who sent this (for messages) Ephemeral *bool `json:"ephemeral,omitempty"` // If true, not exported to JSONL; bulk-deleted when closed RepliesTo *string `json:"replies_to,omitempty"` // Issue ID for conversation threading - // Graph link fields (bd-fu83) + // Graph link fields RelatesTo *string `json:"relates_to,omitempty"` // JSON array of related issue IDs DuplicateOf *string `json:"duplicate_of,omitempty"` // Canonical issue ID if duplicate SupersededBy *string `json:"superseded_by,omitempty"` // Replacement issue ID if obsolete - // Pinned field (bd-iea) + // Pinned field Pinned *bool `json:"pinned,omitempty"` // If true, issue is a persistent context marker - // Reparenting field (bd-cj2e) + // Reparenting field Parent *string `json:"parent,omitempty"` // New parent issue ID (reparents the issue) - // Agent slot fields (gt-h5sza) + // Agent slot fields HookBead *string `json:"hook_bead,omitempty"` // Current work on agent's hook (0..1) RoleBead *string `json:"role_bead,omitempty"` // Role definition bead for agent - // Agent state fields (bd-uxlb) + // Agent state fields AgentState *string `json:"agent_state,omitempty"` // Agent state (idle|running|stuck|stopped|dead) LastActivity *bool `json:"last_activity,omitempty"` // If true, update last_activity to now } @@ -192,16 +192,16 @@ type ListArgs struct { PriorityMin *int `json:"priority_min,omitempty"` PriorityMax *int `json:"priority_max,omitempty"` - // Pinned filtering (bd-p8e) + // Pinned filtering Pinned *bool `json:"pinned,omitempty"` - // Template filtering (beads-1ra) + // Template filtering IncludeTemplates bool `json:"include_templates,omitempty"` - // Parent filtering (bd-yqhh) + // Parent filtering ParentID string `json:"parent_id,omitempty"` - // Ephemeral filtering (bd-bkul) + // Ephemeral filtering Ephemeral *bool `json:"ephemeral,omitempty"` } @@ -455,7 +455,7 @@ type GetMutationsArgs struct { Since int64 `json:"since"` // Unix timestamp in milliseconds (0 for all recent) } -// Gate operations (bd-likt) +// Gate operations // GateCreateArgs represents arguments for creating a gate type GateCreateArgs struct { diff --git a/internal/rpc/server_issues_epics.go b/internal/rpc/server_issues_epics.go index 1436e4ec..6e5ec682 100644 --- a/internal/rpc/server_issues_epics.go +++ b/internal/rpc/server_issues_epics.go @@ -77,7 +77,7 @@ func updatesFromArgs(a UpdateArgs) map[string]interface{} { if a.IssueType != nil { u["issue_type"] = *a.IssueType } - // Messaging fields (bd-kwro) + // Messaging fields if a.Sender != nil { u["sender"] = *a.Sender } @@ -87,7 +87,7 @@ func updatesFromArgs(a UpdateArgs) map[string]interface{} { if a.RepliesTo != nil { u["replies_to"] = *a.RepliesTo } - // Graph link fields (bd-fu83) + // Graph link fields if a.RelatesTo != nil { u["relates_to"] = *a.RelatesTo } @@ -97,18 +97,18 @@ func updatesFromArgs(a UpdateArgs) map[string]interface{} { if a.SupersededBy != nil { u["superseded_by"] = *a.SupersededBy } - // Pinned field (bd-iea) + // Pinned field if a.Pinned != nil { u["pinned"] = *a.Pinned } - // Agent slot fields (gt-h5sza) + // Agent slot fields if a.HookBead != nil { u["hook_bead"] = *a.HookBead } if a.RoleBead != nil { u["role_bead"] = *a.RoleBead } - // Agent state fields (bd-uxlb) + // Agent state fields if a.AgentState != nil { u["agent_state"] = *a.AgentState } @@ -189,11 +189,11 @@ func (s *Server) handleCreate(req *Request) Response { ExternalRef: externalRef, EstimatedMinutes: createArgs.EstimatedMinutes, Status: types.StatusOpen, - // Messaging fields (bd-kwro) + // Messaging fields Sender: createArgs.Sender, Ephemeral: createArgs.Ephemeral, // NOTE: RepliesTo now handled via replies-to dependency (Decision 004) - // ID generation (bd-hobo) + // ID generation IDPrefix: createArgs.IDPrefix, CreatedBy: createArgs.CreatedBy, } @@ -326,7 +326,7 @@ func (s *Server) handleCreate(req *Request) Response { } } - // Add waits-for dependency if specified (bd-xo1o.2) + // Add waits-for dependency if specified if createArgs.WaitsFor != "" { // Validate gate type gate := createArgs.WaitsForGate @@ -480,7 +480,7 @@ func (s *Server) handleUpdate(req *Request) Response { } } - // Handle reparenting (bd-cj2e) + // Handle reparenting if updateArgs.Parent != nil { newParentID := *updateArgs.Parent @@ -715,7 +715,7 @@ func (s *Server) handleDelete(req *Request) Response { continue } - // Create tombstone instead of hard delete (bd-rp4o fix) + // Create tombstone instead of hard delete // This preserves deletion history and prevents resurrection during sync type tombstoner interface { CreateTombstone(ctx context.Context, id string, actor string, reason string) error @@ -901,21 +901,21 @@ func (s *Server) handleList(req *Request) Response { filter.PriorityMin = listArgs.PriorityMin filter.PriorityMax = listArgs.PriorityMax - // Pinned filtering (bd-p8e) + // Pinned filtering filter.Pinned = listArgs.Pinned - // Template filtering (beads-1ra): exclude templates by default + // Template filtering: exclude templates by default if !listArgs.IncludeTemplates { isTemplate := false filter.IsTemplate = &isTemplate } - // Parent filtering (bd-yqhh) + // Parent filtering if listArgs.ParentID != "" { filter.ParentID = &listArgs.ParentID } - // Ephemeral filtering (bd-bkul) + // Ephemeral filtering filter.Ephemeral = listArgs.Ephemeral // Guard against excessive ID lists to avoid SQLite parameter limits @@ -1522,7 +1522,7 @@ func (s *Server) handleEpicStatus(req *Request) Response { } } -// Gate handlers (bd-likt) +// Gate handlers func (s *Server) handleGateCreate(req *Request) Response { var args GateCreateArgs diff --git a/internal/rpc/server_labels_deps_comments.go b/internal/rpc/server_labels_deps_comments.go index b84782e6..d7973701 100644 --- a/internal/rpc/server_labels_deps_comments.go +++ b/internal/rpc/server_labels_deps_comments.go @@ -32,7 +32,7 @@ func (s *Server) handleDepAdd(req *Request) Response { } } - // Check for child→parent dependency anti-pattern (bd-nim5) + // Check for child->parent dependency anti-pattern // This creates a deadlock: child can't start (parent open), parent can't close (children not done) if isChildOf(depArgs.FromID, depArgs.ToID) { return Response{ diff --git a/internal/rpc/server_routing_validation_diagnostics.go b/internal/rpc/server_routing_validation_diagnostics.go index f7fedc54..b1b87161 100644 --- a/internal/rpc/server_routing_validation_diagnostics.go +++ b/internal/rpc/server_routing_validation_diagnostics.go @@ -56,7 +56,7 @@ func (s *Server) checkVersionCompatibility(clientVersion string) error { clientVersion, ServerVersion) } - // Compare full versions - daemon must be >= client (bd-ckvw: strict minor version gating) + // Compare full versions - daemon must be >= client (strict minor version gating) // This prevents stale daemons from serving requests with old schema assumptions cmp := semver.Compare(serverVer, clientVer) if cmp < 0 { @@ -146,7 +146,7 @@ func (s *Server) handleRequest(req *Request) Response { } } - // Check for stale JSONL and auto-import if needed (bd-160) + // Check for stale JSONL and auto-import if needed // Skip for write operations that will trigger export anyway // Skip for import operation itself to avoid recursion if req.Operation != OpPing && req.Operation != OpHealth && req.Operation != OpMetrics && @@ -227,7 +227,7 @@ func (s *Server) handleRequest(req *Request) Response { resp = s.handleGetWorkerStatus(req) case OpShutdown: resp = s.handleShutdown(req) - // Gate operations (bd-likt) + // Gate operations case OpGateCreate: resp = s.handleGateCreate(req) case OpGateList: diff --git a/internal/storage/sqlite/batch_ops.go b/internal/storage/sqlite/batch_ops.go index 87baed0d..20a2d525 100644 --- a/internal/storage/sqlite/batch_ops.go +++ b/internal/storage/sqlite/batch_ops.go @@ -17,7 +17,7 @@ func validateBatchIssues(issues []*types.Issue) error { } // validateBatchIssuesWithCustomStatuses validates all issues in a batch, -// allowing custom statuses in addition to built-in ones (bd-1pj6). +// allowing custom statuses in addition to built-in ones. func validateBatchIssuesWithCustomStatuses(issues []*types.Issue, customStatuses []string) error { now := time.Now() for i, issue := range issues { @@ -67,7 +67,7 @@ func (s *SQLiteStorage) generateBatchIDs(ctx context.Context, conn *sql.Conn, is var prefix string err := conn.QueryRowContext(ctx, `SELECT value FROM config WHERE key = ?`, "issue_prefix").Scan(&prefix) if err == sql.ErrNoRows || prefix == "" { - // CRITICAL: Reject operation if issue_prefix config is missing (bd-166) + // CRITICAL: Reject operation if issue_prefix config is missing return fmt.Errorf("database not initialized: issue_prefix config is missing (run 'bd init --prefix ' first)") } else if err != nil { return fmt.Errorf("failed to get config: %w", err) @@ -214,7 +214,7 @@ func checkForExistingIDs(ctx context.Context, conn *sql.Conn, issues []*types.Is // } // // // After importing with explicit IDs, sync counters to prevent collisions -// REMOVED (bd-c7af): SyncAllCounters example - no longer needed with hash IDs +// REMOVED: SyncAllCounters example - no longer needed with hash IDs // // Performance: // - 100 issues: ~30ms (vs ~900ms with CreateIssue loop) @@ -250,7 +250,7 @@ func (s *SQLiteStorage) CreateIssuesWithFullOptions(ctx context.Context, issues return nil } - // Fetch custom statuses for validation (bd-1pj6) + // Fetch custom statuses for validation customStatuses, err := s.GetCustomStatuses(ctx) if err != nil { return fmt.Errorf("failed to get custom statuses: %w", err) @@ -268,7 +268,7 @@ func (s *SQLiteStorage) CreateIssuesWithFullOptions(ctx context.Context, issues } defer func() { _ = conn.Close() }() - // Use retry logic with exponential backoff to handle SQLITE_BUSY under concurrent load (bd-ola6) + // Use retry logic with exponential backoff to handle SQLITE_BUSY under concurrent load if err := beginImmediateWithRetry(ctx, conn, 5, 10*time.Millisecond); err != nil { return fmt.Errorf("failed to begin immediate transaction: %w", err) } diff --git a/internal/storage/sqlite/dependencies.go b/internal/storage/sqlite/dependencies.go index 4cf4a401..fb516786 100644 --- a/internal/storage/sqlite/dependencies.go +++ b/internal/storage/sqlite/dependencies.go @@ -33,7 +33,7 @@ func (s *SQLiteStorage) AddDependency(ctx context.Context, dep *types.Dependency return fmt.Errorf("issue %s not found", dep.IssueID) } - // External refs (external::) don't need target validation (bd-zmmy) + // External refs (external::) don't need target validation // They are resolved lazily at query time by CheckExternalDep isExternalRef := strings.HasPrefix(dep.DependsOnID, "external:") @@ -169,7 +169,7 @@ func (s *SQLiteStorage) AddDependency(ctx context.Context, dep *types.Dependency return wrapDBError("mark issues dirty after adding dependency", err) } - // Invalidate blocked issues cache since dependencies changed (bd-5qim) + // Invalidate blocked issues cache since dependencies changed // Only invalidate for types that affect ready work calculation if dep.Type.AffectsReadyWork() { if err := s.invalidateBlockedCache(ctx, tx); err != nil { @@ -231,7 +231,7 @@ func (s *SQLiteStorage) RemoveDependency(ctx context.Context, issueID, dependsOn return wrapDBError("mark issues dirty after removing dependency", err) } - // Invalidate blocked issues cache if this was a blocking dependency (bd-5qim) + // Invalidate blocked issues cache if this was a blocking dependency if needsCacheInvalidation { if err := s.invalidateBlockedCache(ctx, tx); err != nil { return fmt.Errorf("failed to invalidate blocked cache: %w", err) @@ -627,7 +627,7 @@ func (s *SQLiteStorage) GetDependencyTree(ctx context.Context, issueID string, m nodes = append(nodes, &node) } - // Fetch external dependencies for all issues in the tree (bd-vks2) + // Fetch external dependencies for all issues in the tree // External deps like "external:project:capability" don't exist in the issues // table, so the recursive CTE above doesn't find them. We add them as // synthetic leaf nodes here. @@ -871,14 +871,14 @@ func (s *SQLiteStorage) scanIssues(ctx context.Context, rows *sql.Rows) ([]*type var deletedBy sql.NullString var deleteReason sql.NullString var originalType sql.NullString - // Messaging fields (bd-kwro) + // Messaging fields var sender sql.NullString var wisp sql.NullInt64 - // Pinned field (bd-7h5) + // Pinned field var pinned sql.NullInt64 - // Template field (beads-1ra) + // Template field var isTemplate sql.NullInt64 - // Gate fields (bd-udsi) + // Gate fields var awaitType sql.NullString var awaitID sql.NullString var timeoutNs sql.NullInt64 @@ -929,22 +929,22 @@ func (s *SQLiteStorage) scanIssues(ctx context.Context, rows *sql.Rows) ([]*type if originalType.Valid { issue.OriginalType = originalType.String } - // Messaging fields (bd-kwro) + // Messaging fields if sender.Valid { issue.Sender = sender.String } if wisp.Valid && wisp.Int64 != 0 { issue.Ephemeral = true } - // Pinned field (bd-7h5) + // Pinned field if pinned.Valid && pinned.Int64 != 0 { issue.Pinned = true } - // Template field (beads-1ra) + // Template field if isTemplate.Valid && isTemplate.Int64 != 0 { issue.IsTemplate = true } - // Gate fields (bd-udsi) + // Gate fields if awaitType.Valid { issue.AwaitType = awaitType.String } @@ -993,14 +993,14 @@ func (s *SQLiteStorage) scanIssuesWithDependencyType(ctx context.Context, rows * var deletedBy sql.NullString var deleteReason sql.NullString var originalType sql.NullString - // Messaging fields (bd-kwro) + // Messaging fields var sender sql.NullString var wisp sql.NullInt64 - // Pinned field (bd-7h5) + // Pinned field var pinned sql.NullInt64 - // Template field (beads-1ra) + // Template field var isTemplate sql.NullInt64 - // Gate fields (bd-udsi) + // Gate fields var awaitType sql.NullString var awaitID sql.NullString var timeoutNs sql.NullInt64 @@ -1050,22 +1050,22 @@ func (s *SQLiteStorage) scanIssuesWithDependencyType(ctx context.Context, rows * if originalType.Valid { issue.OriginalType = originalType.String } - // Messaging fields (bd-kwro) + // Messaging fields if sender.Valid { issue.Sender = sender.String } if wisp.Valid && wisp.Int64 != 0 { issue.Ephemeral = true } - // Pinned field (bd-7h5) + // Pinned field if pinned.Valid && pinned.Int64 != 0 { issue.Pinned = true } - // Template field (beads-1ra) + // Template field if isTemplate.Valid && isTemplate.Int64 != 0 { issue.IsTemplate = true } - // Gate fields (bd-udsi) + // Gate fields if awaitType.Valid { issue.AwaitType = awaitType.String } diff --git a/internal/storage/sqlite/migrations.go b/internal/storage/sqlite/migrations.go index 0d2d9399..c0b11c60 100644 --- a/internal/storage/sqlite/migrations.go +++ b/internal/storage/sqlite/migrations.go @@ -85,19 +85,19 @@ func getMigrationDescription(name string) string { "source_repo_column": "Adds source_repo column for multi-repo support", "repo_mtimes_table": "Adds repo_mtimes table for multi-repo hydration caching", "child_counters_table": "Adds child_counters table for hierarchical ID generation with ON DELETE CASCADE", - "blocked_issues_cache": "Adds blocked_issues_cache table for GetReadyWork performance optimization (bd-5qim)", - "orphan_detection": "Detects orphaned child issues and logs them for user action (bd-3852)", - "close_reason_column": "Adds close_reason column to issues table for storing closure explanations (bd-uyu)", - "tombstone_columns": "Adds tombstone columns (deleted_at, deleted_by, delete_reason, original_type) for inline soft-delete (bd-vw8)", - "messaging_fields": "Adds messaging fields (sender, ephemeral, replies_to, relates_to, duplicate_of, superseded_by) for inter-agent communication (bd-kwro)", + "blocked_issues_cache": "Adds blocked_issues_cache table for GetReadyWork performance optimization", + "orphan_detection": "Detects orphaned child issues and logs them for user action", + "close_reason_column": "Adds close_reason column to issues table for storing closure explanations", + "tombstone_columns": "Adds tombstone columns (deleted_at, deleted_by, delete_reason, original_type) for inline soft-delete", + "messaging_fields": "Adds messaging fields (sender, ephemeral, replies_to, relates_to, duplicate_of, superseded_by) for inter-agent communication", "edge_consolidation": "Adds metadata and thread_id columns to dependencies table for edge schema consolidation (Decision 004)", "migrate_edge_fields": "Migrates existing issue fields (replies_to, relates_to, duplicate_of, superseded_by) to dependency edges (Decision 004 Phase 3)", "drop_edge_columns": "Drops deprecated edge columns (replies_to, relates_to, duplicate_of, superseded_by) from issues table (Decision 004 Phase 4)", - "pinned_column": "Adds pinned column for persistent context markers (bd-7h5)", - "is_template_column": "Adds is_template column for template molecules (beads-1ra)", - "remove_depends_on_fk": "Removes FK constraint on depends_on_id to allow external references (bd-zmmy)", - "additional_indexes": "Adds performance optimization indexes for common query patterns (bd-h0we)", - "gate_columns": "Adds gate columns (await_type, await_id, timeout_ns, waiters) for async coordination (bd-udsi)", + "pinned_column": "Adds pinned column for persistent context markers", + "is_template_column": "Adds is_template column for template molecules", + "remove_depends_on_fk": "Removes FK constraint on depends_on_id to allow external references", + "additional_indexes": "Adds performance optimization indexes for common query patterns", + "gate_columns": "Adds gate columns (await_type, await_id, timeout_ns, waiters) for async coordination", } if desc, ok := descriptions[name]; ok { diff --git a/internal/storage/sqlite/migrations/015_blocked_issues_cache.go b/internal/storage/sqlite/migrations/015_blocked_issues_cache.go index 7b587bfe..ec5b9923 100644 --- a/internal/storage/sqlite/migrations/015_blocked_issues_cache.go +++ b/internal/storage/sqlite/migrations/015_blocked_issues_cache.go @@ -7,7 +7,7 @@ import ( // MigrateBlockedIssuesCache creates the blocked_issues_cache table for performance optimization // This cache materializes the recursive CTE computation from GetReadyWork to avoid -// expensive recursive queries on every call (bd-5qim) +// expensive recursive queries on every call func MigrateBlockedIssuesCache(db *sql.DB) error { // Check if table already exists var tableName string diff --git a/internal/storage/sqlite/migrations/018_tombstone_columns.go b/internal/storage/sqlite/migrations/018_tombstone_columns.go index 58f2f2b7..186b6e02 100644 --- a/internal/storage/sqlite/migrations/018_tombstone_columns.go +++ b/internal/storage/sqlite/migrations/018_tombstone_columns.go @@ -6,7 +6,7 @@ import ( ) // MigrateTombstoneColumns adds tombstone support columns to the issues table. -// These columns support inline soft-delete (bd-vw8) replacing deletions.jsonl: +// These columns support inline soft-delete, replacing deletions.jsonl: // - deleted_at: when the issue was deleted // - deleted_by: who deleted the issue // - delete_reason: why the issue was deleted @@ -43,7 +43,7 @@ func MigrateTombstoneColumns(db *sql.DB) error { } } - // Add partial index on deleted_at for efficient TTL queries (bd-saa) + // Add partial index on deleted_at for efficient TTL queries // Only indexes non-NULL values, making it very efficient for tombstone filtering _, err := db.Exec(`CREATE INDEX IF NOT EXISTS idx_issues_deleted_at ON issues(deleted_at) WHERE deleted_at IS NOT NULL`) if err != nil { diff --git a/internal/storage/sqlite/migrations/019_messaging_fields.go b/internal/storage/sqlite/migrations/019_messaging_fields.go index 6b44d237..82f39da4 100644 --- a/internal/storage/sqlite/migrations/019_messaging_fields.go +++ b/internal/storage/sqlite/migrations/019_messaging_fields.go @@ -6,7 +6,7 @@ import ( ) // MigrateMessagingFields adds messaging and graph link support columns to the issues table. -// These columns support inter-agent communication (bd-kwro): +// These columns support inter-agent communication: // - sender: who sent this message // - ephemeral: can be bulk-deleted when closed // - replies_to: issue ID for conversation threading diff --git a/internal/storage/sqlite/migrations/023_pinned_column.go b/internal/storage/sqlite/migrations/023_pinned_column.go index 73c238dc..76d2013b 100644 --- a/internal/storage/sqlite/migrations/023_pinned_column.go +++ b/internal/storage/sqlite/migrations/023_pinned_column.go @@ -6,7 +6,7 @@ import ( ) // MigratePinnedColumn adds the pinned column to the issues table. -// Pinned issues are persistent context markers that should not be treated as work items (bd-7h5). +// Pinned issues are persistent context markers that should not be treated as work items. func MigratePinnedColumn(db *sql.DB) error { // Check if column already exists var columnExists bool diff --git a/internal/storage/sqlite/migrations/026_additional_indexes.go b/internal/storage/sqlite/migrations/026_additional_indexes.go index c729d4a8..417ec0ea 100644 --- a/internal/storage/sqlite/migrations/026_additional_indexes.go +++ b/internal/storage/sqlite/migrations/026_additional_indexes.go @@ -6,14 +6,14 @@ import ( ) // MigrateAdditionalIndexes adds performance optimization indexes identified -// during schema review (bd-h0we). +// during schema review. // // Indexes added: -// - idx_issues_updated_at: For GetStaleIssues date filtering (bd-bha9) -// - idx_issues_status_priority: For common list query patterns (bd-a9y3) -// - idx_labels_label_issue: Covering index for label lookups (bd-jke6) -// - idx_dependencies_issue_type: For blocked issues queries (bd-8x3w) -// - idx_events_issue_type: For close reason queries (bd-lk39) +// - idx_issues_updated_at: For GetStaleIssues date filtering +// - idx_issues_status_priority: For common list query patterns +// - idx_labels_label_issue: Covering index for label lookups +// - idx_dependencies_issue_type: For blocked issues queries +// - idx_events_issue_type: For close reason queries func MigrateAdditionalIndexes(db *sql.DB) error { indexes := []struct { name string diff --git a/internal/storage/sqlite/migrations/027_gate_columns.go b/internal/storage/sqlite/migrations/027_gate_columns.go index 5d4fc3e9..1236e383 100644 --- a/internal/storage/sqlite/migrations/027_gate_columns.go +++ b/internal/storage/sqlite/migrations/027_gate_columns.go @@ -5,7 +5,7 @@ import ( "fmt" ) -// MigrateGateColumns adds gate-related columns to the issues table for async coordination (bd-udsi). +// MigrateGateColumns adds gate-related columns to the issues table for async coordination. // Gate fields enable agents to wait on external conditions (CI completion, human approval, etc.) func MigrateGateColumns(db *sql.DB) error { columns := []struct { diff --git a/internal/storage/sqlite/migrations/030_agent_fields.go b/internal/storage/sqlite/migrations/030_agent_fields.go index 5ab220b4..8d0e764c 100644 --- a/internal/storage/sqlite/migrations/030_agent_fields.go +++ b/internal/storage/sqlite/migrations/030_agent_fields.go @@ -6,7 +6,7 @@ import ( ) // MigrateAgentFields adds agent-specific fields to the issues table. -// These fields support the agent-as-bead pattern (gt-v2gkv, gt-h5sza): +// These fields support the agent-as-bead pattern: // - hook_bead: current work attached to agent's hook (0..1 cardinality) // - role_bead: reference to role definition bead // - agent_state: agent-reported state (idle|running|stuck|stopped) diff --git a/internal/storage/sqlite/queries.go b/internal/storage/sqlite/queries.go index e134185f..38d9c1bc 100644 --- a/internal/storage/sqlite/queries.go +++ b/internal/storage/sqlite/queries.go @@ -59,23 +59,23 @@ func formatJSONStringArray(arr []string) string { return string(data) } -// REMOVED (bd-8e05): getNextIDForPrefix and AllocateNextID - sequential ID generation +// REMOVED: getNextIDForPrefix and AllocateNextID - sequential ID generation // no longer needed with hash-based IDs -// Migration functions moved to migrations.go (bd-fc2d, bd-b245) +// Migration functions moved to migrations.go // getNextChildNumber atomically generates the next child number for a parent ID // Uses the child_counters table for atomic, cross-process child ID generation -// Hash ID generation functions moved to hash_ids.go (bd-90a5) +// Hash ID generation functions moved to hash_ids.go -// REMOVED (bd-c7af): SyncAllCounters - no longer needed with hash IDs +// REMOVED: SyncAllCounters - no longer needed with hash IDs -// REMOVED (bd-166): derivePrefixFromPath was causing duplicate issues with wrong prefix +// REMOVED: derivePrefixFromPath was causing duplicate issues with wrong prefix // The database should ALWAYS have issue_prefix config set explicitly (by 'bd init' or auto-import) // Never derive prefix from filename - it leads to silent data corruption // CreateIssue creates a new issue func (s *SQLiteStorage) CreateIssue(ctx context.Context, issue *types.Issue, actor string) error { - // Fetch custom statuses for validation (bd-1pj6) + // Fetch custom statuses for validation customStatuses, err := s.GetCustomStatuses(ctx) if err != nil { return fmt.Errorf("failed to get custom statuses: %w", err) @@ -116,7 +116,7 @@ func (s *SQLiteStorage) CreateIssue(ctx context.Context, issue *types.Issue, act return fmt.Errorf("validation failed: %w", err) } - // Compute content hash (bd-95) + // Compute content hash if issue.ContentHash == "" { issue.ContentHash = issue.ComputeContentHash() } @@ -138,7 +138,7 @@ func (s *SQLiteStorage) CreateIssue(ctx context.Context, issue *types.Issue, act // We use raw Exec instead of BeginTx because database/sql doesn't support transaction // modes in BeginTx, and modernc.org/sqlite's BeginTx always uses DEFERRED mode. // - // Use retry logic with exponential backoff to handle SQLITE_BUSY under concurrent load (bd-ola6) + // Use retry logic with exponential backoff to handle SQLITE_BUSY under concurrent load if err := beginImmediateWithRetry(ctx, conn, 5, 10*time.Millisecond); err != nil { return fmt.Errorf("failed to begin immediate transaction: %w", err) } @@ -156,14 +156,14 @@ func (s *SQLiteStorage) CreateIssue(ctx context.Context, issue *types.Issue, act var configPrefix string err = conn.QueryRowContext(ctx, `SELECT value FROM config WHERE key = ?`, "issue_prefix").Scan(&configPrefix) if err == sql.ErrNoRows || configPrefix == "" { - // CRITICAL: Reject operation if issue_prefix config is missing (bd-166) + // CRITICAL: Reject operation if issue_prefix config is missing // This prevents duplicate issues with wrong prefix return fmt.Errorf("database not initialized: issue_prefix config is missing (run 'bd init --prefix ' first)") } else if err != nil { return fmt.Errorf("failed to get config: %w", err) } - // Use IDPrefix override if set, combined with config prefix (bd-hobo) + // Use IDPrefix override if set, combined with config prefix // e.g., configPrefix="bd" + IDPrefix="wisp" → "bd-wisp" prefix := configPrefix if issue.IDPrefix != "" { @@ -172,14 +172,14 @@ func (s *SQLiteStorage) CreateIssue(ctx context.Context, issue *types.Issue, act // Generate or validate ID if issue.ID == "" { - // Generate hash-based ID with adaptive length based on database size (bd-ea2a13) + // Generate hash-based ID with adaptive length based on database size generatedID, err := GenerateIssueID(ctx, conn, prefix, issue, actor) if err != nil { return wrapDBError("generate issue ID", err) } issue.ID = generatedID } else { - // Validate that explicitly provided ID matches the configured prefix (bd-177) + // Validate that explicitly provided ID matches the configured prefix if err := ValidateIssueIDPrefix(issue.ID, prefix); err != nil { return wrapDBError("validate issue ID prefix", err) } @@ -235,7 +235,7 @@ func (s *SQLiteStorage) CreateIssue(ctx context.Context, issue *types.Issue, act } // validateBatchIssues validates all issues in a batch and sets timestamps -// Batch operation functions moved to batch_ops.go (bd-c796) +// Batch operation functions moved to batch_ops.go // GetIssue retrieves an issue by ID func (s *SQLiteStorage) GetIssue(ctx context.Context, id string) (*types.Issue, error) { @@ -260,19 +260,19 @@ func (s *SQLiteStorage) GetIssue(ctx context.Context, id string) (*types.Issue, var deletedBy sql.NullString var deleteReason sql.NullString var originalType sql.NullString - // Messaging fields (bd-kwro) + // Messaging fields var sender sql.NullString var wisp sql.NullInt64 - // Pinned field (bd-7h5) + // Pinned field var pinned sql.NullInt64 - // Template field (beads-1ra) + // Template field var isTemplate sql.NullInt64 - // Gate fields (bd-udsi) + // Gate fields var awaitType sql.NullString var awaitID sql.NullString var timeoutNs sql.NullInt64 var waiters sql.NullString - // Agent fields (gt-h5sza) + // Agent fields var hookBead sql.NullString var roleBead sql.NullString var agentState sql.NullString @@ -353,22 +353,22 @@ func (s *SQLiteStorage) GetIssue(ctx context.Context, id string) (*types.Issue, if originalType.Valid { issue.OriginalType = originalType.String } - // Messaging fields (bd-kwro) + // Messaging fields if sender.Valid { issue.Sender = sender.String } if wisp.Valid && wisp.Int64 != 0 { issue.Ephemeral = true } - // Pinned field (bd-7h5) + // Pinned field if pinned.Valid && pinned.Int64 != 0 { issue.Pinned = true } - // Template field (beads-1ra) + // Template field if isTemplate.Valid && isTemplate.Int64 != 0 { issue.IsTemplate = true } - // Gate fields (bd-udsi) + // Gate fields if awaitType.Valid { issue.AwaitType = awaitType.String } @@ -381,7 +381,7 @@ func (s *SQLiteStorage) GetIssue(ctx context.Context, id string) (*types.Issue, if waiters.Valid && waiters.String != "" { issue.Waiters = parseJSONStringArray(waiters.String) } - // Agent fields (gt-h5sza) + // Agent fields if hookBead.Valid { issue.HookBead = hookBead.String } @@ -503,14 +503,14 @@ func (s *SQLiteStorage) GetIssueByExternalRef(ctx context.Context, externalRef s var deletedBy sql.NullString var deleteReason sql.NullString var originalType sql.NullString - // Messaging fields (bd-kwro) + // Messaging fields var sender sql.NullString var wisp sql.NullInt64 - // Pinned field (bd-7h5) + // Pinned field var pinned sql.NullInt64 - // Template field (beads-1ra) + // Template field var isTemplate sql.NullInt64 - // Gate fields (bd-udsi) + // Gate fields var awaitType sql.NullString var awaitID sql.NullString var timeoutNs sql.NullInt64 @@ -585,22 +585,22 @@ func (s *SQLiteStorage) GetIssueByExternalRef(ctx context.Context, externalRef s if originalType.Valid { issue.OriginalType = originalType.String } - // Messaging fields (bd-kwro) + // Messaging fields if sender.Valid { issue.Sender = sender.String } if wisp.Valid && wisp.Int64 != 0 { issue.Ephemeral = true } - // Pinned field (bd-7h5) + // Pinned field if pinned.Valid && pinned.Int64 != 0 { issue.Pinned = true } - // Template field (beads-1ra) + // Template field if isTemplate.Valid && isTemplate.Int64 != 0 { issue.IsTemplate = true } - // Gate fields (bd-udsi) + // Gate fields if awaitType.Valid { issue.AwaitType = awaitType.String } @@ -638,14 +638,14 @@ var allowedUpdateFields = map[string]bool{ "estimated_minutes": true, "external_ref": true, "closed_at": true, - // Messaging fields (bd-kwro) + // Messaging fields "sender": true, "wisp": true, // Database column is 'ephemeral', mapped in UpdateIssue - // Pinned field (bd-7h5) + // Pinned field "pinned": true, // NOTE: replies_to, relates_to, duplicate_of, superseded_by removed per Decision 004 // Use AddDependency() to create graph edges instead - // Agent slot fields (gt-h5sza) + // Agent slot fields "hook_bead": true, "role_bead": true, "agent_state": true, @@ -655,7 +655,7 @@ var allowedUpdateFields = map[string]bool{ } // validatePriority validates a priority value -// Validation functions moved to validators.go (bd-d9e0) +// Validation functions moved to validators.go // determineEventType determines the event type for an update based on old and new status func determineEventType(oldIssue *types.Issue, updates map[string]interface{}) types.EventType { @@ -734,7 +734,7 @@ func (s *SQLiteStorage) UpdateIssue(ctx context.Context, id string, updates map[ return fmt.Errorf("issue %s not found", id) } - // Fetch custom statuses for validation (bd-1pj6) + // Fetch custom statuses for validation customStatuses, err := s.GetCustomStatuses(ctx) if err != nil { return wrapDBError("get custom statuses", err) @@ -767,7 +767,7 @@ func (s *SQLiteStorage) UpdateIssue(ctx context.Context, id string, updates map[ // Auto-manage closed_at when status changes (enforce invariant) setClauses, args = manageClosedAt(oldIssue, updates, setClauses, args) - // Recompute content_hash if any content fields changed (bd-95) + // Recompute content_hash if any content fields changed contentChanged := false contentFields := []string{"title", "description", "design", "acceptance_criteria", "notes", "status", "priority", "issue_type", "assignee", "external_ref"} for _, field := range contentFields { @@ -886,7 +886,7 @@ func (s *SQLiteStorage) UpdateIssue(ctx context.Context, id string, updates map[ return fmt.Errorf("failed to mark issue dirty: %w", err) } - // Invalidate blocked issues cache if status changed (bd-5qim) + // Invalidate blocked issues cache if status changed // Status changes affect which issues are blocked (blockers must be open/in_progress/blocked) if _, statusChanged := updates["status"]; statusChanged { if err := s.invalidateBlockedCache(ctx, tx); err != nil { @@ -1023,14 +1023,14 @@ func (s *SQLiteStorage) RenameDependencyPrefix(ctx context.Context, oldPrefix, n return nil } -// RenameCounterPrefix is a no-op with hash-based IDs (bd-8e05) +// RenameCounterPrefix is a no-op with hash-based IDs // Kept for backward compatibility with rename-prefix command func (s *SQLiteStorage) RenameCounterPrefix(ctx context.Context, oldPrefix, newPrefix string) error { // Hash-based IDs don't use counters, so nothing to update return nil } -// ResetCounter is a no-op with hash-based IDs (bd-8e05) +// ResetCounter is a no-op with hash-based IDs // Kept for backward compatibility func (s *SQLiteStorage) ResetCounter(ctx context.Context, prefix string) error { // Hash-based IDs don't use counters, so nothing to reset @@ -1086,7 +1086,7 @@ func (s *SQLiteStorage) CloseIssue(ctx context.Context, id string, reason string return fmt.Errorf("failed to mark issue dirty: %w", err) } - // Invalidate blocked issues cache since status changed to closed (bd-5qim) + // Invalidate blocked issues cache since status changed to closed // Closed issues don't block others, so this affects blocking calculations if err := s.invalidateBlockedCache(ctx, tx); err != nil { return fmt.Errorf("failed to invalidate blocked cache: %w", err) @@ -1155,7 +1155,7 @@ func (s *SQLiteStorage) CreateTombstone(ctx context.Context, id string, actor st return fmt.Errorf("failed to mark issue dirty: %w", err) } - // Invalidate blocked issues cache since status changed (bd-5qim) + // Invalidate blocked issues cache since status changed // Tombstone issues don't block others, so this affects blocking calculations if err := s.invalidateBlockedCache(ctx, tx); err != nil { return fmt.Errorf("failed to invalidate blocked cache: %w", err) @@ -1188,7 +1188,7 @@ func (s *SQLiteStorage) DeleteIssue(ctx context.Context, id string) error { return fmt.Errorf("failed to delete events: %w", err) } - // Delete comments (no FK cascade on this table) (bd-687g) + // Delete comments (no FK cascade on this table) _, err = tx.ExecContext(ctx, `DELETE FROM comments WHERE issue_id = ?`, id) if err != nil { return fmt.Errorf("failed to delete comments: %w", err) @@ -1218,7 +1218,7 @@ func (s *SQLiteStorage) DeleteIssue(ctx context.Context, id string) error { return wrapDBError("commit delete transaction", err) } - // REMOVED (bd-c7af): Counter sync after deletion - no longer needed with hash IDs + // REMOVED: Counter sync after deletion - no longer needed with hash IDs return nil } @@ -1272,7 +1272,7 @@ func (s *SQLiteStorage) DeleteIssues(ctx context.Context, ids []string, cascade return nil, fmt.Errorf("failed to commit transaction: %w", err) } - // REMOVED (bd-c7af): Counter sync after deletion - no longer needed with hash IDs + // REMOVED: Counter sync after deletion - no longer needed with hash IDs return result, nil } @@ -1424,7 +1424,7 @@ func (s *SQLiteStorage) populateDeleteStats(ctx context.Context, tx *sql.Tx, inC } func (s *SQLiteStorage) executeDelete(ctx context.Context, tx *sql.Tx, inClause string, args []interface{}, result *DeleteIssuesResult) error { - // Note: This method now creates tombstones instead of hard-deleting (bd-3b4) + // Note: This method now creates tombstones instead of hard-deleting // Only dependencies are deleted - issues are converted to tombstones // 1. Delete dependencies - tombstones don't block other issues @@ -1500,7 +1500,7 @@ func (s *SQLiteStorage) executeDelete(ctx context.Context, tx *sql.Tx, inClause } } - // 4. Invalidate blocked issues cache since statuses changed (bd-5qim) + // 4. Invalidate blocked issues cache since statuses changed if err := s.invalidateBlockedCache(ctx, tx); err != nil { return fmt.Errorf("failed to invalidate blocked cache: %w", err) } @@ -1591,7 +1591,7 @@ func (s *SQLiteStorage) SearchIssues(ctx context.Context, query string, filter t whereClauses = append(whereClauses, "status = ?") args = append(args, *filter.Status) } else if !filter.IncludeTombstones { - // Exclude tombstones by default unless explicitly filtering for them (bd-1bu) + // Exclude tombstones by default unless explicitly filtering for them whereClauses = append(whereClauses, "status != ?") args = append(args, types.StatusTombstone) } @@ -1686,7 +1686,7 @@ func (s *SQLiteStorage) SearchIssues(ctx context.Context, query string, filter t whereClauses = append(whereClauses, fmt.Sprintf("id IN (%s)", strings.Join(placeholders, ", "))) } - // Wisp filtering (bd-kwro.9) + // Wisp filtering if filter.Ephemeral != nil { if *filter.Ephemeral { whereClauses = append(whereClauses, "ephemeral = 1") // SQL column is still 'ephemeral' @@ -1695,7 +1695,7 @@ func (s *SQLiteStorage) SearchIssues(ctx context.Context, query string, filter t } } - // Pinned filtering (bd-7h5) + // Pinned filtering if filter.Pinned != nil { if *filter.Pinned { whereClauses = append(whereClauses, "pinned = 1") @@ -1704,7 +1704,7 @@ func (s *SQLiteStorage) SearchIssues(ctx context.Context, query string, filter t } } - // Template filtering (beads-1ra) + // Template filtering if filter.IsTemplate != nil { if *filter.IsTemplate { whereClauses = append(whereClauses, "is_template = 1") @@ -1713,7 +1713,7 @@ func (s *SQLiteStorage) SearchIssues(ctx context.Context, query string, filter t } } - // Parent filtering (bd-yqhh): filter children by parent issue + // Parent filtering: filter children by parent issue if filter.ParentID != nil { whereClauses = append(whereClauses, "id IN (SELECT issue_id FROM dependencies WHERE type = 'parent-child' AND depends_on_id = ?)") args = append(args, *filter.ParentID) diff --git a/internal/storage/sqlite/ready.go b/internal/storage/sqlite/ready.go index 840d3d24..fdc3270b 100644 --- a/internal/storage/sqlite/ready.go +++ b/internal/storage/sqlite/ready.go @@ -13,16 +13,16 @@ import ( // GetReadyWork returns issues with no open blockers // By default, shows both 'open' and 'in_progress' issues so epics/tasks -// ready to close are visible (bd-165) -// Excludes pinned issues which are persistent anchors, not actionable work (bd-92u) +// ready to close are visible. +// Excludes pinned issues which are persistent anchors, not actionable work. func (s *SQLiteStorage) GetReadyWork(ctx context.Context, filter types.WorkFilter) ([]*types.Issue, error) { whereClauses := []string{ - "i.pinned = 0", // Exclude pinned issues (bd-92u) - "(i.ephemeral = 0 OR i.ephemeral IS NULL)", // Exclude wisps (hq-t15s) + "i.pinned = 0", // Exclude pinned issues + "(i.ephemeral = 0 OR i.ephemeral IS NULL)", // Exclude wisps } args := []interface{}{} - // Default to open OR in_progress if not specified (bd-165) + // Default to open OR in_progress if not specified if filter.Status == "" { whereClauses = append(whereClauses, "i.status IN ('open', 'in_progress')") } else { @@ -30,12 +30,12 @@ func (s *SQLiteStorage) GetReadyWork(ctx context.Context, filter types.WorkFilte args = append(args, filter.Status) } - // Filter by issue type (gt-ktf3: MQ integration) + // Filter by issue type for MQ integration if filter.Type != "" { whereClauses = append(whereClauses, "i.issue_type = ?") args = append(args, filter.Type) } else { - // Exclude workflow types from ready work by default (gt-7xtn) + // Exclude workflow types from ready work by default // These are internal workflow items, not work for polecats to claim: // - merge-request: processed by Refinery // - gate: async wait conditions @@ -123,7 +123,7 @@ func (s *SQLiteStorage) GetReadyWork(ctx context.Context, filter types.WorkFilte } orderBySQL := buildOrderByClause(sortPolicy) - // Use blocked_issues_cache for performance (bd-5qim) + // Use blocked_issues_cache for performance // This optimization replaces the recursive CTE that computed blocked issues on every query. // Performance improvement: 752ms → 29ms on 10K issues (25x speedup). // @@ -162,7 +162,7 @@ func (s *SQLiteStorage) GetReadyWork(ctx context.Context, filter types.WorkFilte return nil, err } - // Filter out issues with unsatisfied external dependencies (bd-zmmy) + // Filter out issues with unsatisfied external dependencies // Only check if external_projects are configured if len(config.GetExternalProjects()) > 0 && len(issues) > 0 { issues, err = s.filterByExternalDeps(ctx, issues) @@ -324,14 +324,14 @@ func (s *SQLiteStorage) GetStaleIssues(ctx context.Context, filter types.StaleFi var deletedBy sql.NullString var deleteReason sql.NullString var originalType sql.NullString - // Messaging fields (bd-kwro) + // Messaging fields var sender sql.NullString var ephemeral sql.NullInt64 - // Pinned field (bd-7h5) + // Pinned field var pinned sql.NullInt64 - // Template field (beads-1ra) + // Template field var isTemplate sql.NullInt64 - // Gate fields (bd-udsi) + // Gate fields var awaitType sql.NullString var awaitID sql.NullString var timeoutNs sql.NullInt64 @@ -395,22 +395,22 @@ func (s *SQLiteStorage) GetStaleIssues(ctx context.Context, filter types.StaleFi if originalType.Valid { issue.OriginalType = originalType.String } - // Messaging fields (bd-kwro) + // Messaging fields if sender.Valid { issue.Sender = sender.String } if ephemeral.Valid && ephemeral.Int64 != 0 { issue.Ephemeral = true } - // Pinned field (bd-7h5) + // Pinned field if pinned.Valid && pinned.Int64 != 0 { issue.Pinned = true } - // Template field (beads-1ra) + // Template field if isTemplate.Valid && isTemplate.Int64 != 0 { issue.IsTemplate = true } - // Gate fields (bd-udsi) + // Gate fields if awaitType.Valid { issue.AwaitType = awaitType.String } @@ -431,18 +431,18 @@ func (s *SQLiteStorage) GetStaleIssues(ctx context.Context, filter types.StaleFi } // GetBlockedIssues returns issues that are blocked by dependencies or have status=blocked -// Note: Pinned issues are excluded from the output (beads-ei4) -// Note: Includes external: references in blocked_by list (bd-om4a) +// Note: Pinned issues are excluded from the output. +// Note: Includes external: references in blocked_by list. func (s *SQLiteStorage) GetBlockedIssues(ctx context.Context, filter types.WorkFilter) ([]*types.BlockedIssue, error) { // Use UNION to combine: // 1. Issues with open/in_progress/blocked status that have dependency blockers // 2. Issues with status=blocked (even if they have no dependency blockers) // Use GROUP_CONCAT to get all blocker IDs in a single query (no N+1) - // Exclude pinned issues (beads-ei4) + // Exclude pinned issues. // // For blocked_by_count and blocker_ids: // - Count local blockers (open issues) + external refs (external:*) - // - External refs are always considered "open" until resolved (bd-om4a) + // - External refs are always considered "open" until resolved // Build additional WHERE clauses for filtering var filterClauses []string @@ -572,7 +572,7 @@ func (s *SQLiteStorage) GetBlockedIssues(ctx context.Context, filter types.WorkF blocked = append(blocked, &issue) } - // Filter out satisfied external dependencies from BlockedBy lists (bd-396j) + // Filter out satisfied external dependencies from BlockedBy lists // Only check if external_projects are configured if len(config.GetExternalProjects()) > 0 && len(blocked) > 0 { blocked = filterBlockedByExternalDeps(ctx, blocked) diff --git a/internal/storage/sqlite/store.go b/internal/storage/sqlite/store.go index f6a5b83c..2407129b 100644 --- a/internal/storage/sqlite/store.go +++ b/internal/storage/sqlite/store.go @@ -120,7 +120,7 @@ func NewWithTimeout(ctx context.Context, path string, busyTimeout time.Duration) // For all in-memory databases (including file::memory:), force single connection. // SQLite's in-memory databases are isolated per connection by default. - // Without this, different connections in the pool can't see each other's writes (bd-b121, bd-yvlc). + // Without this, different connections in the pool can't see each other's writes. isInMemory := path == ":memory:" || (strings.HasPrefix(path, "file:") && strings.Contains(path, "mode=memory")) if isInMemory { @@ -130,7 +130,7 @@ func NewWithTimeout(ctx context.Context, path string, busyTimeout time.Duration) // For file-based databases in daemon mode, limit connection pool to prevent // connection exhaustion under concurrent load. SQLite WAL mode supports // 1 writer + unlimited readers, but we limit to prevent goroutine pile-up - // on write lock contention (bd-qhws). + // on write lock contention. maxConns := runtime.NumCPU() + 1 // 1 writer + N readers db.SetMaxOpenConns(maxConns) db.SetMaxIdleConns(2) @@ -159,7 +159,7 @@ func NewWithTimeout(ctx context.Context, path string, busyTimeout time.Duration) return nil, err } - // Verify schema compatibility after migrations (bd-ckvw) + // Verify schema compatibility after migrations // First attempt if err := verifySchemaCompatibility(db); err != nil { // Schema probe failed - retry migrations once @@ -191,7 +191,7 @@ func NewWithTimeout(ctx context.Context, path string, busyTimeout time.Duration) busyTimeout: busyTimeout, } - // Hydrate from multi-repo config if configured (bd-307) + // Hydrate from multi-repo config if configured // Skip for in-memory databases (used in tests) if path != ":memory:" { _, err := storage.HydrateFromMultiRepo(ctx) diff --git a/internal/storage/sqlite/transaction.go b/internal/storage/sqlite/transaction.go index 82607f4a..627bc14b 100644 --- a/internal/storage/sqlite/transaction.go +++ b/internal/storage/sqlite/transaction.go @@ -48,7 +48,7 @@ func (s *SQLiteStorage) RunInTransaction(ctx context.Context, fn func(tx storage defer func() { _ = conn.Close() }() // Start IMMEDIATE transaction to acquire write lock early. - // Use retry logic with exponential backoff to handle SQLITE_BUSY (bd-ola6) + // Use retry logic with exponential backoff to handle SQLITE_BUSY if err := beginImmediateWithRetry(ctx, conn, 5, 10*time.Millisecond); err != nil { return fmt.Errorf("failed to begin transaction: %w", err) } @@ -91,7 +91,7 @@ func (s *SQLiteStorage) RunInTransaction(ctx context.Context, fn func(tx storage // CreateIssue creates a new issue within the transaction. func (t *sqliteTxStorage) CreateIssue(ctx context.Context, issue *types.Issue, actor string) error { - // Fetch custom statuses for validation (bd-1pj6) + // Fetch custom statuses for validation customStatuses, err := t.GetCustomStatuses(ctx) if err != nil { return fmt.Errorf("failed to get custom statuses: %w", err) @@ -132,7 +132,7 @@ func (t *sqliteTxStorage) CreateIssue(ctx context.Context, issue *types.Issue, a return fmt.Errorf("validation failed: %w", err) } - // Compute content hash (bd-95) + // Compute content hash if issue.ContentHash == "" { issue.ContentHash = issue.ComputeContentHash() } @@ -141,13 +141,13 @@ func (t *sqliteTxStorage) CreateIssue(ctx context.Context, issue *types.Issue, a var configPrefix string err = t.conn.QueryRowContext(ctx, `SELECT value FROM config WHERE key = ?`, "issue_prefix").Scan(&configPrefix) if err == sql.ErrNoRows || configPrefix == "" { - // CRITICAL: Reject operation if issue_prefix config is missing (bd-166) + // CRITICAL: Reject operation if issue_prefix config is missing return fmt.Errorf("database not initialized: issue_prefix config is missing (run 'bd init --prefix ' first)") } else if err != nil { return fmt.Errorf("failed to get config: %w", err) } - // Use IDPrefix override if set, combined with config prefix (bd-hobo) + // Use IDPrefix override if set, combined with config prefix // e.g., configPrefix="bd" + IDPrefix="wisp" → "bd-wisp" prefix := configPrefix if issue.IDPrefix != "" { @@ -156,14 +156,14 @@ func (t *sqliteTxStorage) CreateIssue(ctx context.Context, issue *types.Issue, a // Generate or validate ID if issue.ID == "" { - // Generate hash-based ID with adaptive length based on database size (bd-ea2a13) + // Generate hash-based ID with adaptive length based on database size generatedID, err := GenerateIssueID(ctx, t.conn, prefix, issue, actor) if err != nil { return fmt.Errorf("failed to generate issue ID: %w", err) } issue.ID = generatedID } else { - // Validate that explicitly provided ID matches the configured prefix (bd-177) + // Validate that explicitly provided ID matches the configured prefix if err := ValidateIssueIDPrefix(issue.ID, prefix); err != nil { return fmt.Errorf("failed to validate issue ID prefix: %w", err) } @@ -207,7 +207,7 @@ func (t *sqliteTxStorage) CreateIssues(ctx context.Context, issues []*types.Issu return nil } - // Fetch custom statuses for validation (bd-1pj6) + // Fetch custom statuses for validation customStatuses, err := t.GetCustomStatuses(ctx) if err != nil { return fmt.Errorf("failed to get custom statuses: %w", err) @@ -370,7 +370,7 @@ func (t *sqliteTxStorage) UpdateIssue(ctx context.Context, id string, updates ma return fmt.Errorf("issue %s not found", id) } - // Fetch custom statuses for validation (bd-1pj6) + // Fetch custom statuses for validation customStatuses, err := t.GetCustomStatuses(ctx) if err != nil { return fmt.Errorf("failed to get custom statuses: %w", err) @@ -398,7 +398,7 @@ func (t *sqliteTxStorage) UpdateIssue(ctx context.Context, id string, updates ma // Auto-manage closed_at when status changes setClauses, args = manageClosedAt(oldIssue, updates, setClauses, args) - // Recompute content_hash if any content fields changed (bd-95) + // Recompute content_hash if any content fields changed contentChanged := false contentFields := []string{"title", "description", "design", "acceptance_criteria", "notes", "status", "priority", "issue_type", "assignee", "external_ref"} for _, field := range contentFields { @@ -449,7 +449,7 @@ func (t *sqliteTxStorage) UpdateIssue(ctx context.Context, id string, updates ma return fmt.Errorf("failed to mark issue dirty: %w", err) } - // Invalidate blocked issues cache if status changed (bd-1c4h) + // Invalidate blocked issues cache if status changed // Status changes affect which issues are blocked (blockers must be open/in_progress/blocked) if _, statusChanged := updates["status"]; statusChanged { if err := t.parent.invalidateBlockedCache(ctx, t.conn); err != nil { @@ -555,7 +555,7 @@ func (t *sqliteTxStorage) CloseIssue(ctx context.Context, id string, reason stri return fmt.Errorf("failed to mark issue dirty: %w", err) } - // Invalidate blocked issues cache since status changed to closed (bd-1c4h) + // Invalidate blocked issues cache since status changed to closed // Closed issues don't block others, so this affects blocking calculations if err := t.parent.invalidateBlockedCache(ctx, t.conn); err != nil { return fmt.Errorf("failed to invalidate blocked cache: %w", err) @@ -617,7 +617,7 @@ func (t *sqliteTxStorage) AddDependency(ctx context.Context, dep *types.Dependen return fmt.Errorf("issue %s not found", dep.IssueID) } - // External refs (external::) don't need target validation (bd-zmmy) + // External refs (external::) don't need target validation // They are resolved lazily at query time by CheckExternalDep isExternalRef := strings.HasPrefix(dep.DependsOnID, "external:") @@ -720,7 +720,7 @@ func (t *sqliteTxStorage) AddDependency(ctx context.Context, dep *types.Dependen } } - // Invalidate blocked cache for blocking dependencies (bd-1c4h, bd-kzda) + // Invalidate blocked cache for blocking dependencies if dep.Type.AffectsReadyWork() { if err := t.parent.invalidateBlockedCache(ctx, t.conn); err != nil { return fmt.Errorf("failed to invalidate blocked cache: %w", err) @@ -732,13 +732,13 @@ func (t *sqliteTxStorage) AddDependency(ctx context.Context, dep *types.Dependen // RemoveDependency removes a dependency within the transaction. func (t *sqliteTxStorage) RemoveDependency(ctx context.Context, issueID, dependsOnID string, actor string) error { - // First, check what type of dependency is being removed (bd-1c4h) + // First, check what type of dependency is being removed var depType types.DependencyType err := t.conn.QueryRowContext(ctx, ` SELECT type FROM dependencies WHERE issue_id = ? AND depends_on_id = ? `, issueID, dependsOnID).Scan(&depType) - // Store whether cache needs invalidation before deletion (bd-1c4h, bd-kzda) + // Store whether cache needs invalidation before deletion needsCacheInvalidation := false if err == nil { needsCacheInvalidation = depType.AffectsReadyWork() @@ -777,7 +777,7 @@ func (t *sqliteTxStorage) RemoveDependency(ctx context.Context, issueID, depends return fmt.Errorf("failed to mark depends-on issue dirty: %w", err) } - // Invalidate blocked cache if this was a blocking dependency (bd-1c4h) + // Invalidate blocked cache if this was a blocking dependency if needsCacheInvalidation { if err := t.parent.invalidateBlockedCache(ctx, t.conn); err != nil { return fmt.Errorf("failed to invalidate blocked cache: %w", err) @@ -993,7 +993,7 @@ func (t *sqliteTxStorage) SearchIssues(ctx context.Context, query string, filter whereClauses = append(whereClauses, "status = ?") args = append(args, *filter.Status) } else if !filter.IncludeTombstones { - // Exclude tombstones by default unless explicitly filtering for them (bd-1bu) + // Exclude tombstones by default unless explicitly filtering for them whereClauses = append(whereClauses, "status != ?") args = append(args, types.StatusTombstone) } @@ -1088,7 +1088,7 @@ func (t *sqliteTxStorage) SearchIssues(ctx context.Context, query string, filter whereClauses = append(whereClauses, fmt.Sprintf("id IN (%s)", strings.Join(placeholders, ", "))) } - // Wisp filtering (bd-kwro.9) + // Wisp filtering if filter.Ephemeral != nil { if *filter.Ephemeral { whereClauses = append(whereClauses, "ephemeral = 1") // SQL column is still 'ephemeral' @@ -1097,7 +1097,7 @@ func (t *sqliteTxStorage) SearchIssues(ctx context.Context, query string, filter } } - // Pinned filtering (bd-7h5) + // Pinned filtering if filter.Pinned != nil { if *filter.Pinned { whereClauses = append(whereClauses, "pinned = 1") @@ -1106,7 +1106,7 @@ func (t *sqliteTxStorage) SearchIssues(ctx context.Context, query string, filter } } - // Parent filtering (bd-yqhh): filter children by parent issue + // Parent filtering: filter children by parent issue if filter.ParentID != nil { whereClauses = append(whereClauses, "id IN (SELECT issue_id FROM dependencies WHERE type = 'parent-child' AND depends_on_id = ?)") args = append(args, *filter.ParentID) @@ -1171,14 +1171,14 @@ func scanIssueRow(row scanner) (*types.Issue, error) { var deletedBy sql.NullString var deleteReason sql.NullString var originalType sql.NullString - // Messaging fields (bd-kwro) + // Messaging fields var sender sql.NullString var wisp sql.NullInt64 - // Pinned field (bd-7h5) + // Pinned field var pinned sql.NullInt64 - // Template field (beads-1ra) + // Template field var isTemplate sql.NullInt64 - // Gate fields (bd-udsi) + // Gate fields var awaitType sql.NullString var awaitID sql.NullString var timeoutNs sql.NullInt64 @@ -1239,22 +1239,22 @@ func scanIssueRow(row scanner) (*types.Issue, error) { if originalType.Valid { issue.OriginalType = originalType.String } - // Messaging fields (bd-kwro) + // Messaging fields if sender.Valid { issue.Sender = sender.String } if wisp.Valid && wisp.Int64 != 0 { issue.Ephemeral = true } - // Pinned field (bd-7h5) + // Pinned field if pinned.Valid && pinned.Int64 != 0 { issue.Pinned = true } - // Template field (beads-1ra) + // Template field if isTemplate.Valid && isTemplate.Int64 != 0 { issue.IsTemplate = true } - // Gate fields (bd-udsi) + // Gate fields if awaitType.Valid { issue.AwaitType = awaitType.String } diff --git a/internal/syncbranch/worktree.go b/internal/syncbranch/worktree.go index 42adbd6c..b1b750cd 100644 --- a/internal/syncbranch/worktree.go +++ b/internal/syncbranch/worktree.go @@ -45,14 +45,14 @@ type PullResult struct { JSONLPath string // Path to the synced JSONL in main repo Merged bool // True if divergent histories were merged FastForwarded bool // True if fast-forward was possible - Pushed bool // True if changes were pushed after merge (bd-7ch) + Pushed bool // True if changes were pushed after merge - // SafetyCheckTriggered indicates mass deletion was detected during merge (bd-4u8) + // SafetyCheckTriggered indicates mass deletion was detected during merge // When true, callers should check config option sync.require_confirmation_on_mass_delete SafetyCheckTriggered bool - // SafetyCheckDetails contains human-readable details about the mass deletion (bd-4u8) + // SafetyCheckDetails contains human-readable details about the mass deletion SafetyCheckDetails string - // SafetyWarnings contains warning messages from the safety check (bd-7z4) + // SafetyWarnings contains warning messages from the safety check // Caller should display these to the user as appropriate for their output format SafetyWarnings []string } @@ -60,7 +60,7 @@ type PullResult struct { // CommitToSyncBranch commits JSONL changes to the sync branch using a git worktree. // This allows committing to a different branch without changing the user's working directory. // -// IMPORTANT (bd-3s8 fix): Before committing, this function now performs a pre-emptive fetch +// IMPORTANT: Before committing, this function now performs a pre-emptive fetch // and fast-forward if possible. This reduces the likelihood of divergence by ensuring we're // building on top of the latest remote state when possible. // @@ -93,7 +93,7 @@ func CommitToSyncBranch(ctx context.Context, repoRoot, syncBranch, jsonlPath str // Get remote name remote := getRemoteForBranch(ctx, worktreePath, syncBranch) - // Pre-emptive fetch and fast-forward (bd-3s8 fix) + // Pre-emptive fetch and fast-forward // This reduces divergence by ensuring we commit on top of latest remote state if err := preemptiveFetchAndFastForward(ctx, worktreePath, syncBranch, remote); err != nil { // Non-fatal: if fetch fails (e.g., offline), we can still commit locally @@ -188,7 +188,7 @@ func preemptiveFetchAndFastForward(ctx context.Context, worktreePath, branch, re // PullFromSyncBranch pulls changes from the sync branch and copies JSONL to the main repo. // This fetches remote changes without affecting the user's working directory. // -// IMPORTANT (bd-3s8 fix): This function handles diverged histories gracefully by performing +// IMPORTANT: This function handles diverged histories gracefully by performing // a content-based merge instead of relying on git's commit-level merge. When local and remote // sync branches have diverged: // 1. Fetch remote changes (don't pull) @@ -198,11 +198,11 @@ func preemptiveFetchAndFastForward(ctx context.Context, worktreePath, branch, re // 5. Reset to remote's history (adopt remote commit graph) // 6. Commit merged content on top // -// IMPORTANT (bd-7ch): After successful content merge, auto-pushes to remote by default. +// IMPORTANT: After successful content merge, auto-pushes to remote by default. // Includes safety check: warns (but doesn't block) if >50% issues vanished AND >5 existed. // "Vanished" means removed from issues.jsonl entirely, NOT status=closed. // -// IMPORTANT (bd-4u8): If requireMassDeleteConfirmation is true and the safety check triggers, +// IMPORTANT: If requireMassDeleteConfirmation is true and the safety check triggers, // the function will NOT auto-push. Instead, it sets SafetyCheckTriggered=true in the result // and the caller should prompt for confirmation then call PushSyncBranch. // @@ -214,12 +214,12 @@ func preemptiveFetchAndFastForward(ctx context.Context, worktreePath, branch, re // - repoRoot: Path to the git repository root // - syncBranch: Name of the sync branch (e.g., "beads-sync") // - jsonlPath: Absolute path to the JSONL file in the main repo -// - push: If true, push to remote after merge (bd-7ch) -// - requireMassDeleteConfirmation: If true and mass deletion detected, skip push (bd-4u8) +// - push: If true, push to remote after merge +// - requireMassDeleteConfirmation: If true and mass deletion detected, skip push // // Returns PullResult with details about what was done, or error if failed. func PullFromSyncBranch(ctx context.Context, repoRoot, syncBranch, jsonlPath string, push bool, requireMassDeleteConfirmation ...bool) (*PullResult, error) { - // bd-4u8: Extract optional confirmation requirement parameter + // Extract optional confirmation requirement parameter requireConfirmation := false if len(requireMassDeleteConfirmation) > 0 { requireConfirmation = requireMassDeleteConfirmation[0] @@ -296,17 +296,17 @@ func PullFromSyncBranch(ctx context.Context, repoRoot, syncBranch, jsonlPath str return result, nil } - // Case 3: DIVERGED - perform content-based merge (bd-3s8 fix) + // Case 3: DIVERGED - perform content-based merge // This is the key fix: instead of git merge (which can fail), we: // 1. Extract JSONL content from base, local, and remote // 2. Merge at content level using our 3-way merge algorithm // 3. Reset to remote's commit history // 4. Commit merged content on top - // bd-7ch: Extract local content before merge for safety check + // Extract local content before merge for safety check localContent, extractErr := extractJSONLFromCommit(ctx, worktreePath, "HEAD", jsonlRelPath) if extractErr != nil { - // bd-feh: Add warning to result so callers can display appropriately (bd-dtm fix) + // Add warning to result so callers can display appropriately result.SafetyWarnings = append(result.SafetyWarnings, fmt.Sprintf("⚠️ Warning: Could not extract local content for safety check: %v", extractErr)) } @@ -355,7 +355,7 @@ func PullFromSyncBranch(ctx context.Context, repoRoot, syncBranch, jsonlPath str return nil, err } - // bd-7ch: Auto-push after successful content merge + // Auto-push after successful content merge if push && hasChanges { // Safety check: count issues before and after merge to detect mass deletion localCount := countIssuesInContent(localContent) @@ -369,23 +369,23 @@ func PullFromSyncBranch(ctx context.Context, repoRoot, syncBranch, jsonlPath str if localCount > 5 && mergedCount < localCount { vanishedPercent := float64(localCount-mergedCount) / float64(localCount) * 100 if vanishedPercent > 50 { - // bd-4u8: Set safety check fields for caller to handle confirmation + // Set safety check fields for caller to handle confirmation result.SafetyCheckTriggered = true result.SafetyCheckDetails = fmt.Sprintf("%.0f%% of issues vanished during merge (%d → %d issues)", vanishedPercent, localCount, mergedCount) - // bd-7z4: Return warnings in result instead of printing directly to stderr + // Return warnings in result instead of printing directly to stderr result.SafetyWarnings = append(result.SafetyWarnings, fmt.Sprintf("⚠️ Warning: %.0f%% of issues vanished during merge (%d → %d issues)", vanishedPercent, localCount, mergedCount)) - // bd-lsa: Add forensic info to warnings + // Add forensic info to warnings localIssues := parseIssuesFromContent(localContent) mergedIssues := parseIssuesFromContent(mergedContent) forensicLines := formatVanishedIssues(localIssues, mergedIssues, localCount, mergedCount) result.SafetyWarnings = append(result.SafetyWarnings, forensicLines...) - // bd-4u8: Check if confirmation is required before pushing + // Check if confirmation is required before pushing if requireConfirmation { result.SafetyWarnings = append(result.SafetyWarnings, " Push skipped - confirmation required (sync.require_confirmation_on_mass_delete=true)") @@ -758,7 +758,7 @@ func isNonFastForwardError(output string) bool { // 4. Run 3-way content merge (respects tombstones) // 5. Reset to remote, commit merged content // -// Fix for bd-kpy: Sync race where rebase-based divergence recovery resurrects tombstones. +// This fixes a sync race where rebase-based divergence recovery resurrects tombstones. func contentMergeRecovery(ctx context.Context, worktreePath, branch, remote string) error { // The JSONL is always at .beads/issues.jsonl relative to worktree jsonlRelPath := filepath.Join(".beads", "issues.jsonl") @@ -809,7 +809,7 @@ func contentMergeRecovery(ctx context.Context, worktreePath, branch, remote stri } // fetchAndRebaseInWorktree is DEPRECATED - kept for reference only. -// Use contentMergeRecovery instead to avoid tombstone resurrection (bd-kpy). +// Use contentMergeRecovery instead to avoid tombstone resurrection. func fetchAndRebaseInWorktree(ctx context.Context, worktreePath, branch, remote string) error { // Fetch latest from remote fetchCmd := exec.CommandContext(ctx, "git", "-C", worktreePath, "fetch", remote, branch) @@ -889,10 +889,10 @@ func pushFromWorktree(ctx context.Context, worktreePath, branch string) error { // Check if this is a non-fast-forward error (concurrent push conflict) if isNonFastForwardError(outputStr) { - // bd-kpy fix: Use content-level merge instead of git rebase. + // Use content-level merge instead of git rebase. // Git rebase is text-level and can resurrect tombstones. if mergeErr := contentMergeRecovery(ctx, worktreePath, branch, remote); mergeErr != nil { - // Content merge failed - provide clear recovery options (bd-vckm) + // Content merge failed - provide clear recovery options return fmt.Errorf(`sync branch diverged and automatic recovery failed The sync branch '%s' has diverged from remote '%s/%s' and automatic content merge failed. @@ -927,7 +927,7 @@ Merge error: %v`, branch, remote, branch, branch, lastErr, mergeErr) return fmt.Errorf("push failed after %d attempts: %w", maxRetries, lastErr) } -// PushSyncBranch pushes the sync branch to remote. (bd-4u8) +// PushSyncBranch pushes the sync branch to remote. // This is used after confirmation when sync.require_confirmation_on_mass_delete is enabled // and a mass deletion was detected during merge. // @@ -941,7 +941,7 @@ func PushSyncBranch(ctx context.Context, repoRoot, syncBranch string) error { // Worktree path is under .git/beads-worktrees/ worktreePath := filepath.Join(repoRoot, ".git", "beads-worktrees", syncBranch) - // bd-k2n: Recreate worktree if it was cleaned up, using the same pattern as CommitToSyncBranch + // Recreate worktree if it was cleaned up, using the same pattern as CommitToSyncBranch wtMgr := git.NewWorktreeManager(repoRoot) if err := wtMgr.CreateBeadsWorktree(syncBranch, worktreePath); err != nil { return fmt.Errorf("failed to ensure worktree exists: %w", err) @@ -1023,7 +1023,7 @@ func GetRepoRoot(ctx context.Context) (string, error) { } // countIssuesInContent counts the number of non-empty lines in JSONL content. -// Each non-empty line represents one issue. Used for safety checks (bd-7ch). +// Each non-empty line represents one issue. Used for safety checks. func countIssuesInContent(content []byte) int { if len(content) == 0 { return 0 @@ -1037,14 +1037,14 @@ func countIssuesInContent(content []byte) int { return count } -// issueSummary holds minimal issue info for forensic logging (bd-lsa) +// issueSummary holds minimal issue info for forensic logging type issueSummary struct { ID string `json:"id"` Title string `json:"title"` } // parseIssuesFromContent extracts issue IDs and titles from JSONL content. -// Used for forensic logging of vanished issues (bd-lsa). +// Used for forensic logging of vanished issues. func parseIssuesFromContent(content []byte) map[string]issueSummary { result := make(map[string]issueSummary) if len(content) == 0 { @@ -1077,7 +1077,7 @@ func formatVanishedIssues(localIssues, mergedIssues map[string]issueSummary, loc lines = append(lines, fmt.Sprintf(" After merge: %d issues", mergedCount)) lines = append(lines, " Vanished issues:") - // bd-ciu: Collect vanished IDs first, then sort for deterministic output + // Collect vanished IDs first, then sort for deterministic output var vanishedIDs []string for id := range localIssues { if _, exists := mergedIssues[id]; !exists { diff --git a/internal/types/types.go b/internal/types/types.go index d7d0e521..438c7103 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -33,46 +33,46 @@ type Issue struct { CompactedAtCommit *string `json:"compacted_at_commit,omitempty"` // Git commit hash when compacted OriginalSize int `json:"original_size,omitempty"` SourceRepo string `json:"-"` // Internal: Which repo owns this issue (multi-repo support) - NOT exported to JSONL - IDPrefix string `json:"-"` // Internal: Override prefix for ID generation (bd-hobo) - NOT exported to JSONL + IDPrefix string `json:"-"` // Internal: Override prefix for ID generation - NOT exported to JSONL Labels []string `json:"labels,omitempty"` // Populated only for export/import Dependencies []*Dependency `json:"dependencies,omitempty"` // Populated only for export/import Comments []*Comment `json:"comments,omitempty"` // Populated only for export/import - // Tombstone fields (bd-vw8): inline soft-delete support + // Tombstone fields: inline soft-delete support DeletedAt *time.Time `json:"deleted_at,omitempty"` // When the issue was deleted DeletedBy string `json:"deleted_by,omitempty"` // Who deleted the issue DeleteReason string `json:"delete_reason,omitempty"` // Why the issue was deleted OriginalType string `json:"original_type,omitempty"` // Issue type before deletion (for tombstones) - // Messaging fields (bd-kwro): inter-agent communication support + // Messaging fields: inter-agent communication support Sender string `json:"sender,omitempty"` // Who sent this (for messages) Ephemeral bool `json:"ephemeral,omitempty"` // If true, not exported to JSONL; bulk-deleted when closed // NOTE: RepliesTo, RelatesTo, DuplicateOf, SupersededBy moved to dependencies table // per Decision 004 (Edge Schema Consolidation). Use dependency API instead. - // Pinned field (bd-7h5): persistent context markers + // Pinned field: persistent context markers Pinned bool `json:"pinned,omitempty"` // If true, issue is a persistent context marker, not a work item - // Template field (beads-1ra): template molecule support + // Template field: template molecule support IsTemplate bool `json:"is_template,omitempty"` // If true, issue is a read-only template molecule - // Bonding fields (bd-rnnr): compound molecule lineage + // Bonding fields: compound molecule lineage BondedFrom []BondRef `json:"bonded_from,omitempty"` // For compounds: constituent protos - // HOP fields (bd-7pwh): entity tracking for CV chains + // HOP fields: entity tracking for CV chains Creator *EntityRef `json:"creator,omitempty"` // Who created this issue (human, agent, or org) Validations []Validation `json:"validations,omitempty"` // Who validated/approved this work - // Gate fields (bd-udsi): async coordination primitives + // Gate fields: async coordination primitives AwaitType string `json:"await_type,omitempty"` // Condition type: gh:run, gh:pr, timer, human, mail AwaitID string `json:"await_id,omitempty"` // Condition identifier (e.g., run ID, PR number) Timeout time.Duration `json:"timeout,omitempty"` // Max wait time before escalation Waiters []string `json:"waiters,omitempty"` // Mail addresses to notify when gate clears - // Source tracing fields (gt-8tmz.18): track where this issue came from during cooking + // Source tracing fields: track where this issue came from during cooking SourceFormula string `json:"source_formula,omitempty"` // Formula name where this step was defined SourceLocation string `json:"source_location,omitempty"` // Path within source: "steps[0]", "advice[0].after" - // Agent identity fields (gt-v2gkv): agent-as-bead support + // Agent identity fields: agent-as-bead support HookBead string `json:"hook_bead,omitempty"` // Current work attached to agent's hook (0..1) RoleBead string `json:"role_bead,omitempty"` // Role definition bead (required for agents) AgentState AgentState `json:"agent_state,omitempty"` // Agent-reported state (idle|running|stuck|stopped) @@ -121,7 +121,7 @@ func (i *Issue) ComputeContentHash() string { h.Write([]byte("template")) } h.Write([]byte{0}) - // Hash bonded_from for compound molecules (bd-rnnr) + // Hash bonded_from for compound molecules for _, br := range i.BondedFrom { h.Write([]byte(br.ProtoID)) h.Write([]byte{0}) @@ -130,7 +130,7 @@ func (i *Issue) ComputeContentHash() string { h.Write([]byte(br.BondPoint)) h.Write([]byte{0}) } - // Hash creator for HOP entity tracking (bd-m7ib) + // Hash creator for HOP entity tracking if i.Creator != nil { h.Write([]byte(i.Creator.Name)) h.Write([]byte{0}) @@ -141,7 +141,7 @@ func (i *Issue) ComputeContentHash() string { h.Write([]byte(i.Creator.ID)) h.Write([]byte{0}) } - // Hash validations for HOP proof-of-stake (bd-du9h) + // Hash validations for HOP proof-of-stake for _, v := range i.Validations { if v.Validator != nil { h.Write([]byte(v.Validator.Name)) @@ -162,7 +162,7 @@ func (i *Issue) ComputeContentHash() string { } h.Write([]byte{0}) } - // Hash gate fields for async coordination (bd-udsi) + // Hash gate fields for async coordination h.Write([]byte(i.AwaitType)) h.Write([]byte{0}) h.Write([]byte(i.AwaitID)) @@ -173,7 +173,7 @@ func (i *Issue) ComputeContentHash() string { h.Write([]byte(waiter)) h.Write([]byte{0}) } - // Hash agent identity fields (gt-v2gkv) + // Hash agent identity fields h.Write([]byte(i.HookBead)) h.Write([]byte{0}) h.Write([]byte(i.RoleBead)) @@ -198,7 +198,7 @@ const MinTombstoneTTL = 7 * 24 * time.Hour // ClockSkewGrace is added to TTL to handle clock drift between machines const ClockSkewGrace = 1 * time.Hour -// IsTombstone returns true if the issue has been soft-deleted (bd-vw8) +// IsTombstone returns true if the issue has been soft-deleted func (i *Issue) IsTombstone() bool { return i.Status == StatusTombstone } @@ -220,7 +220,7 @@ func (i *Issue) IsExpired(ttl time.Duration) bool { return false } - // Negative TTL means "immediately expired" - for --hard mode (bd-4q8 fix) + // Negative TTL means "immediately expired" - for --hard mode if ttl < 0 { return true } @@ -276,14 +276,14 @@ func (i *Issue) ValidateWithCustomStatuses(customStatuses []string) error { if i.Status != StatusClosed && i.Status != StatusTombstone && i.ClosedAt != nil { return fmt.Errorf("non-closed issues cannot have closed_at timestamp") } - // Enforce tombstone invariants (bd-md2): deleted_at must be set for tombstones, and only for tombstones + // Enforce tombstone invariants: deleted_at must be set for tombstones, and only for tombstones if i.Status == StatusTombstone && i.DeletedAt == nil { return fmt.Errorf("tombstone issues must have deleted_at timestamp") } if i.Status != StatusTombstone && i.DeletedAt != nil { return fmt.Errorf("non-tombstone issues cannot have deleted_at timestamp") } - // Validate agent state if set (gt-v2gkv) + // Validate agent state if set if !i.AgentState.IsValid() { return fmt.Errorf("invalid agent state: %s", i.AgentState) } @@ -319,10 +319,10 @@ const ( StatusOpen Status = "open" StatusInProgress Status = "in_progress" StatusBlocked Status = "blocked" - StatusDeferred Status = "deferred" // Deliberately put on ice for later (bd-4jr) + StatusDeferred Status = "deferred" // Deliberately put on ice for later StatusClosed Status = "closed" - StatusTombstone Status = "tombstone" // Soft-deleted issue (bd-vw8) - StatusPinned Status = "pinned" // Persistent bead that stays open indefinitely (bd-6v2) + StatusTombstone Status = "tombstone" // Soft-deleted issue + StatusPinned Status = "pinned" // Persistent bead that stays open indefinitely ) // IsValid checks if the status value is valid (built-in statuses only) @@ -362,10 +362,10 @@ const ( TypeChore IssueType = "chore" TypeMessage IssueType = "message" // Ephemeral communication between workers TypeMergeRequest IssueType = "merge-request" // Merge queue entry for refinery processing - TypeMolecule IssueType = "molecule" // Template molecule for issue hierarchies (beads-1ra) - TypeGate IssueType = "gate" // Async coordination gate (bd-udsi) - TypeAgent IssueType = "agent" // Agent identity bead (gt-ikyo1) - TypeRole IssueType = "role" // Agent role definition (gt-gzp2y) + TypeMolecule IssueType = "molecule" // Template molecule for issue hierarchies + TypeGate IssueType = "gate" // Async coordination gate + TypeAgent IssueType = "agent" // Agent identity bead + TypeRole IssueType = "role" // Agent role definition ) // IsValid checks if the issue type value is valid @@ -377,7 +377,7 @@ func (t IssueType) IsValid() bool { return false } -// AgentState represents the self-reported state of an agent (gt-v2gkv) +// AgentState represents the self-reported state of an agent type AgentState string // Agent state constants @@ -444,14 +444,14 @@ const ( // Workflow types (affect ready work calculation) DepBlocks DependencyType = "blocks" DepParentChild DependencyType = "parent-child" - DepConditionalBlocks DependencyType = "conditional-blocks" // B runs only if A fails (bd-kzda) - DepWaitsFor DependencyType = "waits-for" // Fanout gate: wait for dynamic children (bd-xo1o.2) + DepConditionalBlocks DependencyType = "conditional-blocks" // B runs only if A fails + DepWaitsFor DependencyType = "waits-for" // Fanout gate: wait for dynamic children // Association types DepRelated DependencyType = "related" DepDiscoveredFrom DependencyType = "discovered-from" - // Graph link types (bd-kwro) + // Graph link types DepRepliesTo DependencyType = "replies-to" // Conversation threading DepRelatesTo DependencyType = "relates-to" // Loose knowledge graph edges DepDuplicates DependencyType = "duplicates" // Deduplication link @@ -603,10 +603,10 @@ type Statistics struct { InProgressIssues int `json:"in_progress_issues"` ClosedIssues int `json:"closed_issues"` BlockedIssues int `json:"blocked_issues"` - DeferredIssues int `json:"deferred_issues"` // Issues on ice (bd-4jr) + DeferredIssues int `json:"deferred_issues"` // Issues on ice ReadyIssues int `json:"ready_issues"` - TombstoneIssues int `json:"tombstone_issues"` // Soft-deleted issues (bd-nyt) - PinnedIssues int `json:"pinned_issues"` // Persistent issues (bd-6v2) + TombstoneIssues int `json:"tombstone_issues"` // Soft-deleted issues + PinnedIssues int `json:"pinned_issues"` // Persistent issues EpicsEligibleForClosure int `json:"epics_eligible_for_closure"` AverageLeadTime float64 `json:"average_lead_time_hours"` } @@ -645,19 +645,19 @@ type IssueFilter struct { PriorityMin *int PriorityMax *int - // Tombstone filtering (bd-1bu) + // Tombstone filtering IncludeTombstones bool // If false (default), exclude tombstones from results - // Ephemeral filtering (bd-kwro.9) + // Ephemeral filtering Ephemeral *bool // Filter by ephemeral flag (nil = any, true = only ephemeral, false = only persistent) - // Pinned filtering (bd-7h5) + // Pinned filtering Pinned *bool // Filter by pinned flag (nil = any, true = only pinned, false = only non-pinned) - // Template filtering (beads-1ra) + // Template filtering IsTemplate *bool // Filter by template flag (nil = any, true = only templates, false = exclude templates) - // Parent filtering (bd-yqhh): filter children by parent issue ID + // Parent filtering: filter children by parent issue ID ParentID *string // Filter by parent issue (via parent-child dependency) } @@ -720,7 +720,7 @@ type EpicStatus struct { EligibleForClose bool `json:"eligible_for_close"` } -// BondRef tracks compound molecule lineage (bd-rnnr). +// BondRef tracks compound molecule lineage. // When protos or molecules are bonded together, BondRefs record // which sources were combined and how they were attached. type BondRef struct {