diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index f48ed468..07172288 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -13,6 +13,7 @@ {"id":"bd-0zp7","title":"Add missing hook calls in mail reply and ack","description":"The mail commands are missing hook calls:\n\n1. runMailReply (mail.go:525-672) creates a message but doesn't call hookRunner.Run(hooks.EventMessage, ...) after creating the reply in direct mode (around line 640)\n\n2. runMailAck (mail.go:432-523) closes messages but doesn't call hookRunner.Run(hooks.EventClose, ...) after closing each message (around line 487 for daemon mode, 493 for direct mode)\n\nThis means GGT hooks won't fire for replies or message acknowledgments.","status":"tombstone","priority":1,"issue_type":"bug","created_at":"2025-12-16T20:52:53.069412-08:00","updated_at":"2025-12-25T01:21:01.952723-08:00","deleted_at":"2025-12-25T01:21:01.952723-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"bug"} {"id":"bd-14ie","title":"Work on beads-2vn: Add simple built-in beads viewer (GH#6...","description":"Work on beads-2vn: Add simple built-in beads viewer (GH#654). Add bd list --pretty with --watch flag, tree view with priority/status symbols. When done, submit MR (not PR) to integration branch for Refinery.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-19T22:56:47.305831-08:00","updated_at":"2025-12-19T23:28:32.429492-08:00","closed_at":"2025-12-19T23:23:13.928323-08:00","close_reason":"Implemented --pretty flag with tree view and symbols. Tests pass."} {"id":"bd-14v0","title":"Add Windows code signing for bd.exe releases","description":"## Context\n\nGo binaries (including bd.exe) are commonly flagged by antivirus software as false positives due to heuristic detection. See docs/ANTIVIRUS.md for full details.\n\n## Problem\n\nKaspersky and other AV software flag bd.exe as PDM:Trojan.Win32.Generic, causing it to be quarantined or deleted.\n\n## Solution\n\nImplement code signing for Windows releases using:\n1. An EV (Extended Validation) code certificate\n2. Integration with GoReleaser to sign Windows binaries during release\n\n## Benefits\n\n- Reduces false positive rates over time as the certificate builds reputation\n- Provides tamper verification for users\n- Improves SmartScreen trust rating on Windows\n- Professional appearance for enterprise users\n\n## Implementation Steps\n\n1. Acquire EV code signing certificate (annual cost ~$300-500)\n2. Set up signtool or osslsigncode in release pipeline\n3. Update .goreleaser.yml to sign Windows binaries\n4. Update checksums to include signed binary hashes\n5. Document signing verification in ANTIVIRUS.md\n\n## References\n\n- docs/ANTIVIRUS.md - Current documentation\n- bd-t4u1 - Original Kaspersky false positive report\n- https://github.com/golang/go/issues/16292 - Go project discussion","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-23T23:46:48.459177-08:00","updated_at":"2025-12-23T23:54:41.912141-08:00","closed_at":"2025-12-23T23:54:41.912141-08:00","close_reason":"Implemented Windows code signing infrastructure. Added signing script, GoReleaser hook, updated release workflow and documentation. Signing is gracefully degraded when certificate secrets are not configured - releases continue as unsigned. Certificate acquisition (EV cert) is still required to actually enable signing.","dependencies":[{"issue_id":"bd-14v0","depends_on_id":"bd-t4u1","type":"discovered-from","created_at":"2025-12-23T23:47:02.024159-08:00","created_by":"daemon"}]} +{"id":"bd-1ban","title":"Test actor direct","status":"open","priority":4,"issue_type":"task","created_at":"2025-12-26T20:46:02.423367-08:00","updated_at":"2025-12-26T20:46:02.423367-08:00"} {"id":"bd-1dez","title":"Mol Mall: Formula marketplace using GitHub as backend","description":"Create a marketplace for sharing molecule formulas using GitHub repos as the hosting backend.\n\n## Architecture Update (Dec 2025)\n\n**Formulas are the sharing layer.** With ephemeral protos (bd-rciw), the architecture is:\n\n```\nFormulas ──cook──→ [ephemeral proto] ──pour/wisp──→ Mol/Wisp\n ↑ │\n └────────────────── distill ─────────────────────────┘\n```\n\n- **Formulas**: JSON source files (.formula.json) - the thing you share\n- **Protos**: Transient compilation artifacts - auto-deleted after use\n- **Mols/Wisps**: Execution instances - not shared directly\n\n**Key operations:**\n- `bd distill \u003cmol-id\u003e` → Extract formula from completed work\n- `bd mol publish \u003cformula\u003e` → Share to GitHub\n- `bd mol install \u003curl\u003e` → Fetch from GitHub\n- `bd pour \u003cformula\u003e` → Cook and spawn (proto is ephemeral)\n\n## Why GitHub?\n\nGitHub solves multiple problems at once:\n- **Hosting**: Raw file URLs for formula.json\n- **Versioning**: Git tags (v1.0.0, v1.2.0)\n- **Auth**: GitHub tokens for private formulas\n- **Discovery**: GitHub search, topics, stars\n- **Collaboration**: PRs for contributions, issues for bugs\n- **Organizations**: Natural scoping (@anthropic/, @gastown/)\n\n## URL Scheme\n\n```bash\n# Direct GitHub URL\nbd mol install github.com/anthropics/mol-code-review\n\n# With version tag\nbd mol install github.com/anthropics/mol-code-review@v1.2.0\n\n# Shorthand (via registry lookup)\nbd mol install @anthropic/mol-code-review\n```\n\n## Architecture\n\nEach formula lives in its own repo (like Go modules):\n```\ngithub.com/anthropics/mol-code-review/\n├── formula.json # The formula\n├── README.md # Documentation\n└── CHANGELOG.md # Version history\n```\n\n## ID Namespace\n\n| Entity | ID Format | Example |\n|--------|-----------|---------|\n| Formula (GitHub) | `github.com/org/repo` | `github.com/anthropics/mol-code-review` |\n| Installed formula | `mol-name` | `mol-code-review` |\n| Poured instance | `\u003cdb\u003e-mol-xxx` | `bd-mol-b8c` |","notes":"Deferred - focusing on Christmas launch first","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-12-25T12:05:17.666574-08:00","updated_at":"2025-12-25T21:53:13.415431-08:00","closed_at":"2025-12-25T21:53:13.415431-08:00","close_reason":"Migrated to gastown rig as gt-uzf2l (Mol Mall is Gas Town infrastructure)"} {"id":"bd-1dez.1","title":"bd distill: Extract formula from mol/epic","description":"Extract a formula from completed work (mol, wisp, or epic).\n\n**Key change**: Distill works on execution artifacts (mols/wisps/epics), not protos.\nProtos are ephemeral - they don't persist. Distillation extracts patterns from\nactual executed work.\n\n## Usage\n```bash\nbd distill bd-mol-xyz -o my-workflow.formula.json\nbd distill bd-epic-abc -o feature-workflow.formula.json\n```\n\n## Use Cases\n- **Emergent patterns**: Structured work manually, want to templatize it\n- **Modified execution**: Poured a formula, added custom steps, want to capture\n- **Learning from success**: Extract what made a complex mol succeed\n\n## Implementation\n1. Load mol/wisp/epic subgraph (root + all children)\n2. Convert to formula JSON structure\n3. Extract variables from patterns (titles, descriptions)\n4. Generate step IDs from issue titles (slugify)\n5. Write .formula.json file\n\n## Output Format\n```json\n{\n \"formula\": \"my-workflow\",\n \"description\": \"...\",\n \"version\": 1,\n \"vars\": { ... },\n \"steps\": [ ... ]\n}\n```\n\n## Architecture Note\nThis closes the formula lifecycle loop:\n Formulas ──cook──→ Mols ──distill──→ Formulas\n\nAll sharing happens via formulas. Mols contain execution context and aren't shared.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T12:05:47.045105-08:00","updated_at":"2025-12-25T18:54:39.967765-08:00","closed_at":"2025-12-25T18:54:39.967765-08:00","close_reason":"Command already implemented; updated help text, added daemon support, and -o shorthand","dependencies":[{"issue_id":"bd-1dez.1","depends_on_id":"bd-1dez","type":"parent-child","created_at":"2025-12-25T12:05:47.045596-08:00","created_by":"daemon"}]} {"id":"bd-1dez.2","title":"bd formula add: Import formula to local catalog","description":"Import a formula file to the local catalog (search path).\n\n**Replaces**: \"bd mol promote\" (proto-to-proto concept is obsolete with ephemeral protos)\n\n## Usage\n```bash\n# Add a formula file to project catalog\nbd formula add my-workflow.formula.json\n\n# Add to user-level catalog\nbd formula add my-workflow.formula.json --scope user\n\n# Add from URL\nbd formula add https://example.com/workflow.formula.json\n```\n\n## Implementation\n1. Parse the formula file (validate JSON structure)\n2. Determine target directory based on scope:\n - project: .beads/formulas/\n - user: ~/.beads/formulas/\n - town: ~/gt/.beads/formulas/\n3. Copy/download formula to target\n4. Verify it is loadable: bd formula show \u003cname\u003e\n\n## Flags\n- `--scope \u003clevel\u003e` - Where to add (project|user|town, default: project)\n- `--name \u003cname\u003e` - Override formula name (default: from file)\n\n## Note\nThis is for manually adding formulas. For GitHub-hosted formulas, use:\n bd mol install github.com/org/formula-name","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-25T12:05:48.588283-08:00","updated_at":"2025-12-25T19:54:35.242576-08:00","closed_at":"2025-12-25T19:54:35.242576-08:00","close_reason":"Implemented bd formula add command with scope and URL support","dependencies":[{"issue_id":"bd-1dez.2","depends_on_id":"bd-1dez","type":"parent-child","created_at":"2025-12-25T12:05:48.590203-08:00","created_by":"daemon"},{"issue_id":"bd-1dez.2","depends_on_id":"bd-1dez.1","type":"blocks","created_at":"2025-12-25T12:07:06.745686-08:00","created_by":"daemon"}]} @@ -309,6 +310,7 @@ {"id":"bd-hy9p","title":"Add --body-file flag to bd create for reading descriptions from files","description":"## Problem\n\nCreating issues with long/complex descriptions via CLI requires shell escaping gymnastics:\n\n```bash\n# Current workaround - awkward heredoc quoting\nbd create --title=\"...\" --description=\"$(cat \u003c\u003c'EOF'\n...markdown...\nEOF\n)\"\n\n# Often fails with quote escaping errors in eval context\n# Agents resort to writing temp files then reading them\n```\n\n## Proposed Solution\n\nAdd `--body-file` and `--description-file` flags to read description from a file, matching `gh` CLI pattern.\n\n```bash\n# Natural pattern that aligns with training data\ncat \u003e /tmp/desc.md \u003c\u003c 'EOF'\n...markdown content...\nEOF\n\nbd create --title=\"...\" --body-file=/tmp/desc.md\n```\n\n## Implementation\n\n### 1. Add new flags to `bd create`\n\n```go\ncreateCmd.Flags().String(\"body-file\", \"\", \"Read description from file (use - for stdin)\")\ncreateCmd.Flags().String(\"description-file\", \"\", \"Alias for --body-file\")\n```\n\n### 2. Flag precedence\n\n- If `--body-file` or `--description-file` is provided, read from file\n- If value is `-`, read from stdin\n- Otherwise fall back to `--body` or `--description` flag\n- If neither provided, description is empty (current behavior)\n\n### 3. Error handling\n\n- File doesn't exist → clear error message\n- File not readable → clear error message\n- stdin specified but not available → clear error message\n\n## Benefits\n\n✅ **Matches training data**: `gh issue create --body-file file.txt` is a common pattern\n✅ **No shell escaping issues**: File content is read directly\n✅ **Works with any content**: Markdown, special characters, quotes, etc.\n✅ **Agent-friendly**: Agents already write complex content to temp files\n✅ **User-friendly**: Easier for humans too when pasting long descriptions\n\n## Related Commands\n\nConsider adding similar support to:\n- `bd update --body-file` (for updating descriptions)\n- `bd comment --body-file` (if/when we add comments)\n\n## Examples\n\n```bash\n# From file\nbd create --title=\"Add new feature\" --body-file=feature.md\n\n# From stdin\necho \"Quick description\" | bd create --title=\"Bug fix\" --body-file=-\n\n# With other flags\nbd create \\\n --title=\"Security issue\" \\\n --type=bug \\\n --priority=0 \\\n --body-file=security-report.md \\\n --label=security\n```\n\n## Testing\n\n- Test with normal files\n- Test with stdin (`-`)\n- Test with non-existent files (error handling)\n- Test with binary files (should handle gracefully)\n- Test with empty files (valid - empty description)\n- Test that `--description-file` and `--body-file` are equivalent aliases","status":"tombstone","priority":1,"issue_type":"feature","created_at":"2025-11-22T00:02:08.762684-08:00","updated_at":"2025-12-25T01:21:01.952723-08:00","deleted_at":"2025-12-25T01:21:01.952723-08:00","deleted_by":"batch delete","delete_reason":"batch delete","original_type":"feature"} {"id":"bd-hzvz","title":"Update info.go versionChanges","description":"Add entry to versionChanges in cmd/bd/info.go with agent-actionable changes for 0.30.7","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-19T22:56:48.649359-08:00","updated_at":"2025-12-19T22:57:31.604229-08:00","closed_at":"2025-12-19T22:57:31.604229-08:00","dependencies":[{"issue_id":"bd-hzvz","depends_on_id":"bd-8pyn","type":"parent-child","created_at":"2025-12-19T22:56:48.652068-08:00","created_by":"stevey"},{"issue_id":"bd-hzvz","depends_on_id":"bd-2ep8","type":"blocks","created_at":"2025-12-19T22:56:48.652376-08:00","created_by":"stevey"}]} {"id":"bd-i0rx","title":"Merge: bd-ao0s","description":"branch: polecat/rictus\ntarget: main\nsource_issue: bd-ao0s\nrig: beads","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-20T01:13:42.716658-08:00","updated_at":"2025-12-20T23:17:26.993744-08:00","closed_at":"2025-12-20T23:17:26.993744-08:00","close_reason":"Branches nuked, MRs obsolete"} +{"id":"bd-i7a6","title":"Test actor flag","status":"open","priority":4,"issue_type":"task","created_at":"2025-12-26T20:47:28.470006-08:00","updated_at":"2025-12-26T20:47:28.470006-08:00"} {"id":"bd-ia3g","title":"BondRef.ProtoID field name is misleading for mol+mol bonds","description":"In bondMolMol, the BondRef.ProtoID field is used to store molecule IDs:\n\n```go\nBondedFrom: append(molA.BondedFrom, types.BondRef{\n ProtoID: molB.ID, // This is a molecule, not a proto\n ...\n})\n```\n\nThis is semantically confusing since ProtoID suggests it should only hold proto references.\n\n**Options:**\n1. Rename ProtoID to SourceID (breaking change, needs migration)\n2. Add documentation clarifying ProtoID can hold molecule IDs in bond context\n3. Leave as-is, accept the naming is imprecise\n\nLow priority since it's just naming, not functionality.","status":"open","priority":2,"issue_type":"task","created_at":"2025-12-21T10:23:00.755067-08:00","updated_at":"2025-12-25T14:30:47.455867-08:00"} {"id":"bd-ibl9","title":"Merge: bd-4qfb","description":"branch: polecat/Polish\ntarget: main\nsource_issue: bd-4qfb\nrig: beads","status":"closed","priority":2,"issue_type":"merge-request","created_at":"2025-12-23T13:37:57.255125-08:00","updated_at":"2025-12-23T19:12:08.352249-08:00","closed_at":"2025-12-23T19:12:08.352249-08:00","close_reason":"Stale merge-requests from orphaned polecat branches - refinery not processing"} {"id":"bd-icfe","title":"gt spawn/crew setup should create .beads/redirect for worktrees","description":"Crew clones and polecats need a .beads/redirect file pointing to the shared beads database (../../mayor/rig/.beads). Currently:\n\n- redirect files can get deleted by git clean\n- not auto-created during gt spawn or worktree setup\n- missing redirects cause 'no beads database found' errors\n\nFound missing in: gastown/joe, beads/zoey (after git clean)\n\nFix options:\n1. gt spawn creates redirect during worktree setup\n2. gt prime regenerates missing redirects\n3. bd commands auto-detect worktree and find shared beads\n\nThis should be standard Gas Town rig configuration.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-21T01:30:26.115872-08:00","updated_at":"2025-12-21T17:51:25.740811-08:00","closed_at":"2025-12-21T17:51:25.740811-08:00","close_reason":"Moved to gastown: gt-b6qm"} @@ -365,7 +367,7 @@ {"id":"bd-l7y3","title":"bd mol bond --pour should set Wisp=false","description":"In mol_bond.go bondProtoMol(), opts.Wisp is hardcoded to true (line 392). This ignores the --pour flag. When user specifies --pour to make an issue persistent, the Wisp field should be false so the issue is not marked for bulk deletion.\n\nCurrent behavior:\n- --pour flag correctly selects regular storage (not wisp storage)\n- But opts.Wisp=true means spawned issues are still marked for cleanup when closed\n\nExpected behavior:\n- --pour should set Wisp=false so persistent issues are not auto-cleaned\n\nComparison with mol_spawn.go (line 204):\n wisp := !pour // Correctly respects --pour flag\n result, err := spawnMolecule(ctx, store, subgraph, vars, assignee, actor, wisp)\n\nFix: Pass pour flag to bondProtoMol and set opts.Wisp = !pour","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-12-23T15:15:00.562346-08:00","updated_at":"2025-12-23T15:25:22.53144-08:00","closed_at":"2025-12-23T15:25:22.53144-08:00","close_reason":"Fixed - pour parameter now passed through bondProtoMol chain"} {"id":"bd-ldb0","title":"Rename ephemeral → wisp throughout codebase","description":"## The Change\n\nRename 'ephemeral' to 'wisp' throughout the beads codebase.\n\n## Why\n\n**Ephemeral** is:\n- 4 syllables (too long)\n- Greek/academic (doesn't match bond/burn/squash)\n- Overused in tech (K8s, networking, storage)\n- Passive/descriptive\n\n**Wisp** is:\n- 1 syllable (matches bond/burn/squash)\n- Evocative - you can SEE a wisp\n- Steam engine metaphor - Gas Town is engines, steam wisps rise and dissipate\n- Will-o'-the-wisp - transient spirits that guide then vanish\n- Unique - nobody else uses it\n\n## The Steam Engine Metaphor\n\n```\nEngine does work → generates steam\nSteam wisps rise → execution trace\nSteam condenses → digest (distillate)\nSteam dissipates → cleaned up (burned)\n```\n\n## Full Vocabulary\n\n| Term | Meaning |\n|------|---------|\n| bond | Attach proto to work (creates wisps) |\n| wisp | Temporary execution step |\n| squash | Condense wisps into digest |\n| burn | Destroy wisps without record |\n| digest | Permanent condensed record |\n\n## Changes Required\n\n### Code\n- `Ephemeral bool` → `Wisp bool` in types/issue.go\n- `--ephemeral` flag → remove (wisp is default)\n- `--persistent` flag → keep as opt-out\n- `bd cleanup --ephemeral` → `bd cleanup --wisps`\n- Update all references in mol_*.go files\n\n### Docs\n- Update all documentation\n- Update CLAUDE.md examples\n- Update CLI help text\n\n### Database Migration\n- Add migration to rename field (or keep internal name, just change API)\n\n## Example Usage After\n\n```bash\nbd mol bond mol-polecat-work # Creates wisps (default)\nbd mol bond mol-xxx --persistent # Creates permanent issues\nbd mol squash bd-xxx # Condenses wisps → digest\nbd cleanup --wisps # Clean old wisps\nbd list --wisps # Show wisp issues\n```","status":"closed","priority":1,"issue_type":"task","created_at":"2025-12-21T14:44:41.576068-08:00","updated_at":"2025-12-22T00:32:31.153738-08:00","closed_at":"2025-12-22T00:32:31.153738-08:00","close_reason":"Renamed ephemeral → wisp throughout codebase"} {"id":"bd-lfak","title":"bd preflight: PR readiness checks for contributors","description":"## Vision\n\nEncode project-specific institutional knowledge into executable checks. CONTRIBUTING.md is documentation that's read once and forgotten; `bd preflight` is documentation that runs at exactly the right moment.\n\n## Problem Statement\n\nContributors face a \"last mile\" problem - they do the work but stumble on project-specific gotchas at PR time:\n- Nix vendorHash gets stale when go.sum changes\n- Beads artifacts leak into PRs (see bd-umbf for namespace solution)\n- Version mismatches between version.go and default.nix\n- Tests/lint not run locally before pushing\n- Other project-specific checks that only surface when CI fails\n\nThese are too obscure to remember, exist in docs nobody reads end-to-end, and waste CI round-trips.\n\n## Why beads?\n\nBeads already has a foothold in the contributor workflow. It knows:\n- Git state (staged files, branch, dirty status)\n- Project structure\n- The specific issue being worked on\n- Project-specific configuration\n\n## Proposed Interface\n\n### Tier 1: Checklist Mode (v1)\n\n $ bd preflight\n PR Readiness Checklist:\n\n [ ] Tests pass: go test -short ./...\n [ ] Lint passes: golangci-lint run ./...\n [ ] No beads pollution: check .beads/issues.jsonl diff\n [ ] Nix hash current: go.sum unchanged or vendorHash updated\n [ ] Version sync: version.go matches default.nix\n\n Run 'bd preflight --check' to validate automatically.\n\n### Tier 2: Check Mode (v2)\n\n $ bd preflight --check\n ✓ Tests pass\n ✓ Lint passes\n ⚠ Beads pollution: 3 issues in diff - are these project issues or personal?\n ✗ Nix hash stale: go.sum changed, vendorHash needs update\n Fix: sha256-KRR6dXzsSw8OmEHGBEVDBOoIgfoZ2p0541T9ayjGHlI=\n ✓ Version sync\n\n 1 error, 1 warning. Run 'bd preflight --fix' to auto-fix where possible.\n\n### Tier 3: Fix Mode (v3)\n\n $ bd preflight --fix\n ✓ Updated vendorHash in default.nix\n ⚠ Cannot auto-fix beads pollution - manual review needed\n\n## Checks to Implement\n\n| Check | Description | Auto-fixable |\n|-------|-------------|--------------|\n| tests | Run go test -short ./... | No |\n| lint | Run golangci-lint | Partial (gofmt) |\n| beads-pollution | Detect personal issues in diff | No (see bd-umbf) |\n| nix-hash | Detect stale vendorHash | Yes (if nix available) |\n| version-sync | version.go matches default.nix | Yes |\n| no-debug | No TODO/FIXME/console.log | Warn only |\n| clean-stage | No unintended files staged | Warn only |\n\n## Future: Configuration\n\nMake checks configurable per-project via .beads/preflight.yaml:\n\n preflight:\n checks:\n - name: tests\n run: go test -short ./...\n required: true\n - name: no-secrets\n pattern: \"**/*.env\"\n staged: deny\n - name: custom-check\n run: ./scripts/validate.sh\n\nThis lets any project using beads define their own preflight checks.\n\n## Implementation Phases\n\n### Phase 1: Static Checklist\n- Implement bd preflight with hardcoded checklist for beads\n- No execution, just prints what to check\n- Update CONTRIBUTING.md to reference it\n\n### Phase 2: Automated Checks\n- Implement bd preflight --check\n- Run tests, lint, detect stale hashes\n- Clear pass/fail/warn output\n\n### Phase 3: Auto-fix\n- Implement bd preflight --fix\n- Fix vendorHash, version sync\n- Integrate with bd-umbf solution for pollution\n\n### Phase 4: Configuration\n- .beads/preflight.yaml support\n- Make it useful for other projects using beads\n- Plugin/hook system for custom checks\n\n## Dependencies\n\n- bd-umbf: Namespace isolation for beads pollution (blocking for full solution)\n\n## Success Metrics\n\n- Fewer CI failures on first PR push\n- Reduced \"fix nix hash\" commits\n- Contributors report preflight caught issues before CI","status":"open","priority":2,"issue_type":"epic","created_at":"2025-12-13T18:01:39.587078-08:00","updated_at":"2025-12-13T18:01:39.587078-08:00","dependencies":[{"issue_id":"bd-lfak","depends_on_id":"bd-umbf","type":"blocks","created_at":"2025-12-13T18:01:46.059901-08:00","created_by":"daemon","metadata":"{}"}]} -{"id":"bd-lfiu","title":"bd dep add: Auto-resolve cross-rig IDs using routes.jsonl","description":"Currently, adding a dependency to an issue in another rig requires verbose external reference syntax:\n\n```bash\n# This fails - can't resolve bd-* from gastown context\nbd dep add gt-xyz bd-abc\n\n# This works but is verbose\nbd dep add gt-xyz external:beads:bd-abc\n```\n\nThe town-level routing (~/gt/.beads/routes.jsonl) already knows how to map prefixes to rigs:\n```json\n{\"prefix\": \"gt-\", \"path\": \"gastown/mayor/rig\"}\n{\"prefix\": \"bd-\", \"path\": \"beads/mayor/rig\"}\n```\n\nEnhancement: When `bd dep add` encounters an ID with a foreign prefix, it should:\n1. Check routes.jsonl for the prefix mapping\n2. Auto-resolve to external:\u003cproject\u003e:\u003cid\u003e internally\n3. Allow the simpler `bd dep add gt-xyz bd-abc` syntax\n\nThis would make cross-rig dependencies much more ergonomic.","status":"open","priority":3,"issue_type":"feature","created_at":"2025-12-26T20:20:40.814713-08:00","updated_at":"2025-12-26T20:20:40.814713-08:00"} +{"id":"bd-lfiu","title":"bd dep add: Auto-resolve cross-rig IDs using routes.jsonl","description":"Currently, adding a dependency to an issue in another rig requires verbose external reference syntax:\n\n```bash\n# This fails - can't resolve bd-* from gastown context\nbd dep add gt-xyz bd-abc\n\n# This works but is verbose\nbd dep add gt-xyz external:beads:bd-abc\n```\n\nThe town-level routing (~/gt/.beads/routes.jsonl) already knows how to map prefixes to rigs:\n```json\n{\"prefix\": \"gt-\", \"path\": \"gastown/mayor/rig\"}\n{\"prefix\": \"bd-\", \"path\": \"beads/mayor/rig\"}\n```\n\nEnhancement: When `bd dep add` encounters an ID with a foreign prefix, it should:\n1. Check routes.jsonl for the prefix mapping\n2. Auto-resolve to external:\u003cproject\u003e:\u003cid\u003e internally\n3. Allow the simpler `bd dep add gt-xyz bd-abc` syntax\n\nThis would make cross-rig dependencies much more ergonomic.","status":"in_progress","priority":3,"issue_type":"feature","created_at":"2025-12-26T20:20:40.814713-08:00","updated_at":"2025-12-26T20:39:29.579011-08:00"} {"id":"bd-likt","title":"Add daemon RPC support for gate commands","description":"Add daemon RPC support for gate commands.\n\n## Current State\nGate commands require --no-daemon flag because they use direct SQLite access:\n- Gate create needs to write await_type, await_id, timeout_ns, waiters fields\n- Gate wait needs to update waiters JSON array\n- Daemon RPC doesnt have methods for these operations\n\n## Implementation\n\n### 1. Add RPC methods to internal/rpc/protocol.go\n\n```go\n// Gate operations\ntype GateCreateArgs struct {\n Title string \\`json:\"title\"\\`\n AwaitType string \\`json:\"await_type\"\\`\n AwaitID string \\`json:\"await_id\"\\`\n Timeout time.Duration \\`json:\"timeout\"\\`\n Waiters []string \\`json:\"waiters\"\\`\n}\n\ntype GateCreateResult struct {\n Issue *types.Issue \\`json:\"issue\"\\`\n}\n\ntype GateListArgs struct {\n All bool \\`json:\"all\"\\` // Include closed gates\n}\n\ntype GateListResult struct {\n Gates []*types.Issue \\`json:\"gates\"\\`\n}\n\ntype GateWaitArgs struct {\n GateID string \\`json:\"gate_id\"\\`\n Waiters []string \\`json:\"waiters\"\\` // Additional waiters to add\n}\n\ntype GateWaitResult struct {\n Gate *types.Issue \\`json:\"gate\"\\`\n AddedCount int \\`json:\"added_count\"\\`\n}\n```\n\n### 2. Add handler methods to internal/daemon/rpc_handler.go\n\n```go\nfunc (h *RPCHandler) GateCreate(ctx context.Context, args *rpc.GateCreateArgs) (*rpc.GateCreateResult, error) {\n now := time.Now()\n gate := \u0026types.Issue{\n Title: args.Title,\n IssueType: types.TypeGate,\n Status: types.StatusOpen,\n Priority: 1,\n Assignee: \"deacon/\",\n Wisp: true,\n AwaitType: args.AwaitType,\n AwaitID: args.AwaitID,\n Timeout: args.Timeout,\n Waiters: args.Waiters,\n CreatedAt: now,\n UpdatedAt: now,\n }\n gate.ContentHash = gate.ComputeContentHash()\n \n if err := h.store.CreateIssue(ctx, gate, h.actor); err != nil {\n return nil, err\n }\n \n return \u0026rpc.GateCreateResult{Issue: gate}, nil\n}\n\nfunc (h *RPCHandler) GateList(ctx context.Context, args *rpc.GateListArgs) (*rpc.GateListResult, error) {\n gateType := types.TypeGate\n filter := types.IssueFilter{IssueType: \u0026gateType}\n if !args.All {\n openStatus := types.StatusOpen\n filter.Status = \u0026openStatus\n }\n \n gates, err := h.store.SearchIssues(ctx, \"\", filter)\n if err != nil {\n return nil, err\n }\n \n return \u0026rpc.GateListResult{Gates: gates}, nil\n}\n\nfunc (h *RPCHandler) GateWait(ctx context.Context, args *rpc.GateWaitArgs) (*rpc.GateWaitResult, error) {\n gate, err := h.store.GetIssue(ctx, args.GateID)\n if err != nil {\n return nil, err\n }\n if gate.IssueType != types.TypeGate {\n return nil, fmt.Errorf(\"%s is not a gate\", args.GateID)\n }\n \n // Merge waiters (dedupe)\n waiterSet := make(map[string]bool)\n for _, w := range gate.Waiters {\n waiterSet[w] = true\n }\n added := 0\n for _, w := range args.Waiters {\n if !waiterSet[w] {\n gate.Waiters = append(gate.Waiters, w)\n waiterSet[w] = true\n added++\n }\n }\n \n if added \u003e 0 {\n // Update via store\n updates := map[string]interface{}{\n \"waiters\": gate.Waiters,\n }\n if err := h.store.UpdateIssue(ctx, args.GateID, updates, h.actor); err != nil {\n return nil, err\n }\n }\n \n return \u0026rpc.GateWaitResult{Gate: gate, AddedCount: added}, nil\n}\n```\n\n### 3. Register methods in daemon\n\nIn internal/daemon/server.go, register the new methods:\n```go\nrpc.RegisterMethod(\"gate.create\", h.GateCreate)\nrpc.RegisterMethod(\"gate.list\", h.GateList)\nrpc.RegisterMethod(\"gate.wait\", h.GateWait)\n```\n\n### 4. Add client methods to internal/rpc/client.go\n\n```go\nfunc (c *Client) GateCreate(ctx context.Context, args *GateCreateArgs) (*GateCreateResult, error) {\n var result GateCreateResult\n err := c.Call(ctx, \"gate.create\", args, \u0026result)\n return \u0026result, err\n}\n\nfunc (c *Client) GateList(ctx context.Context, args *GateListArgs) (*GateListResult, error) {\n var result GateListResult\n err := c.Call(ctx, \"gate.list\", args, \u0026result)\n return \u0026result, err\n}\n\nfunc (c *Client) GateWait(ctx context.Context, args *GateWaitArgs) (*GateWaitResult, error) {\n var result GateWaitResult\n err := c.Call(ctx, \"gate.wait\", args, \u0026result)\n return \u0026result, err\n}\n```\n\n### 5. Update cmd/bd/gate.go to use daemon\n\n```go\n// In gateCreateCmd Run:\nif daemonClient != nil {\n result, err := daemonClient.GateCreate(ctx, \u0026rpc.GateCreateArgs{\n Title: title,\n AwaitType: awaitType,\n AwaitID: awaitID,\n Timeout: timeout,\n Waiters: notifyAddrs,\n })\n if err != nil {\n FatalError(\"gate create: %v\", err)\n }\n gate = result.Issue\n} else {\n // Existing direct store code\n}\n```\n\n## Files to Modify\n\n1. **internal/rpc/protocol.go** - Add Gate*Args/Result types\n2. **internal/daemon/rpc_handler.go** - Add handler methods\n3. **internal/daemon/server.go** - Register methods\n4. **internal/rpc/client.go** - Add client methods\n5. **cmd/bd/gate.go** - Use daemon client when available\n\n## Testing\n\n```bash\n# Start daemon\nbd daemon start\n\n# Test via daemon (should work without --no-daemon)\nbd gate create --await timer:5m --notify beads/dave\nbd gate list\nbd gate wait \u003cid\u003e --notify beads/alice\n\n# Verify daemon handled it\nbd daemons logs . | grep gate\n```\n\n## Success Criteria\n- All gate commands work without --no-daemon\n- Same behavior in daemon vs direct mode\n- Waiters array updates correctly via RPC\n- Tests pass for RPC gate operations","status":"closed","priority":3,"issue_type":"task","assignee":"beads/Gater","created_at":"2025-12-23T12:13:25.778412-08:00","updated_at":"2025-12-23T13:45:58.398604-08:00","closed_at":"2025-12-23T13:45:58.398604-08:00","close_reason":"Implemented daemon RPC support for all gate commands","dependencies":[{"issue_id":"bd-likt","depends_on_id":"bd-udsi","type":"discovered-from","created_at":"2025-12-23T12:13:36.174822-08:00","created_by":"daemon"},{"issue_id":"bd-likt","depends_on_id":"bd-iz5t","type":"parent-child","created_at":"2025-12-23T12:44:07.891992-08:00","created_by":"daemon"}]} {"id":"bd-lk39","title":"Add composite index (issue_id, event_type) on events table","description":"GetCloseReason and GetCloseReasonsForIssues filter by both issue_id and event_type.\n\n**Query (queries.go:355-358):**\n```sql\nSELECT comment FROM events\nWHERE issue_id = ? AND event_type = ?\nORDER BY created_at DESC LIMIT 1\n```\n\n**Problem:** Currently uses idx_events_issue but must filter event_type in memory.\n\n**Solution:** Add migration:\n```sql\nCREATE INDEX IF NOT EXISTS idx_events_issue_type ON events(issue_id, event_type);\n```\n\n**Priority:** Low - events table is typically small relative to issues.","status":"closed","priority":4,"issue_type":"task","created_at":"2025-12-22T22:58:54.070587-08:00","updated_at":"2025-12-22T23:15:13.841988-08:00","closed_at":"2025-12-22T23:15:13.841988-08:00","close_reason":"Implemented in migration 026_additional_indexes.go","dependencies":[{"issue_id":"bd-lk39","depends_on_id":"bd-h0we","type":"discovered-from","created_at":"2025-12-22T22:58:54.071286-08:00","created_by":"daemon"}]} {"id":"bd-llfl","title":"Improve test coverage for cmd/bd CLI (26.2% → 50%)","description":"The main CLI package (cmd/bd) has only 26.2% test coverage. CLI commands should have at least 50% coverage to ensure reliability.\n\nKey areas with low/no coverage:\n- daemon_autostart.go (multiple 0% functions)\n- compact.go (several 0% functions)\n- Various command handlers\n\nCurrent coverage: 26.2%\nTarget coverage: 50%","notes":"## Progress Update (2025-12-23)\n\n### Tests Added\nAdded 683 lines of new tests across 3 files:\n- cmd/bd/daemon_config_test.go (144 lines)\n- cmd/bd/utils_test.go (484 lines) \n- cmd/bd/autostart_test.go (55 additional lines)\n\n### Functions Now Tested\n- daemon_config.go: ensureBeadsDir, getPIDFilePath, getLogFilePath, getSocketPathForPID\n- daemon_autostart.go: determineSocketPath, isDaemonRunningQuiet\n- activity.go: printEvent\n- cleanup.go: showCleanupDeprecationHint\n- upgrade.go: pluralize\n- wisp.go: formatTimeAgo\n- list.go: pinIndicator, sortIssues\n- hooks.go: FormatHookWarnings, isRebaseInProgress, hasBeadsJSONL\n- template.go: extractIDSuffix\n- thanks.go: getContributorsSorted\n\n### Coverage Results\n- Before: 22.5%\n- After: 23.1%\n- Delta: +0.6%\n\n### Remaining Work\nMost remaining untested code (77%) involves:\n1. Daemon/RPC operations (runDaemonLoop, tryAutoStartDaemon, etc.)\n2. Command handlers that require database/daemon setup\n3. Git operations (runPreCommitHook, runPostMergeHook, etc.)\n\nTo reach 50%, would need to:\n- Add integration tests with mocked daemon\n- Add scripttest tests for command handlers\n- Add more database-dependent tests\n\nCommit: 4f949c19","status":"in_progress","priority":2,"issue_type":"task","assignee":"beads/charlie","created_at":"2025-12-13T20:43:03.123341-08:00","updated_at":"2025-12-23T22:45:57.860498-08:00"}