PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE issues (
    id TEXT PRIMARY KEY,
    content_hash TEXT,
    title TEXT NOT NULL CHECK(length(title) <= 500),
    description TEXT NOT NULL DEFAULT '',
    design TEXT NOT NULL DEFAULT '',
    acceptance_criteria TEXT NOT NULL DEFAULT '',
    notes TEXT NOT NULL DEFAULT '',
    status TEXT NOT NULL DEFAULT 'open',
    priority INTEGER NOT NULL DEFAULT 2 CHECK(priority >= 0 AND priority <= 4),
    issue_type TEXT NOT NULL DEFAULT 'task',
    assignee TEXT,
    estimated_minutes INTEGER,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    closed_at DATETIME,
    external_ref TEXT,
    compaction_level INTEGER DEFAULT 0,
    compacted_at DATETIME,
    compacted_at_commit TEXT,
    original_size INTEGER, source_repo TEXT DEFAULT '.',
    CHECK ((status = 'closed') = (closed_at IS NOT NULL))
);
INSERT INTO issues VALUES('bd-736d','d0388dc9bc4c3d756f15d09919d0884d0ab13b33c3c10eaf8b5c1ed4208e621b','Refactor path canonicalization into helper function',unistr('The path canonicalization logic (filepath.Abs + EvalSymlinks) is duplicated in 3 places:\u000a- beads.go:131-137 (BEADS_DIR handling)\u000a- cmd/bd/main.go:446-451 (--no-db cleanup)\u000a- cmd/bd/nodb.go:26-31 (--no-db initialization)\u000a\u000aRefactoring suggestion:\u000aExtract to a helper function like:\u000a  func canonicalizePath(path string) string\u000a\u000aThis would:\u000a- Reduce code duplication\u000a- Make the logic easier to maintain\u000a- Ensure consistent behavior across all path handling\u000a\u000aRelated to bd-e16b implementation.'),'','','','closed',3,'chore',NULL,NULL,'2025-11-02T18:33:47.727443-08:00','2025-11-26T05:48:43.447415698-07:00','2025-11-25T22:27:33.738672-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-9e23','fa94af8126d5d8c816a6f83d5ad191ebdb954687abb87ce30e4f67eee4f1a9ce','Optimize Memory backend GetIssueByExternalRef with index',unistr('Currently GetIssueByExternalRef in Memory storage uses O(n) linear search through all issues.\u000a\u000aCurrent code (memory.go:282-308):\u000afor _, issue := range m.issues {\u000a    if issue.ExternalRef != nil && *issue.ExternalRef == externalRef {\u000a        return &issueCopy, nil\u000a    }\u000a}\u000a\u000aProposed optimization:\u000a- Add externalRefToID map[string]string to MemoryStorage\u000a- Maintain it in CreateIssue, UpdateIssue, DeleteIssue\u000a- Achieve O(1) lookup like SQLite''s index\u000a\u000aImpact: Low (--no-db mode typically has smaller datasets)\u000aRelated: bd-1022'),'','','','open',4,'chore','',NULL,'2025-11-02T15:32:30.242357-08:00','2025-11-02T15:32:30.242357-08:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-9li4','094f45dcf8d4abcce1ead02c93ec0a51149f6a4c99f25e0b175b6d5b56b4a00e','Create Docker image for Agent Mail',unistr('Containerize Agent Mail server for easy deployment.\u000a\u000aAcceptance Criteria:\u000a- Dockerfile with Python 3.14\u000a- Health check endpoint\u000a- Volume mount for storage\u000a- Environment variable configuration\u000a- Multi-arch builds (amd64, arm64)\u000a\u000aFile: deployment/agent-mail/Dockerfile'),'','','','closed',3,'task',NULL,NULL,'2025-11-07T22:43:43.231964-08:00','2025-11-26T05:48:43.449087824-07:00','2025-11-25T17:47:30.777486-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-c362','b859b2521369b11939ecacfcfdc190e5ad33c3565ebd107c1db72d3d547f13b7','Extract database search logic into helper function',unistr('The logic for finding a database in a beads directory is duplicated:\u000a- FindDatabasePath() BEADS_DIR section (beads.go:141-169)\u000a- findDatabaseInTree() (beads.go:248-280)\u000a\u000aBoth implement the same search order:\u000a1. Check config.json first (single source of truth)\u000a2. Fall back to canonical beads.db\u000a3. Search for *.db files, filtering backups and vc.db\u000a\u000aRefactoring suggestion:\u000aExtract to a helper function like:\u000a  func findDatabaseInBeadsDir(beadsDir string) string\u000a\u000aBenefits:\u000a- Single source of truth for database search logic\u000a- Easier to maintain and update search order\u000a- Reduces code duplication\u000a\u000aRelated to [deleted:bd-e16b] implementation.'),'','','','closed',3,'chore',NULL,NULL,'2025-11-02T18:34:02.831543-08:00','2025-11-26T05:48:43.449662048-07:00','2025-11-25T22:27:33.794656-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-e166','000f4f9d069ffedceae13894d967ec30fa4a89e318bfcac4847f3c3b16d44a89','Improve timestamp comparison readability in import',unistr('The timestamp comparison logic uses double-negative which can be confusing:\u000a\u000aCurrent code:\u000aif !incoming.UpdatedAt.After(existing.UpdatedAt) {\u000a    // skip update\u000a}\u000a\u000aMore readable:\u000aif incoming.UpdatedAt.After(existing.UpdatedAt) {\u000a    // perform update\u000a} else {\u000a    // skip (local is newer)\u000a}\u000a\u000aThis is a minor refactor for code clarity.\u000a\u000aRelated: bd-1022\u000aFiles: internal/importer/importer.go:411, 488'),'','','','open',4,'chore','',NULL,'2025-11-02T15:32:12.27108-08:00','2025-11-02T15:32:12.27108-08:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-ye0d','c6b51de5960d95f0c4dafaf5b9a00a043d219e375c15269204557f1e2741da98','troubleshoot GH#278 daemon exits every few secs','','','','','closed',2,'task',NULL,NULL,'2025-11-13T06:27:23.39509215-07:00','2025-11-26T05:48:43.453598459-07:00','2025-11-25T17:48:43.62418-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-81a','13274e47c85513f840163b6a5f448d8af8549549a8d5261af0b3b5a00e13b655','Add programmatic tip injection API','Allow tips to be programmatically injected at runtime based on detected conditions. This enables dynamic tips (not just pre-defined ones) to be shown with custom priority and frequency.','','','','closed',2,'feature',NULL,NULL,'2025-11-11T23:29:46.645583-08:00','2025-11-26T05:48:43.448399968-07:00','2025-11-25T17:52:35.096882-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-d4i','49dfd16d5b1c75c26d4ed3b1fe0c27b620f8530bac28e0be82a1efe2c459a647','Create tip system infrastructure for contextual hints','Implement a tip/hint system that shows helpful contextual messages after successful commands. This is different from the existing error-path "Hint:" messages - tips appear on success paths to educate users about features they might not know about.','','','','closed',2,'feature',NULL,NULL,'2025-11-11T23:29:15.693956-08:00','2025-11-26T05:48:43.450293709-07:00','2025-11-25T17:47:30.747566-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-tne','ef56849fd789049732dc17f21320cc07bb742473038808dbf1f7883ccc812e35','Add Claude setup tip with dynamic priority','Add a predefined tip that suggests running `bd setup claude` when Claude Code is detected but not configured. This tip should have higher priority (shown more frequently) until the setup is complete.','','','','closed',2,'task',NULL,NULL,'2025-11-11T23:29:29.871324-08:00','2025-11-26T05:48:43.451976386-07:00','2025-11-25T17:52:35.044989-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-tru','65d75e5c9f8725ae8abb8c485cc50af3028741e84e6d8620433af20d32e43d4f','Update documentation for bd prime and Claude integration','Update AGENTS.md, README.md, and QUICKSTART.md to document the new `bd prime` command, `bd setup claude` command, and tip system.','','','','closed',2,'task',NULL,NULL,'2025-11-11T23:30:22.77349-08:00','2025-11-26T05:48:43.452824792-07:00','2025-11-25T17:47:30.807069-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-wcl','c08d62ce3627a49126c63f6a630a08c1666e5b1b8d9148ae0c72d7d06611b2a9','Document CLI + hooks as recommended approach over MCP','Update documentation to position CLI + bd prime hooks as the primary recommended approach over MCP server, explaining why minimizing context matters even with large context windows (compute cost, energy, environment, latency).',unistr('## Goals\u000a\u000aPosition CLI + `bd prime` hooks as the **primary recommended approach** for AI agent integration, with MCP server as a legacy/fallback option.\u000a\u000aExplore **hybrid mode** - if certain commands benefit from MCP (UX/DX advantages like no approval prompts), minimize MCP surface area to only those commands.\u000a\u000aThis requires production validation first - only update docs after CLI mode is proven reliable.\u000a\u000a## Why Minimize Context (Even With Large Windows)\u000a\u000a**Context window size ≠ free resource**\u000a\u000aLarge context windows (100k+, 200k+) don''t mean we should fill them wastefully. Every token in context has real costs:\u000a\u000a### Compute Cost\u000a- **Processing overhead**: Larger context = more GPU/CPU cycles per request\u000a- **Memory usage**: 10.5k tokens consume significant RAM/VRAM\u000a- **Scaling impact**: Multiplied across all users, all sessions, all requests\u000a\u000a### Energy & Environment\u000a- **Electricity**: More compute = more power consumption\u000a- **Carbon footprint**: Data centers running on grid power (not all renewable)\u000a- **Sustainability**: Unnecessary token usage contributes to AI''s environmental impact\u000a- **Responsibility**: Efficient tools are better for the planet\u000a\u000a### User Experience\u000a- **Latency**: Larger context = slower processing (noticeable at 10k+ tokens)\u000a- **Cost**: Many AI services charge per token (input + output)\u000a- **Rate limits**: Context counts against API quotas\u000a\u000a### Engineering Excellence\u000a- **Efficiency**: Good engineering minimizes resource usage\u000a- **Scalability**: Efficient tools scale better\u000a- **Best practices**: Optimize for the common case\u000a\u000a**The comparison:**\u000a\u000a| Approach | Standing Context | Efficiency | User Cost | Environmental Impact |\u000a|----------|-----------------|------------|-----------|---------------------|\u000a| **CLI + hooks** | ~1-2k tokens | 80-90% reduction | Lower | Sustainable ✓ |\u000a| **MCP minimal** | ~2-4k tokens | 60-80% reduction | Medium | Better ✓ |\u000a| **MCP full** | ~10.5k tokens | Baseline | Higher | Wasteful ✗ |\u000a\u000a**Functional equivalence:**\u000a- CLI via Bash tool works just as well as MCP native calls\u000a- Same features, same reliability\u000a- No downside except initial learning curve\u000a\u000a## Hybrid Mode: Minimal MCP Surface Area\u000a\u000a**Philosophy:** MCP server doesn''t have to expose everything.\u000a\u000aIf certain commands have legitimate UX/DX benefits from MCP (e.g., no approval prompts, cleaner syntax), we can expose ONLY those commands via MCP while using CLI for everything else.\u000a\u000a### Potential MCP-Only Candidates (TBD)\u000a\u000aCommands that might benefit from MCP native calls:\u000a- `ready` - frequently checked, no side effects, approval prompt annoying\u000a- `show` - read-only, frequently used, approval slows workflow\u000a- `list` - read-only, no risk, approval adds friction\u000a\u000aCommands that work fine via CLI:\u000a- `create` - complex parameters, benefits from explicit confirmation\u000a- `update` - state changes, good to see command explicitly\u000a- `close` - state changes, explicit is better\u000a- `dep` - relationships, good to see what''s being linked\u000a- `sync` - git operations, definitely want visibility\u000a\u000a### Token Budget\u000a\u000a**Full MCP** (current): ~10.5k tokens\u000a- All ~20+ bd commands exposed\u000a- All parameter schemas\u000a- All descriptions and examples\u000a\u000a**Minimal MCP** (proposed): ~2-4k tokens\u000a- 3-5 high-frequency read commands only\u000a- Simplified schemas\u000a- Minimal descriptions\u000a- Everything else via CLI\u000a\u000a**Pure CLI**: ~1-2k tokens (only on SessionStart/PreCompact)\u000a- No MCP tools loaded\u000a- All commands via Bash\u000a\u000a### Investigation Required\u000a\u000aBefore implementing hybrid mode, validate:\u000a\u000a1. **Do MCP calls actually skip approval prompts?**\u000a   - Test with Claude Code approval settings\u000a   - Compare MCP tool calls vs Bash tool calls\u000a   - Measure UX difference in real usage\u000a\u000a2. **What''s the actual token breakdown per command?**\u000a   - Measure individual command schemas\u000a   - Calculate token savings for minimal vs full\u000a\u000a3. **Is approval prompt the only benefit?**\u000a   - Are there other UX advantages to MCP?\u000a   - Does native syntax actually improve experience?\u000a   - User testing with both approaches\u000a\u000a4. **Can we dynamically load MCP tools?**\u000a   - Only load MCP when certain commands needed?\u000a   - Hot-swap between CLI and MCP?\u000a   - Probably not - MCP loads at startup\u000a\u000a### Hybrid Mode Documentation (If Validated)\u000a\u000a```markdown\u000a## Choosing Your Integration Approach\u000a\u000aBeads supports three AI agent integration approaches:\u000a\u000a### CLI + Hooks (Recommended - Most Efficient)\u000a\u000a**Setup:** `bd setup claude`\u000a\u000aUses Claude Code hooks to inject workflow context via `bd prime` command. Agent uses bd via Bash tool.\u000a\u000a**Tokens:** ~1-2k (on SessionStart/PreCompact only)\u000a\u000a**Pros:**\u000a- Maximum efficiency (80-90% reduction vs full MCP)\u000a- Lowest compute/energy usage\u000a- Same functionality as MCP\u000a\u000a**Cons:**\u000a- Bash tool calls may require approval prompts\u000a- Slightly more verbose in conversation\u000a\u000a### Minimal MCP + Hooks (Balanced)\u000a\u000a**Setup:** Install minimal MCP server (read-only commands) + `bd setup claude`\u000a\u000aExposes only high-frequency read commands via MCP (ready, show, list). Everything else via CLI.\u000a\u000a**Tokens:** ~2-4k MCP + ~1-2k hooks\u000a\u000a**Pros:**\u000a- 60-80% reduction vs full MCP\u000a- No approval prompts for common queries\u000a- Cleaner syntax for frequent operations\u000a- Still efficient\u000a\u000a**Cons:**\u000a- Requires MCP server (additional setup)\u000a- Mixed interface (some MCP, some CLI)\u000a\u000a### Full MCP + Hooks (Legacy)\u000a\u000a**Setup:** Install full MCP server + `bd setup claude`\u000a\u000a**Tokens:** ~10.5k MCP + hooks\u000a\u000a**Pros:**\u000a- All commands as native function calls\u000a- Consistent interface\u000a\u000a**Cons:**\u000a- Highest token usage (worst for compute/energy/cost)\u000a- Slowest processing\u000a- Less sustainable\u000a\u000a### Recommendation\u000a\u000a1. **Start with CLI + hooks** - most efficient, works great\u000a2. **Try minimal MCP** if approval prompts become annoying\u000a3. **Avoid full MCP** - wasteful with no significant benefit\u000a```\u000a\u000a## Production Validation Checklist\u000a\u000aBefore making these documentation changes, validate CLI approach works reliably:\u000a\u000a### Phase 1: Pure CLI Validation\u000a- [ ] `bd prime` implemented and tested\u000a- [ ] Hooks installed and working in Claude Code\u000a- [ ] Real-world usage by at least 2-3 developers for 1+ weeks\u000a- [ ] No significant usability issues reported\u000a- [ ] Agent successfully uses bd via Bash tool\u000a- [ ] Document which commands (if any) have approval prompt issues\u000a\u000a### Phase 2: Hybrid Mode Investigation (Optional)\u000a- [ ] Test if MCP calls skip approval prompts vs Bash calls\u000a- [ ] Measure token cost per MCP command\u000a- [ ] Identify minimal set of commands worth exposing via MCP\u000a- [ ] Build minimal MCP server variant\u000a- [ ] Validate token savings (should be 60-80% vs full MCP)\u000a- [ ] User testing shows actual UX improvement\u000a\u000a### Phase 3: Documentation Update\u000a- [ ] Update based on validation results\u000a- [ ] Include measured token counts (not estimates)\u000a- [ ] Provide clear migration paths\u000a- [ ] Update `bd doctor` recommendations\u000a\u000a## Migration Guide (Optional)\u000a\u000aFor users currently using MCP:\u000a\u000a```markdown\u000a### Migrating from Full MCP to CLI + Hooks\u000a\u000aAlready using full MCP server? You can switch to the more efficient CLI approach:\u000a\u000a1. Install hooks: `bd setup claude`\u000a2. Test it works (hooks inject context, agent uses Bash tool)\u000a3. Remove MCP server from `~/.claude/settings.json`\u000a4. Restart Claude Code\u000a\u000aYou''ll get the same functionality with 80-90% less token usage.\u000a\u000a### Migrating to Minimal MCP (If Available)\u000a\u000aIf you find approval prompts annoying for certain commands:\u000a\u000a1. Replace full MCP with minimal MCP in `~/.claude/settings.json`\u000a2. Restart Claude Code\u000a3. Verify high-frequency commands (ready, show, list) work via MCP\u000a4. Everything else automatically uses CLI\u000a\u000aYou''ll get 60-80% token reduction vs full MCP while keeping the UX benefits.\u000a```\u000a\u000a## Files to Update\u000a\u000a- `README.md` - Add recommendation in AI Integration section\u000a- `AGENTS.md` - Add "Choosing Your Integration Approach" section early\u000a- `QUICKSTART.md` - Update AI integration section\u000a- `docs/` - Any other AI integration docs if they exist\u000a- `mcp-server/` - Create minimal variant if hybrid validated\u000a\u000a## Future: Update `bd init`\u000a\u000aOnce validated, update `bd init` to:\u000a- Default to recommending `bd setup claude` (hooks only)\u000a- Mention minimal MCP as option for UX improvement\u000a- Detect existing full MCP and suggest migration\u000a- Provide token usage estimates for each approach\u000a\u000a## MCP Server Architecture Note\u000a\u000a**Key insight:** MCP server doesn''t have to expose all bd functionality.\u000a\u000aCurrent design exposes ~20+ commands (all bd subcommands). This is over-engineered.\u000a\u000a**Better design:**\u000a- **Minimal MCP**: 3-5 read-only commands (~2-4k tokens)\u000a- **CLI**: Everything else via Bash tool\u000a- **Hooks**: Context injection via `bd prime`\u000a\u000aThis achieves best of both worlds:\u000a- Low token usage (efficient)\u000a- No approval prompts for common queries (UX)\u000a- Explicit visibility for state changes (safety)\u000a\u000aIf validation shows NO meaningful benefit to MCP (even minimal), skip hybrid mode entirely and recommend pure CLI.'),unistr('- Documentation explains CLI + hooks as recommended approach\u000a- Explains why context size matters (compute/energy/cost/latency)\u000a- Token comparison table shows 80-90% reduction\u000a- Migration guide for existing MCP users\u000a- Only deployed AFTER production validation\u000a- Clear that both approaches are supported'),'','open',2,'task','',NULL,'2025-11-12T00:15:25.923025-08:00','2025-11-12T00:18:16.786857-08:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-1pj6','de1c1195b29d9a70c88b5f2b05ca1c3497469d1802f9c0be415d5a44b0575deb','Proposal: Custom status states via config',unistr('Proposal to add ''custom status states'' via `bd config`.\u000aUsers could define an optional issue status enum (e.g., awaiting_review, review_in_progress) in the config.\u000aThis would enable multi-step pipelines to process issues where each step correlates to a specific status.\u000a\u000aExamples:\u000a- awaiting_verification\u000a- awaiting_docs\u000a- awaiting_testing\u000a'),'','','','open',3,'feature','',NULL,'2025-11-20T18:55:48.670499-05:00','2025-11-20T18:55:48.670499-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-39o','36d58121cc9218718d262a1991ee84695af722d2823cf9c8415c2dfdd44fb390','Rename last_import_hash metadata key to jsonl_content_hash',unistr('The metadata key ''last_import_hash'' is misleading because it''s updated on both import AND export (sync.go:614, import.go:320).\u000a\u000aBetter names:\u000a- jsonl_content_hash (more accurate)\u000a- last_sync_hash (clearer intent)\u000a\u000aThis is a breaking change requiring migration of existing metadata values.'),'','','','open',2,'task','',NULL,'2025-11-20T21:31:07.568739-05:00','2025-11-20T21:31:07.568739-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-4aao','0b92478491e28ed66fc3a75ae06d16d24c0c384a1497442b8c3448ea0d44bf3e','Fix failing integration tests in beads-mcp','The `beads-mcp` test suite has failures in `tests/test_bd_client_integration.py` (assertion error in `test_init_creates_beads_directory`) and errors in `tests/test_worktree_separate_dbs.py` (setup failures finding database). These need to be investigated and fixed to ensure a reliable CI baseline.','','','','closed',2,'task',NULL,NULL,'2025-11-20T18:53:28.4803-05:00','2025-11-26T05:48:43.439835244-07:00','2025-11-25T21:39:20.967106-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-bt6y','462f08aa379cf2f196b4c0ca096271fa47ab5e1a18c5663c28d2d86fd02115cf','Improve compact/daemon/merge documentation and UX',unistr('Multiple documentation and UX issues encountered:\u000a1. "bd compact --analyze" fails with misleading "requires SQLite storage" error when daemon is running. Needs --no-daemon or better error.\u000a2. "bd merge" help text is outdated (refers to 3-way merge instead of issue merging).\u000a3. Daemon mode purpose isn''t clear to local-only users.\u000a4. Compact/cleanup commands are hard to discover.\u000a\u000aProposed fixes:\u000a- Fix compact+daemon interaction or error message.\u000a- Update "bd merge" help text.\u000a- Add "when to use daemon" section to docs.\u000a- Add maintenance section to quickstart.\u000a'),'','','','open',2,'task','',NULL,'2025-11-20T18:55:43.637047-05:00','2025-11-20T18:55:43.637047-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-j3zt','531ad51101f41375a93d66b8d22105ce7c4913261db78b662bb759e802bc01e2','Fix mypy errors in beads-mcp','Running `mypy .` in `integrations/beads-mcp` reports 287 errors. These should be addressed to improve type safety and code quality.','','','','open',3,'task','',NULL,'2025-11-20T18:53:28.557708-05:00','2025-11-20T18:53:28.557708-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-l954','263dd2111cf0353b307f2e47489aa42ecf607e49b1316b54a6497cad9d3722b0','Performance Testing Framework',unistr('Add comprehensive performance testing for beads focusing on optimization guidance and validating 10K+ database scale. Uses standard Go tooling, follows existing patterns, minimal complexity.\u000a\u000aComponents:\u000a- Benchmark suite for critical operations at 10K-20K scale\u000a- Fixture generator for realistic test data (epic hierarchies, cross-links)\u000a- User diagnostics via bd doctor --perf\u000a- Always-on profiling integration\u000a\u000aGoals:\u000a- Identify bottlenecks for optimization work\u000a- Validate performance at 10K+ issue scale\u000a- Enable users to collect diagnostics for bug reports\u000a- Support both SQLite and JSONL import paths'),'','','','open',2,'epic','',NULL,'2025-11-13T22:22:11.203467-08:00','2025-11-13T22:22:11.203467-08:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-m7ge','f69647eb27bccdbcc19749fe77b18cc5010f1a4491880fbe3c3144f0d3885f75','Add .beads/README.md during ''bd init'' for project documentation and promotion',unistr('When ''bd init'' is run, automatically generate a .beads/README.md file that:\u000a\u000a1. Briefly explains what Beads is (AI-native issue tracking that lives in your repo)\u000a2. Links to the main repository: https://github.com/steveyegge/beads\u000a3. Provides a quick reference of essential commands:\u000a   - bd create: Create new issues\u000a   - bd list: View all issues\u000a   - bd update: Modify issue status/details\u000a   - bd show: View issue details\u000a   - bd sync: Sync with git remote\u000a4. Highlights key benefits for AI coding agents and developers\u000a5. Encourages developers to try it out\u000a\u000aThe README should be enthusiastic and compelling to get open source contributors excited about using Beads for their AI-assisted development workflows.'),'','','','closed',2,'feature',NULL,NULL,'2025-11-16T22:32:50.478681-08:00','2025-11-26T05:48:43.450926142-07:00','2025-11-25T17:49:42.558381-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-mnap','c15d3c631656fe6d21291f127fc545af93e712b5f3f94cce028513fb743a4fdb','Investigate performance issues in VS Code Copilot (Windows)',unistr('Beads unusable in Windows 11 VS Code Copilot chat with Sonnet 4.5.\u000aSummary event happens every 3-4 turns, taking 3 minutes.\u000aCopilot summarizes after ~125k tokens despite model supporting 1M.\u000aLarge context size of beads might be triggering aggressive summarization.\u000aNeed workaround or optimization for context size.\u000a'),'','','','open',2,'task','',NULL,'2025-11-20T18:56:30.124918-05:00','2025-11-20T18:56:30.124918-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-nq41','33f9cfe6a0ef5200dcd5016317b43b1568ff9dc7303537d956bdab02029f6c63','Fix Homebrew warning about Ruby file location',unistr('Homebrew warning: Found Ruby file outside steveyegge/beads tap formula directory.\u000aWarning points to: /opt/homebrew/Library/Taps/steveyegge/homebrew-beads/bd.rb\u000aIt should likely be inside a Formula/ directory or similar structure expected by Homebrew taps.\u000a'),'','','','open',2,'chore','',NULL,'2025-11-20T18:56:21.226579-05:00','2025-11-20T18:56:21.226579-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-p6vp','1df6d3b9b438cdcdbc618c24fea48769c1f22e8a8701af4e742531d4433ca7ea','Clarify .beads/.gitattributes handling in Protected Branches docs',unistr('Protected Branches docs quick start leaves untracked `.beads` directory and `.gitattributes`.\u000aQuestion: Are these changes meant to be checked into the protected branch?\u000aNeed to clarify if these should be ignored or committed, or if the instructions are missing a step.\u000a'),'','','','open',2,'task','',NULL,'2025-11-20T18:56:25.79407-05:00','2025-11-20T18:56:25.79407-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-ybv5','52f6d2143a3e9d63937e7dee2cfb4055740132d3c0831c3e948210179336820f','Refactor AGENTS.md to use external references',unistr('Suggestion to use external references (e.g., "ALWAYS REFER TO ./beads/prompt.md") instead of including all instructions directly within AGENTS.md.\u000aReasons:\u000a1. Agents can follow external references.\u000a2. Prevents context pollution/stuffing in AGENTS.md as more tools append instructions.\u000a'),'','','','open',3,'task','',NULL,'2025-11-20T18:55:53.259144-05:00','2025-11-20T18:55:53.259144-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-zj8e','655c761aaf4d5b0c9edfba7d96d23e608de94760148715667738d35c2033e110','Performance Testing Documentation',unistr('Create docs/performance-testing.md documenting the performance testing framework.\u000a\u000aSections:\u000a1. Overview - What the framework does, goals\u000a2. Running Benchmarks\u000a   - make bench command\u000a   - Running specific benchmarks\u000a   - Interpreting output (ns/op, allocs/op)\u000a3. Profiling and Analysis\u000a   - Viewing CPU profiles with pprof\u000a   - Reading flamegraphs\u000a   - Memory profiling\u000a   - Finding hotspots\u000a4. User Diagnostics\u000a   - bd doctor --perf usage\u000a   - Sharing profiles with bug reports\u000a   - Understanding the report output\u000a5. Comparing Performance\u000a   - Using benchstat for before/after comparisons\u000a   - Detecting regressions\u000a6. Tips for Optimization\u000a   - Common patterns\u000a   - When to profile vs benchmark\u000a\u000aStyle:\u000a- Concise, practical examples\u000a- Screenshots/examples of pprof output\u000a- Clear command-line examples\u000a- Focus on workflow, not theory'),'','','','open',2,'task','',NULL,'2025-11-13T22:23:38.99897-08:00','2025-11-13T22:23:38.99897-08:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-4h3','c31e267da6b7885e45562d6b1d9176a4ea8603de218f7ffd361226e7268d283e','Add test coverage for internal/git package','','Git package has 1 test file. Critical package needs comprehensive testing. Target: 70% coverage',unistr('- At least 4 test files\u000a- Package coverage >= 70%\u000a- Tests cover git commands, error handling'),'','open',2,'task','',NULL,'2025-11-20T21:21:23.497486-05:00','2025-11-20T21:21:23.497486-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-c4rq','4c096e1d84c3ba5b5b4e107692b990a99166b4c99a4262fd26ec08297fb81046','Refactor: Move staleness check inside daemon branch',unistr('## Problem\u000a\u000aCurrently ensureDatabaseFresh() is called before the daemon mode check, but it checks daemonClient != nil internally and returns early. This is redundant.\u000a\u000a**Location:** All read commands (list.go:196, show.go:27, ready.go:102, status.go:80, etc.)\u000a\u000a## Current Pattern\u000a\u000aCall happens before daemon check, function checks daemonClient internally.\u000a\u000a## Better Pattern\u000a\u000aMove staleness check to direct mode branch only, after daemon check.\u000a\u000a## Impact\u000aLow - minor performance improvement (avoids one function call per command in daemon mode)\u000a\u000a## Effort\u000aMedium - requires refactoring 8 command files\u000a\u000a## Priority\u000aLow - can defer to future cleanup PR'),'','','','open',3,'chore','',NULL,'2025-11-20T20:17:45.119583-05:00','2025-11-20T20:17:45.119583-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-e92','12073b3293b06f99051bc9c00188aeb520cd2e4792cf4694f1fa4b784e625e54','Add test coverage for internal/autoimport package','','The autoimport package has only 1 test file. Need comprehensive tests. Target: 70% coverage',unistr('- At least 3 test files\u000a- Package coverage >= 70%\u000a- Tests cover main functionality, error paths, edge cases'),'','open',2,'task','',NULL,'2025-11-20T21:21:22.338577-05:00','2025-11-20T21:21:22.338577-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-ge7','84248781654b9924e1f4284058f141b73d761dead05ef9a3d1cc9b9f8cd4b60d','Improve Beads test coverage from 46% to 80%','',unistr('Currently at 46% test coverage. Need to systematically improve coverage across all subsystems, focusing first on packages with minimal or no tests.\u000a\u000aTarget: 80% overall coverage\u000a\u000aApproach:\u000a- Break down by subsystem (internal/* packages)\u000a- Prioritize packages with 0-1 test files\u000a- Each child issue targets specific coverage goals\u000a- Focus on unit tests for core logic, error paths, and edge cases\u000a\u000aThis epic will be executed by the VC executor to test its ability to handle sustained multi-issue work.'),unistr('- Overall test coverage reaches 80% or higher\u000a- All internal/* packages have at least 60% coverage\u000a- All packages with only 1 test file now have at least 3 test files\u000a- Quality gates (go test, golangci-lint) pass\u000a- Tests are maintainable and test actual behavior, not implementation details'),'','open',1,'epic','',NULL,'2025-11-20T21:21:03.700271-05:00','2025-11-20T21:21:03.700271-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-gqo','21642505de8036d9501f8593b78de7b761f05869f9d8d11758278e9c0b33c9c3','Implement health checks in daemon event loop',unistr('Add health checks to checkDaemonHealth() function in daemon_event_loop.go:170:\u000a- Database integrity check\u000a- Disk space check\u000a- Memory usage check\u000a\u000aCurrently it''s just a no-op placeholder.'),'','','','open',3,'feature','',NULL,'2025-11-21T18:55:07.534304-05:00','2025-11-21T18:55:07.534304-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-hdt','8e6cf1653ef2ea583b39a421b3d708763ab7c042d6cd494e77202a92af0a7398','Implement auto-merge functionality in duplicates command','The duplicates.go file has a TODO at line 95 to implement the performMerge function for automatic duplicate merging. Currently it just prints a warning message. This would automate the merge process instead of just suggesting commands.','','','','open',2,'feature','',NULL,'2025-11-21T18:55:02.828619-05:00','2025-11-21T18:55:02.828619-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-m0w','e8641e225f1d4cf13fbd97c4a83046e3597df180d3ee134125e4a35abc6941cd','Add test coverage for internal/validation package','','Validation package has 1 test file. Critical for data integrity. Target: 80% coverage',unistr('- At least 4 test files\u000a- Package coverage >= 80%\u000a- Tests cover all validation rules'),'','open',2,'task','',NULL,'2025-11-20T21:21:24.129559-05:00','2025-11-20T21:21:24.129559-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-t3b','c32a3a0f2f836148033fb330e209ac22e06dbecf18894153c15e2036f5afae1c','Add test coverage for internal/config package','','Config package has 1 test file. Need comprehensive tests. Target: 70% coverage',unistr('- At least 3 test files\u000a- Package coverage >= 70%'),'','open',2,'task','',NULL,'2025-11-20T21:21:22.91657-05:00','2025-11-20T21:21:22.91657-05:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-3gc','83684e0e79d016a9569ccd04adda44cc072a662ee09556c156bf54e0603c5b6a','Audit remaining cmd/bd files for error handling consistency','Extend ERROR_HANDLING_AUDIT.md to cover: daemon_sync.go, update.go, list.go, show.go, close.go, reopen.go, dep.go, label.go, comments.go, delete.go, compact.go, config.go, validate.go and other high-usage command files','','','','open',3,'task','',NULL,'2025-11-24T00:28:55.890991-08:00','2025-11-24T00:28:55.890991-08:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-s0z','b69df0c8664737b3c04b10e3137652e3c8c3d782de0ecd02bfcd648919f8d944','Consider extracting error handling helpers','Evaluate creating FatalError() and WarnError() helpers as suggested in ERROR_HANDLING.md to reduce boilerplate and enforce consistency. Prototype in a few files first to validate the approach.','','','','open',4,'task','',NULL,'2025-11-24T00:28:57.248959-08:00','2025-11-24T00:28:57.248959-08:00',NULL,NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-03r','82c6a895452676af433a4f893e9592eb7374bafac84e40ef27f0b958f13e7ec6','Document deletions manifest in AGENTS.md and README',unistr('Parent: bd-imj\u000a\u000a## Task\u000aAdd documentation about the deletions manifest feature.\u000a\u000a## Locations to Update\u000a\u000a### AGENTS.md\u000a- Explain that deletions.jsonl is tracked in git\u000a- Document that `bd delete` records to the manifest\u000a- Explain cross-clone propagation mechanism\u000a\u000a### README.md  \u000a- Brief mention in .beads directory structure section\u000a- Link to detailed docs if needed\u000a\u000a### docs/deletions.md (new file)\u000a- Full technical documentation\u000a- Format specification\u000a- Pruning policy\u000a- Git history fallback\u000a- Troubleshooting\u000a\u000a## Acceptance Criteria\u000a- AGENTS.md updated with deletion workflow\u000a- README.md mentions deletions.jsonl purpose\u000a- New docs/deletions.md with complete reference'),'','','','closed',2,'task','',NULL,'2025-11-25T14:56:49.13027-08:00','2025-11-25T15:17:23.145944-08:00','2025-11-25T15:17:23.145944-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-2em','ea104a34660c03a8844408d47cc55663b8d0368c3d1289ee7be12e196246541e','Expand checkHooksQuick to verify all hook versions','Currently checkHooksQuick only checks post-merge hook version. Should also check pre-commit, pre-push, and post-checkout for completeness. Keep it lightweight but catch more outdated hooks.','','','','closed',2,'task','',NULL,'2025-11-25T19:27:47.432243-08:00','2025-11-25T19:50:21.378464-08:00','2025-11-25T19:50:21.378464-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-44e','41ed0a944beb63a8aced243f3b040073ba1f5bcd67e37330a61edc8773954315','Ensure deletions.jsonl is tracked in git',unistr('Parent: bd-imj\u000a\u000aEnsure deletions.jsonl is tracked in git (not ignored).\u000a\u000aUpdate bd init and gitignore upgrade logic to:\u000a1. NOT add deletions.jsonl to .gitignore\u000a2. Ensure it is committed alongside beads.jsonl\u000a\u000aThe file must be in git for cross-clone propagation to work.\u000a\u000aAcceptance criteria:\u000a- bd init does not ignore deletions.jsonl\u000a- Existing .gitignore files are not broken\u000a- File appears in git status when modified'),'','','','closed',2,'task','',NULL,'2025-11-25T09:57:21.663196-08:00','2025-11-25T14:55:43.225883-08:00','2025-11-25T14:55:43.225883-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-4l5','bdaf92d02f2989bad822ed2079ce1916422a3ef014b338dd173cc9ac9d8c753d','bd prime: Detect ephemeral branches and adjust workflow output',unistr('When ''bd prime'' runs on a branch with no upstream (ephemeral branch), it should output a different SESSION CLOSE PROTOCOL.\u000a\u000a**Current output (wrong for ephemeral branches):**\u000a```\u000a[ ] 1. git status\u000a[ ] 2. git add <files>\u000a[ ] 3. bd sync\u000a[ ] 4. git commit -m "..."\u000a[ ] 5. bd sync\u000a[ ] 6. git push\u000a```\u000a\u000a**Needed output for ephemeral branches:**\u000a```\u000a[ ] 1. git status\u000a[ ] 2. git add <files>\u000a[ ] 3. bd sync --from-main  (pull updates from main)\u000a[ ] 4. git commit -m "..."\u000a[ ] 5. (no push - branch is ephemeral)\u000a```\u000a\u000a**Detection:** `git rev-parse --abbrev-ref --symbolic-full-name @{u}` returns error code 128 if no upstream.\u000a\u000aAlso update Sync & Collaboration section to mention `bd sync --from-main` for ephemeral branches.\u000a\u000a**Use case:** Gastown polecats work on ephemeral local branches that are never pushed. Their code gets merged to main via local merge, and beads changes stay local (communicated via gm mail to Overseer).'),'','','','closed',1,'feature','',NULL,'2025-11-25T16:55:24.984104-08:00','2025-11-25T17:12:46.604978-08:00','2025-11-25T17:12:46.604978-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-b8h','5bbe06f5066aa0f2f7a68d58adeadf5cef898bbba4968b9bd7abfecaee559f28','Refactor check-health DB access to avoid repeated path resolution','The runCheckHealth lightweight checks (hintsDisabled, checkVersionMismatch, checkSyncBranchQuick) each have duplicated database path resolution logic. Extract a helper function to DRY this up.','','','','closed',2,'task','',NULL,'2025-11-25T19:27:35.075929-08:00','2025-11-25T19:50:21.272961-08:00','2025-11-25T19:50:21.272961-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-bgs','abb9ec47a026fc0f7c3d2604aaa06376b6df06240d1f0f8ef59963527009815a','Git history fallback doesn''t escape regex special chars in IDs',unistr('## Problem\u000a\u000aIn `batchCheckGitHistory`, IDs are directly interpolated into a regex pattern:\u000a\u000a```go\u000apatterns = append(patterns, fmt.Sprintf(\\`"id":"%s"\\`, id))\u000asearchPattern := strings.Join(patterns, "|")\u000acmd := exec.Command("git", "log", "--all", "-G", searchPattern, ...)\u000a```\u000a\u000aIf an ID contains regex special characters (e.g., `bd-foo.bar` or `bd-test+1`), the pattern will be malformed or match unintended strings.\u000a\u000a## Location\u000a`internal/importer/importer.go:923-926`\u000a\u000a## Impact\u000a- False positives: IDs with `.` could match any character\u000a- Regex errors: IDs with `[` or `(` could cause git to fail\u000a- Security: potential for regex injection (low risk since IDs are validated)\u000a\u000a## Fix\u000aEscape regex special characters:\u000a\u000a```go\u000aimport "regexp"\u000a\u000aescapedID := regexp.QuoteMeta(id)\u000apatterns = append(patterns, fmt.Sprintf(\\`"id":"%s"\\`, escapedID))\u000a```'),'','','','closed',2,'bug','',NULL,'2025-11-25T12:50:30.132232-08:00','2025-11-25T15:04:06.217695-08:00','2025-11-25T15:04:06.217695-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-bhd','fe79f5ed3a0d79ee4034ea9dd917ceb9f2e6c4ac00aa8ff3a2b1652aeaac821a','Git history fallback assumes .beads is direct child of repo root',unistr('## Problem\u000a\u000a`checkGitHistoryForDeletions` assumes the repo structure:\u000a\u000a```go\u000arepoRoot := filepath.Dir(beadsDir)  // Assumes .beads is in repo root\u000ajsonlPath := filepath.Join(".beads", "beads.jsonl")\u000a```\u000a\u000aBut `.beads` could be in a subdirectory (monorepo, nested project), and the actual JSONL filename could be different (configured via `metadata.json`).\u000a\u000a## Location\u000a`internal/importer/importer.go:865-869`\u000a\u000a## Impact\u000a- Git search will fail silently for repos with non-standard structure\u000a- Monorepo users won''t get deletion propagation\u000a\u000a## Fix\u000a1. Use `git rev-parse --show-toplevel` to find actual repo root\u000a2. Compute relative path from repo root to JSONL\u000a3. Or use `git -C <dir>` to run from beadsDir directly'),'','','','closed',2,'bug','',NULL,'2025-11-25T12:51:03.46856-08:00','2025-11-25T15:05:40.754716-08:00','2025-11-25T15:05:40.754716-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-f0n','c4658fef0e05ceb01612369d5154a96c6acd0dda1b5fc690b9f926884f48dce8','Git history fallback missing timeout - could hang on large repos',unistr('## Problem\u000a\u000aThe git commands in `checkGitHistoryForDeletions` have no timeout. On large repos with extensive history, `git log --all -S` or `git log --all -G` can take a very long time (minutes).\u000a\u000a## Location\u000a`internal/importer/importer.go:899` and `:930`\u000a\u000a## Impact\u000a- Import could hang indefinitely\u000a- User has no feedback that git search is running\u000a- No way to cancel except killing the process\u000a\u000a## Fix\u000aAdd context with timeout to git commands:\u000a\u000a```go\u000actx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\u000adefer cancel()\u000acmd := exec.CommandContext(ctx, "git", ...)\u000a```\u000a\u000aAlso consider adding a `--since` flag to bound the git history search.'),'','','','closed',2,'bug','',NULL,'2025-11-25T12:48:24.388639-08:00','2025-11-25T15:04:53.669714-08:00','2025-11-25T15:04:53.669714-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-imj','8c737545b8cfc85ac4a855a17c4c5dfd4468f9fb67cd6b2075fcb740066e5995','Deletion propagation via deletions manifest',unistr('## Problem\u000a\u000aWhen `bd cleanup -f` or `bd delete` removes issues in one clone, those deletions don''t propagate to other clones. The import logic only creates/updates, never deletes. This causes "resurrection" where deleted issues reappear.\u000a\u000a## Root Cause\u000a\u000aImport sees DB issues not in JSONL and assumes they''re "local unpushed work" rather than "intentionally deleted upstream."\u000a\u000a## Solution: Deletions Manifest\u000a\u000aAdd `.beads/deletions.jsonl` - an append-only log of deleted issue IDs with metadata.\u000a\u000a### Format\u000a```jsonl\u000a{"id":"bd-xxx","ts":"2025-11-25T10:00:00Z","by":"stevey"}\u000a{"id":"bd-yyy","ts":"2025-11-25T10:05:00Z","by":"claude","reason":"duplicate of bd-zzz"}\u000a```\u000a\u000a### Fields\u000a- `id`: Issue ID (required)\u000a- `ts`: ISO 8601 UTC timestamp (required)\u000a- `by`: Actor who deleted (required)\u000a- `reason`: Optional context ("cleanup", "duplicate of X", etc.)\u000a\u000a### Import Logic\u000a```\u000aFor each DB issue not in JSONL:\u000a  1. Check deletions manifest → if found, delete from DB\u000a  2. Fallback: check git history → if found, delete + backfill manifest\u000a  3. Neither → keep (local unpushed work)\u000a```\u000a\u000a### Conflict Resolution\u000aSimultaneous deletions from multiple clones are handled naturally:\u000a- Append-only design means both clones append their deletion records\u000a- On merge, file contains duplicate entries (same ID, different timestamps)\u000a- `LoadDeletions` deduplicates by ID (keeps any/first entry)\u000a- Result: deletion propagates correctly, duplicates are harmless\u000a\u000a### Pruning Policy\u000a- Default retention: 7 days (configurable via `deletions.retention_days`)\u000a- Auto-compact during `bd sync` is **opt-in** (disabled by default)\u000a- Hard cap: `deletions.max_entries` (default 50000)\u000a- Git fallback handles pruned entries (self-healing)\u000a\u000a### Self-Healing\u000aWhen git fallback catches a resurrection (pruned entry), it backfills the manifest. One-time git scan cost, then fast again.\u000a\u000a### Size Estimates\u000a- ~80 bytes/entry\u000a- 7-day retention with 100 deletions/day = ~56KB\u000a- Git compressed: ~10KB\u000a\u000a## Benefits\u000a- ✅ Deletions propagate across clones\u000a- ✅ O(1) lookup (no git scan in normal case)\u000a- ✅ Works in shallow clones\u000a- ✅ Survives history rewrite\u000a- ✅ Audit trail (who deleted what when)\u000a- ✅ Self-healing via git fallback\u000a- ✅ Bounded size via time-based pruning\u000a\u000a## References\u000a- Investigation session: 2025-11-25\u000a- Related: bd-2q6d (stale database warnings)'),'','','','closed',0,'epic','',NULL,'2025-11-25T09:56:01.98027-08:00','2025-11-25T16:36:27.965168-08:00','2025-11-25T16:36:27.965168-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-k4b','1011168532e0f24d82ac577cf50bacb255b699098d6627143cfeee868a73d768','Enhance dep tree to show full dependency graph',unistr('When running `bd dep tree <issue-id>`, the current output only shows the issue itself without its dependency relationships.\u000a\u000a## Current Behavior\u000a\u000a```\u000a$ bd dep tree gt-0iqq\u000a🌲 Dependency tree for gt-0iqq:\u000a\u000a→ gt-0iqq: Implement Boss (global overseer) [P2] (open)\u000a```\u000a\u000aThis doesn''t show any of the dependency structure.\u000a\u000a## Desired Behavior\u000a\u000aShow the full dependency DAG rooted at the given issue. For example:\u000a\u000a```\u000a$ bd dep tree gt-0iqq\u000a🌲 Dependency tree for gt-0iqq:\u000a\u000agt-0iqq: Implement Boss (global overseer) [P2] (open)\u000a├── gt-0xh4: Boss session management [P2] (open) [READY]\u000a│   ├── gt-le7c: Boss mail identity [P2] (open)\u000a│   │   ├── gt-r8fe: Boss human escalation queue [P2] (open)\u000a│   │   └── gt-vdak: Boss dispatch loop [P2] (open)\u000a│   │       └── gt-kgy6: Boss resource management [P2] (open)\u000a│   │           └── gt-93iv: Boss wake daemon [P2] (open)\u000a│   └── gt-vdak: (shown above)\u000a```\u000a\u000a## Suggested Options\u000a\u000a- `--direction=down|up|both` - Show dependents (what this blocks), dependencies (what blocks this), or both\u000a- `--status=open` - Filter to only show issues with a given status\u000a- `--depth=N` - Limit tree depth\u000a- Handle DAG cycles gracefully (show "(shown above)" or similar for already-displayed nodes)\u000a\u000a## Use Case\u000a\u000aWhen reorganizing a set of related issues (like I just did with the Boss implementation), being able to visualize the full dependency graph helps verify the structure is correct before syncing.'),'','','','closed',2,'feature','',NULL,'2025-11-25T19:18:18.750649-08:00','2025-11-25T19:50:46.863319-08:00','2025-11-25T19:31:55.312314-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-l7u','f92ccca897e72f00e41104134fce80fefebfdb0a829d23ac7717b2c5731ececa','Duplicate DefaultRetentionDays constants',unistr('## Problem\u000a\u000aThere are now two constants for the same value:\u000a\u000a1. `deletions.DefaultRetentionDays = 7` in `internal/deletions/deletions.go:184`\u000a2. `configfile.DefaultDeletionsRetentionDays = 7` in `internal/configfile/configfile.go:102`\u000a\u000a## Impact\u000a- DRY violation\u000a- Risk of values getting out of sync\u000a- Confusing which one to use\u000a\u000a## Fix\u000aRemove the constant from `deletions` package and have it import from `configfile`, or create a shared constants package.'),'','','','closed',3,'task','',NULL,'2025-11-25T12:49:38.356211-08:00','2025-11-25T15:15:21.964842-08:00','2025-11-25T15:15:21.964842-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-mdw','09f2ddc2a90326cb313071a0fc930e20f8f743dc3126cd83fdbffa52619f7588','Add integration test for cross-clone deletion propagation','','','','','closed',2,'task','',NULL,'2025-11-25T14:56:38.997009-08:00','2025-11-25T16:35:59.052914-08:00','2025-11-25T16:35:59.052914-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-qsm','577146283870a7bf5e5d5ad526411df701ac6ee08856ceb610e25d1e6b7be0cf','Auto-compact deletions during bd sync',unistr('Parent: bd-imj\u000a\u000a## Task\u000aOptionally prune deletions manifest during sync when threshold exceeded.\u000a\u000a**Note: Opt-in feature** - disabled by default to avoid sync latency.\u000a\u000a## Implementation\u000a\u000aIn `bd sync`:\u000a```go\u000afunc (s *Syncer) Sync() error {\u000a    // ... existing sync logic ...\u000a    \u000a    // Auto-compact only if enabled\u000a    if s.config.GetBool("deletions.auto_compact", false) {\u000a        deletionCount := deletions.Count(".beads/deletions.jsonl")\u000a        threshold := s.config.GetInt("deletions.auto_compact_threshold", 1000)\u000a        \u000a        if deletionCount > threshold {\u000a            retentionDays := s.config.GetInt("deletions.retention_days", 7)\u000a            if err := s.compactor.PruneDeletions(retentionDays); err != nil {\u000a                log.Warnf("Failed to auto-compact deletions: %v", err)\u000a                // Non-fatal, continue sync\u000a            }\u000a        }\u000a    }\u000a    \u000a    // ... rest of sync ...\u000a}\u000a```\u000a\u000a## Configuration\u000a```yaml\u000adeletions:\u000a  retention_days: 7\u000a  auto_compact: false              # Opt-in, disabled by default\u000a  auto_compact_threshold: 1000     # Trigger when > N entries (if enabled)\u000a```\u000a\u000a## Acceptance Criteria\u000a- [ ] Auto-compact disabled by default\u000a- [ ] Enabled via config `deletions.auto_compact: true`\u000a- [ ] Sync checks deletion count only when enabled\u000a- [ ] Auto-prunes when threshold exceeded\u000a- [ ] Failure is non-fatal (logged warning)\u000a- [ ] Test: no compaction when disabled\u000a- [ ] Test: compaction triggers when enabled and threshold exceeded'),'','','','closed',1,'task','',NULL,'2025-11-25T09:57:04.522795-08:00','2025-11-25T15:03:01.469629-08:00','2025-11-25T15:03:01.469629-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-tys','efaa2cb87964b5c5b2828249331a2828f3ec2696fcf9de3ac13674ee8041c046','Git history fallback has incorrect logic for detecting deletions',unistr('## Problem\u000a\u000aThe `wasInGitHistory` function in `internal/importer/importer.go:891` returns true if the ID is found **anywhere** in git history. But finding an ID in history doesn''t necessarily mean it was deleted - it could mean:\u000a\u000a1. The issue was added (appears in a commit adding it)\u000a2. The issue was modified (appears in commits updating it)\u000a3. The issue was deleted (appears in a commit removing it)\u000a\u000aThe current logic incorrectly treats all three cases as ''deleted''.\u000a\u000a## Correct Logic\u000a\u000a`git log -S` with `--oneline` shows commits where the string was added OR removed. To detect deletion specifically:\u000a\u000a1. ID appears in git history (was once in JSONL)\u000a2. ID is NOT currently in JSONL\u000a\u000aThe second condition is already checked by the caller (`purgeDeletedIssues`), so technically the logic is correct in context. But the function name and doc comment are misleading.\u000a\u000a## Fix Options\u000a\u000a1. **Rename function** to `wasEverInJSONL` and update doc comment to clarify\u000a2. **Add explicit check** for current JSONL state in the function itself\u000a\u000aOption 1 is simpler and correct since caller already filters.'),'','','','closed',3,'bug','',NULL,'2025-11-25T12:46:16.073661-08:00','2025-11-25T15:11:54.426093-08:00','2025-11-25T15:11:54.426093-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-v29','1a4ada02aff343b50c4940b4c84a143188ad62269e9a41030ae5ae1cc9f1a38f','Deletions pruning doesn''t include results in JSON output',unistr('## Problem\u000a\u000aWhen `bd compact --json` runs with deletions pruning, the prune results are silently discarded:\u000a\u000a```go\u000a// Only report if there were deletions to prune\u000aif result.PrunedCount > 0 {\u000a    if jsonOutput {\u000a        // JSON output will be included in the main response\u000a        return  // <-- BUG: results are NOT included anywhere\u000a    }\u000a    ...\u000a}\u000a```\u000a\u000a## Location\u000a`cmd/bd/compact.go:925-929`\u000a\u000a## Impact\u000a- JSON consumers don''t know deletions were pruned\u000a- No way to audit pruning via automation\u000a\u000a## Fix\u000aReturn prune results and include in JSON output structure:\u000a\u000a```json\u000a{\u000a  "success": true,\u000a  "compacted": {...},\u000a  "deletions_pruned": {\u000a    "count": 5,\u000a    "retention_days": 7\u000a  }\u000a}\u000a```'),'','','','closed',2,'bug','',NULL,'2025-11-25T12:48:59.730979-08:00','2025-11-25T15:11:54.363653-08:00','2025-11-25T15:11:54.363653-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-wmo','284c50f833f01daf32df8950385cfbde9ad11ff74630f08a4ab14bda872deb0f','PruneDeletions iterates map non-deterministically',unistr('## Problem\u000a\u000a`PruneDeletions` iterates over `loadResult.Records` which is a map. Go maps iterate in random order, so:\u000a\u000a1. `result.PrunedIDs` order is non-deterministic\u000a2. `kept` slice order is non-deterministic → `WriteDeletions` output order varies\u000a\u000a## Location\u000a`internal/deletions/deletions.go:213`\u000a\u000a## Impact\u000a- Git diffs are noisy (file changes order on each prune)\u000a- Tests could be flaky if they depend on order\u000a- Harder to debug/audit\u000a\u000a## Fix\u000aSort by ID or timestamp before iterating:\u000a\u000a```go\u000a// Convert map to slice and sort\u000avar records []DeletionRecord\u000afor _, r := range loadResult.Records {\u000a    records = append(records, r)\u000a}\u000asort.Slice(records, func(i, j int) bool {\u000a    return records[i].ID < records[j].ID\u000a})\u000a```'),'','','','closed',3,'bug','',NULL,'2025-11-25T12:49:11.290916-08:00','2025-11-25T15:15:21.903649-08:00','2025-11-25T15:15:21.903649-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-x2i','f1ec5c8f9da394d7bab765106b1b03548d473e5d9dfc430d8ccce82f13c030a4','Add bd deleted command for audit trail',unistr('Parent: bd-imj\u000a\u000aAdd command to view deletion history.\u000a\u000aUsage:\u000a  bd deleted              # Show recent deletions (last 7 days)\u000a  bd deleted --since=30d  # Show deletions in last 30 days\u000a  bd deleted --all        # Show all tracked deletions\u000a  bd deleted bd-xxx       # Show deletion details for specific issue\u000a\u000aOutput format:\u000a  bd-xxx  2025-11-25 10:00  stevey  duplicate of bd-yyy\u000a  bd-yyy  2025-11-25 10:05  claude  cleanup\u000a\u000aAcceptance criteria:\u000a- List deletions with timestamp, actor, reason\u000a- Filter by time range\u000a- Lookup specific issue ID\u000a- JSON output option for scripting'),'','','','closed',2,'task','',NULL,'2025-11-25T09:57:21.113861-08:00','2025-11-25T15:13:53.781519-08:00','2025-11-25T15:13:53.781519-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-xyc','38535e356e979208ac1200ee68fd3b3347dc22179ab012b2eb10f46349af763f','Consolidate check-health DB opens into single connection','The --check-health flag opens the database 3 separate times (once per quick check). Consolidate into a single DB open for better performance, especially on slower filesystems.','','','','closed',2,'task','',NULL,'2025-11-25T19:27:42.034178-08:00','2025-11-25T19:50:21.32375-08:00','2025-11-25T19:50:21.32375-08:00',NULL,0,NULL,NULL,NULL,'.');
INSERT INTO issues VALUES('bd-c6w','6cc279fbdcff724be4af10044277d783e81ea5b581b5a215c7860ced4d17bcd8','bd info whats-new missing releases','Current release is v0.25.1 but `bd info --whats-new` stops at v0.23.0, indicating something is missing in the create new release workflow.','','','github issue #386','in_progress',2,'task','',NULL,'2025-11-26T05:50:37.252394374-07:00','2025-11-26T06:05:16.038580771-07:00',NULL,NULL,0,NULL,NULL,NULL,'.');
CREATE TABLE dependencies (
    issue_id TEXT NOT NULL,
    depends_on_id TEXT NOT NULL,
    type TEXT NOT NULL DEFAULT 'blocks',
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    created_by TEXT NOT NULL,
    PRIMARY KEY (issue_id, depends_on_id),
    FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE,
    FOREIGN KEY (depends_on_id) REFERENCES issues(id) ON DELETE CASCADE
);
INSERT INTO dependencies VALUES('bd-81a','bd-d4i','blocks','2025-11-11T23:29:46.646327-08:00','daemon');
INSERT INTO dependencies VALUES('bd-tne','bd-d4i','blocks','2025-11-11T23:29:29.872081-08:00','daemon');
INSERT INTO dependencies VALUES('bd-4h3','bd-ge7','blocks','2025-11-20T21:21:31.277639-05:00','daemon');
INSERT INTO dependencies VALUES('bd-e92','bd-ge7','blocks','2025-11-20T21:21:31.128625-05:00','daemon');
INSERT INTO dependencies VALUES('bd-m0w','bd-ge7','blocks','2025-11-20T21:21:31.350477-05:00','daemon');
INSERT INTO dependencies VALUES('bd-t3b','bd-ge7','blocks','2025-11-20T21:21:31.201036-05:00','daemon');
INSERT INTO dependencies VALUES('bd-imj','bd-qsm','blocks','2025-11-25T09:57:42.821911-08:00','daemon');
INSERT INTO dependencies VALUES('bd-imj','bd-x2i','blocks','2025-11-25T09:57:42.851712-08:00','daemon');
INSERT INTO dependencies VALUES('bd-imj','bd-44e','blocks','2025-11-25T09:57:42.88154-08:00','daemon');
INSERT INTO dependencies VALUES('bd-imj','bd-bhd','blocks','2025-11-25T14:56:23.675787-08:00','daemon');
INSERT INTO dependencies VALUES('bd-imj','bd-bgs','blocks','2025-11-25T14:56:23.744648-08:00','daemon');
INSERT INTO dependencies VALUES('bd-imj','bd-f0n','blocks','2025-11-25T14:56:23.80649-08:00','daemon');
INSERT INTO dependencies VALUES('bd-imj','bd-v29','blocks','2025-11-25T14:56:23.864569-08:00','daemon');
INSERT INTO dependencies VALUES('bd-imj','bd-mdw','blocks','2025-11-25T14:56:48.592492-08:00','daemon');
INSERT INTO dependencies VALUES('bd-imj','bd-03r','blocks','2025-11-25T14:56:54.295851-08:00','daemon');
CREATE TABLE labels (
    issue_id TEXT NOT NULL,
    label TEXT NOT NULL,
    PRIMARY KEY (issue_id, label),
    FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE
);
CREATE TABLE comments (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    issue_id TEXT NOT NULL,
    author TEXT NOT NULL,
    text TEXT NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE
);
CREATE TABLE events (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    issue_id TEXT NOT NULL,
    event_type TEXT NOT NULL,
    actor TEXT NOT NULL,
    old_value TEXT,
    new_value TEXT,
    comment TEXT,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE
);
INSERT INTO events VALUES(162,'bd-736d','created','import',NULL,'{"id":"bd-736d","content_hash":"4743b1f41ff07fee3daa63240f0d5f7ac3f876e928b22c4ce0bee2cdf544e53a","title":"Refactor path canonicalization into helper function","description":"The path canonicalization logic (filepath.Abs + EvalSymlinks) is duplicated in 3 places:\n- beads.go:131-137 (BEADS_DIR handling)\n- cmd/bd/main.go:446-451 (--no-db cleanup)\n- cmd/bd/nodb.go:26-31 (--no-db initialization)\n\nRefactoring suggestion:\nExtract to a helper function like:\n  func canonicalizePath(path string) string\n\nThis would:\n- Reduce code duplication\n- Make the logic easier to maintain\n- Ensure consistent behavior across all path handling\n\nRelated to bd-e16b implementation.","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:33:47.727443-08:00","updated_at":"2025-11-02T18:33:47.727443-08:00","source_repo":"."}',NULL,'2025-11-08 20:26:48');
INSERT INTO events VALUES(222,'bd-9e23','created','import',NULL,'{"id":"bd-9e23","content_hash":"fa94af8126d5d8c816a6f83d5ad191ebdb954687abb87ce30e4f67eee4f1a9ce","title":"Optimize Memory backend GetIssueByExternalRef with index","description":"Currently GetIssueByExternalRef in Memory storage uses O(n) linear search through all issues.\n\nCurrent code (memory.go:282-308):\nfor _, issue := range m.issues {\n    if issue.ExternalRef != nil \u0026\u0026 *issue.ExternalRef == externalRef {\n        return \u0026issueCopy, nil\n    }\n}\n\nProposed optimization:\n- Add externalRefToID map[string]string to MemoryStorage\n- Maintain it in CreateIssue, UpdateIssue, DeleteIssue\n- Achieve O(1) lookup like SQLite''s index\n\nImpact: Low (--no-db mode typically has smaller datasets)\nRelated: bd-1022","status":"open","priority":4,"issue_type":"chore","created_at":"2025-11-02T15:32:30.242357-08:00","updated_at":"2025-11-02T15:32:30.242357-08:00","source_repo":"."}',NULL,'2025-11-08 20:26:48');
INSERT INTO events VALUES(227,'bd-9li4','created','import',NULL,'{"id":"bd-9li4","content_hash":"7ae7b885e82a2de333584c01f690dbc3ecb924603f18e316f5c91cc44e2256f8","title":"Create Docker image for Agent Mail","description":"Containerize Agent Mail server for easy deployment.\n\nAcceptance Criteria:\n- Dockerfile with Python 3.14\n- Health check endpoint\n- Volume mount for storage\n- Environment variable configuration\n- Multi-arch builds (amd64, arm64)\n\nFile: deployment/agent-mail/Dockerfile","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-07T22:43:43.231964-08:00","updated_at":"2025-11-07T22:43:43.231964-08:00","source_repo":"."}',NULL,'2025-11-08 20:26:48');
INSERT INTO events VALUES(265,'bd-c362','created','import',NULL,'{"id":"bd-c362","content_hash":"3b9c44101d7f31fb6cbf4913873a4e140e74fbe7403907e8532bfaaabf875197","title":"Extract database search logic into helper function","description":"The logic for finding a database in a beads directory is duplicated:\n- FindDatabasePath() BEADS_DIR section (beads.go:141-169)\n- findDatabaseInTree() (beads.go:248-280)\n\nBoth implement the same search order:\n1. Check config.json first (single source of truth)\n2. Fall back to canonical beads.db\n3. Search for *.db files, filtering backups and vc.db\n\nRefactoring suggestion:\nExtract to a helper function like:\n  func findDatabaseInBeadsDir(beadsDir string) string\n\nBenefits:\n- Single source of truth for database search logic\n- Easier to maintain and update search order\n- Reduces code duplication\n\nRelated to bd-e16b implementation.","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:34:02.831543-08:00","updated_at":"2025-11-02T18:34:02.831543-08:00","source_repo":".","dependencies":[{"issue_id":"bd-c362","depends_on_id":"bd-e16b","type":"blocks","created_at":"2025-11-02T18:34:02.832607-08:00","created_by":"daemon"}]}',NULL,'2025-11-08 20:26:48');
INSERT INTO events VALUES(302,'bd-e166','created','import',NULL,'{"id":"bd-e166","content_hash":"000f4f9d069ffedceae13894d967ec30fa4a89e318bfcac4847f3c3b16d44a89","title":"Improve timestamp comparison readability in import","description":"The timestamp comparison logic uses double-negative which can be confusing:\n\nCurrent code:\nif !incoming.UpdatedAt.After(existing.UpdatedAt) {\n    // skip update\n}\n\nMore readable:\nif incoming.UpdatedAt.After(existing.UpdatedAt) {\n    // perform update\n} else {\n    // skip (local is newer)\n}\n\nThis is a minor refactor for code clarity.\n\nRelated: bd-1022\nFiles: internal/importer/importer.go:411, 488","status":"open","priority":4,"issue_type":"chore","created_at":"2025-11-02T15:32:12.27108-08:00","updated_at":"2025-11-02T15:32:12.27108-08:00","source_repo":"."}',NULL,'2025-11-08 20:26:48');
INSERT INTO events VALUES(551,'bd-c362','dependency_added','import',NULL,NULL,'Added dependency: bd-c362 blocks bd-e16b','2025-11-08 20:26:48');
INSERT INTO events VALUES(758,'bd-ye0d','created','daemon',NULL,'{"id":"bd-ye0d","content_hash":"40962ef4e144b58167a07ae13458b40cedff3f3549fccab3a172ca908cd754bc","title":"troubleshoot GH#278 daemon exits every few secs","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-13T06:27:23.39509215-07:00","updated_at":"2025-11-13T06:27:23.39509215-07:00"}',NULL,'2025-11-13 13:27:23');
INSERT INTO events VALUES(761,'bd-81a','created','import',NULL,'{"id":"bd-81a","content_hash":"0f43da9e36bc3c5db20f302b82021377685a9425f519a36bab5a2cf1b85f13d8","title":"Add programmatic tip injection API","description":"Allow tips to be programmatically injected at runtime based on detected conditions. This enables dynamic tips (not just pre-defined ones) to be shown with custom priority and frequency.","design":"## API Design\n\nAdd to `cmd/bd/tips.go`:\n\n```go\n// InjectTip adds a dynamic tip to the registry at runtime\nfunc InjectTip(id, message string, priority int, frequency time.Duration, probability float64, condition func() bool) {\n    tipsMutex.Lock()\n    defer tipsMutex.Unlock()\n    \n    tips = append(tips, Tip{\n        ID:          id,\n        Condition:   condition,\n        Message:     message,\n        Frequency:   frequency,\n        Priority:    priority,\n        Probability: probability,\n    })\n}\n\n// RemoveTip removes a tip from the registry\nfunc RemoveTip(id string) {\n    tipsMutex.Lock()\n    defer tipsMutex.Unlock()\n    \n    for i, tip := range tips {\n        if tip.ID == id {\n            tips = append(tips[:i], tips[i+1:]...)\n            return\n        }\n    }\n}\n```\n\n## Use Cases\n\n### Example 1: Critical Security Update\n```go\n// In bd version check code\nif criticalSecurityUpdate {\n    InjectTip(\n        \"security_update\",\n        fmt.Sprintf(\"CRITICAL: Security update available (bd %s). Update immediately!\", remoteVersion),\n        100,         // Highest priority\n        0,           // No frequency limit\n        1.0,         // Always show (100% probability)\n        func() bool { return true },\n    )\n}\n```\n\n### Example 2: New Version Available\n```go\n// In bd version check code\nif remoteVersion \u003e currentVersion {\n    InjectTip(\n        \"upgrade_available\",\n        fmt.Sprintf(\"New bd version %s available (you have %s). Run: go install github.com/steveyegge/beads/cmd/bd@latest\", remoteVersion, currentVersion),\n        90,          // High priority\n        7 * 24 * time.Hour,  // Weekly\n        0.8,         // 80% probability (frequent but not always)\n        func() bool { return true },\n    )\n}\n```\n\n### Example 3: Large Issue Count Suggestion\n```go\n// In bd list code\nif issueCount \u003e 100 {\n    InjectTip(\n        \"use_filters\",\n        \"You have many issues. Use filters: ''bd list --status=open --priority=1''\",\n        50,          // Medium priority\n        14 * 24 * time.Hour,  // Bi-weekly\n        0.4,         // 40% probability (occasional suggestion)\n        func() bool { return true },\n    )\n}\n```\n\n### Example 4: No Dependencies Used\n```go\n// After analyzing project\nif hasIssues \u0026\u0026 noDependenciesCreated {\n    InjectTip(\n        \"try_dependencies\",\n        \"Try using dependencies: ''bd dep \u003cissue\u003e \u003cblocks-issue\u003e'' to track blockers\",\n        30,          // Low priority\n        30 * 24 * time.Hour,  // Monthly\n        0.3,         // 30% probability (low-key suggestion)\n        func() bool { return true },\n    )\n}\n```\n\n## Probability Guidelines\n\n- **1.0 (100%)**: Critical security, breaking changes, data loss prevention\n- **0.7-0.9 (70-90%)**: Important updates, major new features\n- **0.4-0.6 (40-60%)**: General tips, workflow improvements, feature discovery\n- **0.1-0.3 (10-30%)**: Nice-to-know features, advanced tips, optional optimizations\n\n## Thread Safety\n- Use mutex to protect tip registry\n- Safe for concurrent command execution\n- Deterministic testing via BEADS_TIP_SEED env var","acceptance_criteria":"- InjectTip() API exists and is documented\n- RemoveTip() API exists\n- Thread-safe with mutex protection\n- Can inject tips from any command\n- Injected tips participate in priority/frequency rotation\n- Unit tests for injection API\n- Example usage in code comments","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:29:46.645583-08:00","updated_at":"2025-11-11T23:50:12.209135-08:00","source_repo":".","dependencies":[{"issue_id":"bd-81a","depends_on_id":"bd-d4i","type":"blocks","created_at":"2025-11-11T23:29:46.646327-08:00","created_by":"daemon"}]}',NULL,'2025-11-13 13:29:47');
INSERT INTO events VALUES(764,'bd-d4i','created','import',NULL,'{"id":"bd-d4i","content_hash":"41cafb4bfa5377a84005b08cddd3e703c1317e98ef32b050ddaabf1bdc7718c9","title":"Create tip system infrastructure for contextual hints","description":"Implement a tip/hint system that shows helpful contextual messages after successful commands. This is different from the existing error-path \"Hint:\" messages - tips appear on success paths to educate users about features they might not know about.","design":"## Implementation\n\nCreate `cmd/bd/tips.go` with:\n\n### Core Infrastructure\n```go\ntype Tip struct {\n    ID          string\n    Condition   func() bool      // Should this tip be eligible?\n    Message     string\n    Frequency   time.Duration    // Minimum gap between showings\n    Priority    int              // Higher = shown first when eligible\n    Probability float64          // 0.0 to 1.0 - chance of showing\n}\n\nfunc maybeShowTip(store storage.Storage) {\n    if jsonOutput || quietMode {\n        return // Respect output flags\n    }\n    \n    tip := selectNextTip(store)\n    if tip != nil {\n        fmt.Fprintf(os.Stdout, \"\\n💡 Tip: %s\\n\", tip.Message)\n        recordTipShown(store, tip.ID)\n    }\n}\n\nfunc selectNextTip(store storage.Storage) *Tip {\n    now := time.Now()\n    var eligibleTips []Tip\n    \n    // Filter to eligible tips (condition + frequency check)\n    for _, tip := range tips {\n        if !tip.Condition() {\n            continue\n        }\n        \n        lastShown := getLastShown(store, tip.ID)\n        if !lastShown.IsZero() \u0026\u0026 now.Sub(lastShown) \u003c tip.Frequency {\n            continue\n        }\n        \n        eligibleTips = append(eligibleTips, tip)\n    }\n    \n    if len(eligibleTips) == 0 {\n        return nil\n    }\n    \n    // Sort by priority (highest first)\n    sort.Slice(eligibleTips, func(i, j int) bool {\n        return eligibleTips[i].Priority \u003e eligibleTips[j].Priority\n    })\n    \n    // Apply probability roll (in priority order)\n    for _, tip := range eligibleTips {\n        if rand.Float64() \u003c tip.Probability {\n            return \u0026tip\n        }\n    }\n    \n    return nil  // No tips won probability roll\n}\n```\n\n### Probability Examples\n\n```go\n// High priority, high probability = shows often\n{Priority: 90, Probability: 0.8}  // 80% chance when eligible\n\n// High priority, medium probability = important but not spammy\n{Priority: 100, Probability: 0.6}  // 60% chance\n\n// Low priority, low probability = rare suggestion\n{Priority: 30, Probability: 0.3}  // 30% chance\n```\n\n### Metadata Storage\nUse existing metadata table to track:\n- `tip_{id}_last_shown` - Timestamp of last display (RFC3339 format)\n- `tip_{id}_dismissed` - User permanently dismissed (future feature)\n\n### Integration Points\nCall `maybeShowTip()` at end of:\n- `bd list` - After showing issues\n- `bd ready` - After showing ready work\n- `bd create` - After creating issue\n- `bd show` - After showing issue details\n\n## Design Decisions\n- Tips shown on stdout (informational, not errors)\n- Respects `--json` and `--quiet` flags\n- Frequency enforces minimum gap between showings\n- Priority determines evaluation order\n- Probability reduces spam (not every eligible tip shows)\n- Store state in metadata table (no new files)\n- Deterministic seed for testing (optional BEADS_TIP_SEED env var)","acceptance_criteria":"- Tip infrastructure exists in cmd/bd/tips.go\n- Tips respect --json and --quiet flags\n- Frequency tracking works (no spam)\n- Metadata table stores tip state\n- Unit tests for tip selection logic\n- Documentation in code comments","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:29:15.693956-08:00","updated_at":"2025-11-11T23:49:50.812933-08:00","source_repo":"."}',NULL,'2025-11-13 13:29:47');
INSERT INTO events VALUES(767,'bd-tne','created','import',NULL,'{"id":"bd-tne","content_hash":"2a6596980450714800bddc88e106026743a1a131e96f09198eb7dc2a16d75ca4","title":"Add Claude setup tip with dynamic priority","description":"Add a predefined tip that suggests running `bd setup claude` when Claude Code is detected but not configured. This tip should have higher priority (shown more frequently) until the setup is complete.","design":"## Implementation\n\nAdd to tip registry in `cmd/bd/tips.go`:\n\n```go\n{\n    ID: \"claude_setup\",\n    Condition: func() bool {\n        return isClaudeDetected() \u0026\u0026 !isClaudeSetupComplete()\n    },\n    Message: \"Run ''bd setup claude'' to enable automatic context recovery in Claude Code\",\n    Frequency: 24 * time.Hour,  // Daily minimum gap\n    Priority: 100,              // Highest priority\n    Probability: 0.6,           // 60% chance when eligible\n}\n```\n\n## Detection Logic\n\n```go\nfunc isClaudeDetected() bool {\n    // Check environment variables\n    if os.Getenv(\"CLAUDE_CODE\") != \"\" || os.Getenv(\"ANTHROPIC_CLI\") != \"\" {\n        return true\n    }\n    // Check if .claude/ directory exists\n    if _, err := os.Stat(filepath.Join(os.Getenv(\"HOME\"), \".claude\")); err == nil {\n        return true\n    }\n    return false\n}\n\nfunc isClaudeSetupComplete() bool {\n    // Check for global installation\n    home, err := os.UserHomeDir()\n    if err == nil {\n        _, err1 := os.Stat(filepath.Join(home, \".claude/commands/prime_beads.md\"))\n        _, err2 := os.Stat(filepath.Join(home, \".claude/hooks/sessionstart\"))\n        if err1 == nil \u0026\u0026 err2 == nil {\n            return true  // Global hooks installed\n        }\n    }\n    \n    // Check for project installation\n    _, err1 := os.Stat(\".claude/commands/prime_beads.md\")\n    _, err2 := os.Stat(\".claude/hooks/sessionstart\")\n    return err1 == nil \u0026\u0026 err2 == nil\n}\n```\n\n## Priority and Probability Behavior\n\n**Why 60% probability?**\n- Important message (priority 100) but not critical\n- Daily frequency + 60% = shows ~4 times per week\n- Avoids spam while staying visible\n- Balances persistence with user experience\n\n**Comparison with other probabilities:**\n- 100% probability: Shows EVERY day (annoying)\n- 80% probability: Shows ~6 days per week (too frequent)\n- 60% probability: Shows ~4 days per week (balanced)\n- 40% probability: Shows ~3 days per week (might be missed)\n\n**Auto-stops when setup complete:**\n- Condition becomes false after `bd setup claude`\n- No manual dismissal needed\n- Tip naturally disappears from rotation","acceptance_criteria":"- Claude setup tip added to registry\n- isClaudeDetected() checks environment and filesystem\n- isClaudeSetupComplete() verifies hook installation\n- Tip shows daily until setup complete\n- Tip stops showing after setup\n- Unit tests for detection functions","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-11T23:29:29.871324-08:00","updated_at":"2025-11-11T23:50:29.756454-08:00","source_repo":".","dependencies":[{"issue_id":"bd-tne","depends_on_id":"bd-d4i","type":"blocks","created_at":"2025-11-11T23:29:29.872081-08:00","created_by":"daemon"},{"issue_id":"bd-tne","depends_on_id":"bd-br8","type":"blocks","created_at":"2025-11-11T23:29:29.87252-08:00","created_by":"daemon"}]}',NULL,'2025-11-13 13:29:47');
INSERT INTO events VALUES(768,'bd-tru','created','import',NULL,'{"id":"bd-tru","content_hash":"0de12031088519a3dcd27968d6bf17eb3a92d1853264e5a0dceef3310b3a2b04","title":"Update documentation for bd prime and Claude integration","description":"Update AGENTS.md, README.md, and QUICKSTART.md to document the new `bd prime` command, `bd setup claude` command, and tip system.","design":"## Documentation Updates\n\n### AGENTS.md\nAdd new section \"Context Recovery\":\n```markdown\n## Context Recovery\n\n### The Problem\nAfter context compaction or clearing conversation, AI agents may forget to use Beads and revert to markdown TODOs. Claude Code hooks solve this.\n\n### bd prime Command\nThe `bd prime` command outputs essential Beads workflow context in AI-optimized markdown format (~1-2k tokens).\n\n**When to use:**\n- After context compaction\n- After clearing conversation\n- Starting new session\n- When agent seems to forget bd workflow\n- Manual context refresh\n\n**Usage:**\n```bash\nbd prime              # Output workflow context\n```\n\n### Automatic Integration (Recommended)\n\nRun `bd setup claude` to install hooks that auto-refresh bd context:\n- **SessionStart hook**: Loads context in new sessions\n- **PreCompact hook**: Refreshes context before compaction (survives better)\n- **Works with MCP**: Hooks complement MCP server (not replace)\n- **Works without MCP**: bd prime provides workflow via CLI\n\n**Why hooks matter even with MCP:**\n- MCP provides native tools, but agent may forget to use them\n- Hooks keep \"use bd, not markdown\" fresh in context\n- PreCompact refreshes workflow before compaction\n\n### MCP Server vs bd prime\n\n**Not an either/or choice** - they solve different problems:\n\n| Aspect | MCP Server | bd prime | Both |\n|--------|-----------|----------|------|\n| **Purpose** | Native bd tools | Workflow context | Best of both |\n| **Tokens** | 10.5k always loaded | ~1-2k when called | 10.5k + ~2k |\n| **Tool access** | Function calls | CLI via Bash | Function calls |\n| **Context memory** | Can fade after compaction | Hooks keep fresh | Hooks + tools |\n| **Recommended** | Heavy usage | Token optimization | Best experience |\n\n**Setup options:**\n```bash\nbd setup claude           # Install hooks (works with or without MCP)\nbd setup claude --local   # Per-project only\nbd setup claude --remove  # Remove hooks\n```\n```\n\n### README.md\nAdd to \"Getting Started\" section:\n```markdown\n### AI Agent Integration\n\n**Claude Code users:** Run `bd setup claude` to install automatic context recovery hooks.\n\nHooks work with both MCP server and CLI approaches, preventing agents from forgetting bd workflow after compaction.\n\n**MCP vs bd prime:**\n- **With MCP server**: Hooks keep agent using bd tools (prevents markdown TODO reversion)\n- **Without MCP server**: Hooks provide workflow context via `bd prime` (~1-2k tokens)\n```\n\n### QUICKSTART.md\nAdd section on agent integration:\n```markdown\n## For AI Agents\n\n**Context loading:**\n```bash\nbd prime    # Load workflow context (~1-2k tokens)\n```\n\n**Automatic setup (Claude Code):**\n```bash\nbd setup claude    # Install hooks for automatic context recovery\n```\n\nHooks prevent agents from forgetting bd workflow after compaction.\n```","acceptance_criteria":"- AGENTS.md has Context Recovery section\n- README.md mentions bd setup claude\n- QUICKSTART.md mentions bd prime\n- Examples show when to use bd prime vs MCP\n- Clear comparison of trade-offs","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-11T23:30:22.77349-08:00","updated_at":"2025-11-11T23:45:23.242658-08:00","source_repo":".","dependencies":[{"issue_id":"bd-tru","depends_on_id":"bd-rpn","type":"blocks","created_at":"2025-11-11T23:30:22.774216-08:00","created_by":"daemon"},{"issue_id":"bd-tru","depends_on_id":"bd-br8","type":"blocks","created_at":"2025-11-11T23:30:22.774622-08:00","created_by":"daemon"},{"issue_id":"bd-tru","depends_on_id":"bd-90v","type":"parent-child","created_at":"2025-11-11T23:31:35.277819-08:00","created_by":"daemon"}]}',NULL,'2025-11-13 13:29:47');
INSERT INTO events VALUES(769,'bd-wcl','created','import',NULL,'{"id":"bd-wcl","content_hash":"c08d62ce3627a49126c63f6a630a08c1666e5b1b8d9148ae0c72d7d06611b2a9","title":"Document CLI + hooks as recommended approach over MCP","description":"Update documentation to position CLI + bd prime hooks as the primary recommended approach over MCP server, explaining why minimizing context matters even with large context windows (compute cost, energy, environment, latency).","design":"## Goals\n\nPosition CLI + `bd prime` hooks as the **primary recommended approach** for AI agent integration, with MCP server as a legacy/fallback option.\n\nExplore **hybrid mode** - if certain commands benefit from MCP (UX/DX advantages like no approval prompts), minimize MCP surface area to only those commands.\n\nThis requires production validation first - only update docs after CLI mode is proven reliable.\n\n## Why Minimize Context (Even With Large Windows)\n\n**Context window size ≠ free resource**\n\nLarge context windows (100k+, 200k+) don''t mean we should fill them wastefully. Every token in context has real costs:\n\n### Compute Cost\n- **Processing overhead**: Larger context = more GPU/CPU cycles per request\n- **Memory usage**: 10.5k tokens consume significant RAM/VRAM\n- **Scaling impact**: Multiplied across all users, all sessions, all requests\n\n### Energy \u0026 Environment\n- **Electricity**: More compute = more power consumption\n- **Carbon footprint**: Data centers running on grid power (not all renewable)\n- **Sustainability**: Unnecessary token usage contributes to AI''s environmental impact\n- **Responsibility**: Efficient tools are better for the planet\n\n### User Experience\n- **Latency**: Larger context = slower processing (noticeable at 10k+ tokens)\n- **Cost**: Many AI services charge per token (input + output)\n- **Rate limits**: Context counts against API quotas\n\n### Engineering Excellence\n- **Efficiency**: Good engineering minimizes resource usage\n- **Scalability**: Efficient tools scale better\n- **Best practices**: Optimize for the common case\n\n**The comparison:**\n\n| Approach | Standing Context | Efficiency | User Cost | Environmental Impact |\n|----------|-----------------|------------|-----------|---------------------|\n| **CLI + hooks** | ~1-2k tokens | 80-90% reduction | Lower | Sustainable ✓ |\n| **MCP minimal** | ~2-4k tokens | 60-80% reduction | Medium | Better ✓ |\n| **MCP full** | ~10.5k tokens | Baseline | Higher | Wasteful ✗ |\n\n**Functional equivalence:**\n- CLI via Bash tool works just as well as MCP native calls\n- Same features, same reliability\n- No downside except initial learning curve\n\n## Hybrid Mode: Minimal MCP Surface Area\n\n**Philosophy:** MCP server doesn''t have to expose everything.\n\nIf certain commands have legitimate UX/DX benefits from MCP (e.g., no approval prompts, cleaner syntax), we can expose ONLY those commands via MCP while using CLI for everything else.\n\n### Potential MCP-Only Candidates (TBD)\n\nCommands that might benefit from MCP native calls:\n- `ready` - frequently checked, no side effects, approval prompt annoying\n- `show` - read-only, frequently used, approval slows workflow\n- `list` - read-only, no risk, approval adds friction\n\nCommands that work fine via CLI:\n- `create` - complex parameters, benefits from explicit confirmation\n- `update` - state changes, good to see command explicitly\n- `close` - state changes, explicit is better\n- `dep` - relationships, good to see what''s being linked\n- `sync` - git operations, definitely want visibility\n\n### Token Budget\n\n**Full MCP** (current): ~10.5k tokens\n- All ~20+ bd commands exposed\n- All parameter schemas\n- All descriptions and examples\n\n**Minimal MCP** (proposed): ~2-4k tokens\n- 3-5 high-frequency read commands only\n- Simplified schemas\n- Minimal descriptions\n- Everything else via CLI\n\n**Pure CLI**: ~1-2k tokens (only on SessionStart/PreCompact)\n- No MCP tools loaded\n- All commands via Bash\n\n### Investigation Required\n\nBefore implementing hybrid mode, validate:\n\n1. **Do MCP calls actually skip approval prompts?**\n   - Test with Claude Code approval settings\n   - Compare MCP tool calls vs Bash tool calls\n   - Measure UX difference in real usage\n\n2. **What''s the actual token breakdown per command?**\n   - Measure individual command schemas\n   - Calculate token savings for minimal vs full\n\n3. **Is approval prompt the only benefit?**\n   - Are there other UX advantages to MCP?\n   - Does native syntax actually improve experience?\n   - User testing with both approaches\n\n4. **Can we dynamically load MCP tools?**\n   - Only load MCP when certain commands needed?\n   - Hot-swap between CLI and MCP?\n   - Probably not - MCP loads at startup\n\n### Hybrid Mode Documentation (If Validated)\n\n```markdown\n## Choosing Your Integration Approach\n\nBeads supports three AI agent integration approaches:\n\n### CLI + Hooks (Recommended - Most Efficient)\n\n**Setup:** `bd setup claude`\n\nUses Claude Code hooks to inject workflow context via `bd prime` command. Agent uses bd via Bash tool.\n\n**Tokens:** ~1-2k (on SessionStart/PreCompact only)\n\n**Pros:**\n- Maximum efficiency (80-90% reduction vs full MCP)\n- Lowest compute/energy usage\n- Same functionality as MCP\n\n**Cons:**\n- Bash tool calls may require approval prompts\n- Slightly more verbose in conversation\n\n### Minimal MCP + Hooks (Balanced)\n\n**Setup:** Install minimal MCP server (read-only commands) + `bd setup claude`\n\nExposes only high-frequency read commands via MCP (ready, show, list). Everything else via CLI.\n\n**Tokens:** ~2-4k MCP + ~1-2k hooks\n\n**Pros:**\n- 60-80% reduction vs full MCP\n- No approval prompts for common queries\n- Cleaner syntax for frequent operations\n- Still efficient\n\n**Cons:**\n- Requires MCP server (additional setup)\n- Mixed interface (some MCP, some CLI)\n\n### Full MCP + Hooks (Legacy)\n\n**Setup:** Install full MCP server + `bd setup claude`\n\n**Tokens:** ~10.5k MCP + hooks\n\n**Pros:**\n- All commands as native function calls\n- Consistent interface\n\n**Cons:**\n- Highest token usage (worst for compute/energy/cost)\n- Slowest processing\n- Less sustainable\n\n### Recommendation\n\n1. **Start with CLI + hooks** - most efficient, works great\n2. **Try minimal MCP** if approval prompts become annoying\n3. **Avoid full MCP** - wasteful with no significant benefit\n```\n\n## Production Validation Checklist\n\nBefore making these documentation changes, validate CLI approach works reliably:\n\n### Phase 1: Pure CLI Validation\n- [ ] `bd prime` implemented and tested\n- [ ] Hooks installed and working in Claude Code\n- [ ] Real-world usage by at least 2-3 developers for 1+ weeks\n- [ ] No significant usability issues reported\n- [ ] Agent successfully uses bd via Bash tool\n- [ ] Document which commands (if any) have approval prompt issues\n\n### Phase 2: Hybrid Mode Investigation (Optional)\n- [ ] Test if MCP calls skip approval prompts vs Bash calls\n- [ ] Measure token cost per MCP command\n- [ ] Identify minimal set of commands worth exposing via MCP\n- [ ] Build minimal MCP server variant\n- [ ] Validate token savings (should be 60-80% vs full MCP)\n- [ ] User testing shows actual UX improvement\n\n### Phase 3: Documentation Update\n- [ ] Update based on validation results\n- [ ] Include measured token counts (not estimates)\n- [ ] Provide clear migration paths\n- [ ] Update `bd doctor` recommendations\n\n## Migration Guide (Optional)\n\nFor users currently using MCP:\n\n```markdown\n### Migrating from Full MCP to CLI + Hooks\n\nAlready using full MCP server? You can switch to the more efficient CLI approach:\n\n1. Install hooks: `bd setup claude`\n2. Test it works (hooks inject context, agent uses Bash tool)\n3. Remove MCP server from `~/.claude/settings.json`\n4. Restart Claude Code\n\nYou''ll get the same functionality with 80-90% less token usage.\n\n### Migrating to Minimal MCP (If Available)\n\nIf you find approval prompts annoying for certain commands:\n\n1. Replace full MCP with minimal MCP in `~/.claude/settings.json`\n2. Restart Claude Code\n3. Verify high-frequency commands (ready, show, list) work via MCP\n4. Everything else automatically uses CLI\n\nYou''ll get 60-80% token reduction vs full MCP while keeping the UX benefits.\n```\n\n## Files to Update\n\n- `README.md` - Add recommendation in AI Integration section\n- `AGENTS.md` - Add \"Choosing Your Integration Approach\" section early\n- `QUICKSTART.md` - Update AI integration section\n- `docs/` - Any other AI integration docs if they exist\n- `mcp-server/` - Create minimal variant if hybrid validated\n\n## Future: Update `bd init`\n\nOnce validated, update `bd init` to:\n- Default to recommending `bd setup claude` (hooks only)\n- Mention minimal MCP as option for UX improvement\n- Detect existing full MCP and suggest migration\n- Provide token usage estimates for each approach\n\n## MCP Server Architecture Note\n\n**Key insight:** MCP server doesn''t have to expose all bd functionality.\n\nCurrent design exposes ~20+ commands (all bd subcommands). This is over-engineered.\n\n**Better design:**\n- **Minimal MCP**: 3-5 read-only commands (~2-4k tokens)\n- **CLI**: Everything else via Bash tool\n- **Hooks**: Context injection via `bd prime`\n\nThis achieves best of both worlds:\n- Low token usage (efficient)\n- No approval prompts for common queries (UX)\n- Explicit visibility for state changes (safety)\n\nIf validation shows NO meaningful benefit to MCP (even minimal), skip hybrid mode entirely and recommend pure CLI.","acceptance_criteria":"- Documentation explains CLI + hooks as recommended approach\n- Explains why context size matters (compute/energy/cost/latency)\n- Token comparison table shows 80-90% reduction\n- Migration guide for existing MCP users\n- Only deployed AFTER production validation\n- Clear that both approaches are supported","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-12T00:15:25.923025-08:00","updated_at":"2025-11-12T00:18:16.786857-08:00","source_repo":"."}',NULL,'2025-11-13 13:29:47');
INSERT INTO events VALUES(770,'bd-81a','dependency_added','import',NULL,NULL,'Added dependency: bd-81a blocks bd-d4i','2025-11-13 13:29:47');
INSERT INTO events VALUES(777,'bd-tne','dependency_added','import',NULL,NULL,'Added dependency: bd-tne blocks bd-d4i','2025-11-13 13:29:47');
INSERT INTO events VALUES(778,'bd-tne','dependency_added','import',NULL,NULL,'Added dependency: bd-tne blocks bd-br8','2025-11-13 13:29:47');
INSERT INTO events VALUES(779,'bd-tru','dependency_added','import',NULL,NULL,'Added dependency: bd-tru blocks bd-rpn','2025-11-13 13:29:47');
INSERT INTO events VALUES(780,'bd-tru','dependency_added','import',NULL,NULL,'Added dependency: bd-tru blocks bd-br8','2025-11-13 13:29:47');
INSERT INTO events VALUES(781,'bd-tru','dependency_added','import',NULL,NULL,'Added dependency: bd-tru parent-child bd-90v','2025-11-13 13:29:47');
INSERT INTO events VALUES(788,'bd-c362','updated','import','{"id":"bd-c362","content_hash":"3b9c44101d7f31fb6cbf4913873a4e140e74fbe7403907e8532bfaaabf875197","title":"Extract database search logic into helper function","description":"The logic for finding a database in a beads directory is duplicated:\n- FindDatabasePath() BEADS_DIR section (beads.go:141-169)\n- findDatabaseInTree() (beads.go:248-280)\n\nBoth implement the same search order:\n1. Check config.json first (single source of truth)\n2. Fall back to canonical beads.db\n3. Search for *.db files, filtering backups and vc.db\n\nRefactoring suggestion:\nExtract to a helper function like:\n  func findDatabaseInBeadsDir(beadsDir string) string\n\nBenefits:\n- Single source of truth for database search logic\n- Easier to maintain and update search order\n- Reduces code duplication\n\nRelated to bd-e16b implementation.","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:34:02.831543-08:00","updated_at":"2025-11-02T18:34:02.831543-08:00","source_repo":"."}','{"acceptance_criteria":"","assignee":null,"closed_at":null,"description":"The logic for finding a database in a beads directory is duplicated:\n- FindDatabasePath() BEADS_DIR section (beads.go:141-169)\n- findDatabaseInTree() (beads.go:248-280)\n\nBoth implement the same search order:\n1. Check config.json first (single source of truth)\n2. Fall back to canonical beads.db\n3. Search for *.db files, filtering backups and vc.db\n\nRefactoring suggestion:\nExtract to a helper function like:\n  func findDatabaseInBeadsDir(beadsDir string) string\n\nBenefits:\n- Single source of truth for database search logic\n- Easier to maintain and update search order\n- Reduces code duplication\n\nRelated to [deleted:[deleted:[deleted:bd-e16b]]] implementation.","design":"","external_ref":null,"issue_type":"chore","notes":"","priority":3,"status":"open","title":"Extract database search logic into helper function"}',NULL,'2025-11-21 13:58:10');
INSERT INTO events VALUES(791,'bd-1pj6','created','import',NULL,'{"id":"bd-1pj6","content_hash":"de1c1195b29d9a70c88b5f2b05ca1c3497469d1802f9c0be415d5a44b0575deb","title":"Proposal: Custom status states via config","description":"Proposal to add ''custom status states'' via `bd config`.\nUsers could define an optional issue status enum (e.g., awaiting_review, review_in_progress) in the config.\nThis would enable multi-step pipelines to process issues where each step correlates to a specific status.\n\nExamples:\n- awaiting_verification\n- awaiting_docs\n- awaiting_testing\n","status":"open","priority":3,"issue_type":"feature","created_at":"2025-11-20T18:55:48.670499-05:00","updated_at":"2025-11-20T18:55:48.670499-05:00","source_repo":"."}',NULL,'2025-11-21 13:58:10');
INSERT INTO events VALUES(794,'bd-39o','created','import',NULL,'{"id":"bd-39o","content_hash":"36d58121cc9218718d262a1991ee84695af722d2823cf9c8415c2dfdd44fb390","title":"Rename last_import_hash metadata key to jsonl_content_hash","description":"The metadata key ''last_import_hash'' is misleading because it''s updated on both import AND export (sync.go:614, import.go:320).\n\nBetter names:\n- jsonl_content_hash (more accurate)\n- last_sync_hash (clearer intent)\n\nThis is a breaking change requiring migration of existing metadata values.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:31:07.568739-05:00","updated_at":"2025-11-20T21:31:07.568739-05:00","source_repo":".","dependencies":[{"issue_id":"bd-39o","depends_on_id":"bd-khnb","type":"blocks","created_at":"2025-11-20T21:31:07.5698-05:00","created_by":"daemon"}]}',NULL,'2025-11-21 13:58:10');
INSERT INTO events VALUES(797,'bd-4aao','created','import',NULL,'{"id":"bd-4aao","content_hash":"67e1bab2ec59b16ea0daf6220b137588a6704793584663d1cf6d58765d41437e","title":"Fix failing integration tests in beads-mcp","description":"The `beads-mcp` test suite has failures in `tests/test_bd_client_integration.py` (assertion error in `test_init_creates_beads_directory`) and errors in `tests/test_worktree_separate_dbs.py` (setup failures finding database). These need to be investigated and fixed to ensure a reliable CI baseline.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T18:53:28.4803-05:00","updated_at":"2025-11-20T18:53:28.4803-05:00","source_repo":"."}',NULL,'2025-11-21 13:58:10');
INSERT INTO events VALUES(805,'bd-bt6y','created','import',NULL,'{"id":"bd-bt6y","content_hash":"462f08aa379cf2f196b4c0ca096271fa47ab5e1a18c5663c28d2d86fd02115cf","title":"Improve compact/daemon/merge documentation and UX","description":"Multiple documentation and UX issues encountered:\n1. \"bd compact --analyze\" fails with misleading \"requires SQLite storage\" error when daemon is running. Needs --no-daemon or better error.\n2. \"bd merge\" help text is outdated (refers to 3-way merge instead of issue merging).\n3. Daemon mode purpose isn''t clear to local-only users.\n4. Compact/cleanup commands are hard to discover.\n\nProposed fixes:\n- Fix compact+daemon interaction or error message.\n- Update \"bd merge\" help text.\n- Add \"when to use daemon\" section to docs.\n- Add maintenance section to quickstart.\n","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T18:55:43.637047-05:00","updated_at":"2025-11-20T18:55:43.637047-05:00","source_repo":"."}',NULL,'2025-11-21 13:58:10');
INSERT INTO events VALUES(811,'bd-j3zt','created','import',NULL,'{"id":"bd-j3zt","content_hash":"531ad51101f41375a93d66b8d22105ce7c4913261db78b662bb759e802bc01e2","title":"Fix mypy errors in beads-mcp","description":"Running `mypy .` in `integrations/beads-mcp` reports 287 errors. These should be addressed to improve type safety and code quality.","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-20T18:53:28.557708-05:00","updated_at":"2025-11-20T18:53:28.557708-05:00","source_repo":"."}',NULL,'2025-11-21 13:58:10');
INSERT INTO events VALUES(814,'bd-l954','created','import',NULL,'{"id":"bd-l954","content_hash":"263dd2111cf0353b307f2e47489aa42ecf607e49b1316b54a6497cad9d3722b0","title":"Performance Testing Framework","description":"Add comprehensive performance testing for beads focusing on optimization guidance and validating 10K+ database scale. Uses standard Go tooling, follows existing patterns, minimal complexity.\n\nComponents:\n- Benchmark suite for critical operations at 10K-20K scale\n- Fixture generator for realistic test data (epic hierarchies, cross-links)\n- User diagnostics via bd doctor --perf\n- Always-on profiling integration\n\nGoals:\n- Identify bottlenecks for optimization work\n- Validate performance at 10K+ issue scale\n- Enable users to collect diagnostics for bug reports\n- Support both SQLite and JSONL import paths","status":"open","priority":2,"issue_type":"epic","created_at":"2025-11-13T22:22:11.203467-08:00","updated_at":"2025-11-13T22:22:11.203467-08:00","source_repo":"."}',NULL,'2025-11-21 13:58:10');
INSERT INTO events VALUES(816,'bd-m7ge','created','import',NULL,'{"id":"bd-m7ge","content_hash":"bb08f2bcbbdd2e392733d92bff2e46a51000337ac019d306dd6a2983916873c4","title":"Add .beads/README.md during ''bd init'' for project documentation and promotion","description":"When ''bd init'' is run, automatically generate a .beads/README.md file that:\n\n1. Briefly explains what Beads is (AI-native issue tracking that lives in your repo)\n2. Links to the main repository: https://github.com/steveyegge/beads\n3. Provides a quick reference of essential commands:\n   - bd create: Create new issues\n   - bd list: View all issues\n   - bd update: Modify issue status/details\n   - bd show: View issue details\n   - bd sync: Sync with git remote\n4. Highlights key benefits for AI coding agents and developers\n5. Encourages developers to try it out\n\nThe README should be enthusiastic and compelling to get open source contributors excited about using Beads for their AI-assisted development workflows.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-16T22:32:50.478681-08:00","updated_at":"2025-11-16T22:32:58.492868-08:00","source_repo":"."}',NULL,'2025-11-21 13:58:10');
INSERT INTO events VALUES(818,'bd-mnap','created','import',NULL,'{"id":"bd-mnap","content_hash":"c15d3c631656fe6d21291f127fc545af93e712b5f3f94cce028513fb743a4fdb","title":"Investigate performance issues in VS Code Copilot (Windows)","description":"Beads unusable in Windows 11 VS Code Copilot chat with Sonnet 4.5.\nSummary event happens every 3-4 turns, taking 3 minutes.\nCopilot summarizes after ~125k tokens despite model supporting 1M.\nLarge context size of beads might be triggering aggressive summarization.\nNeed workaround or optimization for context size.\n","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T18:56:30.124918-05:00","updated_at":"2025-11-20T18:56:30.124918-05:00","source_repo":"."}',NULL,'2025-11-21 13:58:10');
INSERT INTO events VALUES(819,'bd-nq41','created','import',NULL,'{"id":"bd-nq41","content_hash":"33f9cfe6a0ef5200dcd5016317b43b1568ff9dc7303537d956bdab02029f6c63","title":"Fix Homebrew warning about Ruby file location","description":"Homebrew warning: Found Ruby file outside steveyegge/beads tap formula directory.\nWarning points to: /opt/homebrew/Library/Taps/steveyegge/homebrew-beads/bd.rb\nIt should likely be inside a Formula/ directory or similar structure expected by Homebrew taps.\n","status":"open","priority":2,"issue_type":"chore","created_at":"2025-11-20T18:56:21.226579-05:00","updated_at":"2025-11-20T18:56:21.226579-05:00","source_repo":"."}',NULL,'2025-11-21 13:58:10');
INSERT INTO events VALUES(821,'bd-p6vp','created','import',NULL,'{"id":"bd-p6vp","content_hash":"1df6d3b9b438cdcdbc618c24fea48769c1f22e8a8701af4e742531d4433ca7ea","title":"Clarify .beads/.gitattributes handling in Protected Branches docs","description":"Protected Branches docs quick start leaves untracked `.beads` directory and `.gitattributes`.\nQuestion: Are these changes meant to be checked into the protected branch?\nNeed to clarify if these should be ignored or committed, or if the instructions are missing a step.\n","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T18:56:25.79407-05:00","updated_at":"2025-11-20T18:56:25.79407-05:00","source_repo":"."}',NULL,'2025-11-21 13:58:10');
INSERT INTO events VALUES(828,'bd-ybv5','created','import',NULL,'{"id":"bd-ybv5","content_hash":"52f6d2143a3e9d63937e7dee2cfb4055740132d3c0831c3e948210179336820f","title":"Refactor AGENTS.md to use external references","description":"Suggestion to use external references (e.g., \"ALWAYS REFER TO ./beads/prompt.md\") instead of including all instructions directly within AGENTS.md.\nReasons:\n1. Agents can follow external references.\n2. Prevents context pollution/stuffing in AGENTS.md as more tools append instructions.\n","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-20T18:55:53.259144-05:00","updated_at":"2025-11-20T18:55:53.259144-05:00","source_repo":"."}',NULL,'2025-11-21 13:58:10');
INSERT INTO events VALUES(830,'bd-zj8e','created','import',NULL,'{"id":"bd-zj8e","content_hash":"655c761aaf4d5b0c9edfba7d96d23e608de94760148715667738d35c2033e110","title":"Performance Testing Documentation","description":"Create docs/performance-testing.md documenting the performance testing framework.\n\nSections:\n1. Overview - What the framework does, goals\n2. Running Benchmarks\n   - make bench command\n   - Running specific benchmarks\n   - Interpreting output (ns/op, allocs/op)\n3. Profiling and Analysis\n   - Viewing CPU profiles with pprof\n   - Reading flamegraphs\n   - Memory profiling\n   - Finding hotspots\n4. User Diagnostics\n   - bd doctor --perf usage\n   - Sharing profiles with bug reports\n   - Understanding the report output\n5. Comparing Performance\n   - Using benchstat for before/after comparisons\n   - Detecting regressions\n6. Tips for Optimization\n   - Common patterns\n   - When to profile vs benchmark\n\nStyle:\n- Concise, practical examples\n- Screenshots/examples of pprof output\n- Clear command-line examples\n- Focus on workflow, not theory","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-13T22:23:38.99897-08:00","updated_at":"2025-11-13T22:23:38.99897-08:00","source_repo":"."}',NULL,'2025-11-21 13:58:10');
INSERT INTO events VALUES(832,'bd-39o','dependency_added','import',NULL,NULL,'Added dependency: bd-39o blocks bd-khnb','2025-11-21 13:58:10');
INSERT INTO events VALUES(876,'bd-4h3','created','import',NULL,'{"id":"bd-4h3","content_hash":"c31e267da6b7885e45562d6b1d9176a4ea8603de218f7ffd361226e7268d283e","title":"Add test coverage for internal/git package","description":"","design":"Git package has 1 test file. Critical package needs comprehensive testing. Target: 70% coverage","acceptance_criteria":"- At least 4 test files\n- Package coverage \u003e= 70%\n- Tests cover git commands, error handling","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:23.497486-05:00","updated_at":"2025-11-20T21:21:23.497486-05:00","source_repo":".","dependencies":[{"issue_id":"bd-4h3","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.277639-05:00","created_by":"daemon"}]}',NULL,'2025-11-22 22:18:47');
INSERT INTO events VALUES(891,'bd-c4rq','created','import',NULL,'{"id":"bd-c4rq","content_hash":"4c096e1d84c3ba5b5b4e107692b990a99166b4c99a4262fd26ec08297fb81046","title":"Refactor: Move staleness check inside daemon branch","description":"## Problem\n\nCurrently ensureDatabaseFresh() is called before the daemon mode check, but it checks daemonClient != nil internally and returns early. This is redundant.\n\n**Location:** All read commands (list.go:196, show.go:27, ready.go:102, status.go:80, etc.)\n\n## Current Pattern\n\nCall happens before daemon check, function checks daemonClient internally.\n\n## Better Pattern\n\nMove staleness check to direct mode branch only, after daemon check.\n\n## Impact\nLow - minor performance improvement (avoids one function call per command in daemon mode)\n\n## Effort\nMedium - requires refactoring 8 command files\n\n## Priority\nLow - can defer to future cleanup PR","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-20T20:17:45.119583-05:00","updated_at":"2025-11-20T20:17:45.119583-05:00","source_repo":"."}',NULL,'2025-11-22 22:18:47');
INSERT INTO events VALUES(897,'bd-e92','created','import',NULL,'{"id":"bd-e92","content_hash":"12073b3293b06f99051bc9c00188aeb520cd2e4792cf4694f1fa4b784e625e54","title":"Add test coverage for internal/autoimport package","description":"","design":"The autoimport package has only 1 test file. Need comprehensive tests. Target: 70% coverage","acceptance_criteria":"- At least 3 test files\n- Package coverage \u003e= 70%\n- Tests cover main functionality, error paths, edge cases","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:22.338577-05:00","updated_at":"2025-11-20T21:21:22.338577-05:00","source_repo":".","dependencies":[{"issue_id":"bd-e92","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.128625-05:00","created_by":"daemon"}]}',NULL,'2025-11-22 22:18:47');
INSERT INTO events VALUES(899,'bd-ge7','created','import',NULL,'{"id":"bd-ge7","content_hash":"84248781654b9924e1f4284058f141b73d761dead05ef9a3d1cc9b9f8cd4b60d","title":"Improve Beads test coverage from 46% to 80%","description":"","design":"Currently at 46% test coverage. Need to systematically improve coverage across all subsystems, focusing first on packages with minimal or no tests.\n\nTarget: 80% overall coverage\n\nApproach:\n- Break down by subsystem (internal/* packages)\n- Prioritize packages with 0-1 test files\n- Each child issue targets specific coverage goals\n- Focus on unit tests for core logic, error paths, and edge cases\n\nThis epic will be executed by the VC executor to test its ability to handle sustained multi-issue work.","acceptance_criteria":"- Overall test coverage reaches 80% or higher\n- All internal/* packages have at least 60% coverage\n- All packages with only 1 test file now have at least 3 test files\n- Quality gates (go test, golangci-lint) pass\n- Tests are maintainable and test actual behavior, not implementation details","status":"open","priority":1,"issue_type":"epic","created_at":"2025-11-20T21:21:03.700271-05:00","updated_at":"2025-11-20T21:21:03.700271-05:00","source_repo":"."}',NULL,'2025-11-22 22:18:47');
INSERT INTO events VALUES(900,'bd-gqo','created','import',NULL,'{"id":"bd-gqo","content_hash":"21642505de8036d9501f8593b78de7b761f05869f9d8d11758278e9c0b33c9c3","title":"Implement health checks in daemon event loop","description":"Add health checks to checkDaemonHealth() function in daemon_event_loop.go:170:\n- Database integrity check\n- Disk space check\n- Memory usage check\n\nCurrently it''s just a no-op placeholder.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-11-21T18:55:07.534304-05:00","updated_at":"2025-11-21T18:55:07.534304-05:00","source_repo":"."}',NULL,'2025-11-22 22:18:47');
INSERT INTO events VALUES(903,'bd-hdt','created','import',NULL,'{"id":"bd-hdt","content_hash":"8e6cf1653ef2ea583b39a421b3d708763ab7c042d6cd494e77202a92af0a7398","title":"Implement auto-merge functionality in duplicates command","description":"The duplicates.go file has a TODO at line 95 to implement the performMerge function for automatic duplicate merging. Currently it just prints a warning message. This would automate the merge process instead of just suggesting commands.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-21T18:55:02.828619-05:00","updated_at":"2025-11-21T18:55:02.828619-05:00","source_repo":"."}',NULL,'2025-11-22 22:18:47');
INSERT INTO events VALUES(911,'bd-m0w','created','import',NULL,'{"id":"bd-m0w","content_hash":"e8641e225f1d4cf13fbd97c4a83046e3597df180d3ee134125e4a35abc6941cd","title":"Add test coverage for internal/validation package","description":"","design":"Validation package has 1 test file. Critical for data integrity. Target: 80% coverage","acceptance_criteria":"- At least 4 test files\n- Package coverage \u003e= 80%\n- Tests cover all validation rules","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:24.129559-05:00","updated_at":"2025-11-20T21:21:24.129559-05:00","source_repo":".","dependencies":[{"issue_id":"bd-m0w","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.350477-05:00","created_by":"daemon"}]}',NULL,'2025-11-22 22:18:47');
INSERT INTO events VALUES(923,'bd-t3b','created','import',NULL,'{"id":"bd-t3b","content_hash":"c32a3a0f2f836148033fb330e209ac22e06dbecf18894153c15e2036f5afae1c","title":"Add test coverage for internal/config package","description":"","design":"Config package has 1 test file. Need comprehensive tests. Target: 70% coverage","acceptance_criteria":"- At least 3 test files\n- Package coverage \u003e= 70%","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T21:21:22.91657-05:00","updated_at":"2025-11-20T21:21:22.91657-05:00","source_repo":".","dependencies":[{"issue_id":"bd-t3b","depends_on_id":"bd-ge7","type":"blocks","created_at":"2025-11-20T21:21:31.201036-05:00","created_by":"daemon"}]}',NULL,'2025-11-22 22:18:47');
INSERT INTO events VALUES(958,'bd-4h3','dependency_added','import',NULL,NULL,'Added dependency: bd-4h3 blocks bd-ge7','2025-11-22 22:18:47');
INSERT INTO events VALUES(983,'bd-e92','dependency_added','import',NULL,NULL,'Added dependency: bd-e92 blocks bd-ge7','2025-11-22 22:18:47');
INSERT INTO events VALUES(990,'bd-m0w','dependency_added','import',NULL,NULL,'Added dependency: bd-m0w blocks bd-ge7','2025-11-22 22:18:47');
INSERT INTO events VALUES(998,'bd-t3b','dependency_added','import',NULL,NULL,'Added dependency: bd-t3b blocks bd-ge7','2025-11-22 22:18:47');
INSERT INTO events VALUES(1053,'bd-c362','updated','import','{"id":"bd-c362","content_hash":"9bbfaede59e2433760f69b45649405ee0885f18849cb30ff0357e56c90c8d4cd","title":"Extract database search logic into helper function","description":"The logic for finding a database in a beads directory is duplicated:\n- FindDatabasePath() BEADS_DIR section (beads.go:141-169)\n- findDatabaseInTree() (beads.go:248-280)\n\nBoth implement the same search order:\n1. Check config.json first (single source of truth)\n2. Fall back to canonical beads.db\n3. Search for *.db files, filtering backups and vc.db\n\nRefactoring suggestion:\nExtract to a helper function like:\n  func findDatabaseInBeadsDir(beadsDir string) string\n\nBenefits:\n- Single source of truth for database search logic\n- Easier to maintain and update search order\n- Reduces code duplication\n\nRelated to [deleted:[deleted:[deleted:bd-e16b]]] implementation.","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:34:02.831543-08:00","updated_at":"2025-11-21T06:58:10.019497477-07:00","source_repo":"."}','{"acceptance_criteria":"","assignee":null,"closed_at":null,"description":"The logic for finding a database in a beads directory is duplicated:\n- FindDatabasePath() BEADS_DIR section (beads.go:141-169)\n- findDatabaseInTree() (beads.go:248-280)\n\nBoth implement the same search order:\n1. Check config.json first (single source of truth)\n2. Fall back to canonical beads.db\n3. Search for *.db files, filtering backups and vc.db\n\nRefactoring suggestion:\nExtract to a helper function like:\n  func findDatabaseInBeadsDir(beadsDir string) string\n\nBenefits:\n- Single source of truth for database search logic\n- Easier to maintain and update search order\n- Reduces code duplication\n\nRelated to [deleted:bd-e16b] implementation.","design":"","external_ref":null,"issue_type":"chore","notes":"","priority":3,"status":"open","title":"Extract database search logic into helper function"}',NULL,'2025-11-25 13:31:29');
INSERT INTO events VALUES(1064,'bd-3gc','created','import',NULL,'{"id":"bd-3gc","content_hash":"83684e0e79d016a9569ccd04adda44cc072a662ee09556c156bf54e0603c5b6a","title":"Audit remaining cmd/bd files for error handling consistency","description":"Extend ERROR_HANDLING_AUDIT.md to cover: daemon_sync.go, update.go, list.go, show.go, close.go, reopen.go, dep.go, label.go, comments.go, delete.go, compact.go, config.go, validate.go and other high-usage command files","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-24T00:28:55.890991-08:00","updated_at":"2025-11-24T00:28:55.890991-08:00","dependencies":[{"issue_id":"bd-3gc","depends_on_id":"bd-1qwo","type":"blocks","created_at":"2025-11-24T00:28:55.891827-08:00","created_by":"daemon"}]}',NULL,'2025-11-25 13:31:29');
INSERT INTO events VALUES(1075,'bd-s0z','created','import',NULL,'{"id":"bd-s0z","content_hash":"b69df0c8664737b3c04b10e3137652e3c8c3d782de0ecd02bfcd648919f8d944","title":"Consider extracting error handling helpers","description":"Evaluate creating FatalError() and WarnError() helpers as suggested in ERROR_HANDLING.md to reduce boilerplate and enforce consistency. Prototype in a few files first to validate the approach.","status":"open","priority":4,"issue_type":"task","created_at":"2025-11-24T00:28:57.248959-08:00","updated_at":"2025-11-24T00:28:57.248959-08:00","dependencies":[{"issue_id":"bd-s0z","depends_on_id":"bd-1qwo","type":"blocks","created_at":"2025-11-24T00:28:57.249945-08:00","created_by":"daemon"}]}',NULL,'2025-11-25 13:31:29');
INSERT INTO events VALUES(1080,'bd-3gc','dependency_added','import',NULL,NULL,'Added dependency: bd-3gc blocks bd-1qwo','2025-11-25 13:31:29');
INSERT INTO events VALUES(1087,'bd-s0z','dependency_added','import',NULL,NULL,'Added dependency: bd-s0z blocks bd-1qwo','2025-11-25 13:31:29');
INSERT INTO events VALUES(1089,'bd-c362','updated','matt','{"id":"bd-c362","content_hash":"11887d087e215372ce1ef2a05c342cd74a2b4604825ad74f3c5daf3f33fa9916","title":"Extract database search logic into helper function","description":"The logic for finding a database in a beads directory is duplicated:\n- FindDatabasePath() BEADS_DIR section (beads.go:141-169)\n- findDatabaseInTree() (beads.go:248-280)\n\nBoth implement the same search order:\n1. Check config.json first (single source of truth)\n2. Fall back to canonical beads.db\n3. Search for *.db files, filtering backups and vc.db\n\nRefactoring suggestion:\nExtract to a helper function like:\n  func findDatabaseInBeadsDir(beadsDir string) string\n\nBenefits:\n- Single source of truth for database search logic\n- Easier to maintain and update search order\n- Reduces code duplication\n\nRelated to [deleted:bd-e16b] implementation.","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:34:02.831543-08:00","updated_at":"2025-11-25T06:31:29.799228222-07:00","source_repo":"."}','{"description":"The logic for finding a database in a beads directory is duplicated:\n- FindDatabasePath() BEADS_DIR section (beads.go:141-169)\n- findDatabaseInTree() (beads.go:248-280)\n\nBoth implement the same search order:\n1. Check config.json first (single source of truth)\n2. Fall back to canonical beads.db\n3. Search for *.db files, filtering backups and vc.db\n\nRefactoring suggestion:\nExtract to a helper function like:\n  func findDatabaseInBeadsDir(beadsDir string) string\n\nBenefits:\n- Single source of truth for database search logic\n- Easier to maintain and update search order\n- Reduces code duplication\n\nRelated to [deleted:[deleted:bd-e16b]] implementation."}',NULL,'2025-11-25 13:34:58');
INSERT INTO events VALUES(1090,'bd-4aao','updated','import','{"id":"bd-4aao","content_hash":"67e1bab2ec59b16ea0daf6220b137588a6704793584663d1cf6d58765d41437e","title":"Fix failing integration tests in beads-mcp","description":"The `beads-mcp` test suite has failures in `tests/test_bd_client_integration.py` (assertion error in `test_init_creates_beads_directory`) and errors in `tests/test_worktree_separate_dbs.py` (setup failures finding database). These need to be investigated and fixed to ensure a reliable CI baseline.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-20T18:53:28.4803-05:00","updated_at":"2025-11-20T18:53:28.4803-05:00","source_repo":"."}','{"acceptance_criteria":"","assignee":null,"closed_at":"2025-11-25T21:39:20.967106-08:00","description":"The `beads-mcp` test suite has failures in `tests/test_bd_client_integration.py` (assertion error in `test_init_creates_beads_directory`) and errors in `tests/test_worktree_separate_dbs.py` (setup failures finding database). These need to be investigated and fixed to ensure a reliable CI baseline.","design":"","external_ref":null,"issue_type":"task","notes":"","priority":2,"status":"closed","title":"Fix failing integration tests in beads-mcp"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1091,'bd-736d','updated','import','{"id":"bd-736d","content_hash":"4743b1f41ff07fee3daa63240f0d5f7ac3f876e928b22c4ce0bee2cdf544e53a","title":"Refactor path canonicalization into helper function","description":"The path canonicalization logic (filepath.Abs + EvalSymlinks) is duplicated in 3 places:\n- beads.go:131-137 (BEADS_DIR handling)\n- cmd/bd/main.go:446-451 (--no-db cleanup)\n- cmd/bd/nodb.go:26-31 (--no-db initialization)\n\nRefactoring suggestion:\nExtract to a helper function like:\n  func canonicalizePath(path string) string\n\nThis would:\n- Reduce code duplication\n- Make the logic easier to maintain\n- Ensure consistent behavior across all path handling\n\nRelated to bd-e16b implementation.","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:33:47.727443-08:00","updated_at":"2025-11-02T18:33:47.727443-08:00","source_repo":"."}','{"acceptance_criteria":"","assignee":null,"closed_at":"2025-11-25T22:27:33.738672-08:00","description":"The path canonicalization logic (filepath.Abs + EvalSymlinks) is duplicated in 3 places:\n- beads.go:131-137 (BEADS_DIR handling)\n- cmd/bd/main.go:446-451 (--no-db cleanup)\n- cmd/bd/nodb.go:26-31 (--no-db initialization)\n\nRefactoring suggestion:\nExtract to a helper function like:\n  func canonicalizePath(path string) string\n\nThis would:\n- Reduce code duplication\n- Make the logic easier to maintain\n- Ensure consistent behavior across all path handling\n\nRelated to bd-e16b implementation.","design":"","external_ref":null,"issue_type":"chore","notes":"","priority":3,"status":"closed","title":"Refactor path canonicalization into helper function"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1092,'bd-81a','updated','import','{"id":"bd-81a","content_hash":"0f43da9e36bc3c5db20f302b82021377685a9425f519a36bab5a2cf1b85f13d8","title":"Add programmatic tip injection API","description":"Allow tips to be programmatically injected at runtime based on detected conditions. This enables dynamic tips (not just pre-defined ones) to be shown with custom priority and frequency.","design":"## API Design\n\nAdd to `cmd/bd/tips.go`:\n\n```go\n// InjectTip adds a dynamic tip to the registry at runtime\nfunc InjectTip(id, message string, priority int, frequency time.Duration, probability float64, condition func() bool) {\n    tipsMutex.Lock()\n    defer tipsMutex.Unlock()\n    \n    tips = append(tips, Tip{\n        ID:          id,\n        Condition:   condition,\n        Message:     message,\n        Frequency:   frequency,\n        Priority:    priority,\n        Probability: probability,\n    })\n}\n\n// RemoveTip removes a tip from the registry\nfunc RemoveTip(id string) {\n    tipsMutex.Lock()\n    defer tipsMutex.Unlock()\n    \n    for i, tip := range tips {\n        if tip.ID == id {\n            tips = append(tips[:i], tips[i+1:]...)\n            return\n        }\n    }\n}\n```\n\n## Use Cases\n\n### Example 1: Critical Security Update\n```go\n// In bd version check code\nif criticalSecurityUpdate {\n    InjectTip(\n        \"security_update\",\n        fmt.Sprintf(\"CRITICAL: Security update available (bd %s). Update immediately!\", remoteVersion),\n        100,         // Highest priority\n        0,           // No frequency limit\n        1.0,         // Always show (100% probability)\n        func() bool { return true },\n    )\n}\n```\n\n### Example 2: New Version Available\n```go\n// In bd version check code\nif remoteVersion \u003e currentVersion {\n    InjectTip(\n        \"upgrade_available\",\n        fmt.Sprintf(\"New bd version %s available (you have %s). Run: go install github.com/steveyegge/beads/cmd/bd@latest\", remoteVersion, currentVersion),\n        90,          // High priority\n        7 * 24 * time.Hour,  // Weekly\n        0.8,         // 80% probability (frequent but not always)\n        func() bool { return true },\n    )\n}\n```\n\n### Example 3: Large Issue Count Suggestion\n```go\n// In bd list code\nif issueCount \u003e 100 {\n    InjectTip(\n        \"use_filters\",\n        \"You have many issues. Use filters: ''bd list --status=open --priority=1''\",\n        50,          // Medium priority\n        14 * 24 * time.Hour,  // Bi-weekly\n        0.4,         // 40% probability (occasional suggestion)\n        func() bool { return true },\n    )\n}\n```\n\n### Example 4: No Dependencies Used\n```go\n// After analyzing project\nif hasIssues \u0026\u0026 noDependenciesCreated {\n    InjectTip(\n        \"try_dependencies\",\n        \"Try using dependencies: ''bd dep \u003cissue\u003e \u003cblocks-issue\u003e'' to track blockers\",\n        30,          // Low priority\n        30 * 24 * time.Hour,  // Monthly\n        0.3,         // 30% probability (low-key suggestion)\n        func() bool { return true },\n    )\n}\n```\n\n## Probability Guidelines\n\n- **1.0 (100%)**: Critical security, breaking changes, data loss prevention\n- **0.7-0.9 (70-90%)**: Important updates, major new features\n- **0.4-0.6 (40-60%)**: General tips, workflow improvements, feature discovery\n- **0.1-0.3 (10-30%)**: Nice-to-know features, advanced tips, optional optimizations\n\n## Thread Safety\n- Use mutex to protect tip registry\n- Safe for concurrent command execution\n- Deterministic testing via BEADS_TIP_SEED env var","acceptance_criteria":"- InjectTip() API exists and is documented\n- RemoveTip() API exists\n- Thread-safe with mutex protection\n- Can inject tips from any command\n- Injected tips participate in priority/frequency rotation\n- Unit tests for injection API\n- Example usage in code comments","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:29:46.645583-08:00","updated_at":"2025-11-11T23:50:12.209135-08:00","source_repo":"."}','{"acceptance_criteria":"","assignee":null,"closed_at":"2025-11-25T17:52:35.096882-08:00","description":"Allow tips to be programmatically injected at runtime based on detected conditions. This enables dynamic tips (not just pre-defined ones) to be shown with custom priority and frequency.","design":"","external_ref":null,"issue_type":"feature","notes":"","priority":2,"status":"closed","title":"Add programmatic tip injection API"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1093,'bd-9li4','updated','import','{"id":"bd-9li4","content_hash":"7ae7b885e82a2de333584c01f690dbc3ecb924603f18e316f5c91cc44e2256f8","title":"Create Docker image for Agent Mail","description":"Containerize Agent Mail server for easy deployment.\n\nAcceptance Criteria:\n- Dockerfile with Python 3.14\n- Health check endpoint\n- Volume mount for storage\n- Environment variable configuration\n- Multi-arch builds (amd64, arm64)\n\nFile: deployment/agent-mail/Dockerfile","status":"open","priority":3,"issue_type":"task","created_at":"2025-11-07T22:43:43.231964-08:00","updated_at":"2025-11-07T22:43:43.231964-08:00","source_repo":"."}','{"acceptance_criteria":"","assignee":null,"closed_at":"2025-11-25T17:47:30.777486-08:00","description":"Containerize Agent Mail server for easy deployment.\n\nAcceptance Criteria:\n- Dockerfile with Python 3.14\n- Health check endpoint\n- Volume mount for storage\n- Environment variable configuration\n- Multi-arch builds (amd64, arm64)\n\nFile: deployment/agent-mail/Dockerfile","design":"","external_ref":null,"issue_type":"task","notes":"","priority":3,"status":"closed","title":"Create Docker image for Agent Mail"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1094,'bd-c362','updated','import','{"id":"bd-c362","content_hash":"7256c67655e80242f62c3012a3e0e761296e3a85ca56e449d66be9d7c34e7a87","title":"Extract database search logic into helper function","description":"The logic for finding a database in a beads directory is duplicated:\n- FindDatabasePath() BEADS_DIR section (beads.go:141-169)\n- findDatabaseInTree() (beads.go:248-280)\n\nBoth implement the same search order:\n1. Check config.json first (single source of truth)\n2. Fall back to canonical beads.db\n3. Search for *.db files, filtering backups and vc.db\n\nRefactoring suggestion:\nExtract to a helper function like:\n  func findDatabaseInBeadsDir(beadsDir string) string\n\nBenefits:\n- Single source of truth for database search logic\n- Easier to maintain and update search order\n- Reduces code duplication\n\nRelated to [deleted:[deleted:bd-e16b]] implementation.","status":"open","priority":3,"issue_type":"chore","created_at":"2025-11-02T18:34:02.831543-08:00","updated_at":"2025-11-25T06:34:58.663147082-07:00","source_repo":"."}','{"acceptance_criteria":"","assignee":null,"closed_at":"2025-11-25T22:27:33.794656-08:00","description":"The logic for finding a database in a beads directory is duplicated:\n- FindDatabasePath() BEADS_DIR section (beads.go:141-169)\n- findDatabaseInTree() (beads.go:248-280)\n\nBoth implement the same search order:\n1. Check config.json first (single source of truth)\n2. Fall back to canonical beads.db\n3. Search for *.db files, filtering backups and vc.db\n\nRefactoring suggestion:\nExtract to a helper function like:\n  func findDatabaseInBeadsDir(beadsDir string) string\n\nBenefits:\n- Single source of truth for database search logic\n- Easier to maintain and update search order\n- Reduces code duplication\n\nRelated to [deleted:bd-e16b] implementation.","design":"","external_ref":null,"issue_type":"chore","notes":"","priority":3,"status":"closed","title":"Extract database search logic into helper function"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1095,'bd-d4i','updated','import','{"id":"bd-d4i","content_hash":"41cafb4bfa5377a84005b08cddd3e703c1317e98ef32b050ddaabf1bdc7718c9","title":"Create tip system infrastructure for contextual hints","description":"Implement a tip/hint system that shows helpful contextual messages after successful commands. This is different from the existing error-path \"Hint:\" messages - tips appear on success paths to educate users about features they might not know about.","design":"## Implementation\n\nCreate `cmd/bd/tips.go` with:\n\n### Core Infrastructure\n```go\ntype Tip struct {\n    ID          string\n    Condition   func() bool      // Should this tip be eligible?\n    Message     string\n    Frequency   time.Duration    // Minimum gap between showings\n    Priority    int              // Higher = shown first when eligible\n    Probability float64          // 0.0 to 1.0 - chance of showing\n}\n\nfunc maybeShowTip(store storage.Storage) {\n    if jsonOutput || quietMode {\n        return // Respect output flags\n    }\n    \n    tip := selectNextTip(store)\n    if tip != nil {\n        fmt.Fprintf(os.Stdout, \"\\n💡 Tip: %s\\n\", tip.Message)\n        recordTipShown(store, tip.ID)\n    }\n}\n\nfunc selectNextTip(store storage.Storage) *Tip {\n    now := time.Now()\n    var eligibleTips []Tip\n    \n    // Filter to eligible tips (condition + frequency check)\n    for _, tip := range tips {\n        if !tip.Condition() {\n            continue\n        }\n        \n        lastShown := getLastShown(store, tip.ID)\n        if !lastShown.IsZero() \u0026\u0026 now.Sub(lastShown) \u003c tip.Frequency {\n            continue\n        }\n        \n        eligibleTips = append(eligibleTips, tip)\n    }\n    \n    if len(eligibleTips) == 0 {\n        return nil\n    }\n    \n    // Sort by priority (highest first)\n    sort.Slice(eligibleTips, func(i, j int) bool {\n        return eligibleTips[i].Priority \u003e eligibleTips[j].Priority\n    })\n    \n    // Apply probability roll (in priority order)\n    for _, tip := range eligibleTips {\n        if rand.Float64() \u003c tip.Probability {\n            return \u0026tip\n        }\n    }\n    \n    return nil  // No tips won probability roll\n}\n```\n\n### Probability Examples\n\n```go\n// High priority, high probability = shows often\n{Priority: 90, Probability: 0.8}  // 80% chance when eligible\n\n// High priority, medium probability = important but not spammy\n{Priority: 100, Probability: 0.6}  // 60% chance\n\n// Low priority, low probability = rare suggestion\n{Priority: 30, Probability: 0.3}  // 30% chance\n```\n\n### Metadata Storage\nUse existing metadata table to track:\n- `tip_{id}_last_shown` - Timestamp of last display (RFC3339 format)\n- `tip_{id}_dismissed` - User permanently dismissed (future feature)\n\n### Integration Points\nCall `maybeShowTip()` at end of:\n- `bd list` - After showing issues\n- `bd ready` - After showing ready work\n- `bd create` - After creating issue\n- `bd show` - After showing issue details\n\n## Design Decisions\n- Tips shown on stdout (informational, not errors)\n- Respects `--json` and `--quiet` flags\n- Frequency enforces minimum gap between showings\n- Priority determines evaluation order\n- Probability reduces spam (not every eligible tip shows)\n- Store state in metadata table (no new files)\n- Deterministic seed for testing (optional BEADS_TIP_SEED env var)","acceptance_criteria":"- Tip infrastructure exists in cmd/bd/tips.go\n- Tips respect --json and --quiet flags\n- Frequency tracking works (no spam)\n- Metadata table stores tip state\n- Unit tests for tip selection logic\n- Documentation in code comments","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-11T23:29:15.693956-08:00","updated_at":"2025-11-11T23:49:50.812933-08:00","source_repo":"."}','{"acceptance_criteria":"","assignee":null,"closed_at":"2025-11-25T17:47:30.747566-08:00","description":"Implement a tip/hint system that shows helpful contextual messages after successful commands. This is different from the existing error-path \"Hint:\" messages - tips appear on success paths to educate users about features they might not know about.","design":"","external_ref":null,"issue_type":"feature","notes":"","priority":2,"status":"closed","title":"Create tip system infrastructure for contextual hints"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1096,'bd-m7ge','updated','import','{"id":"bd-m7ge","content_hash":"bb08f2bcbbdd2e392733d92bff2e46a51000337ac019d306dd6a2983916873c4","title":"Add .beads/README.md during ''bd init'' for project documentation and promotion","description":"When ''bd init'' is run, automatically generate a .beads/README.md file that:\n\n1. Briefly explains what Beads is (AI-native issue tracking that lives in your repo)\n2. Links to the main repository: https://github.com/steveyegge/beads\n3. Provides a quick reference of essential commands:\n   - bd create: Create new issues\n   - bd list: View all issues\n   - bd update: Modify issue status/details\n   - bd show: View issue details\n   - bd sync: Sync with git remote\n4. Highlights key benefits for AI coding agents and developers\n5. Encourages developers to try it out\n\nThe README should be enthusiastic and compelling to get open source contributors excited about using Beads for their AI-assisted development workflows.","status":"open","priority":2,"issue_type":"feature","created_at":"2025-11-16T22:32:50.478681-08:00","updated_at":"2025-11-16T22:32:58.492868-08:00","source_repo":"."}','{"acceptance_criteria":"","assignee":null,"closed_at":"2025-11-25T17:49:42.558381-08:00","description":"When ''bd init'' is run, automatically generate a .beads/README.md file that:\n\n1. Briefly explains what Beads is (AI-native issue tracking that lives in your repo)\n2. Links to the main repository: https://github.com/steveyegge/beads\n3. Provides a quick reference of essential commands:\n   - bd create: Create new issues\n   - bd list: View all issues\n   - bd update: Modify issue status/details\n   - bd show: View issue details\n   - bd sync: Sync with git remote\n4. Highlights key benefits for AI coding agents and developers\n5. Encourages developers to try it out\n\nThe README should be enthusiastic and compelling to get open source contributors excited about using Beads for their AI-assisted development workflows.","design":"","external_ref":null,"issue_type":"feature","notes":"","priority":2,"status":"closed","title":"Add .beads/README.md during ''bd init'' for project documentation and promotion"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1097,'bd-tne','updated','import','{"id":"bd-tne","content_hash":"2a6596980450714800bddc88e106026743a1a131e96f09198eb7dc2a16d75ca4","title":"Add Claude setup tip with dynamic priority","description":"Add a predefined tip that suggests running `bd setup claude` when Claude Code is detected but not configured. This tip should have higher priority (shown more frequently) until the setup is complete.","design":"## Implementation\n\nAdd to tip registry in `cmd/bd/tips.go`:\n\n```go\n{\n    ID: \"claude_setup\",\n    Condition: func() bool {\n        return isClaudeDetected() \u0026\u0026 !isClaudeSetupComplete()\n    },\n    Message: \"Run ''bd setup claude'' to enable automatic context recovery in Claude Code\",\n    Frequency: 24 * time.Hour,  // Daily minimum gap\n    Priority: 100,              // Highest priority\n    Probability: 0.6,           // 60% chance when eligible\n}\n```\n\n## Detection Logic\n\n```go\nfunc isClaudeDetected() bool {\n    // Check environment variables\n    if os.Getenv(\"CLAUDE_CODE\") != \"\" || os.Getenv(\"ANTHROPIC_CLI\") != \"\" {\n        return true\n    }\n    // Check if .claude/ directory exists\n    if _, err := os.Stat(filepath.Join(os.Getenv(\"HOME\"), \".claude\")); err == nil {\n        return true\n    }\n    return false\n}\n\nfunc isClaudeSetupComplete() bool {\n    // Check for global installation\n    home, err := os.UserHomeDir()\n    if err == nil {\n        _, err1 := os.Stat(filepath.Join(home, \".claude/commands/prime_beads.md\"))\n        _, err2 := os.Stat(filepath.Join(home, \".claude/hooks/sessionstart\"))\n        if err1 == nil \u0026\u0026 err2 == nil {\n            return true  // Global hooks installed\n        }\n    }\n    \n    // Check for project installation\n    _, err1 := os.Stat(\".claude/commands/prime_beads.md\")\n    _, err2 := os.Stat(\".claude/hooks/sessionstart\")\n    return err1 == nil \u0026\u0026 err2 == nil\n}\n```\n\n## Priority and Probability Behavior\n\n**Why 60% probability?**\n- Important message (priority 100) but not critical\n- Daily frequency + 60% = shows ~4 times per week\n- Avoids spam while staying visible\n- Balances persistence with user experience\n\n**Comparison with other probabilities:**\n- 100% probability: Shows EVERY day (annoying)\n- 80% probability: Shows ~6 days per week (too frequent)\n- 60% probability: Shows ~4 days per week (balanced)\n- 40% probability: Shows ~3 days per week (might be missed)\n\n**Auto-stops when setup complete:**\n- Condition becomes false after `bd setup claude`\n- No manual dismissal needed\n- Tip naturally disappears from rotation","acceptance_criteria":"- Claude setup tip added to registry\n- isClaudeDetected() checks environment and filesystem\n- isClaudeSetupComplete() verifies hook installation\n- Tip shows daily until setup complete\n- Tip stops showing after setup\n- Unit tests for detection functions","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-11T23:29:29.871324-08:00","updated_at":"2025-11-11T23:50:29.756454-08:00","source_repo":"."}','{"acceptance_criteria":"","assignee":null,"closed_at":"2025-11-25T17:52:35.044989-08:00","description":"Add a predefined tip that suggests running `bd setup claude` when Claude Code is detected but not configured. This tip should have higher priority (shown more frequently) until the setup is complete.","design":"","external_ref":null,"issue_type":"task","notes":"","priority":2,"status":"closed","title":"Add Claude setup tip with dynamic priority"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1098,'bd-tru','updated','import','{"id":"bd-tru","content_hash":"0de12031088519a3dcd27968d6bf17eb3a92d1853264e5a0dceef3310b3a2b04","title":"Update documentation for bd prime and Claude integration","description":"Update AGENTS.md, README.md, and QUICKSTART.md to document the new `bd prime` command, `bd setup claude` command, and tip system.","design":"## Documentation Updates\n\n### AGENTS.md\nAdd new section \"Context Recovery\":\n```markdown\n## Context Recovery\n\n### The Problem\nAfter context compaction or clearing conversation, AI agents may forget to use Beads and revert to markdown TODOs. Claude Code hooks solve this.\n\n### bd prime Command\nThe `bd prime` command outputs essential Beads workflow context in AI-optimized markdown format (~1-2k tokens).\n\n**When to use:**\n- After context compaction\n- After clearing conversation\n- Starting new session\n- When agent seems to forget bd workflow\n- Manual context refresh\n\n**Usage:**\n```bash\nbd prime              # Output workflow context\n```\n\n### Automatic Integration (Recommended)\n\nRun `bd setup claude` to install hooks that auto-refresh bd context:\n- **SessionStart hook**: Loads context in new sessions\n- **PreCompact hook**: Refreshes context before compaction (survives better)\n- **Works with MCP**: Hooks complement MCP server (not replace)\n- **Works without MCP**: bd prime provides workflow via CLI\n\n**Why hooks matter even with MCP:**\n- MCP provides native tools, but agent may forget to use them\n- Hooks keep \"use bd, not markdown\" fresh in context\n- PreCompact refreshes workflow before compaction\n\n### MCP Server vs bd prime\n\n**Not an either/or choice** - they solve different problems:\n\n| Aspect | MCP Server | bd prime | Both |\n|--------|-----------|----------|------|\n| **Purpose** | Native bd tools | Workflow context | Best of both |\n| **Tokens** | 10.5k always loaded | ~1-2k when called | 10.5k + ~2k |\n| **Tool access** | Function calls | CLI via Bash | Function calls |\n| **Context memory** | Can fade after compaction | Hooks keep fresh | Hooks + tools |\n| **Recommended** | Heavy usage | Token optimization | Best experience |\n\n**Setup options:**\n```bash\nbd setup claude           # Install hooks (works with or without MCP)\nbd setup claude --local   # Per-project only\nbd setup claude --remove  # Remove hooks\n```\n```\n\n### README.md\nAdd to \"Getting Started\" section:\n```markdown\n### AI Agent Integration\n\n**Claude Code users:** Run `bd setup claude` to install automatic context recovery hooks.\n\nHooks work with both MCP server and CLI approaches, preventing agents from forgetting bd workflow after compaction.\n\n**MCP vs bd prime:**\n- **With MCP server**: Hooks keep agent using bd tools (prevents markdown TODO reversion)\n- **Without MCP server**: Hooks provide workflow context via `bd prime` (~1-2k tokens)\n```\n\n### QUICKSTART.md\nAdd section on agent integration:\n```markdown\n## For AI Agents\n\n**Context loading:**\n```bash\nbd prime    # Load workflow context (~1-2k tokens)\n```\n\n**Automatic setup (Claude Code):**\n```bash\nbd setup claude    # Install hooks for automatic context recovery\n```\n\nHooks prevent agents from forgetting bd workflow after compaction.\n```","acceptance_criteria":"- AGENTS.md has Context Recovery section\n- README.md mentions bd setup claude\n- QUICKSTART.md mentions bd prime\n- Examples show when to use bd prime vs MCP\n- Clear comparison of trade-offs","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-11T23:30:22.77349-08:00","updated_at":"2025-11-11T23:45:23.242658-08:00","source_repo":"."}','{"acceptance_criteria":"","assignee":null,"closed_at":"2025-11-25T17:47:30.807069-08:00","description":"Update AGENTS.md, README.md, and QUICKSTART.md to document the new `bd prime` command, `bd setup claude` command, and tip system.","design":"","external_ref":null,"issue_type":"task","notes":"","priority":2,"status":"closed","title":"Update documentation for bd prime and Claude integration"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1099,'bd-ye0d','updated','import','{"id":"bd-ye0d","content_hash":"40962ef4e144b58167a07ae13458b40cedff3f3549fccab3a172ca908cd754bc","title":"troubleshoot GH#278 daemon exits every few secs","description":"","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-13T06:27:23.39509215-07:00","updated_at":"2025-11-13T06:27:23.39509215-07:00","source_repo":"."}','{"acceptance_criteria":"","assignee":null,"closed_at":"2025-11-25T17:48:43.62418-08:00","description":"","design":"","external_ref":null,"issue_type":"task","notes":"","priority":2,"status":"closed","title":"troubleshoot GH#278 daemon exits every few secs"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1100,'bd-03r','created','import',NULL,'{"id":"bd-03r","content_hash":"82c6a895452676af433a4f893e9592eb7374bafac84e40ef27f0b958f13e7ec6","title":"Document deletions manifest in AGENTS.md and README","description":"Parent: bd-imj\n\n## Task\nAdd documentation about the deletions manifest feature.\n\n## Locations to Update\n\n### AGENTS.md\n- Explain that deletions.jsonl is tracked in git\n- Document that `bd delete` records to the manifest\n- Explain cross-clone propagation mechanism\n\n### README.md  \n- Brief mention in .beads directory structure section\n- Link to detailed docs if needed\n\n### docs/deletions.md (new file)\n- Full technical documentation\n- Format specification\n- Pruning policy\n- Git history fallback\n- Troubleshooting\n\n## Acceptance Criteria\n- AGENTS.md updated with deletion workflow\n- README.md mentions deletions.jsonl purpose\n- New docs/deletions.md with complete reference","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-25T14:56:49.13027-08:00","updated_at":"2025-11-25T15:17:23.145944-08:00","closed_at":"2025-11-25T15:17:23.145944-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1101,'bd-2em','created','import',NULL,'{"id":"bd-2em","content_hash":"ea104a34660c03a8844408d47cc55663b8d0368c3d1289ee7be12e196246541e","title":"Expand checkHooksQuick to verify all hook versions","description":"Currently checkHooksQuick only checks post-merge hook version. Should also check pre-commit, pre-push, and post-checkout for completeness. Keep it lightweight but catch more outdated hooks.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-25T19:27:47.432243-08:00","updated_at":"2025-11-25T19:50:21.378464-08:00","closed_at":"2025-11-25T19:50:21.378464-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1102,'bd-44e','created','import',NULL,'{"id":"bd-44e","content_hash":"41ed0a944beb63a8aced243f3b040073ba1f5bcd67e37330a61edc8773954315","title":"Ensure deletions.jsonl is tracked in git","description":"Parent: bd-imj\n\nEnsure deletions.jsonl is tracked in git (not ignored).\n\nUpdate bd init and gitignore upgrade logic to:\n1. NOT add deletions.jsonl to .gitignore\n2. Ensure it is committed alongside beads.jsonl\n\nThe file must be in git for cross-clone propagation to work.\n\nAcceptance criteria:\n- bd init does not ignore deletions.jsonl\n- Existing .gitignore files are not broken\n- File appears in git status when modified","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-25T09:57:21.663196-08:00","updated_at":"2025-11-25T14:55:43.225883-08:00","closed_at":"2025-11-25T14:55:43.225883-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1103,'bd-4l5','created','import',NULL,'{"id":"bd-4l5","content_hash":"bdaf92d02f2989bad822ed2079ce1916422a3ef014b338dd173cc9ac9d8c753d","title":"bd prime: Detect ephemeral branches and adjust workflow output","description":"When ''bd prime'' runs on a branch with no upstream (ephemeral branch), it should output a different SESSION CLOSE PROTOCOL.\n\n**Current output (wrong for ephemeral branches):**\n```\n[ ] 1. git status\n[ ] 2. git add \u003cfiles\u003e\n[ ] 3. bd sync\n[ ] 4. git commit -m \"...\"\n[ ] 5. bd sync\n[ ] 6. git push\n```\n\n**Needed output for ephemeral branches:**\n```\n[ ] 1. git status\n[ ] 2. git add \u003cfiles\u003e\n[ ] 3. bd sync --from-main  (pull updates from main)\n[ ] 4. git commit -m \"...\"\n[ ] 5. (no push - branch is ephemeral)\n```\n\n**Detection:** `git rev-parse --abbrev-ref --symbolic-full-name @{u}` returns error code 128 if no upstream.\n\nAlso update Sync \u0026 Collaboration section to mention `bd sync --from-main` for ephemeral branches.\n\n**Use case:** Gastown polecats work on ephemeral local branches that are never pushed. Their code gets merged to main via local merge, and beads changes stay local (communicated via gm mail to Overseer).","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-11-25T16:55:24.984104-08:00","updated_at":"2025-11-25T17:12:46.604978-08:00","closed_at":"2025-11-25T17:12:46.604978-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1104,'bd-b8h','created','import',NULL,'{"id":"bd-b8h","content_hash":"5bbe06f5066aa0f2f7a68d58adeadf5cef898bbba4968b9bd7abfecaee559f28","title":"Refactor check-health DB access to avoid repeated path resolution","description":"The runCheckHealth lightweight checks (hintsDisabled, checkVersionMismatch, checkSyncBranchQuick) each have duplicated database path resolution logic. Extract a helper function to DRY this up.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-25T19:27:35.075929-08:00","updated_at":"2025-11-25T19:50:21.272961-08:00","closed_at":"2025-11-25T19:50:21.272961-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1105,'bd-bgs','created','import',NULL,'{"id":"bd-bgs","content_hash":"abb9ec47a026fc0f7c3d2604aaa06376b6df06240d1f0f8ef59963527009815a","title":"Git history fallback doesn''t escape regex special chars in IDs","description":"## Problem\n\nIn `batchCheckGitHistory`, IDs are directly interpolated into a regex pattern:\n\n```go\npatterns = append(patterns, fmt.Sprintf(\\`\"id\":\"%s\"\\`, id))\nsearchPattern := strings.Join(patterns, \"|\")\ncmd := exec.Command(\"git\", \"log\", \"--all\", \"-G\", searchPattern, ...)\n```\n\nIf an ID contains regex special characters (e.g., `bd-foo.bar` or `bd-test+1`), the pattern will be malformed or match unintended strings.\n\n## Location\n`internal/importer/importer.go:923-926`\n\n## Impact\n- False positives: IDs with `.` could match any character\n- Regex errors: IDs with `[` or `(` could cause git to fail\n- Security: potential for regex injection (low risk since IDs are validated)\n\n## Fix\nEscape regex special characters:\n\n```go\nimport \"regexp\"\n\nescapedID := regexp.QuoteMeta(id)\npatterns = append(patterns, fmt.Sprintf(\\`\"id\":\"%s\"\\`, escapedID))\n```","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-25T12:50:30.132232-08:00","updated_at":"2025-11-25T15:04:06.217695-08:00","closed_at":"2025-11-25T15:04:06.217695-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1106,'bd-bhd','created','import',NULL,'{"id":"bd-bhd","content_hash":"fe79f5ed3a0d79ee4034ea9dd917ceb9f2e6c4ac00aa8ff3a2b1652aeaac821a","title":"Git history fallback assumes .beads is direct child of repo root","description":"## Problem\n\n`checkGitHistoryForDeletions` assumes the repo structure:\n\n```go\nrepoRoot := filepath.Dir(beadsDir)  // Assumes .beads is in repo root\njsonlPath := filepath.Join(\".beads\", \"beads.jsonl\")\n```\n\nBut `.beads` could be in a subdirectory (monorepo, nested project), and the actual JSONL filename could be different (configured via `metadata.json`).\n\n## Location\n`internal/importer/importer.go:865-869`\n\n## Impact\n- Git search will fail silently for repos with non-standard structure\n- Monorepo users won''t get deletion propagation\n\n## Fix\n1. Use `git rev-parse --show-toplevel` to find actual repo root\n2. Compute relative path from repo root to JSONL\n3. Or use `git -C \u003cdir\u003e` to run from beadsDir directly","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-25T12:51:03.46856-08:00","updated_at":"2025-11-25T15:05:40.754716-08:00","closed_at":"2025-11-25T15:05:40.754716-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1107,'bd-f0n','created','import',NULL,'{"id":"bd-f0n","content_hash":"c4658fef0e05ceb01612369d5154a96c6acd0dda1b5fc690b9f926884f48dce8","title":"Git history fallback missing timeout - could hang on large repos","description":"## Problem\n\nThe git commands in `checkGitHistoryForDeletions` have no timeout. On large repos with extensive history, `git log --all -S` or `git log --all -G` can take a very long time (minutes).\n\n## Location\n`internal/importer/importer.go:899` and `:930`\n\n## Impact\n- Import could hang indefinitely\n- User has no feedback that git search is running\n- No way to cancel except killing the process\n\n## Fix\nAdd context with timeout to git commands:\n\n```go\nctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\ndefer cancel()\ncmd := exec.CommandContext(ctx, \"git\", ...)\n```\n\nAlso consider adding a `--since` flag to bound the git history search.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-25T12:48:24.388639-08:00","updated_at":"2025-11-25T15:04:53.669714-08:00","closed_at":"2025-11-25T15:04:53.669714-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1108,'bd-imj','created','import',NULL,'{"id":"bd-imj","content_hash":"8c737545b8cfc85ac4a855a17c4c5dfd4468f9fb67cd6b2075fcb740066e5995","title":"Deletion propagation via deletions manifest","description":"## Problem\n\nWhen `bd cleanup -f` or `bd delete` removes issues in one clone, those deletions don''t propagate to other clones. The import logic only creates/updates, never deletes. This causes \"resurrection\" where deleted issues reappear.\n\n## Root Cause\n\nImport sees DB issues not in JSONL and assumes they''re \"local unpushed work\" rather than \"intentionally deleted upstream.\"\n\n## Solution: Deletions Manifest\n\nAdd `.beads/deletions.jsonl` - an append-only log of deleted issue IDs with metadata.\n\n### Format\n```jsonl\n{\"id\":\"bd-xxx\",\"ts\":\"2025-11-25T10:00:00Z\",\"by\":\"stevey\"}\n{\"id\":\"bd-yyy\",\"ts\":\"2025-11-25T10:05:00Z\",\"by\":\"claude\",\"reason\":\"duplicate of bd-zzz\"}\n```\n\n### Fields\n- `id`: Issue ID (required)\n- `ts`: ISO 8601 UTC timestamp (required)\n- `by`: Actor who deleted (required)\n- `reason`: Optional context (\"cleanup\", \"duplicate of X\", etc.)\n\n### Import Logic\n```\nFor each DB issue not in JSONL:\n  1. Check deletions manifest → if found, delete from DB\n  2. Fallback: check git history → if found, delete + backfill manifest\n  3. Neither → keep (local unpushed work)\n```\n\n### Conflict Resolution\nSimultaneous deletions from multiple clones are handled naturally:\n- Append-only design means both clones append their deletion records\n- On merge, file contains duplicate entries (same ID, different timestamps)\n- `LoadDeletions` deduplicates by ID (keeps any/first entry)\n- Result: deletion propagates correctly, duplicates are harmless\n\n### Pruning Policy\n- Default retention: 7 days (configurable via `deletions.retention_days`)\n- Auto-compact during `bd sync` is **opt-in** (disabled by default)\n- Hard cap: `deletions.max_entries` (default 50000)\n- Git fallback handles pruned entries (self-healing)\n\n### Self-Healing\nWhen git fallback catches a resurrection (pruned entry), it backfills the manifest. One-time git scan cost, then fast again.\n\n### Size Estimates\n- ~80 bytes/entry\n- 7-day retention with 100 deletions/day = ~56KB\n- Git compressed: ~10KB\n\n## Benefits\n- ✅ Deletions propagate across clones\n- ✅ O(1) lookup (no git scan in normal case)\n- ✅ Works in shallow clones\n- ✅ Survives history rewrite\n- ✅ Audit trail (who deleted what when)\n- ✅ Self-healing via git fallback\n- ✅ Bounded size via time-based pruning\n\n## References\n- Investigation session: 2025-11-25\n- Related: bd-2q6d (stale database warnings)","status":"closed","priority":0,"issue_type":"epic","created_at":"2025-11-25T09:56:01.98027-08:00","updated_at":"2025-11-25T16:36:27.965168-08:00","closed_at":"2025-11-25T16:36:27.965168-08:00","dependencies":[{"issue_id":"bd-imj","depends_on_id":"bd-qsm","type":"blocks","created_at":"2025-11-25T09:57:42.821911-08:00","created_by":"daemon"},{"issue_id":"bd-imj","depends_on_id":"bd-x2i","type":"blocks","created_at":"2025-11-25T09:57:42.851712-08:00","created_by":"daemon"},{"issue_id":"bd-imj","depends_on_id":"bd-44e","type":"blocks","created_at":"2025-11-25T09:57:42.88154-08:00","created_by":"daemon"},{"issue_id":"bd-imj","depends_on_id":"bd-bhd","type":"blocks","created_at":"2025-11-25T14:56:23.675787-08:00","created_by":"daemon"},{"issue_id":"bd-imj","depends_on_id":"bd-bgs","type":"blocks","created_at":"2025-11-25T14:56:23.744648-08:00","created_by":"daemon"},{"issue_id":"bd-imj","depends_on_id":"bd-f0n","type":"blocks","created_at":"2025-11-25T14:56:23.80649-08:00","created_by":"daemon"},{"issue_id":"bd-imj","depends_on_id":"bd-v29","type":"blocks","created_at":"2025-11-25T14:56:23.864569-08:00","created_by":"daemon"},{"issue_id":"bd-imj","depends_on_id":"bd-mdw","type":"blocks","created_at":"2025-11-25T14:56:48.592492-08:00","created_by":"daemon"},{"issue_id":"bd-imj","depends_on_id":"bd-03r","type":"blocks","created_at":"2025-11-25T14:56:54.295851-08:00","created_by":"daemon"}]}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1109,'bd-k4b','created','import',NULL,'{"id":"bd-k4b","content_hash":"1011168532e0f24d82ac577cf50bacb255b699098d6627143cfeee868a73d768","title":"Enhance dep tree to show full dependency graph","description":"When running `bd dep tree \u003cissue-id\u003e`, the current output only shows the issue itself without its dependency relationships.\n\n## Current Behavior\n\n```\n$ bd dep tree gt-0iqq\n🌲 Dependency tree for gt-0iqq:\n\n→ gt-0iqq: Implement Boss (global overseer) [P2] (open)\n```\n\nThis doesn''t show any of the dependency structure.\n\n## Desired Behavior\n\nShow the full dependency DAG rooted at the given issue. For example:\n\n```\n$ bd dep tree gt-0iqq\n🌲 Dependency tree for gt-0iqq:\n\ngt-0iqq: Implement Boss (global overseer) [P2] (open)\n├── gt-0xh4: Boss session management [P2] (open) [READY]\n│   ├── gt-le7c: Boss mail identity [P2] (open)\n│   │   ├── gt-r8fe: Boss human escalation queue [P2] (open)\n│   │   └── gt-vdak: Boss dispatch loop [P2] (open)\n│   │       └── gt-kgy6: Boss resource management [P2] (open)\n│   │           └── gt-93iv: Boss wake daemon [P2] (open)\n│   └── gt-vdak: (shown above)\n```\n\n## Suggested Options\n\n- `--direction=down|up|both` - Show dependents (what this blocks), dependencies (what blocks this), or both\n- `--status=open` - Filter to only show issues with a given status\n- `--depth=N` - Limit tree depth\n- Handle DAG cycles gracefully (show \"(shown above)\" or similar for already-displayed nodes)\n\n## Use Case\n\nWhen reorganizing a set of related issues (like I just did with the Boss implementation), being able to visualize the full dependency graph helps verify the structure is correct before syncing.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-11-25T19:18:18.750649-08:00","updated_at":"2025-11-25T19:50:46.863319-08:00","closed_at":"2025-11-25T19:31:55.312314-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1110,'bd-l7u','created','import',NULL,'{"id":"bd-l7u","content_hash":"f92ccca897e72f00e41104134fce80fefebfdb0a829d23ac7717b2c5731ececa","title":"Duplicate DefaultRetentionDays constants","description":"## Problem\n\nThere are now two constants for the same value:\n\n1. `deletions.DefaultRetentionDays = 7` in `internal/deletions/deletions.go:184`\n2. `configfile.DefaultDeletionsRetentionDays = 7` in `internal/configfile/configfile.go:102`\n\n## Impact\n- DRY violation\n- Risk of values getting out of sync\n- Confusing which one to use\n\n## Fix\nRemove the constant from `deletions` package and have it import from `configfile`, or create a shared constants package.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-11-25T12:49:38.356211-08:00","updated_at":"2025-11-25T15:15:21.964842-08:00","closed_at":"2025-11-25T15:15:21.964842-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1111,'bd-mdw','created','import',NULL,'{"id":"bd-mdw","content_hash":"09f2ddc2a90326cb313071a0fc930e20f8f743dc3126cd83fdbffa52619f7588","title":"Add integration test for cross-clone deletion propagation","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-25T14:56:38.997009-08:00","updated_at":"2025-11-25T16:35:59.052914-08:00","closed_at":"2025-11-25T16:35:59.052914-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1112,'bd-qsm','created','import',NULL,'{"id":"bd-qsm","content_hash":"577146283870a7bf5e5d5ad526411df701ac6ee08856ceb610e25d1e6b7be0cf","title":"Auto-compact deletions during bd sync","description":"Parent: bd-imj\n\n## Task\nOptionally prune deletions manifest during sync when threshold exceeded.\n\n**Note: Opt-in feature** - disabled by default to avoid sync latency.\n\n## Implementation\n\nIn `bd sync`:\n```go\nfunc (s *Syncer) Sync() error {\n    // ... existing sync logic ...\n    \n    // Auto-compact only if enabled\n    if s.config.GetBool(\"deletions.auto_compact\", false) {\n        deletionCount := deletions.Count(\".beads/deletions.jsonl\")\n        threshold := s.config.GetInt(\"deletions.auto_compact_threshold\", 1000)\n        \n        if deletionCount \u003e threshold {\n            retentionDays := s.config.GetInt(\"deletions.retention_days\", 7)\n            if err := s.compactor.PruneDeletions(retentionDays); err != nil {\n                log.Warnf(\"Failed to auto-compact deletions: %v\", err)\n                // Non-fatal, continue sync\n            }\n        }\n    }\n    \n    // ... rest of sync ...\n}\n```\n\n## Configuration\n```yaml\ndeletions:\n  retention_days: 7\n  auto_compact: false              # Opt-in, disabled by default\n  auto_compact_threshold: 1000     # Trigger when \u003e N entries (if enabled)\n```\n\n## Acceptance Criteria\n- [ ] Auto-compact disabled by default\n- [ ] Enabled via config `deletions.auto_compact: true`\n- [ ] Sync checks deletion count only when enabled\n- [ ] Auto-prunes when threshold exceeded\n- [ ] Failure is non-fatal (logged warning)\n- [ ] Test: no compaction when disabled\n- [ ] Test: compaction triggers when enabled and threshold exceeded","status":"closed","priority":1,"issue_type":"task","created_at":"2025-11-25T09:57:04.522795-08:00","updated_at":"2025-11-25T15:03:01.469629-08:00","closed_at":"2025-11-25T15:03:01.469629-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1113,'bd-tys','created','import',NULL,'{"id":"bd-tys","content_hash":"efaa2cb87964b5c5b2828249331a2828f3ec2696fcf9de3ac13674ee8041c046","title":"Git history fallback has incorrect logic for detecting deletions","description":"## Problem\n\nThe `wasInGitHistory` function in `internal/importer/importer.go:891` returns true if the ID is found **anywhere** in git history. But finding an ID in history doesn''t necessarily mean it was deleted - it could mean:\n\n1. The issue was added (appears in a commit adding it)\n2. The issue was modified (appears in commits updating it)\n3. The issue was deleted (appears in a commit removing it)\n\nThe current logic incorrectly treats all three cases as ''deleted''.\n\n## Correct Logic\n\n`git log -S` with `--oneline` shows commits where the string was added OR removed. To detect deletion specifically:\n\n1. ID appears in git history (was once in JSONL)\n2. ID is NOT currently in JSONL\n\nThe second condition is already checked by the caller (`purgeDeletedIssues`), so technically the logic is correct in context. But the function name and doc comment are misleading.\n\n## Fix Options\n\n1. **Rename function** to `wasEverInJSONL` and update doc comment to clarify\n2. **Add explicit check** for current JSONL state in the function itself\n\nOption 1 is simpler and correct since caller already filters.","status":"closed","priority":3,"issue_type":"bug","created_at":"2025-11-25T12:46:16.073661-08:00","updated_at":"2025-11-25T15:11:54.426093-08:00","closed_at":"2025-11-25T15:11:54.426093-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1114,'bd-v29','created','import',NULL,'{"id":"bd-v29","content_hash":"1a4ada02aff343b50c4940b4c84a143188ad62269e9a41030ae5ae1cc9f1a38f","title":"Deletions pruning doesn''t include results in JSON output","description":"## Problem\n\nWhen `bd compact --json` runs with deletions pruning, the prune results are silently discarded:\n\n```go\n// Only report if there were deletions to prune\nif result.PrunedCount \u003e 0 {\n    if jsonOutput {\n        // JSON output will be included in the main response\n        return  // \u003c-- BUG: results are NOT included anywhere\n    }\n    ...\n}\n```\n\n## Location\n`cmd/bd/compact.go:925-929`\n\n## Impact\n- JSON consumers don''t know deletions were pruned\n- No way to audit pruning via automation\n\n## Fix\nReturn prune results and include in JSON output structure:\n\n```json\n{\n  \"success\": true,\n  \"compacted\": {...},\n  \"deletions_pruned\": {\n    \"count\": 5,\n    \"retention_days\": 7\n  }\n}\n```","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-11-25T12:48:59.730979-08:00","updated_at":"2025-11-25T15:11:54.363653-08:00","closed_at":"2025-11-25T15:11:54.363653-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1115,'bd-wmo','created','import',NULL,'{"id":"bd-wmo","content_hash":"284c50f833f01daf32df8950385cfbde9ad11ff74630f08a4ab14bda872deb0f","title":"PruneDeletions iterates map non-deterministically","description":"## Problem\n\n`PruneDeletions` iterates over `loadResult.Records` which is a map. Go maps iterate in random order, so:\n\n1. `result.PrunedIDs` order is non-deterministic\n2. `kept` slice order is non-deterministic → `WriteDeletions` output order varies\n\n## Location\n`internal/deletions/deletions.go:213`\n\n## Impact\n- Git diffs are noisy (file changes order on each prune)\n- Tests could be flaky if they depend on order\n- Harder to debug/audit\n\n## Fix\nSort by ID or timestamp before iterating:\n\n```go\n// Convert map to slice and sort\nvar records []DeletionRecord\nfor _, r := range loadResult.Records {\n    records = append(records, r)\n}\nsort.Slice(records, func(i, j int) bool {\n    return records[i].ID \u003c records[j].ID\n})\n```","status":"closed","priority":3,"issue_type":"bug","created_at":"2025-11-25T12:49:11.290916-08:00","updated_at":"2025-11-25T15:15:21.903649-08:00","closed_at":"2025-11-25T15:15:21.903649-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1116,'bd-x2i','created','import',NULL,'{"id":"bd-x2i","content_hash":"f1ec5c8f9da394d7bab765106b1b03548d473e5d9dfc430d8ccce82f13c030a4","title":"Add bd deleted command for audit trail","description":"Parent: bd-imj\n\nAdd command to view deletion history.\n\nUsage:\n  bd deleted              # Show recent deletions (last 7 days)\n  bd deleted --since=30d  # Show deletions in last 30 days\n  bd deleted --all        # Show all tracked deletions\n  bd deleted bd-xxx       # Show deletion details for specific issue\n\nOutput format:\n  bd-xxx  2025-11-25 10:00  stevey  duplicate of bd-yyy\n  bd-yyy  2025-11-25 10:05  claude  cleanup\n\nAcceptance criteria:\n- List deletions with timestamp, actor, reason\n- Filter by time range\n- Lookup specific issue ID\n- JSON output option for scripting","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-25T09:57:21.113861-08:00","updated_at":"2025-11-25T15:13:53.781519-08:00","closed_at":"2025-11-25T15:13:53.781519-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1117,'bd-xyc','created','import',NULL,'{"id":"bd-xyc","content_hash":"38535e356e979208ac1200ee68fd3b3347dc22179ab012b2eb10f46349af763f","title":"Consolidate check-health DB opens into single connection","description":"The --check-health flag opens the database 3 separate times (once per quick check). Consolidate into a single DB open for better performance, especially on slower filesystems.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-11-25T19:27:42.034178-08:00","updated_at":"2025-11-25T19:50:21.32375-08:00","closed_at":"2025-11-25T19:50:21.32375-08:00"}',NULL,'2025-11-26 12:48:43');
INSERT INTO events VALUES(1118,'bd-imj','dependency_added','import',NULL,NULL,'Added dependency: bd-imj blocks bd-qsm','2025-11-26 12:48:43');
INSERT INTO events VALUES(1119,'bd-imj','dependency_added','import',NULL,NULL,'Added dependency: bd-imj blocks bd-x2i','2025-11-26 12:48:43');
INSERT INTO events VALUES(1120,'bd-imj','dependency_added','import',NULL,NULL,'Added dependency: bd-imj blocks bd-44e','2025-11-26 12:48:43');
INSERT INTO events VALUES(1121,'bd-imj','dependency_added','import',NULL,NULL,'Added dependency: bd-imj blocks bd-bhd','2025-11-26 12:48:43');
INSERT INTO events VALUES(1122,'bd-imj','dependency_added','import',NULL,NULL,'Added dependency: bd-imj blocks bd-bgs','2025-11-26 12:48:43');
INSERT INTO events VALUES(1123,'bd-imj','dependency_added','import',NULL,NULL,'Added dependency: bd-imj blocks bd-f0n','2025-11-26 12:48:43');
INSERT INTO events VALUES(1124,'bd-imj','dependency_added','import',NULL,NULL,'Added dependency: bd-imj blocks bd-v29','2025-11-26 12:48:43');
INSERT INTO events VALUES(1125,'bd-imj','dependency_added','import',NULL,NULL,'Added dependency: bd-imj blocks bd-mdw','2025-11-26 12:48:43');
INSERT INTO events VALUES(1126,'bd-imj','dependency_added','import',NULL,NULL,'Added dependency: bd-imj blocks bd-03r','2025-11-26 12:48:43');
INSERT INTO events VALUES(1127,'bd-c6w','created','daemon',NULL,'{"id":"bd-c6w","content_hash":"1a2277e4a3e86d3c1c341d4ec7f90858460b0b01891b25ed6d56be5be1957dc2","title":"bd info whats-new missing releases","description":"Current release is v0.25.1 but \n🆕 What''s New in bd (Current: v0.25.1)\n=============================================================\n\n## v0.23.0 (2025-11-08)\n\n  • Agent Mail integration - Python adapter library with 98.5% reduction in git traffic\n  • `bd info --whats-new` - Quick upgrade summaries for agents (shows last 3 versions)\n  • `bd hooks install` - Embedded git hooks command (replaces external script)\n  • `bd cleanup` - Bulk deletion for agent-driven compaction\n  • `bd new` alias added - Agents often tried this instead of `bd create`\n  • `bd list` now one-line-per-issue by default - Prevents agent miscounting (use --long for old format)\n  • 3-way JSONL merge auto-invoked on conflicts - No manual intervention needed\n  • Daemon crash recovery - Panic handler with socket cleanup prevents orphaned processes\n  • Auto-import when database missing - `bd import` now auto-initializes\n  • Stale database export prevention - ID-based staleness detection\n\n## v0.22.1 (2025-11-06)\n\n  • Native `bd merge` command vendored from beads-merge - no external binary needed\n  • `bd info` detects outdated git hooks - warns if version mismatch\n  • Multi-workspace deletion tracking fixed - deletions now propagate correctly\n  • Hash ID recognition improved - recognizes Base36 IDs without a-f letters\n  • Import/export deadlock fixed - no hanging when daemon running\n\n## v0.22.0 (2025-11-05)\n\n  • Intelligent merge driver auto-configured - eliminates most JSONL conflicts\n  • Onboarding wizards: `bd init --contributor` and `bd init --team`\n  • New `bd migrate-issues` command - migrate issues between repos with dependencies\n  • `bd show` displays blocker status - ''Blocked by N open issues'' or ''Ready to work''\n  • SearchIssues N+1 query fixed - batch-loads labels for better performance\n  • Sync validation prevents infinite dirty loop - verifies JSONL export\n\n## v0.21.0 (2025-11-04)\n\n  • Hash-based IDs eliminate collisions - remove ID coordination workarounds\n  • Event-driven daemon mode (opt-in) - set BEADS_DAEMON_MODE=events\n  • Agent Mail integration - real-time multi-agent coordination (\u003c100ms latency)\n  • `bd duplicates --auto-merge` - automated duplicate detection and merging\n  • Hierarchical children for epics - dotted IDs (bd-abc.1, bd-abc.2) up to 3 levels\n  • `--discovered-from` inline syntax - create with dependency in one command\n\n💡 Tip: Use `bd info --whats-new --json` for machine-readable output stops at v0.23.0, indicating something is missing in the create new release workflow.","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-26T05:50:37.252394374-07:00","updated_at":"2025-11-26T05:50:37.252394374-07:00"}',NULL,'2025-11-26 12:50:37');
INSERT INTO events VALUES(1129,'bd-c6w','updated','daemon','{"id":"bd-c6w","content_hash":"b9ecf3e8d0850f525334521c37ca2cdd4691020d244c9125b1a69b0db344fd9c","title":"bd info whats-new missing releases","description":"Current release is v0.25.1 but \n🆕 What''s New in bd (Current: v0.25.1)\n=============================================================\n\n## v0.23.0 (2025-11-08)\n\n  • Agent Mail integration - Python adapter library with 98.5% reduction in git traffic\n  • `bd info --whats-new` - Quick upgrade summaries for agents (shows last 3 versions)\n  • `bd hooks install` - Embedded git hooks command (replaces external script)\n  • `bd cleanup` - Bulk deletion for agent-driven compaction\n  • `bd new` alias added - Agents often tried this instead of `bd create`\n  • `bd list` now one-line-per-issue by default - Prevents agent miscounting (use --long for old format)\n  • 3-way JSONL merge auto-invoked on conflicts - No manual intervention needed\n  • Daemon crash recovery - Panic handler with socket cleanup prevents orphaned processes\n  • Auto-import when database missing - `bd import` now auto-initializes\n  • Stale database export prevention - ID-based staleness detection\n\n## v0.22.1 (2025-11-06)\n\n  • Native `bd merge` command vendored from beads-merge - no external binary needed\n  • `bd info` detects outdated git hooks - warns if version mismatch\n  • Multi-workspace deletion tracking fixed - deletions now propagate correctly\n  • Hash ID recognition improved - recognizes Base36 IDs without a-f letters\n  • Import/export deadlock fixed - no hanging when daemon running\n\n## v0.22.0 (2025-11-05)\n\n  • Intelligent merge driver auto-configured - eliminates most JSONL conflicts\n  • Onboarding wizards: `bd init --contributor` and `bd init --team`\n  • New `bd migrate-issues` command - migrate issues between repos with dependencies\n  • `bd show` displays blocker status - ''Blocked by N open issues'' or ''Ready to work''\n  • SearchIssues N+1 query fixed - batch-loads labels for better performance\n  • Sync validation prevents infinite dirty loop - verifies JSONL export\n\n## v0.21.0 (2025-11-04)\n\n  • Hash-based IDs eliminate collisions - remove ID coordination workarounds\n  • Event-driven daemon mode (opt-in) - set BEADS_DAEMON_MODE=events\n  • Agent Mail integration - real-time multi-agent coordination (\u003c100ms latency)\n  • `bd duplicates --auto-merge` - automated duplicate detection and merging\n  • Hierarchical children for epics - dotted IDs (bd-abc.1, bd-abc.2) up to 3 levels\n  • `--discovered-from` inline syntax - create with dependency in one command\n\n💡 Tip: Use `bd info --whats-new --json` for machine-readable output stops at v0.23.0, indicating something is missing in the create new release workflow.","notes":"github issue #386","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-26T05:50:37.252394374-07:00","updated_at":"2025-11-26T05:56:46.902193638-07:00","source_repo":"."}','{"description":"Current release is v0.25.1 but `bd info --whats-new` stops at v0.23.0, indicating something is missing in the create new release workflow."}',NULL,'2025-11-26 12:59:09');
INSERT INTO events VALUES(1130,'bd-c6w','status_changed','daemon','{"id":"bd-c6w","content_hash":"34399fcdd76e5789fdb82b8fd28a8f879690f58841d7d5fe81153274a2d01f5e","title":"bd info whats-new missing releases","description":"Current release is v0.25.1 but `bd info --whats-new` stops at v0.23.0, indicating something is missing in the create new release workflow.","notes":"github issue #386","status":"open","priority":2,"issue_type":"task","created_at":"2025-11-26T05:50:37.252394374-07:00","updated_at":"2025-11-26T05:59:09.62857369-07:00","source_repo":"."}','{"status":"in_progress"}',NULL,'2025-11-26 13:05:16');
CREATE TABLE config (
    key TEXT PRIMARY KEY,
    value TEXT NOT NULL
);
INSERT INTO config VALUES('compaction_enabled','false');
INSERT INTO config VALUES('compact_tier1_days','30');
INSERT INTO config VALUES('compact_tier1_dep_levels','2');
INSERT INTO config VALUES('compact_tier2_days','90');
INSERT INTO config VALUES('compact_tier2_dep_levels','5');
INSERT INTO config VALUES('compact_tier2_commits','100');
INSERT INTO config VALUES('compact_model','claude-3-5-haiku-20241022');
INSERT INTO config VALUES('compact_batch_size','50');
INSERT INTO config VALUES('compact_parallel_workers','5');
INSERT INTO config VALUES('auto_compact_enabled','false');
INSERT INTO config VALUES('issue_prefix','bd');
INSERT INTO config VALUES('sync.branch','main');
CREATE TABLE metadata (
    key TEXT PRIMARY KEY,
    value TEXT NOT NULL
);
INSERT INTO metadata VALUES('bd_version','0.25.1');
INSERT INTO metadata VALUES('repo_id','123ceaa73983774f66b7ab664d23ba94');
INSERT INTO metadata VALUES('clone_id','4c88762610e67515');
INSERT INTO metadata VALUES('last_import_hash','cf5da18d0f1396c5af0cb45354b16e8568197ad6496e6cc2d0f33867dd560ebc');
INSERT INTO metadata VALUES('last_import_time','2025-11-26T06:08:33-07:00');
INSERT INTO metadata VALUES('jsonl_file_hash','c67a8856919cef4a04602f2edd874186187103b3f61cdff174370547910e7581');
INSERT INTO metadata VALUES('last_import_mtime','1764077489');
CREATE TABLE dirty_issues (
    issue_id TEXT PRIMARY KEY,
    marked_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, content_hash TEXT,
    FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE
);
CREATE TABLE export_hashes (
    issue_id TEXT PRIMARY KEY,
    content_hash TEXT NOT NULL,
    exported_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE
);
CREATE TABLE child_counters (
    parent_id TEXT PRIMARY KEY,
    last_child INTEGER NOT NULL DEFAULT 0,
    FOREIGN KEY (parent_id) REFERENCES issues(id) ON DELETE CASCADE
);
CREATE TABLE issue_snapshots (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    issue_id TEXT NOT NULL,
    snapshot_time DATETIME NOT NULL,
    compaction_level INTEGER NOT NULL,
    original_size INTEGER NOT NULL,
    compressed_size INTEGER NOT NULL,
    original_content TEXT NOT NULL,
    archived_events TEXT,
    FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE
);
CREATE TABLE compaction_snapshots (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    issue_id TEXT NOT NULL,
    compaction_level INTEGER NOT NULL,
    snapshot_json BLOB NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE
);
CREATE TABLE repo_mtimes (
    repo_path TEXT PRIMARY KEY,  -- Absolute path to the repository root
    jsonl_path TEXT NOT NULL,    -- Absolute path to the .beads/issues.jsonl file
    mtime_ns INTEGER NOT NULL,   -- Modification time in nanoseconds since epoch
    last_checked DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE blocked_issues_cache (
				issue_id TEXT NOT NULL,
				PRIMARY KEY (issue_id),
				FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE
			);
INSERT INTO blocked_issues_cache VALUES('bd-4h3');
INSERT INTO blocked_issues_cache VALUES('bd-e92');
INSERT INTO blocked_issues_cache VALUES('bd-m0w');
INSERT INTO blocked_issues_cache VALUES('bd-t3b');
PRAGMA writable_schema=ON;
CREATE TABLE IF NOT EXISTS sqlite_sequence(name,seq);
DELETE FROM sqlite_sequence;
INSERT INTO sqlite_sequence VALUES('events',1130);
INSERT INTO sqlite_sequence VALUES('comments',18);
CREATE VIEW ready_issues AS
WITH RECURSIVE
  -- Find issues blocked directly by dependencies
  blocked_directly AS (
    SELECT DISTINCT d.issue_id
    FROM dependencies d
    JOIN issues blocker ON d.depends_on_id = blocker.id
    WHERE d.type = 'blocks'
      AND blocker.status IN ('open', 'in_progress', 'blocked')
  ),
  -- Propagate blockage to all descendants via parent-child
  blocked_transitively AS (
    -- Base case: directly blocked issues
    SELECT issue_id, 0 as depth
    FROM blocked_directly
    UNION ALL
    -- Recursive case: children of blocked issues inherit blockage
    SELECT d.issue_id, bt.depth + 1
    FROM blocked_transitively bt
    JOIN dependencies d ON d.depends_on_id = bt.issue_id
    WHERE d.type = 'parent-child'
      AND bt.depth < 50
  )
SELECT i.*
FROM issues i
WHERE i.status = 'open'
  AND NOT EXISTS (
    SELECT 1 FROM blocked_transitively WHERE issue_id = i.id
  )
;
CREATE VIEW blocked_issues AS
SELECT
    i.*,
    COUNT(d.depends_on_id) as blocked_by_count
FROM issues i
JOIN dependencies d ON i.id = d.issue_id
JOIN issues blocker ON d.depends_on_id = blocker.id
WHERE i.status IN ('open', 'in_progress', 'blocked')
  AND d.type = 'blocks'
  AND blocker.status IN ('open', 'in_progress', 'blocked')
GROUP BY i.id;
CREATE INDEX idx_issues_status ON issues(status);
CREATE INDEX idx_issues_priority ON issues(priority);
CREATE INDEX idx_issues_assignee ON issues(assignee);
CREATE INDEX idx_issues_created_at ON issues(created_at);
CREATE INDEX idx_issues_external_ref ON issues(external_ref);
CREATE INDEX idx_dependencies_issue ON dependencies(issue_id);
CREATE INDEX idx_dependencies_depends_on ON dependencies(depends_on_id);
CREATE INDEX idx_dependencies_depends_on_type ON dependencies(depends_on_id, type);
CREATE INDEX idx_labels_label ON labels(label);
CREATE INDEX idx_comments_issue ON comments(issue_id);
CREATE INDEX idx_comments_created_at ON comments(created_at);
CREATE INDEX idx_events_issue ON events(issue_id);
CREATE INDEX idx_events_created_at ON events(created_at);
CREATE INDEX idx_dirty_issues_marked_at ON dirty_issues(marked_at);
CREATE INDEX idx_snapshots_issue ON issue_snapshots(issue_id);
CREATE INDEX idx_snapshots_level ON issue_snapshots(compaction_level);
CREATE INDEX idx_comp_snap_issue_level_created ON compaction_snapshots(issue_id, compaction_level, created_at DESC);
CREATE INDEX idx_repo_mtimes_checked ON repo_mtimes(last_checked);
CREATE UNIQUE INDEX idx_issues_external_ref_unique ON issues(external_ref) WHERE external_ref IS NOT NULL;
CREATE INDEX idx_issues_source_repo ON issues(source_repo);
CREATE INDEX idx_dependencies_depends_on_type_issue ON dependencies(depends_on_id, type, issue_id);
PRAGMA writable_schema=OFF;
COMMIT;
