Agent beads: structured labels for filtering

## Agent Beads Need Queryable Labels

Currently agent beads have role_type/rig in description text, not as labels. This breaks @group resolution in gt mail.

## Current State

```json
{
  "id": "gt-gastown-witness",
  "issue_type": "agent",
  "description": "...\\nrole_type: witness\\nrig: gastown\\n..."
}
```

Cannot query: `bd list --type=agent --label=role_type:witness` returns nothing.

## Required

Agent bead creation should add labels:
- `role_type:<type>` (witness, refinery, crew, polecat, dog, mayor, deacon)
- `rig:<rig>` (gastown, beads, or "town" for town-level)

## Where to Fix

gt polecat/crew/agent creation commands should add labels:
```bash
bd create --type=agent ... --labels="role_type:witness,rig:gastown"
```

## Queries Enabled

```bash
bd list --type=agent --label=role_type:witness    # All witnesses
bd list --type=agent --label=rig:gastown          # All gastown agents
bd list --type=agent --label=role_type:dog        # All dogs
```

## Acceptance
- New agent beads created with role_type/rig labels
- Existing agent beads backfilled (one-time script)
- @group patterns work in gt mail router


Add {{version}} to versionChanges in info.go

Add new entry at TOP of versionChanges in cmd/bd/info.go with release notes from CHANGELOG.md. Must do before bump-version.sh --commit.


Code Health Review Dec 2025: Technical Debt Cleanup

Epic grouping technical debt identified in the Dec 16, 2025 code health review.

## Overall Health Grade: B (Solid foundation, needs cleanup)

### P1 (High Priority):
- bd-74w1: Consolidate duplicate path-finding utilities
- [deleted:bd-b6xo]: Remove/fix ClearDirtyIssues() race condition
- [deleted:bd-b3og]: Fix TestImportBugIntegration deadlock

### P2 (Medium Priority):
- bd-05a8: Split large files (doctor.go, sync.go)
- bd-qioh: Standardize error handling patterns
- bd-rgyd: Split queries.go (1586 lines)
- bd-9g1z: Fix/remove TestFindJSONLPathDefault

### P3 (Low Priority):
- bd-ork0: Add comments to 30+ ignored errors
- bd-4nqq: Remove dead test code in info_test.go
- bd-dhza: Reduce global state in main.go

## Key Areas:
1. Code duplication in path utilities
2. Large monolithic files (5 files >1000 lines)
3. Global state (25+ variables, 3 deprecated)
4. Silent error suppression (30+ instances)
5. Test gaps and dead test code
6. Atomicity risks in batch operations


CLI cleanup: Consolidate bd top-level commands

## Problem
bd has 76 top-level commands, making it hard to discover and remember.

## Proposed Changes

### Remove from top-level (nest instead):
- `bd cook` → `bd formula cook` (cooking is a formula operation)
- `bd pin` → already covered by `bd mol` commands
- `bd thanks` → `bd info --thanks` or just README
- `bd quickstart` → `bd help quickstart` or docs
- `bd detect-pollution` → `bd doctor --check=pollution`

### Consolidate migrations under `bd migrate`:
- `bd migrate-hash-ids` → `bd migrate hash-ids`
- `bd migrate-issues` → `bd migrate issues`
- `bd migrate-sync` → `bd migrate sync`
- `bd migrate-tombstones` → `bd migrate tombstones`

### Consolidate admin under `bd admin`:
- `bd cleanup` → `bd admin cleanup`
- `bd compact` → `bd admin compact`
- `bd reset` → `bd admin reset`

## Backwards Compatibility
Keep old commands as hidden aliases for one release cycle.


Merge: bd-n386

branch: polecat/immortan
target: main
source_issue: bd-n386
rig: beads


Add thread-safety warning to git.ResetCaches() doc comment

Code review finding from bd-7di fix.

ResetCaches() reassigns sync.Once values which is not thread-safe. While this is only used in tests (which are single-threaded), the function is exported and could be misused.

Add a warning comment:
```go
// ResetCaches resets all cached git information.
// WARNING: Not thread-safe. Only call from single-threaded test contexts.
```

File: internal/git/gitdir.go


Code smell: Issue struct is a God Object (50+ fields)

attached_args: Refactor Issue struct God Object

The Issue struct in internal/types/types.go has 50+ fields covering many different concerns:

- Basic issue tracking (ID, Title, Description, Status, Priority)
- Messaging/communication (Sender, Ephemeral, etc.)
- Agent identity (HookBead, RoleBead, AgentState, RoleType, Rig)
- Gate/async coordination (AwaitType, AwaitID, Timeout, Waiters)
- Source tracing (SourceFormula, SourceLocation)
- HOP validation/entities (Creator, Validations)
- Compaction (CompactionLevel, CompactedAt, OriginalSize)
- Tombstones (DeletedAt, DeletedBy, DeleteReason)

Consider:
1. Extracting field groups into embedded structs (e.g., AgentFields, GateFields)
2. Using composition pattern to make the struct more modular
3. At minimum, grouping related fields together with section comments

Location: internal/types/types.go:12-82


Monitor PyPI publish

Watch the PyPI publish action:
https://github.com/steveyegge/beads/actions/workflows/pypi-publish.yml

Verify at: https://pypi.org/project/beads-mcp/0.30.4/

Check:
```bash
pip index versions beads-mcp 2>/dev/null | grep -q '0.30.4'
```

```verify
pip index versions beads-mcp 2>/dev/null | grep -q '0.30.4' || curl -s https://pypi.org/pypi/beads-mcp/json | jq -e '.releases["0.30.4"]'
```


Review SQLite indexes and scaling bottlenecks

Audit the beads SQLite schema for:

## Index Review
- Are all frequently-queried columns indexed?
- Are compound indexes needed for common query patterns?
- Any missing indexes on foreign keys or filter columns?

## Scaling Bottlenecks
- How does performance degrade with 10k, 100k, 1M issues?
- Full table scans in hot paths?
- JSONL export/import performance at scale
- Transaction contention in multi-agent scenarios

## Common Query Patterns to Optimize
- bd ready (status + blocked_by resolution)
- bd list with filters (status, type, priority, labels)
- bd show with dependency graph traversal
- bd sync import/export

## Deliverables
- Document current indexes
- Identify missing indexes
- Benchmark key operations at scale
- Recommend schema improvements


Document sync.branch 'always dirty' working tree behavior

## Context

When sync.branch is configured, the .beads/issues.jsonl file in main's working tree is ALWAYS dirty. This is by design:

1. bd sync commits to beads-sync branch (via worktree)
2. bd sync copies JSONL to main's working tree (so CLI commands work)
3. This copy is NOT committed to main (to reduce commit noise)

Contributors who watch main branch history pushed for sync.branch to avoid constant beads commit noise. But users need to understand the trade-off.

## Documentation Needed

Update README.md sync.branch section with:

1. **Clear explanation** of why .beads/ is always dirty on main
2. **"Be Zen about it"** - this is expected, not a bug
3. **Workflow options:**
   - Accept dirty state, use `bd sync --merge` periodically to snapshot to main
   - Or disable sync.branch if clean working tree is more important
4. **Shell alias tip** to hide beads from git status:
   ```bash
   alias gs='git status -- ":!.beads/"'
   ```
5. **When to merge**: releases, milestones, or periodic snapshots

## Related

- bd-7b7h: Fix that allows bd sync --merge to work with dirty .beads/
- bd-elqd: Investigation that identified this as expected behavior


Execute molecule bd-mol-xga: Release beads 0.37.0


Fix resolvePartialID stub in workflow.go

The resolvePartialID function at workflow.go:921-925 is a stub that just returns the ID unchanged. Should use utils.ResolvePartialID for proper partial ID resolution in direct mode (non-daemon).


Refinery Patrol

Merge queue processor patrol loop with verification gates.


Pinned field available in beads v0.37.0

Hey max,

Heads up on your mail overhaul work:

1. **Pinned field is available** - beads v0.37.0 (released by dave earlier) includes the pinned field on issues. You'll want to add this to BeadsMessage in types.go.

2. **Database migration** - Check if existing .beads databases need migration to support the pinned field. Run `bd doctor` to see if it flags anything.

3. **Sorting task** - Once you have the pinned field, gt-ngu1 (pinned beads first in mail inbox) needs implementing. Since messages now come from `bd list --type=message`, you'll need to either:
   - Sort in listBeads() after fetching, or
   - Ensure bd list returns pinned items first (may already do this?)

Check what version of bd you're building against.

-- Mayor


beads-release

Beads release workflow - from version bump to verified release.

This formula orchestrates a complete release cycle:
1. Preflight checks (clean git, up to date)
2. Documentation updates (CHANGELOG, info.go)
3. Version bump (all components)
4. Git operations (commit, tag, push)
5. CI verification (GitHub Actions)
6. Artifact verification (GitHub, npm, PyPI)
7. Local installation update
8. Daemon restart

## Usage

```bash
bd wisp create beads-release --var version=0.37.0
```

Or assign to a polecat:
```bash
gt sling beads/polecats/p1 --formula beads-release --var version=0.37.0
```


## Agent Beads Need Queryable Labels

Currently agent beads have role_type/rig in description text, not as labels. This breaks @group resolution in gt mail.

## Current State
```json
{
  "id": "gt-gastown-witness",
  "issue_type": "agent",
  "description": "...\\nrole_type: witness\\nrig: gastown\\n..."
}
```

Cannot query: `bd list --type=agent --label=role_type:witness` returns nothing.

## Required
Agent bead creation should add labels:
- `role_type:<type>` (witness, refinery, crew, polecat, dog, mayor, deacon)
- `rig:<rig>` (gastown, beads, or "town" for town-level)

## Where to Fix
gt polecat/crew/agent creation commands should add labels.

## Acceptance
- New agent beads created with role_type/rig labels
- @group patterns work in gt mail router


bd mail uses git user.name for sender instead of BEADS_AGENT_NAME

When sending mail via `bd mail send`, the sender field in the stored issue uses git config user.name instead of the BEADS_AGENT_NAME environment variable.

Reproduction:
1. Set BEADS_AGENT_NAME=gastown-alpha
2. Run: bd mail send mayor/ -s 'Test' -m 'Body'
3. Check the issue.jsonl: sender is 'Steve Yegge' (git user.name) not 'gastown-alpha'

Expected: The sender field should use BEADS_AGENT_NAME when set.

This breaks the mail system for multi-agent workflows where agents need to identify themselves by their role (polecat, refinery, etc.) rather than the human user's git identity.

Related: gt mail routing integration with Gas Town


Merge: bd-ykd9

branch: polecat/Doctor
target: main
source_issue: bd-ykd9
rig: beads


Code smell: init.go is 1928 lines - needs splitting

cmd/bd/init.go is 1928 lines covering multiple init modes, contributor/team setup, hooks setup, and stealth mode.

**Problem:**
- File is too large to understand and maintain
- Multiple responsibilities within single file
- Harder to test individual components

**Acceptance Criteria:**
- [ ] Split into logical files (init_setup.go, init_hooks.go, init_stealth.go, etc.)
- [ ] Each file under 500 lines
- [ ] No functionality changes
- [ ] Tests pass


Swarm: Test coordinator display

Swarm molecule orchestrating epic bd-2rkr.

Epic: bd-2rkr
Coordinator:


Update local installation

Update local bd to the new version.

Option 1 - Homebrew:
```bash
brew upgrade bd
```

Option 2 - Install script:
```bash
curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
```

Verify:
```bash
bd --version
```

Should show 0.41.0.


Update cmd/bd/version.go to 0.30.4

Update the Version constant in cmd/bd/version.go:
```go
Version = "0.30.4"
```

```verify
grep -q 'Version = "0.30.4"' cmd/bd/version.go
```


Implement formula features: repeat, for_each, branch, gate, compose.split

Multiple formula features in internal/formula/types.go are marked as "Not yet implemented":

IMPLEMENTED (TODOs removed):
- Step.Expand: Inline expansion - implemented in ApplyInlineExpansions (expand.go)
- Step.ExpandVars: Variable overrides for expansion - implemented alongside Expand

STILL NOT IMPLEMENTED (TODOs remain):
- Step.Condition: Make step optional based on variable (types.go:177-180)
- Step.Gate: Async wait condition for step (types.go:185-187)
- Gate struct: Schema defined but not processed in bd cook (types.go:209-210)

File: internal/formula/types.go


Compound visualization in bd mol show

Enhance bd mol show to display compound structure.

ENHANCEMENTS:
- Show constituent protos and how they're bonded
- Display bond type (sequential/parallel) between components
- Indicate attachment points
- Show combined variable requirements across all protos

EXAMPLE OUTPUT:

  Compound: proto-feature-with-tests
  Bonded from:
    └─ proto-feature (root)
       └─ proto-testing (sequential, after completion)

  Variables: {{name}}, {{version}}, {{test_suite}}

  Structure:
    proto-feature-with-tests
    ├─ Design feature {{name}}
    ├─ Implement core
    ├─ Write unit tests      ← from proto-testing
    └─ Run test suite {{test_suite}}  ← from proto-testing


bd dep tree doesn't display external dependencies

GetDependencyTree (dependencies.go:464-624) uses a recursive CTE that JOINs with the issues table, which means external refs (external:project:capability) are invisible in the tree output.

When an issue has an external blocking dependency, running 'bd dep tree <id>' won't show it.

Options:
1. Query dependencies table separately for external refs and display them as leaf nodes
2. Add a synthetic 'external' node type that shows the ref and resolution status
3. Document that external deps aren't shown in tree view (use bd show for full deps)

Lower priority since bd show <id> displays all dependencies including external refs.


Preflight: Check git status

Ensure working tree is clean before starting release.

```bash
git status
```

If there are uncommitted changes, either:
- Commit them first
- Stash them: `git stash`
- Abort and resolve


bd sync deleted non-.beads files (skills/beads/*)

On 2025-12-23, commit 7b671662 (bd sync) inadvertently deleted 5 files from skills/beads/ that were added by PR #722 (commit e432fcc8). These files are outside .beads/ and should never be touched by bd sync.

Files deleted:
- skills/beads/README.md
- skills/beads/references/INTEGRATION_PATTERNS.md
- skills/beads/references/MOLECULES.md
- skills/beads/references/PATTERNS.md
- skills/beads/references/TROUBLESHOOTING.md

Investigation needed:
1. How did bd sync stage/commit files outside .beads/?
2. Was this a one-time accident or is there a systematic bug?
3. Add safeguards to prevent bd sync from touching non-.beads paths

Reported via GH#738.


Code smell: Multiple CLI command files exceed 1000 lines

Several CLI command files are very large and could benefit from splitting:

| File | Lines | Notes |
|------|-------|-------|
| init.go | 1928 | Multiple init modes, contributor/team setup |
| show.go | 1592 | Display formatting, tree views, output modes |
| doctor.go | 1295 | Many health checks |
| sync.go | 1201 | Sync branch operations |
| compact.go | 1199 | Compaction logic |
| linear.go | 1190 | Linear integration |
| main.go | 1148 | Entry point and globals |

Consider:
1. Splitting init.go into init_core.go, init_contributor.go (already exists), init_team.go (already exists)
2. Moving show.go formatters to internal/ui package
3. Doctor checks could be individual files under doctor/ subpackage (already started)

Location: cmd/bd/*.go


Merge: bd-by0d

branch: polecat/furiosa
target: main
source_issue: bd-by0d
rig: beads


Verify PyPI package

Confirm PyPI package published.

```bash
pip index versions beads-mcp 2>/dev/null | head -3
```

Or check: https://pypi.org/project/beads-mcp/

Should show 0.99.0-test.


Remove Storage Cache from Server Struct

Eliminate cache fields and use s.storage directly


Merge: obsidian-1767106243818

branch: polecat/obsidian-1767106243818
target: main
source_issue: obsidian-1767106243818
rig: beads


Merge: bd-rgyd

branch: polecat/Splitter
target: main
source_issue: bd-rgyd
rig: beads


Review PR #514: fix plugin install docs

Review and merge PR #514 from aspiers. This PR fixes incorrect docs for installing Claude Code plugin from source in docs/PLUGIN.md. Clarifies shell vs Claude Code commands and fixes the . vs ./beads argument issue. URL: https://github.com/anthropics/beads/pull/514


bd mol bond: Dynamic bond with variable substitution

Implement dynamic molecule bonding with runtime variable substitution.

## Command
```bash
bd mol bond <proto-id> <parent-wisp-id> --var key=value --var key2=value2
```

## Behavior
1. Parse proto molecule template
2. Substitute {{key}} placeholders with provided values
3. Create wisp children under the parent molecule
4. Child IDs follow pattern: parent-id.child-ref (e.g., patrol-x7k.arm-ace)
5. Nested children: parent-id.child-ref.step-ref (e.g., patrol-x7k.arm-ace.capture)

## Variable Substitution
- In step titles: "Inspect {{polecat_name}}" -> "Inspect ace"
- In descriptions: Full template substitution
- In Needs directives: Allow referencing parent steps

## Output
```
✓ Bonded mol-polecat-arm to patrol-x7k
  Created: patrol-x7k.arm-ace (5 steps)
```


Implement bd pin/unpin commands

Add 'bd pin <id>' and 'bd unpin <id>' commands to toggle the pinned status of issues. Should support multiple IDs like other bd commands.


Verify version consistency

Confirm all versions match 0.39.0.

```bash
grep 'Version = ' cmd/bd/version.go
jq -r '.version' .claude-plugin/plugin.json
jq -r '.version' npm-package/package.json
grep 'version = ' integrations/beads-mcp/pyproject.toml
```

All should show 0.39.0.


Create migration script for edge field to dependency conversion

Migration must:
1. Read existing JSONL with old fields
2. Convert field values to dependency records
3. Write updated JSONL without old fields
4. Handle edge cases (missing refs, duplicates)

Run via: bd migrate or automatic on bd prime


Merge: quartz-1767083470444

branch: polecat/quartz-1767083470444
target: main
source_issue: quartz-1767083470444
rig: beads


bd create -f crashes with nil pointer dereference

GitHub issue #674. The markdown import feature crashes at markdown.go:338 because global variables (store, ctx, actor) aren't initialized when createIssuesFromMarkdown is called. The function uses globals set by cobra command framework but is being called before they're ready. Need to either initialize globals at start of function or pass them as parameters.


Code cleanup: Search for leftover debugging code

Scan the beads codebase for debugging artifacts that should be removed before release:

## Patterns to search for:
- `fmt.Printf` debugging statements (vs proper logging)
- `// DEBUG`, `// TODO: remove`, `// TEMP` comments
- `log.Printf` that should use structured logging
- Hardcoded test values or paths
- `panic()` calls that should be proper error handling
- Commented-out code blocks
- `time.Sleep` debugging delays

## Files to check:
- cmd/bd/*.go
- internal/**/*.go

## Acceptance:
- Remove or convert all debugging artifacts
- Ensure no test pollution in production code


Ephemeral issue cleanup and history compaction

## Problem

Beads history grows without bound. Every message, handoff, work assignment
stays in issues.jsonl forever. Enterprise users will balk at "git as database."

## Solution: Two-Tier Cleanup

### Tier 1: Ephemeral Cleanup (v1)

bd cleanup --ephemeral --closed

- Deletes closed issues where ephemeral=true from issues.jsonl
- Safe: only removes explicitly marked ephemeral + closed
- Preserves git history (commits still exist)
- Run after swarm completion

### Tier 2: History Compaction (v2)

bd compact --squash

- Rewrites issues.jsonl to remove tombstones
- Optionally squashes git history (interactive rebase equivalent)
- Preserves Merkle proofs for deleted items
- Advanced: cold storage tiering

## HOP Context

| Layer | HOP Role | Persistence |
|-------|----------|-------------|
| Execution trace | None | Ephemeral |
| Work scaffolding | None | Summarizable |
| Work outcome | CV entry | Permanent |
| Validation record | Stake proof | Permanent |

"Execution is ephemeral. Outcomes are permanent. You can't squash your CV."

## Success Criteria

- After cleanup --ephemeral: issues.jsonl only contains persistent work
- Work outcomes preserved (CV entries)
- Validation records preserved (stake proofs)
- Execution scaffolding removed (transient coordination)

## Implementation Plan (REVISED after code review)

See history/EPHEMERAL_MOLECULES_DESIGN.md for comprehensive design + review.

## Key Simplification

After code review, Tier 1 is MUCH simpler than originally designed:

- **Original**: Separate ephemeral repo with routing.ephemeral config
- **Revised**: Just set Wisp: true in cloneSubgraph()

The wisp field and bd cleanup --wisp already exist\!

## Child Tasks (in dependency order)

1. **bd-2vh3.2**: Tier 1 - Ephemeral spawning (SIMPLIFIED) [READY]
   - Just add Wisp: true to template.go:474
   - Add --persistent flag to opt out
2. **bd-2vh3.3**: Tier 2 - Basic bd mol squash command
3. **bd-2vh3.4**: Tier 3 - AI-powered squash summarization
4. **bd-2vh3.5**: Tier 4 - Auto-squash on molecule completion
5. **bd-2vh3.6**: Tier 5 - JSONL archive rotation (DEFERRED: post-1.0)

## What Already Exists

| Component | Location |
|-----------|----------|
| Ephemeral field | internal/types/types.go:45 |
| bd cleanup --wisp | cmd/bd/cleanup.go:72 |
| cloneSubgraph() | cmd/bd/template.go:456 |
| loadTemplateSubgraph() | cmd/bd/template.go |

## HOP Alignment

'Execution is ephemeral. Outcomes are permanent. You can't squash your CV.'


Update CHANGELOG header

Change [Unreleased] to [{{version}}] - {{date}} and add new empty [Unreleased] section above it.


Consider FTS5 for text search at scale

SearchIssues uses LIKE patterns for text search which can't use indexes.

**Current query (queries.go:1475-1477):**
```sql
(title LIKE ? OR description LIKE ? OR id LIKE ?)
```

**Problem:** Full table scan on every text search. At 100K+ issues, this becomes slow.

**SQLite FTS5 solution:**
```sql
CREATE VIRTUAL TABLE issues_fts USING fts5(
  id, title, description, design, notes,
  content='issues',
  content_rowid='rowid'
);

-- Triggers to keep FTS in sync
CREATE TRIGGER issues_ai AFTER INSERT ON issues BEGIN
  INSERT INTO issues_fts(rowid, id, title, description, design, notes)
  VALUES (new.rowid, new.id, new.title, new.description, new.design, new.notes);
END;
-- (similar for UPDATE, DELETE)
```

**Trade-offs:**
- Database size increase (~30-50% for text content)
- Additional write overhead (trigger execution)
- Better search capabilities (ranking, phrase search)

**Decision needed:** Is full-text search a priority feature? Current LIKE search may be acceptable for most use cases.

**Benchmark first:** Measure SearchIssues at 100K scale before implementing.


mol-beads-release

Release checklist for beads version 0.99.0.

This molecule ensures all release steps are completed properly.
Variable: 0.99.0 - target version (e.g., 0.35.0)

## Step: update-release-notes
Update cmd/bd/info.go with release notes for 0.99.0.

Add a new VersionChange entry at the top of versionChanges slice:
```go
{
    Version: "0.99.0",
    Date:    "YYYY-MM-DD",
    Changes: []string{
        "NEW: Feature description",
        "FIX: Bug fix description",
        "IMPROVED: Enhancement description",
    },
},
```

Run `git log --oneline v<previous>..HEAD` to see what changed.

## Step: update-changelog
Update CHANGELOG.md with detailed release notes.

Add a new section after [Unreleased]:
```markdown
## [0.99.0] - YYYY-MM-DD

### Added
- **Feature name** (issue-id) - Description

### Changed
- **Change description** (issue-id)

### Fixed
- **Bug fix** (issue-id) - Description
```

Sort by importance, not chronologically.
Needs: update-release-notes

## Step: bump-version
Run the version bump script.

```bash
./scripts/bump-version.sh 0.99.0
```

This updates version in all files:
- cmd/bd/version.go
- .claude-plugin/*.json
- integrations/beads-mcp/pyproject.toml
- npm-package/package.json
- Hook templates

Needs: update-changelog

## Step: run-tests
Run tests and verify lint passes.

```bash
go test -short ./...
```

CI will run full lint, but fix any obvious issues first.
Needs: bump-version

## Step: commit-release
Commit the release changes.

```bash
git add -A
git commit -m "chore: bump version to v0.99.0"
```

Needs: run-tests

## Step: push-and-tag
Push commit and create release tag.

```bash
git push origin main
git tag v0.99.0
git push origin v0.99.0
```

This triggers GitHub Actions release workflow.
Needs: commit-release

## Step: wait-for-ci
Wait for GitHub Actions to complete.

Monitor: https://github.com/steveyegge/beads/actions

CI will:
- Build binaries via GoReleaser
- Create GitHub Release with assets
- Publish to npm (@beads/bd)
- Publish to PyPI (beads-mcp)
- Update Homebrew tap

Wait until all jobs succeed (~5-10 min).
Needs: push-and-tag

## Step: verify-release
Verify the release is complete.

```bash
# Check GitHub release
gh release view v0.99.0

# Check Homebrew
brew update && brew info steveyegge/beads/bd

# Check npm
npm view @beads/bd version

# Check PyPI
pip index versions beads-mcp
```

Needs: wait-for-ci

## Step: update-local
Update local installations.

```bash
# Upgrade Homebrew
brew upgrade steveyegge/beads/bd

# Or install from source
./scripts/bump-version.sh 0.99.0 --install

# Install MCP locally
pip install -e integrations/beads-mcp

# Restart daemons
pkill -f "bd daemon" || true
```

Verify: `bd --version` shows 0.99.0
Needs: verify-release

## Step: manual-publish
(Optional) Manual publish if CI failed.

```bash
# npm (requires npm login)
./scripts/bump-version.sh 0.99.0 --publish-npm

# PyPI (requires TWINE credentials)
./scripts/bump-version.sh 0.99.0 --publish-pypi

# Or both
./scripts/bump-version.sh 0.99.0 --publish-all
```

Only needed if CI publishing failed.
Needs: wait-for-ci


Release v0.34.0

Minor version release for beads v0.34.0. This bead serves as my persistent work assignment; the actual release steps are tracked in an attached wisp.


Merge: topaz-1767083484329

branch: polecat/topaz-1767083484329
target: main
source_issue: topaz-1767083484329
rig: beads


Verify npm package

Confirm npm package published.

```bash
npm show @beads/bd version
```

Should show 0.41.0.

Also check: https://www.npmjs.com/package/@beads/bd


Gate await fields cleared by --no-daemon CLI access (not multi-repo)


bd wisp create doesn't set Wisp flag on spawned issues

When running 'bd wisp create <proto>', the spawned issues don't have Wisp: true set. They show up in 'bd ready' and get synced to JSONL.

Example: gt-lqc6m and gt-wisp-ry9 are mol-deacon-patrol issues that should be wisps but have wisp: null.

This causes patrol cycles to pollute the issue database and show up as ready work.


Merge: quartz-1767082908528

branch: polecat/quartz-1767082908528
target: main
source_issue: quartz-1767082908528
rig: beads


Implement await type handlers (gh:run, gh:pr, timer, human, mail)

Implement condition checking for each await type.

## Handlers Needed
- gh:run:<id> - Check GitHub Actions run status via gh CLI
- gh:pr:<id> - Check PR merged/closed status via gh CLI
- timer:<duration> - Simple elapsed time check
- human:<prompt> - Check for human approval (via mail?)
- mail:<pattern> - Check for mail matching pattern

## Implementation Location
This is Deacon logic, so likely in Gas Town (gt) not beads.

## Interface
```go
type AwaitHandler interface {
    Check(awaitID string) (completed bool, result string, err error)
}
```


Update .claude-plugin/plugin.json to 0.30.4

Update version field in .claude-plugin/plugin.json:
```json
"version": "0.30.4"
```

```verify
jq -e '.version == "0.30.4"' .claude-plugin/plugin.json
```


Phase 1.2: Separate bdt executable - Initial structure

Create minimal bdt command structure completely separate from bd. Must not share code, config, or database.

## Subtasks
1. Create cmd/bdt/ directory with main.go
2. Implement bdt version, help, and status commands
3. Configure separate database location: $HOME/.bdt/ (not $HOME/.beads/)
4. Create separate issues file: issues.toon (not issues.jsonl)
5. Update build system:
   - Makefile: Add bdt target
   - .goreleaser.yml: Add bdt binary config

## Files to Create
- cmd/bdt/main.go - Entry point
- cmd/bdt/version.go - Version handling
- cmd/bdt/help.go - Help text (separate from bd)

## Success Criteria
- `make build` produces both `bd` and `bdt` executables
- `bdt version` shows distinct version output from bd
- `bdt --help` shows distinct help text
- bdt uses $HOME/.bdt/ directory (verify with `bdt info`)
- bd and bdt completely isolated (no shared imports beyond stdlib)


Restart running daemons

Kill and restart any running bd daemons to pick up new version: pkill -f 'bd daemon' && bd daemon --start


Add tests for delete operations

Core delete functionality including deleteViaDaemon, createTombstone, and deleteIssue functions have 0% coverage. These are critical for data integrity and need comprehensive test coverage.


Test comment display


GH#692: Code quality and refactoring improvements

Epic for implementing refactoring suggestions from GitHub issue #692 (rsnodgrass). These are code quality improvements that don't change functionality but improve maintainability, type safety, and performance.

Original issue: https://github.com/steveyegge/beads/issues/692

High priority items:
1. Replace map[string]interface{} with typed structs for JSON output
2. Adopt slices.SortFunc instead of sort.Slice (Go 1.21+)
3. Split large files (sync.go, init.go, show.go)
4. Introduce slog for structured logging in daemon

Lower priority:
5. Further CLI helper extraction
6. Preallocate slices in hot paths
7. Polish items (error wrapping, table-driven parsing)


Add orphan detection migration

Create migration to detect orphaned children in existing databases. Query: SELECT id FROM issues WHERE id LIKE '%.%' AND substr(id, 1, instr(id || '.', '.') - 1) NOT IN (SELECT id FROM issues). Log results, let user decide action (delete orphans or convert to top-level).


Commit the release changes.

Commit the release changes.

```bash
git add -A
git commit -m "chore: bump version to v0.37.0"
```

instantiated_from: bd-mol-xga
step: commit-release


Merge: jade-1767138549967

branch: polecat/jade-1767138549967
target: main
source_issue: jade-1767138549967
rig: beads


Verify PyPI package

Confirm PyPI package published.

```bash
pip index versions beads-mcp 2>/dev/null | head -3
```

Or check: https://pypi.org/project/beads-mcp/

Should show 0.39.0.


Verify npm package

Confirm npm package published.

```bash
npm show @beads/bd version
```

Should show 0.39.0.

Also check: https://www.npmjs.com/package/@beads/bd


getLocalSyncBranch silently ignores YAML parse errors

In autoimport.go:170-172, YAML parsing errors are silently ignored. If a user has malformed YAML in config.yaml, sync-branch will just silently be empty with no feedback.

Recommendation: Add debug logging since this function is only called during auto-import, and debugging silent failures is painful.

Add: debug.Logf("Warning: failed to parse config.yaml: %v", err)


Integrate migration detection into bd doctor

Multiple migration commands (migrate_hash_ids.go, migrate_issues.go, migrate_sync.go, migrate_tombstones.go, migrate.go) have TODOs suggesting integration into 'bd doctor' for automatic migration detection. This would allow bd doctor to detect when migrations are needed and suggest running them.

Files:
- cmd/bd/migrate_hash_ids.go:24
- cmd/bd/migrate_issues.go:15
- cmd/bd/migrate_sync.go:16
- cmd/bd/migrate_tombstones.go:72
- cmd/bd/migrate.go:22


Merge: bd-ot0w

branch: polecat/dementus
target: main
source_issue: bd-ot0w
rig: beads


Support external: prefix in blocked_by field

Allow blocked_by to include external project references:

```bash
bd update gt-xyz --blocked-by="external:beads:mol-run-assignee"
```

Syntax: `external:<project>:<capability>`
- project: name from external_projects config
- capability: matches provides:<capability> label in target project

Storage: Store as-is in blocked_by array. Resolution happens at query time.

Part of cross-project dependency system.
See: gastown/docs/cross-project-deps.md


Update CHANGELOG.md with release notes

Add meaningful release notes to CHANGELOG.md describing what changed in {{version}}


Add 'hooked' status for GUPP work assignment

## Summary

Separate the semantics of `pinned` (identity records) from work-on-hook (GUPP assignment).

**Current problem:** `pinned` is overloaded to mean both:
1. Agent identity beads (gt-mayor, gt-crew-gastown-max) - should never block
2. Work attached to an agent's hook - should block until closed

The blocking logic excludes `pinned` from blocking, which means work on hooks doesn't block its dependents.

## Semantic Split

| Status | Meaning | Blocks dependents? |
|--------|---------|-------------------|
| `pinned` | Domain table / identity record (agents, roles) | No |
| `hooked` | Work on an agent's hook (GUPP invoked) | Yes |

**Terminology:**
- **Pin** (verb): Establish a permanent identity record
- **Hook** (verb): Attach work to an agent's hook
- **Sling** (verb): The act of hooking work to an agent

## Lifecycles

**Molecule** (the work):
  open -> hooked -> closed

**Persistent agent** (Mayor, Witness, Crew):
  idle <-> working (cycles)
Agent bead stays pinned. Operational state derived from hook slot occupancy.

**Polecat** (ephemeral worker):
  spawned-with-work -> working -> despawning
Polecats never idle - spawned for one molecule, nuked after.

The `hooked` status belongs to the **molecule**, not the agent. Agent identity beads remain `pinned` throughout their existence.

## in_progress vs hooked

Both remain valid statuses with different semantics:
- `in_progress` = Soft claim, cooperative (humans juggling multiple issues)
- `hooked` = Hard claim, GUPP-driven (molecule on agent's hook)

Gas Town molecules use `hooked`. Humans/non-Gas Town workflows may use `in_progress`.

## Success Criteria

1. `hooked` is a valid status in beads schema
2. Blocking logic treats `hooked` as blocking (like `in_progress`)
3. gt sling sets status=hooked on the molecule (not pinned)
4. Existing pinned work items migrated to hooked where appropriate
5. Agent/role beads remain pinned and non-blocking


Enhancement: bd swarm status accepts swarm molecule ID

Currently `bd swarm status` only accepts an epic ID.

Would be more intuitive to also accept the swarm molecule ID and follow the relates-to link to find the epic:

```bash
bd swarm status bd-swarm-xyz  # Follow link to epic, show status
bd swarm status bd-epic-123   # Direct epic lookup (current behavior)
```

Detect by checking if the issue has mol_type=swarm.


HOP-compatible schema additions

Add optional fields to Beads schema to enable future HOP integration.
All fields are backwards-compatible (optional, omitted if empty).

## Reference
See ~/gt/docs/hop/BEADS-SCHEMA-CHANGES.md for full specification.

## P1 Changes (Must Have Before Launch)

### 1. EntityRef type
Structured entity reference that can become HOP URI:
```go
type EntityRef struct {
    Name     string // "polecat/Nux"
    Platform string // "gastown"
    Org      string // "steveyegge"
    ID       string // "polecat-nux"
}
```

### 2. creator field
Every issue tracks who created it (EntityRef).

### 3. assignee_ref field
Structured form alongside existing string assignee.

### 4. validations array
Track who validated work completion:
```go
type Validation struct {
    Validator *EntityRef
    Outcome   string    // accepted, rejected, revision_requested
    Timestamp time.Time
    Score     *float32  // Future
}
```

## P2 Changes (Should Have)

### 5. work_type field
"mutex" (default) or "open_competition"

### 6. crystallizes field
Boolean - does this work compound (true) or evaporate (false)?

### 7. cross_refs field
Array of URIs to beads in other repos:
- "beads://github/anthropics/claude-code/bd-xyz"

## P3 Changes (Nice to Have)

### 8. skill_vector placeholder
Reserved for future embeddings: []float32

## Implementation Notes
- All fields optional in JSONL serialization
- Empty/null fields omit from output
- No migration needed for existing data
- CLI additions: --creator, --validated-by filters

Scope reduced after review. P1 only: EntityRef type, creator field, validations array. Deferred: assignee_ref, work_type, crystallizes, cross_refs, skill_vector (YAGNI - semantics unclear, can add later when needed).


Test role bead


Mol Mall: Formula marketplace using GitHub as backend

Create a marketplace for sharing molecule formulas using GitHub repos as the hosting backend.

## Architecture Update (Dec 2025)

**Formulas are the sharing layer.** With ephemeral protos (bd-rciw), the architecture is:

```
Formulas ──cook──→ [ephemeral proto] ──pour/wisp──→ Mol/Wisp
    ↑                                                    │
    └────────────────── distill ─────────────────────────┘
```

- **Formulas**: JSON source files (.formula.json) - the thing you share
- **Protos**: Transient compilation artifacts - auto-deleted after use
- **Mols/Wisps**: Execution instances - not shared directly

**Key operations:**
- `bd distill <mol-id>` → Extract formula from completed work
- `bd mol publish <formula>` → Share to GitHub
- `bd mol install <url>` → Fetch from GitHub
- `bd pour <formula>` → Cook and spawn (proto is ephemeral)

## Why GitHub?

GitHub solves multiple problems at once:
- **Hosting**: Raw file URLs for formula.json
- **Versioning**: Git tags (v1.0.0, v1.2.0)
- **Auth**: GitHub tokens for private formulas
- **Discovery**: GitHub search, topics, stars
- **Collaboration**: PRs for contributions, issues for bugs
- **Organizations**: Natural scoping (@anthropic/, @gastown/)

## URL Scheme

```bash
# Direct GitHub URL
bd mol install github.com/anthropics/mol-code-review

# With version tag
bd mol install github.com/anthropics/mol-code-review@v1.2.0

# Shorthand (via registry lookup)
bd mol install @anthropic/mol-code-review
```

## Architecture

Each formula lives in its own repo (like Go modules):
```
github.com/anthropics/mol-code-review/
├── formula.json      # The formula
├── README.md         # Documentation
└── CHANGELOG.md      # Version history
```

## ID Namespace

| Entity | ID Format | Example |
|--------|-----------|---------|
| Formula (GitHub) | `github.com/org/repo` | `github.com/anthropics/mol-code-review` |
| Installed formula | `mol-name` | `mol-code-review` |
| Poured instance | `<db>-mol-xxx` | `bd-mol-b8c` |

Deferred - focusing on Christmas launch first


GH#519: bd sync fails when sync.branch is currently checked-out branch


GH#444: Fix inconsistent status naming in_progress vs in-progress

Documentation uses in-progress (hyphen) but code expects in_progress (underscore). Update all docs to use canonical in_progress. See GitHub issue #444.


bd swarm status command

Add bd swarm status to show swarm state derived from beads.

## Context
This is the key command that demonstrates 'discovery over tracking'.
Swarm status is COMPUTED from:
- Epic children statuses
- Dependency structure
- Issue assignments

NOT stored separately. If beads changes, status changes.

## Implementation
1. New command: bd swarm status <swarm-mol-id>
2. Find linked epic from swarm molecule
3. Query all children of epic
4. Compute and display:
   - Ready front (unblocked, open issues)
   - In progress (in_progress status)
   - Completed (closed)
   - Blocked (has unmet dependencies)
   - Progress percentage
   - Coordinator
   - Estimated remaining (based on avg session time)

## Output Format
Ready Front Analysis: gt-epic-xxx

Completed:     ✓ gt-001 (2h ago)
Active:        ⟳ gt-002 [nux], ⟳ gt-003 [toast]
Ready:         ○ gt-004, ○ gt-005
Blocked:       ◌ gt-006 (needs 004, 005)

Progress: 1/6 complete, 2/6 active (17%)

## Reference
~/gt/docs/swarm-architecture.md - 'Ready Front Visualization'

## Acceptance
- bd swarm status <mol> shows accurate state
- State reflects current beads (not cached)
- --json output for programmatic use


Gate await fields cleared by auto-flush/auto-import cycle

## Problem

When creating a gate with `--await` fields (e.g., `gh:run:123`), the await_type and await_id are initially stored correctly in the SQLite database. However, they get cleared (set to empty strings) during subsequent bd commands due to the auto-flush/auto-import cycle.

## Reproduction Steps

1. Create a gate with await:
   ```
   bd gate create --molecule test-mol --await gh:run:20517738002
   ```
   Output shows correct `await_type: gh:run, await_id: 20517738002`

2. Check database - fields are present

3. Run any bd command (e.g., `bd list`)

4. Check database again - await_type and await_id are now empty

## Root Cause

Gates are wisps (ephemeral issues). During the auto-flush cycle:
1. Auto-flush exports issues to JSONL (filtering out wisps)
2. Auto-import reads JSONL and updates DB rows
3. The update clears fields that weren't in the JSONL (including await fields)

## Workaround

Using `--no-auto-import --no-auto-flush` flags preserves the fields, but this isn't practical for normal use.

## Impact

GitHub gate evaluation (`bd gate eval`) cannot work because by the time eval runs, the await fields have been cleared.

## Suggested Fix

Either:
1. Don't clear await fields during auto-import if they weren't in the source
2. Store wisp fields separately from the main JSONL export
3. Include wisps in export but filter them at sync time


Commit release v{{version}}

Stage and commit the version bump:

```bash
git add cmd/bd/version.go cmd/bd/info.go CHANGELOG.md
git commit -m "release: v{{version}}"
```

Do NOT push yet - tag first.


mol-christmas-launch: 3-day execution plan

Christmas Launch Molecule - execute phases in order, survive restarts.

PIN THIS BEAD. Check progress each session start.

## Step: phase0-beads-foundation
Fix blocking issues before swarming:
1. Verify gastown beads schema works: bd list --status=open
2. Ensure bd mol bond exists (check bd-usro)
3. Verify bd-2vh3 (squash) is filed

## Step: phase1-polecat-loop
Serial work on polecat execution:
1. gt-9nf: Fresh polecats only
2. gt-975: Molecule execution support
3. gt-8v8: Refuse uncommitted work
Then swarm: gt-e1y, gt-f8v, gt-eu9
Needs: phase0-beads-foundation

## Step: phase2-refinery
Serial work on refinery autonomy:
1. gt-5gkd: Refinery CLAUDE.md
2. gt-bj6f: Refinery context in gt prime
3. gt-0qki: Refinery-Witness protocol
Needs: phase1-polecat-loop

## Step: phase3-deacon
Health monitoring infrastructure:
1. gt-5af.4: Simplify daemon
2. gt-5af.7: Crew session patterns
3. gt-976: Crew lifecycle
Needs: phase2-refinery

## Step: phase4-code-review
Self-improvement flywheel:
1. Define mol-code-review (gt-fjvo)
2. Test on open MRs
3. Integrate with Refinery
Needs: phase3-deacon

## Step: phase5-polish
Demo readiness:
1. gt-b2hj: Find orphaned work
2. Doctor checks
3. Clean up open MRs
Needs: phase4-code-review

## Step: verify-flywheel
Success criteria:
- gt spawn works with molecules
- Refinery processes MRs autonomously
- mol-code-review runs on a PR
- bd cleanup --ephemeral works
Needs: phase5-polish


Fix multi-round convergence for N-way collisions

**Summary:** Multi-round collision resolution was identified as a critical issue preventing complete synchronization across distributed clones. The problem stemmed from incomplete final pulls that didn't fully propagate all changes between system instances.

**Key Decisions:**
- Implement multi-round sync mechanism
- Ensure bounded convergence (≤N rounds)
- Guarantee idempotent import without data loss

**Resolution:** Developed a sync strategy that ensures all clones converge to the same complete set of issues, unblocking the bd-cbed9619 epic and improving distributed system reliability.


test hash length


(Optional) Manual publish if CI failed.

(Optional) Manual publish if CI failed.

```bash
# npm (requires npm login)
./scripts/bump-version.sh 0.37.0 --publish-npm

# PyPI (requires TWINE credentials)
./scripts/bump-version.sh 0.37.0 --publish-pypi

# Or both
./scripts/bump-version.sh 0.37.0 --publish-all
```

Only needed if CI publishing failed.

instantiated_from: bd-mol-xga
step: manual-publish


Code smell: 20+ global variables in main.go

main.go lines 63-103 have over 20 global variables managing command-line state, daemon connection, auto-flush, auto-import, and error handling.

**Globals include:**
dbPath, actor, store, jsonOutput, daemonStatus, daemonClient, noDaemon, rootCtx, rootCancel, autoFlushEnabled, flushMutex, storeMutex, storeActive, flushFailureCount, lastFlushError, flushManager, hookRunner, skipFinalFlush, autoImportEnabled, versionUpgradeDetected, previousVersion, upgradeAcknowledged

**Problem:**
- Global state makes testing difficult
- Race conditions possible between goroutines
- Hard to track which functions modify which globals

**Acceptance Criteria:**
- [ ] Create CommandContext struct to hold runtime state
- [ ] Pass context through command execution
- [ ] Reduce global count to essential minimum
- [ ] Tests pass


Test Second Parent


Push to main

Push the release commit to origin.

```bash
git push origin main
```

If rejected, someone else pushed. Pull, rebase, try again.


Work on beads-2nh: Fix gt spawn --issue to find issues in...

Work on beads-2nh: Fix gt spawn --issue to find issues in rig's beads database. When done, submit MR (not PR) to integration branch for Refinery.


Create release tag

Create annotated git tag.

```bash
git tag -a v0.41.0 -m "Release v0.41.0"
```

Verify: `git tag -l | tail -5`


Deacon Patrol

Mayor's daemon patrol loop for handling callbacks, health checks, and cleanup.


Add covering index (label, issue_id) for label queries

GetIssuesByLabel joins labels table but requires table lookup after using idx_labels_label.

**Query (labels.go:165):**
```sql
SELECT ... FROM issues i
JOIN labels l ON i.id = l.issue_id
WHERE l.label = ?
```

**Problem:** Current idx_labels_label index doesn't cover issue_id, requiring row lookup.

**Solution:** Add migration:
```sql
CREATE INDEX IF NOT EXISTS idx_labels_label_issue ON labels(label, issue_id);
```

This is a covering index - query can be satisfied entirely from the index without touching the labels table rows.


Merge: onyx-1767083477016

branch: polecat/onyx-1767083477016
target: main
source_issue: onyx-1767083477016
rig: beads


Merge: bd-au0.7

branch: polecat/dementus
target: main
source_issue: bd-au0.7
rig: beads


Review changes since last release

Understand what's being released.

```bash
git log $(git describe --tags --abbrev=0)..HEAD --oneline
```

Categorize changes:
- Features (feat:)
- Fixes (fix:)
- Breaking changes
- Documentation


CLI API Audit for OSS Launch

Comprehensive CLI API audit before OSS launch.

## Tasks
1. Review gt command groupings - propose consolidation
2. Review bd command groupings
3. Document gt vs bd ownership boundaries
4. Identify naming inconsistencies
5. Document flag vs subcommand criteria

## Context
- Pre-OSS launch cleanup
- Goal: clean, consistent, discoverable CLI surface


Test stdin body-file


Give --all flag actual meaning in bd list

The --all flag exists but is currently a no-op ('flag provided for CLI familiarity'). Once we change the default to non-closed, --all should override to show all issues including closed.

This provides backwards compatibility for scripts that depend on seeing all issues.

## Implementation Plan

### Code Changes (cmd/bd/list.go)

1. **Update --all flag handling** (~line 889):
```go
// Currently: listCmd.Flags().Bool("all", false, "Show all issues (default behavior; flag provided for CLI familiarity)")
// Change to:
listCmd.Flags().Bool("all", false, "Show all issues including closed (overrides default filter)")
```

2. **Check for --all in Run function** (before applying default filter):
```go
allFlag, _ := cmd.Flags().GetBool("all")
if status == "" && !allFlag {
    // Apply default non-closed filter
    filter.ExcludeStatus = []types.Status{"closed"}
}
// If --all is set, no ExcludeStatus applied = show everything
```

### Testing
- `bd list --all` shows all issues including closed
- `bd list` shows non-closed (from bd-mypl)
- `bd list --all --status=open` - --all is ignored when explicit status given

### Documentation
- Update --help text
- Add to migration guide: "Use --all for previous default behavior"


Push release v{{version}} to remote

Push the commit and tag:

```bash
git push && git push --tags
```

Verify on GitHub that the tag appears in releases.


Exclude pinned issues from bd blocked

Update bd blocked to exclude pinned issues. Pinned issues are context markers and should not appear in the blocked work list.


mol-beads-release

Release checklist for beads version 0.37.0.

This molecule ensures all release steps are completed properly.
Variable: 0.37.0 - target version (e.g., 0.35.0)

## Step: update-release-notes
Update cmd/bd/info.go with release notes for 0.37.0.

Add a new VersionChange entry at the top of versionChanges slice:
```go
{
    Version: "0.37.0",
    Date:    "YYYY-MM-DD",
    Changes: []string{
        "NEW: Feature description",
        "FIX: Bug fix description",
        "IMPROVED: Enhancement description",
    },
},
```

Run `git log --oneline v<previous>..HEAD` to see what changed.

## Step: update-changelog
Update CHANGELOG.md with detailed release notes.

Add a new section after [Unreleased]:
```markdown
## [0.37.0] - YYYY-MM-DD

### Added
- **Feature name** (issue-id) - Description

### Changed
- **Change description** (issue-id)

### Fixed
- **Bug fix** (issue-id) - Description
```

Sort by importance, not chronologically.
Needs: update-release-notes

## Step: bump-version
Run the version bump script.

```bash
./scripts/bump-version.sh 0.37.0
```

This updates version in all files:
- cmd/bd/version.go
- .claude-plugin/*.json
- integrations/beads-mcp/pyproject.toml
- npm-package/package.json
- Hook templates

Needs: update-changelog

## Step: run-tests
Run tests and verify lint passes.

```bash
go test -short ./...
```

CI will run full lint, but fix any obvious issues first.
Needs: bump-version

## Step: commit-release
Commit the release changes.

```bash
git add -A
git commit -m "chore: bump version to v0.37.0"
```

Needs: run-tests

## Step: push-and-tag
Push commit and create release tag.

```bash
git push origin main
git tag v0.37.0
git push origin v0.37.0
```

This triggers GitHub Actions release workflow.
Needs: commit-release

## Step: wait-for-ci
Wait for GitHub Actions to complete.

Monitor: https://github.com/steveyegge/beads/actions

CI will:
- Build binaries via GoReleaser
- Create GitHub Release with assets
- Publish to npm (@beads/bd)
- Publish to PyPI (beads-mcp)
- Update Homebrew tap

Wait until all jobs succeed (~5-10 min).
Needs: push-and-tag

## Step: verify-release
Verify the release is complete.

```bash
# Check GitHub release
gh release view v0.37.0

# Check Homebrew
brew update && brew info steveyegge/beads/bd

# Check npm
npm view @beads/bd version

# Check PyPI
pip index versions beads-mcp
```

Needs: wait-for-ci

## Step: update-local
Update local installations.

```bash
# Upgrade Homebrew
brew upgrade steveyegge/beads/bd

# Or install from source
./scripts/bump-version.sh 0.37.0 --install

# Install MCP locally
pip install -e integrations/beads-mcp

# Restart daemons
pkill -f "bd daemon" || true
```

Verify: `bd --version` shows 0.37.0
Needs: verify-release

## Step: manual-publish
(Optional) Manual publish if CI failed.

```bash
# npm (requires npm login)
./scripts/bump-version.sh 0.37.0 --publish-npm

# PyPI (requires TWINE credentials)
./scripts/bump-version.sh 0.37.0 --publish-pypi

# Or both
./scripts/bump-version.sh 0.37.0 --publish-all
```

Only needed if CI publishing failed.
Needs: wait-for-ci


Tier 1: Ephemeral repo routing

Add routing.ephemeral config option to route ephemeral=true issues to separate location.

## Changes Required

1. Add `routing.ephemeral` config option (default: empty = disabled)
2. Update routing logic in `determineRepo()` to check ephemeral flag
3. Update `bd create` to respect ephemeral routing
4. Update import/export for multi-location support
5. Ephemeral repo can be:
   - Separate git repo (~/.beads-ephemeral)
   - Non-git directory (just filesystem)
   - Same repo, different branch (future)

## Config

```bash
bd config set routing.ephemeral "~/.beads-ephemeral"
```

## Acceptance Criteria

- `bd create "test" --ephemeral` creates in ephemeral repo when configured
- `bd list` shows issues from both repos
- Ephemeral repo never synced to remote


Improve version bump molecule with missing steps

During v0.32.1 release, discovered missing steps in the release molecule:

**Missing from molecule:**
1. Rebuild ~/go/bin/bd (only did ~/.local/bin/bd)
2. Install beads-mcp from local source: `uv tool install --reinstall ./integrations/beads-mcp`
3. Restart daemons with `bd daemons killall`
4. (Optional) Publish beads-mcp to PyPI

**Current molecule steps (bd-6s61):**
1. Update CHANGELOG.md
2. Update info.go versionChanges
3. Run bump-version.sh
4. Run tests and linting
5. Update local installation
6. Commit and push release
7. Wait for CI
8. Verify release artifacts

**Proposed additions:**
- After "Update local installation": rebuild BOTH ~/.local/bin/bd AND ~/go/bin/bd
- Add: "Install beads-mcp from source" step
- Add: "Restart daemons" step
- Add: "Verify all versions match" step that checks all artifacts

**Also learned:**
- Must run from mayor/rig to avoid git conflicts with bd sync (already documented in bump-version.sh)

CORRECTION: npm publishing IS automated and working!

**Package naming:**
- OLD: `beads` (npm) - deprecated, stuck at 0.2.1
- CURRENT: `@beads/bd` (npm) - scoped package, auto-published by CI

**How it works:**
- CI uses OIDC trusted publishing (no token needed)
- Workflow: .github/workflows/release.yml → publish-npm job
- Permissions: `id-token: write` enables GitHub OIDC
- To install: `npm install -g @beads/bd` (not `npm install beads`)

**All publishing is automated on tag push:**
1. GitHub Release - goreleaser ✓
2. PyPI - publish-pypi job ✓
3. Homebrew - update-homebrew job ✓
4. npm (@beads/bd) - publish-npm job ✓

**Remaining molecule improvements (local steps only):**
- Rebuild BOTH ~/.local/bin/bd AND ~/go/bin/bd
- Install beads-mcp from source: `uv tool install --reinstall ./integrations/beads-mcp`
- Restart daemons: `bd daemons killall`
- Run from mayor/rig to avoid git conflicts with bd sync
- Final verification step to check all local versions match


bd list --parent: filter by parent issue

Add --parent flag to bd list to filter issues by parent.

Example:
```bash
bd list --parent=gt-h5n --status=open
```

Would show all open children of gt-h5n.

Useful for:
- Checking epic progress
- Finding swarmable work within an epic
- Molecule step listing


Auto-repair stale merge driver configs with invalid placeholders

Old bd versions (<0.24.0) installed merge driver with invalid placeholders %L %R instead of %A %B. Add detection to bd doctor --fix: check if git config merge.beads.driver contains %L or %R, auto-repair to 'bd merge %A %O %A %B'. One-time migration for users who initialized with old versions.


Merge: bd-bqcc

branch: polecat/capable
target: main
source_issue: bd-bqcc
rig: beads


Code Review Followup Summary: PR #481 + PR #551

## Merged PRs Summary

### PR #551: Persist close_reason to issues table
- ✅ Merged successfully
- ✅ Bug fix: close_reason now persisted in database column (not just events table)
- ✅ Comprehensive test coverage added
- ✅ Handles reopen case (clearing close_reason)

**Followup Issues Filed:**
- bd-lxzx: Document close_reason in JSONL export format
- bd-077e: Update CLI documentation for close_reason field

---

### PR #481: Context Engineering Optimizations (80-90% context reduction)
- ✅ Merged successfully
- ✅ Lazy tool discovery: discover_tools() + get_tool_info()
- ✅ Minimal issue models: IssueMinimal (~80% smaller than full Issue)
- ✅ Result compaction: Auto-compacts results >20 items
- ✅ All 28 tests passing
- ⚠ Breaking change: ready() and list() return type changed

**Followup Issues Filed:**
- bd-b318: Add integration tests for CompactedResult
- bd-4u2b: Make compaction settings configurable (THRESHOLD, PREVIEW_COUNT)
- bd-2kf8: Document CompactedResult response format in CONTEXT_ENGINEERING.md
- bd-pdr2: Document backwards compatibility considerations

---

## Overall Assessment

Both PRs are production-ready with solid implementations. All critical functionality works and tests pass. Followup issues focus on:
1. Documentation improvements (5 issues)
2. Integration test coverage (1 issue)
3. Configuration flexibility (1 issue)
4. Backwards compatibility guidance (1 issue)

No critical bugs or design issues found.

## Review Completed By
Code review process completed. Issues auto-created for tracking improvements.


Review PR #512: clarify bd ready docs

Review and merge PR #512 from aspiers. This PR clarifies what bd ready does after git pull in README.md. Simple 1-line change. URL: https://github.com/anthropics/beads/pull/512


Merge: bd-05a8

branch: polecat/valkyrie
target: main
source_issue: bd-05a8
rig: beads


Merge: garnet-1767138539231

branch: polecat/garnet-1767138539231
target: main
source_issue: garnet-1767138539231
rig: beads


Merge: quartz-1767106247671

branch: polecat/quartz-1767106247671
target: main
source_issue: quartz-1767106247671
rig: beads


Release v0.30.4

## Version Bump Workflow

Coordinating release from 0.30.3 to 0.30.4.

### Components Updated
- Go CLI (cmd/bd/version.go)
- Claude Plugin (.claude-plugin/*.json)
- MCP Server (integrations/beads-mcp/)
- npm Package (npm-package/package.json)
- Git hooks (cmd/bd/templates/hooks/)

### Release Channels
- GitHub Releases (GoReleaser)
- PyPI (beads-mcp)
- npm (@beads/cli)
- Homebrew (homebrew-beads tap)


Merge: bd-u2sc.3

branch: polecat/Modular
target: main
source_issue: bd-u2sc.3
rig: beads


Fix G104 errors unhandled in internal/storage/sqlite/queries.go:1181

Linting issue: G104: Errors unhandled (gosec) at internal/storage/sqlite/queries.go:1181:4. Error: rows.Close()


Beads commands operate on stale database without warning

All beads read operations should validate database is in sync with JSONL before proceeding.

**Current Behavior:**
- Commands can query/read from stale database
- Only mutation operations (like 'bd sync') check if JSONL is newer
- User gets incorrect results without realizing database is out of sync

**Expected Behavior:**
- All beads commands should have pre-flight check for database freshness
- If JSONL is newer than database, refuse to operate with error: "Database out of sync. Run 'bd import' first."
- Same safety check that exists for 'bd sync' should apply to ALL operations

**Impact:**
- Users make decisions based on incomplete/outdated data
- Silent failures lead to confusion (e.g., thinking issues don't exist when they do)
- Similar to running git commands on stale repo without being warned to pull

**Example:**
- Searched for bd-g9eu issue file: not found
- Issue exists in .beads/issues.jsonl (in git)
- Database was stale, but no warning was given
- Led to incorrect conclusion that issue was already closed/deleted

## Implementation Complete

**Phase 1: Created staleness check (cmd/bd/staleness.go)**
- ensureDatabaseFresh() function checks JSONL mtime vs last_import_time
- Returns error with helpful message when database is stale
- Auto-skips in daemon mode (daemon has auto-import)

**Phase 2: Added to all read commands**
- list, show, ready, status, stale, info, duplicates, validate
- Check runs before database queries in direct mode
- Daemon mode already protected via checkAndAutoImportIfStale()

**Phase 3: Code Review Findings**
See follow-up issues:
- bd-XXXX: Add warning when staleness check errors
- bd-YYYY: Improve CheckStaleness error handling
- bd-ZZZZ: Refactor redundant daemon checks (low priority)

**Testing:**
- Build successful: go build ./cmd/bd
- Binary works: ./bd --version
- Ready for manual testing

**Next Steps:**
1. Test with stale database scenario
2. Implement review improvements
3. Close issue when tests pass


Add tests for daemon functionality

Critical daemon functions have 0% test coverage including daemon lifecycle, health checks, and RPC server functionality. These are essential for system reliability and need comprehensive test coverage.


Split large cmd/bd files into logical modules for maintainability.

## Current State
| File | Lines | Status |
|------|-------|--------|
| sync.go | 2203 | Too large |
| init.go | 1742 | Too large |
| show.go | 1419 | Too large |
| compact.go | 1190 | Borderline |

## Proposed Splits

### 1. sync.go (2203 lines) → 4 files

**sync.go** (~500 lines) - Main command and coordination
```go
var syncCmd = &cobra.Command{...}
func init() {...}
func doSync(...) {...}
```

**sync_export.go** (~400 lines) - Export operations
```go
func exportToJSONL(...)
func markDirtyAndScheduleFlush(...)
func flushPendingChanges(...)
```

**sync_import.go** (~500 lines) - Import operations
```go
func importFromJSONL(...)
func handleImportConflicts(...)
func mergeImportedIssues(...)
```

**sync_branch.go** (~400 lines) - Git branch operations
```go
func commitToSyncBranch(...)
func pullFromSyncBranch(...)
func handleSyncBranchDivergence(...)
```

### 2. init.go (1742 lines) → 3 files

**init.go** (~400 lines) - Main init command
```go
var initCmd = &cobra.Command{...}
func runInit(...)
func determinePrefix(...)
```

**init_wizard.go** (~500 lines) - Interactive setup
```go
func runContributorWizard(...)
func runTeamWizard(...)
func promptForConfig(...)
```

**init_hooks.go** (~400 lines) - Git hooks setup
```go
func installGitHooks(...)
func configureAutosync(...)
func setupMergeDriver(...)
```

### 3. show.go (1419 lines) → 3 files

**show.go** (~400 lines) - Main show command
```go
var showCmd = &cobra.Command{...}
func showIssue(...)
func showMultipleIssues(...)
```

**show_format.go** (~400 lines) - Output formatting
```go
func formatIssueText(...)
func formatIssueMarkdown(...)
func formatDependencyTree(...)
```

**show_threads.go** (~300 lines) - Thread/conversation display
```go
func showThread(...)
func formatThreadMessages(...)
```

### 4. compact.go (1190 lines) → 2 files

**compact.go** (~600 lines) - Main compact command
```go
var compactCmd = &cobra.Command{...}
func runCompact(...)
```

**compact_tiers.go** (~400 lines) - Tier-specific logic
```go
func compactTier1(...)
func compactTier2(...)
func squashWisps(...)
```

## Implementation Steps

1. **Start with sync.go** (largest file)
2. **Create new files** with same package declaration
3. **Move functions** maintaining related code together
4. **Update any file-local variables** that need to be shared
5. **Run tests** after each split:
   ```bash
   go test -short ./cmd/bd/...
   ```

## File Organization After Split
```
cmd/bd/
├── sync.go           (~500 lines)
├── sync_export.go    (~400 lines)
├── sync_import.go    (~500 lines)
├── sync_branch.go    (~400 lines)
├── init.go           (~400 lines)
├── init_wizard.go    (~500 lines)
├── init_hooks.go     (~400 lines)
├── show.go           (~400 lines)
├── show_format.go    (~400 lines)
├── show_threads.go   (~300 lines)
├── compact.go        (~600 lines)
└── compact_tiers.go  (~400 lines)
```

## Success Criteria
- No file > 600 lines
- All tests pass
- Related code stays together
- Clear file naming indicates purpose


Merge: bd-14ie

branch: polecat/toast
target: main
source_issue: bd-14ie
rig: beads


Improve test coverage for internal/rpc (47.5% → 60%)

The RPC package has only 47.5% test coverage. RPC is the communication layer for daemon operations.

Current coverage: 47.5%
Target coverage: 60%


Fix unparam unused parameter in cmd/bd/doctor.go:1879

Linting issue: checkGitHooks - path is unused (unparam) at cmd/bd/doctor.go:1879:20. Error: func checkGitHooks(path string) doctorCheck {


Distill: promote ad-hoc epic to proto

Extract a reusable proto from an existing ad-hoc epic.

COMMAND: bd mol distill <epic-id> [--as <proto-name>]

BEHAVIOR:
- Clone the epic and all children as a new proto
- Set is_template=true on all cloned issues
- Replace concrete values with {{variable}} placeholders (interactive or --var flags)
- Add to proto catalog

FLAGS:
- --as NAME: Custom proto ID (default: proto-<epic-id>)
- --var field=placeholder: Replace value with variable placeholder
- --interactive: Prompt for each field that looks parameterizable
- --dry-run: Preview the proto structure

EXAMPLE:
  bd mol distill bd-o5xe --as proto-feature-workflow \
    --var title=feature_name \
    --var assignee=worker

USE CASES:
- Team develops good workflow organically, wants to reuse it
- Capture tribal knowledge as executable templates
- Create starting point for similar future work

The reverse of spawn: instead of proto → molecule, it's molecule → proto.


Push release tag

Push the version tag to trigger CI release.

```bash
git push origin v0.39.0
```

This triggers GitHub Actions to build artifacts and publish.


Graph Link: duplicates for deduplication

Implement duplicates link type for marking issues as duplicates.

New command:
- bd duplicate <id> --of <canonical> - marks id as duplicate of canonical
- Auto-closes the duplicate issue

Query support:
- bd show <id> shows 'Duplicate of: <canonical>'
- bd list --duplicates shows all duplicate pairs

Storage:
- duplicates column pointing to canonical issue ID

Essential for large issue databases with many similar reports.


Investigate Claude Code crash logging improvements

## Problem

Claude Code doesn't leave useful crash logs when it terminates unexpectedly. Investigation of a crash on 2025-12-26 showed:

- Debug logs in ~/.claude/debug/ just stop mid-stream with no error/exit message
- No signal handlers appear to log SIGTERM/SIGKILL/SIGINT
- No dedicated crash log file exists
- When Node.js crashes hard or gets killed, there's no record of why

## What we found

- Session debug log (02080b1a-...) stopped at 22:58:40 UTC mid-operation
- No 'exit', 'error', 'crash', 'signal' entries at end of file
- macOS DiagnosticReports showed Chrome crashes but no Node crashes
- System logs showed no relevant kill/OOM events

## Desired improvements

1. Exit handlers that log graceful shutdown
2. Signal handlers that log SIGTERM/SIGINT before exiting
3. A dedicated crash log or at least a 'last known state' file
4. Possibly CLI flags to enable verbose crash debugging

## Investigation paths

- Check if Claude Code has --debug or similar flags
- Look at Node.js crash handling best practices
- Consider if we can wrap claude invocations to capture crashes

## Related

This came up while investigating why a crew worker session crashed at end of a code review task.


Documentation for messaging and graph links

Document all new features.

Files to update:
- README.md - brief mention of messaging capability
- AGENTS.md - update for AI agents using bd mail
- docs/messaging.md (new) - full messaging reference
- docs/graph-links.md (new) - graph link reference
- CHANGELOG.md - v0.30.2 release notes

Topics to cover:
- Mail commands with examples
- Graph link types and use cases
- Identity configuration
- Hooks setup for notifications
- Migration notes


Implement conditional bond type for mol bond

The mol bond command accepts 'conditional' as a bond type but doesn't implement any conditional-specific behavior. It currently behaves identically to 'parallel'.

**Expected behavior:**
Conditional bonds should mean 'B runs only if A fails' per the help text (mol.go:318).

**Implementation needed:**
- Add failure-condition dependency handling
- Possibly new dependency type or status-based blocking
- Update bondProtoProto, bondProtoMol, bondMolMol to handle conditional

**Alternative:**
Remove 'conditional' from valid bond types until implemented.

This is new functionality, not a regression.


Add stale molecule check to bd doctor

Extend bd doctor to detect stale molecules.

**New check:**
- Name: 'Stale Molecules'
- Category: Workflow
- Severity: Warning (don't fail overall check)

**Detection:**
Reuse logic from bd mol stale command:
- Find mols where Completed >= Total but root is open
- Filter to orphaned (not assigned, not pinned)
- Extra weight if blocking other work

**Output:**
```
⚠ Stale Molecules
  Found 2 complete-but-unclosed molecules:
  - bd-xyz: Version bump v0.36.0 (blocking 1 issue)
  - bd-uvw: Old patrol (not blocking)
  Fix: bd close <id> or bd mol squash <id>
```

**--fix behavior:**
- Auto-close stale mols (with reason 'Auto-closed by bd doctor')
- Or prompt interactively with -i flag

Depends on: bd mol stale command


Enrich MutationEvent with title and assignee

Current MutationEvent only has IssueID, no context. Add Title and Assignee fields so activity feeds can display meaningful info without extra lookups. Emit these fields when creating mutation events in server_core.go.


Update Homebrew formula

./scripts/update-homebrew.sh {{version}}


Merge: bd-au0.5

branch: polecat/Searcher
target: main
source_issue: bd-au0.5
rig: beads


Document labels-as-state pattern for operational state

Labels on role beads cache current operational state for fast queries.

Convention: <dimension>:<value>
- patrol:muted / patrol:active
- mode:degraded / mode:normal
- status:idle / status:working

Pattern:
1. Create event bead (full context, immutable history)
2. Update role bead labels (current state cache)

No schema change needed - labels already exist. This task:
- Document the convention in beads docs
- Consider helper: bd state <role> <dimension> (queries label)
- Consider helper: bd set-state <role> <dimension>=<value> (creates event + updates label)

Events are source of truth. Labels are cache.


Merge: bd-t4sb

branch: polecat/capable
target: main
source_issue: bd-t4sb
rig: beads


Version Bump: {{version}}

Release checklist for version {{version}}. This molecule ensures all release steps are completed properly.


Fix daemon/direct mode inconsistency in relate and duplicate commands

The relate.go and duplicate.go commands have inconsistent daemon/direct mode handling:

When daemonClient is connected, they resolve IDs via RPC but then perform updates directly via store.UpdateIssue(), bypassing the daemon.

Affected locations:
- relate.go:125-139 (runRelate update)
- relate.go:235-246 (runUnrelate update)
- duplicate.go:120 (runDuplicate update)
- duplicate.go:207 (runSupersede update)

Should either use RPC for updates when daemon is running, or document why direct access is intentional.


Add integration tests for bd reset command

End-to-end integration tests for the reset command.

## Test Scenarios

### Basic reset
1. Init beads, create some issues
2. Run bd reset --force
3. Verify .beads/ is fresh, issues gone

### Hard reset
1. Init beads, create issues, commit
2. Run bd reset --hard --force
3. Verify git history has reset commits

### Backup functionality
1. Init beads, create issues
2. Run bd reset --backup --force
3. Verify backup exists with correct contents
4. Verify main .beads/ is reset

### Dry run
1. Init beads, create issues
2. Run bd reset --dry-run
3. Verify nothing changed

### Confirmation prompt
1. Init beads
2. Run bd reset (no --force)
3. Verify prompts for confirmation
4. Test both y and n responses

## Location
tests/integration/reset_test.go or similar


Release v0.33.2

Version bump workflow for beads release 0.33.2.

## Variables
- `0.33.2` - The new version number (e.g., 0.31.0)
- `2025-12-21` - Release date (YYYY-MM-DD format)

## Workflow Steps
1. Kill running daemons
2. Run tests and linting
3. Bump version in all files (10 files total)
4. Update cmd/bd/info.go with release notes
5. Commit and push version bump
6. Create and push git tag
7. Update Homebrew formula
8. Upgrade local Homebrew installation
9. Verify installation

## Files Updated by bump-version.sh
- cmd/bd/version.go
- .claude-plugin/plugin.json
- .claude-plugin/marketplace.json
- integrations/beads-mcp/pyproject.toml
- integrations/beads-mcp/src/beads_mcp/__init__.py
- README.md
- npm-package/package.json
- cmd/bd/templates/hooks/* (4 files)
- CHANGELOG.md

## Manual Step Required
- cmd/bd/info.go - Add versionChanges entry with release notes


Update local installation

Update local bd to the new version.

Option 1 - Homebrew:
```bash
brew upgrade bd
```

Option 2 - Install script:
```bash
curl -fsSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
```

Verify:
```bash
bd --version
```

Should show 0.99.0-test.


doctor --fix should export when DB has more issues than JSONL

When 'bd doctor' detects a count mismatch (DB has more issues than JSONL), it currently recommends 'bd sync --import-only', which imports JSONL into DB. But JSONL is the source of truth, not the DB.

**Current behavior:**
- Doctor detects: DB has 355 issues, JSONL has 292
- Recommends: 'bd sync --import-only'
- User runs it: Returns '0 created, 0 updated' (no-op, because JSONL hasn't changed)
- User is stuck

**Root cause:**
The doctor fix is one-directional (JSONL→DB) when it should be bidirectional. If DB has MORE issues, they haven't been exported yet - the fix should be 'bd export' (DB→JSONL), not import.

**Desired fix:**
In fix.DBJSONLSync(), detect which has more data:
- If DB > JSONL: Run 'bd export' to sync JSONL (since DB is the working copy)
- If JSONL > DB: Run 'bd sync --import-only' to import (JSONL is source of truth)
- If equal but timestamps differ: Detect based on file mtime

This makes 'bd doctor --fix' actually fix the problem instead of being a no-op.


Test and document molecular chemistry commands

## Context

Implemented the molecular chemistry UX commands per the design docs:
- gastown/mayor/rig/docs/molecular-chemistry.md
- gastown/mayor/rig/docs/chemistry-design-changes.md

Commit: cadf798b

## New Commands to Test

| Command | Purpose |
|---------|---------|
| `bd pour <proto>` | Instantiate proto as persistent mol |
| `bd wisp create <proto>` | Instantiate proto as ephemeral wisp |
| `bd hook [--agent]` | Inspect what's on an agent's hook |

## Enhanced Commands to Test

| Command | Changes |
|---------|---------|
| `bd mol spawn --pour` | New flag, `--persistent` deprecated |
| `bd mol bond --pour` | Force liquid phase on wisp target |
| `bd pin --for <agent> --start` | Chemistry workflow support |

## Test Scenarios

1. **bd pour**: Create persistent mol from a proto
   - Verify creates in .beads/ (not .beads-wisp/)
   - Verify variable substitution works
   - Verify --dry-run works

2. **bd wisp create**: Create ephemeral wisp from proto
   - Verify creates in .beads-wisp/
   - Verify bd wisp list shows it
   - Verify bd mol squash works
   - Verify bd mol burn works

3. **bd hook**: Inspect pinned work
   - Pin something, verify bd hook shows it
   - Test --agent flag
   - Test --json output

4. **bd pin --for**: Assign work to agent
   - Verify sets pinned=true
   - Verify sets assignee
   - Verify --start sets status=in_progress

5. **bd mol bond --pour**: Force liquid on wisp target
   - Bond a proto to a wisp with --pour
   - Verify spawned issues are in .beads/

## Documentation

- Update CLAUDE.md with new commands
- Add examples to --help output (already done)
- Consider adding to docs/CLI_REFERENCE.md

## Code Review

- Check for edge cases
- Verify error messages are helpful
- Ensure --json output is consistent


Fix N+1 query pattern in swarm status blocked check

In getSwarmStatus, when checking if an issue is blocked, we query each dependency individually with GetIssue. With 100 issues and 5 deps each, thats 500 extra queries. Fix: Build a status map upfront from the already-fetched childIssues slice. File: cmd/bd/swarm.go:706-710


Consolidate git context into single cached struct

Code review finding from bd-7di fix.

Currently there are 3 separate caches:
- isWorktreeOnce/isWorktreeResult
- mainRepoRootOnce/mainRepoRootResult/mainRepoRootErr
- repoRootOnce/repoRootResult

These have redundant git calls - e.g. both isWorktreeUncached() and getMainRepoRootUncached() call getGitDirNoError("--git-common-dir").

Could consolidate into a single cached struct:
```go
type gitContext struct {
    gitDir     string
    commonDir  string
    repoRoot   string
    isWorktree bool
}
```

This would reduce git calls further and simplify ResetCaches().

File: internal/git/gitdir.go


Technical debt: Scattered TODOs should be tracked as issues

Multiple TODO comments exist in the codebase that should be tracked as proper issues:

1. cmd/bd/migrate_hash_ids.go:24 - 'Consider integrating into bd doctor migration detection'
2. cmd/bd/migrate_tombstones.go:72 - Same
3. cmd/bd/migrate_sync.go:16 - Same
4. cmd/bd/migrate_issues.go:15 - Same
5. cmd/bd/create.go:164 - 'Switch to target repo for multi-repo support'
6. cmd/bd/create.go:208 - 'Add RPC method to get config in daemon mode'
7. cmd/bd/daemon_logger.go:131 - 'Remove this once all callers are updated'
8. cmd/bd/mol_stale.go:67 - 'Add RPC endpoint for stale check'
9. cmd/bd/sync_test.go:444 - 'Refactor to use direct import logic'
10. cmd/bd/jira.go:633 - 'In a full implementation, fetch Jira issue and compare timestamps'
11. internal/formula/types.go:170,174,179,186,210 - Multiple 'Not yet implemented' TODOs
12. internal/importer/importer_test.go:1010 - 'Test hangs due to database deadlock'

Consider:
1. Running 'grep -r TODO' periodically to find new ones
2. Adding a lint rule to discourage inline TODOs
3. Converting each to a bd issue with proper tracking

Location: Various files across codebase


Relocate quickstart to bd help quickstart or docs

## Task
Move `bd quickstart` → `bd help quickstart` or convert to documentation.

## Options

### Option A: Move to bd help quickstart
- Create a custom help topic
- Cobra supports additional help topics

### Option B: Convert to docs only
- Keep content in docs/QUICKSTART.md
- Remove the command entirely
- Update references to point to docs

## Recommendation
Option B - quickstart is essentially documentation, not a functional command.
The command just prints formatted text that could live in docs.

## Implementation (Option B)
1. Ensure docs/QUICKSTART.md has equivalent content
2. Add hidden alias that prints "See docs/QUICKSTART.md or bd help"
3. Update all references:
   - README.md
   - docs/INSTALLING.md
   - docs/EXTENDING.md
   - npm-package/INTEGRATION_GUIDE.md
   - .beads/README.md

## Files to modify
- cmd/bd/quickstart.go (hide or remove)
- Multiple docs (update references)


Integrate detect-pollution into bd doctor

## Task
Move `bd detect-pollution` → `bd doctor --check=pollution`

## Current state
- detect-pollution already shows deprecation hint pointing to doctor
- Doctor command exists with multiple checks

## Implementation

### 1. Update doctor.go
- Add pollution check to the doctor checks
- Add `--check=pollution` flag option
- Integrate detect-pollution logic

### 2. Update detect_pollution.go
- Mark as hidden (deprecated)
- Forward to doctor --check=pollution
- Keep for one release cycle

### 3. Update docs
- Remove detect-pollution from any command lists
- Update doctor docs to include pollution check

## Files to modify
- cmd/bd/doctor.go
- cmd/bd/detect_pollution.go


Update Homebrew formula

Update the Homebrew tap with new version:

```bash
./scripts/update-homebrew.sh 0.33.2
```

This script waits for GitHub Actions to complete (~5 min), then updates the formula with new SHA256 hashes.


Polecat sessions terminate unexpectedly during work

During swarm bd-784c, polecat sessions (Toast, Nux) terminated mid-task without completing their work.

**Observed:**
- Polecats were actively working (edits in progress, tests running)
- Sessions suddenly showed 'not running' in gt polecat status
- tmux sessions existed but were empty/reset
- Work was partially complete (some commits made, issue still open)

**Timeline example:**
1. Toast working on bd-1tkd, making edits
2. Check status 30s later - session empty, state shows 'idle'
3. Had to re-sling to restart

**Impact:**
- Lost work progress
- Required manual intervention to restart
- Unclear if work was saved/committed

**Possible causes:**
- Session timeout?
- Claude Code crash?
- Resource limit?

**Suggestion:**
- Add session health monitoring
- Auto-restart on unexpected termination
- Log session exit reasons


Create release tag

Create annotated git tag.

```bash
git tag -a v0.99.0-test -m "Release v0.99.0-test"
```

Verify: `git tag -l | tail -5`


Performance Validation

Confirm no performance regression from cache removal


Run bump-version.sh

Update all component versions atomically.

```bash
./scripts/bump-version.sh 0.99.0-test
```

This updates:
- cmd/bd/version.go
- .claude-plugin/*.json
- integrations/beads-mcp/pyproject.toml
- integrations/beads-mcp/src/beads_mcp/__init__.py
- npm-package/package.json
- Hook templates
- README.md
- CHANGELOG.md (adds date)


Sync race: rebase-based divergence recovery resurrects tombstones

## Problem
When two repos sync simultaneously, tombstones can be resurrected:

1. Repo A deletes issue (creates tombstone), pushes to sync branch
2. Repo B (with 'closed' status) exports and tries to push
3. Push fails (non-fast-forward)
4. fetchAndRebaseInWorktree does git rebase
5. Git rebase applies B's 'closed' patch on top of A's 'tombstone'
6. TEXT-level rebase doesn't invoke beads merge driver
7. 'closed' overwrites 'tombstone' = resurrection

## Root Cause
CommitToSyncBranch uses git rebase for divergence recovery, but rebase is text-level, not content-level. The proper content-level merge in PullFromSyncBranch handles tombstones correctly, but it runs AFTER the problematic push.

## Proposed Fix
Option 1: Don't push in CommitToSyncBranch - let PullFromSyncBranch handle merge+push
Option 2: Replace git rebase with content-level merge in fetchAndRebaseInWorktree
Option 3: Reorder sync steps: Export → Pull/Merge → Commit → Push

## Workaround Applied
Excluded tombstones from orphan detection warnings (commit 1e97d9cc).

See also: bd-3852 (Add orphan detection migration)


Wait for GoReleaser

gh run list --workflow=release.yml - wait for success


Update local binary

cp ./bd ~/.local/bin/bd


Update hook templates to 0.30.4

Update bd-hooks-version comment in all 4 hook templates:
- cmd/bd/templates/hooks/pre-commit
- cmd/bd/templates/hooks/post-merge
- cmd/bd/templates/hooks/pre-push
- cmd/bd/templates/hooks/post-checkout

Each should have:
```bash
# bd-hooks-version: 0.30.4
```

```verify
grep -l 'bd-hooks-version: 0.30.4' cmd/bd/templates/hooks/* | wc -l | grep -q '4'
```


Merge: bd-4opy

branch: polecat/angharad
target: main
source_issue: bd-4opy
rig: beads


Implement CLI command (cmd/bd/reset.go)

Wire up the reset command with Cobra CLI.

## Responsibilities
- Define command and all flags
- User confirmation prompt (unless --force)
- Display impact summary before confirmation
- Colored output and progress indicators
- Call core reset package
- Handle errors with user-friendly messages
- Register command with rootCmd in init()

## Flags
```go
--hard       bool   "Also remove from git and commit"
--force      bool   "Skip confirmation prompt"
--backup     bool   "Create backup before reset"
--dry-run    bool   "Preview what would happen"
--skip-init  bool   "Do not re-initialize after reset"
--verbose    bool   "Show detailed progress output"
```

## Output Format
```
⚠  This will reset beads to a clean state.

Will be deleted:
  • 47 issues (23 open, 24 closed)
  • 12 tombstones

Continue? [y/N] y

→ Stopping daemons... ✓
→ Removing .beads/... ✓
→ Initializing fresh... ✓

✓ Reset complete. Run 'bd onboard' to set up hooks.
```

## Implementation Notes
- Confirmation logic lives HERE, not in core package
- Use color package (github.com/fatih/color) for output
- Follow patterns from other commands (init.go, doctor.go)
- Add to rootCmd in init() function

## File Location
`cmd/bd/reset.go`


Add 'convoy' issue type with reactive completion

Add convoy as a new issue type with reactive completion semantics.

Behavior:
- Convoy has list of tracked issues (via 'tracks' relation)
- When all tracked issues close (including wontfix), convoy auto-closes
- Supports cross-prefix tracking (convoy in hq-* tracks gt-*, bd-*)

Implementation:
- New type: convoy
- Reactive completion trigger on tracked issue closure
- Query support: 'bd list --type=convoy'

Related: hq-7h8jx (Convoy System epic in town beads)


Fix JSON error output consistency across all commands

## Problem

When `--json` flag is specified, error output should return JSON format, not plain text. Currently only `bd show` uses `FatalErrorRespectJSON` - all other commands use direct `fmt.Fprintf(os.Stderr, ...)`.

## Audit Findings (bd-au0.7)

| File | stderr writes | Commands affected |
|------|---------------|-------------------|
| show.go | 51 | update, close, edit |
| dep.go | 41 | dep add/remove/tree/cycles |
| label.go | 19 | label add/remove/list |
| comments.go | ~10 | comments add/list |
| epic.go | ~5 | epic status/close-eligible |

## Solution

Replace `fmt.Fprintf(os.Stderr, ...) + os.Exit(1)` patterns with `FatalErrorRespectJSON()` in all commands that support `--json` flag.

## Pattern

```go
// Before (inconsistent)
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)

// After (respects --json)
FatalErrorRespectJSON("%v", err)
```

## Success Criteria

- All commands return JSON errors when `--json` flag is set
- Error format: `{"error": "message"}`
- Exit code 1 preserved for errors


Run tests

TMPDIR=/tmp go test -short ./...


GH#532: bd sync circular error (suggests running bd sync)

bd sync error message recommends running bd sync to fix the bd sync error. Fix error handling to provide useful guidance. See GitHub issue #532.


Daemon should be singleton and aggressively kill stale instances

Found 2 bd daemons running (PIDs 76868, 77515) during shutdown. The daemon should:

1. Be a singleton - only one instance per rig allowed
2. On startup, check for existing daemon and kill it before starting
3. Use a PID file or lock file to enforce this

Currently stale daemons can accumulate, causing confusion and resource waste.

**Investigation 2025-12-21:**

The singleton mechanism is already implemented and working correctly:

1. **daemon.lock** uses flock (exclusive non-blocking) to prevent duplicate daemons
2. **bd.sock.startlock** coordinates concurrent auto-starts via O_CREATE|O_EXCL
3. **Registry** tracks all daemons globally in ~/.beads/registry.json

Testing shows:
- Trying to start a second daemon gives: 'Error: daemon already running (PID X)'
- Multiple daemons for *different* rigs is expected/correct behavior

The original report ('Found 2 bd daemons running PIDs 76868, 77515') was likely:
1. Two daemons for different rigs (expected), OR
2. An edge case that's since been fixed

Consider closing as RESOLVED or clarifying the original scenario.


Add bd daemon --stop-all command to kill all daemon processes

Currently there's no easy way to stop all running bd daemon processes. Users must resort to pkill -f 'bd daemon' or similar shell commands.

Add a --stop-all flag to bd daemon that:
1. Finds all running bd daemon processes (not just the current repo's daemon)
2. Gracefully stops them all
3. Reports how many were stopped

This is useful when:
- Multiple daemons are running and causing race conditions
- User wants a clean slate before running bd sync
- Debugging daemon-related issues


Spawn-time bonding: --attach flag

Add --attach flag to bd mol spawn for on-the-fly composition.

COMMAND: bd mol spawn proto-feature --attach proto-docs --attach proto-testing

BEHAVIOR:
- Spawn the primary proto as normal
- For each --attach: spawn that proto and wire to primary
- Attachments become children of primary's root epic
- Dependencies wired based on bond type (default: sequential)

FLAGS:
- --attach PROTO: Attach a proto (can repeat)
- --attach-type TYPE: sequential (default) or parallel for all attachments
- --after ISSUE: Attachment point for attached protos

VARIABLE HANDLING:
- All attached protos share variable namespace
- Warn on variable name conflicts
- All --var flags apply to all protos

DESIGN NOTE: This is syntactic sugar. Equivalent to:
  bd mol spawn proto-A
  bd mol bond $new_epic_id proto-B

Keeping as separate task because it's a common UX pattern worth optimizing.


Improve test coverage for internal/compact (18.2% → 70%)

Improve test coverage for internal/compact package from 17% to 70%.

## Current State
- Coverage: 17.3%
- Files: compactor.go, git.go, haiku.go
- Tests: compactor_test.go (minimal tests)

## Functions Needing Tests

### compactor.go (core compaction)
- [ ] New - needs config validation tests
- [ ] CompactTier1 - needs single issue compaction tests
- [ ] CompactTier1Batch - needs batch processing tests
- [ ] compactSingleWithResult - internal, test via public API

### git.go
- [ ] GetCurrentCommitHash - needs git repo fixture tests

### haiku.go (AI summarization) - MOCK REQUIRED
- [ ] NewHaikuClient - needs API key validation tests
- [ ] SummarizeTier1 - needs mock API response tests
- [ ] callWithRetry - needs retry logic tests
- [ ] isRetryable - needs error classification tests
- [ ] renderTier1Prompt - needs template rendering tests

## Implementation Guide

1. **Mock the Anthropic API:**
   ```go
   // Create mock HTTP server
   server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
       json.NewEncoder(w).Encode(map[string]interface{}{
           "content": []map[string]string{{"text": "Summarized content"}},
       })
   }))
   defer server.Close()

   // Point client at mock
   client.baseURL = server.URL
   ```

2. **Test scenarios:**
   - Successful compaction with AI summary
   - API failure with retry
   - Rate limit handling
   - Empty issue handling
   - Large issue truncation

3. **Use test database:**
   ```go
   store, cleanup := testutil.NewTestStore(t)
   defer cleanup()
   ```

## Success Criteria
- Coverage ≥ 70%
- AI calls properly mocked (no real API calls in tests)
- Retry logic verified
- Error paths covered

## Run Tests
```bash
go test -v -cover ./internal/compact
go test -race ./internal/compact
```


Add MCP server functions for repair commands

**Summary:** Added MCP server repair functions for agent dependency management, system validation, and pollution detection. Implemented across BdClientBase, BdCliClient, and daemon clients to enhance system diagnostics and self-healing capabilities.

**Key Decisions:**
- Expose repair_deps(), detect_pollution(), validate() via MCP server
- Create abstract method stubs with fallback to CLI execution
- Use @mcp.tool decorators for function registration

**Resolution:** Successfully implemented comprehensive repair command infrastructure, enabling more robust system health monitoring and automated remediation with full CLI and daemon support.

Implemented all three MCP server functions:

1. **repair_deps(fix=False)** - Find/fix orphaned dependencies
2. **detect_pollution(clean=False)** - Detect/clean test issues
3. **validate(checks=None, fix_all=False)** - Run comprehensive health checks

Changes:
- Added abstract methods to BdClientBase
- Implemented in BdCliClient (CLI execution)
- Added NotImplementedError stubs in BdDaemonClient (falls back to CLI)
- Created wrapper functions in tools.py
- Registered @mcp.tool decorators in server.py

All commands tested and working with --no-daemon flag.


Swarm: 13 beads backlog issues for polecat execution

## Swarm Overview

13 issues prepared for parallel polecat execution. All issues have been enhanced with concrete implementation guidance, file lists, and success criteria.

## Issue List

### Bug (1) - HIGH PRIORITY
| ID | Priority | Title |
|----|----------|-------|
| bd-phtv | P1 | Pinned field overwritten by subsequent commands |

### Test Coverage (3)
| ID | Package | Target |
|----|---------|--------|
| bd-io8c | internal/syncbranch | 27% → 70% |
| bd-thgk | internal/compact | 17% → 70% |
| bd-tvu3 | internal/beads | 48% → 70% |

### Code Quality (3)
| ID | Task |
|----|------|
| bd-qioh | FatalError pattern standardization |
| bd-rgyd | Split queries.go (1704 lines → 5 files) |
| bd-u2sc.3 | Split cmd/bd files (sync/init/show/compact) |

### Features (4)
| ID | Task |
|----|------|
| bd-au0.5 | Search date/priority filters |
| bd-ykd9 | Doctor --fix auto-repair |
| bd-g4b4 | Close hooks system |
| bd-likt | Gate daemon RPC |

### Polish (2)
| ID | Task |
|----|------|
| bd-4qfb | Doctor output formatting |
| bd-u2sc.4 | slog structured logging |

## Issue Details

All issues have been enhanced with:
- Concrete file lists to modify
- Code snippets and patterns
- Success criteria
- Test commands

Run `bd show <id>` for full details on any issue.

## Execution Notes

- All issues are independent (no blockers between them)
- bd-phtv (P1 bug) should get priority - affects bd pin functionality
- Test coverage tasks are straightforward but time-consuming
- File split tasks (bd-rgyd, bd-u2sc.3) are mechanical but important

## Completed During Prep

- bd-ucgz (P2 bug) - Fixed inline: external deps orphan check (commit f2db0a1d)
- Moved 5 gastown issues out of beads backlog (gt-dh65, gt-ng6g, gt-fqcz, gt-gswn, gt-rw2z)
- Deferred 4 premature/post-1.0 issues
- Closed bd-udsi epic (core implementation complete)


Update CHANGELOG.md for {{version}}

In CHANGELOG.md:

1. Change `## [Unreleased]` section header to `## [{{version}}] - {{date}}`
2. Add new empty `## [Unreleased]` section above it
3. Review and clean up the changes list

Format:
```markdown
## [Unreleased]

## [{{version}}] - {{date}}

### Added
- ...

### Changed
- ...

### Fixed
- ...
```


Merge: amber-1767138546434

branch: polecat/amber-1767138546434
target: main
source_issue: amber-1767138546434
rig: beads


Add gate issue type to beads

Add 'gate' as a new issue type for async coordination.

## Changes Needed
- Add 'gate' to IssueType enum in internal/types/types.go
- Update validation to accept gate type
- Update CLI help text and completion

## Gate Type Semantics
- Gates are ephemeral (live in wisp storage)
- Managed by Deacon patrol
- Have special fields: await_type, await_id, timeout, waiters[]


Mol Mall: Formula marketplace using GitHub as backend

Create a marketplace for sharing molecule formulas using GitHub repos as the hosting backend.

## Why GitHub?

GitHub solves multiple problems at once:
- **Hosting**: Raw file URLs for formula.json
- **Versioning**: Git tags (v1.0.0, v1.2.0)
- **Auth**: GitHub tokens for private formulas
- **Discovery**: GitHub search, topics, stars
- **Collaboration**: PRs for contributions, issues for bugs
- **Organizations**: Natural scoping (@anthropic/, @gastown/)

## URL Scheme

```bash
# Direct GitHub URL
bd mol install github.com/anthropics/mol-code-review

# With version tag
bd mol install github.com/anthropics/mol-code-review@v1.2.0

# Shorthand (via registry lookup)
bd mol install @anthropic/mol-code-review
```

## Architecture

### Distributed Model (like Go modules)
Each formula lives in its own repo:
```
github.com/anthropics/mol-code-review/
├── formula.json      # The formula
├── README.md         # Documentation
└── CHANGELOG.md      # Version history
```

### Optional Registry (for discovery)
```
github.com/anthropics/mol-mall/
└── registry.json     # Index pointing to formula repos
```

## Child Issues

1. `bd mol export` - Proto → Formula file
2. `bd mol promote` - Distilled proto → Catalog proto (one step)
3. `bd mol install` - GitHub → Local proto
4. `bd mol update` - Check for newer versions
5. `bd mol search` - Find formulas (GitHub API)
6. `bd mol publish` - Push formula to GitHub repo
7. Formula versioning - Version field + git tag integration
8. Installation tracking - .beads/installed.json

## ID Namespace Design

| Entity | ID Format | Example |
|--------|-----------|---------|
| Formula (GitHub) | `github.com/org/repo` | `github.com/anthropics/mol-code-review` |
| Catalog proto (local) | `mol-name` | `mol-code-review` |
| Distilled proto | `<db>-proto-xxx` | `bd-proto-a7f` |
| Poured instance | `<db>-mol-xxx` | `gt-mol-b8c` |
| Wisp instance | `<db>-wisp-xxx` | `hq-wisp-d9e` |


Document BEADS_DIR pattern for multi-agent workspaces (Gas Town)

Gas Town and similar multi-agent systems need to configure separate beads databases per workspace/rig, distinct from any project-level beads.

## Use Case

In Gas Town:
- Each 'rig' (managed project) has multiple agents (polecats, refinery, witness)
- All agents in a rig should share a single beads database at the rig level
- This should be separate from any .beads/ the project itself uses
- The BEADS_DIR env var enables this

## Documentation Needed

1. Add a section to docs explaining BEADS_DIR for multi-agent setups
2. Example: setting BEADS_DIR in agent startup scripts/hooks
3. Clarify interaction with project-level .beads/ (BEADS_DIR takes precedence)

## Current Support

Already implemented in internal/beads/beads.go:FindDatabasePath():
- BEADS_DIR env var is checked first (preferred)
- BEADS_DB env var still supported (deprecated)
- Falls back to .beads/ search in tree

Just needs documentation for the multi-agent workspace pattern.


Migration invariants should exclude external dependencies from orphan check

## Summary

The `checkForeignKeys` function in `migration_invariants.go` flags external dependencies as orphaned because they dont exist in the local issues table.

## Location

`internal/storage/sqlite/migration_invariants.go` around line 150-162

## Current Code (buggy)

```go
// Check for orphaned dependencies
var orphanCount int
err = db.QueryRowContext(ctx, \`
    SELECT COUNT(*)
    FROM dependencies d
    WHERE NOT EXISTS (SELECT 1 FROM issues WHERE id = d.depends_on_id)
\`).Scan(&orphanCount)
```

## Fix

Exclude external references (format: `external:<project>:<capability>`):

```go
// Check for orphaned dependencies (excluding external refs)
var orphanCount int
err = db.QueryRowContext(ctx, \`
    SELECT COUNT(*)
    FROM dependencies d
    WHERE NOT EXISTS (SELECT 1 FROM issues WHERE id = d.depends_on_id)
      AND d.depends_on_id NOT LIKE 'external:%'
\`).Scan(&orphanCount)
```

## Reproduction

```bash
# Add external dependency
bd dep add bd-xxx external:other-project:some-capability

# Try to sync - fails
bd sync
# Error: found 1 orphaned dependencies
```

## Files to Modify

1. **internal/storage/sqlite/migration_invariants.go** - Add WHERE clause

## Testing

```bash
# Create issue with external dep
bd create "Test external deps" -t task
bd dep add bd-xxx external:beads:release-workflow

# Sync should succeed
bd sync

# Verify dep exists
bd show bd-xxx --json | jq .dependencies
```

## Success Criteria
- External dependencies dont trigger orphan check
- `bd sync` succeeds with external deps
- Regular orphan detection still works for internal deps


Add daemon RPC endpoints for config and stale check

Two TODOs request daemon RPC endpoints:

1. cmd/bd/create.go:208 - Add RPC method to get config in daemon mode
2. cmd/bd/mol_stale.go:67 - Add RPC endpoint for stale check

These would allow the CLI to query the daemon for configuration and staleness checks instead of reading directly.

Files:
- cmd/bd/create.go:208
- cmd/bd/mol_stale.go:67