Enhance bd doctor to suggest reset for broken states

Update bd doctor to detect severely broken states and suggest reset.

## Detection Criteria
Suggest reset when:
- Multiple unfixable errors detected
- Corrupted JSONL that can't be repaired
- Schema version mismatch that can't be migrated
- Daemon state inconsistent and unkillable

## Implementation
Add to doctor's check/fix flow:
```go
if unfixableErrors > threshold {
    suggest('State may be too broken to fix. Consider: bd reset')
}
```

## Output Example
```
✗ Found 5 unfixable errors

  Your beads state may be too corrupted to repair.
  Consider running 'bd reset' to start fresh.
  (Use 'bd reset --backup' to save current state first)
```

## Notes
- Don't auto-run reset, just suggest
- This is lower priority, can be done in parallel with main work


Identity Configuration

Implement identity system for sender field.

Configuration sources (in priority order):
1. --identity flag on commands
2. BEADS_IDENTITY environment variable
3. .beads/config.json: {"identity": "worker-name"}
4. Default: git user.name or hostname

New config file support:
- .beads/config.json for per-repo settings
- identity field for messaging

Helper function:
- GetIdentity() string - resolves identity from sources

Update bd mail send to use GetIdentity() for sender field.


Implement content-first idempotent import

**Summary:** Refactored issue import to be content-first and idempotent, ensuring consistent data synchronization across multiple import rounds by prioritizing content hash matching over ID-based updates.

**Key Decisions:**
- Implement content hash as primary matching mechanism
- Create global collision resolution algorithm
- Ensure importing same data multiple times results in no-op

**Resolution:** The new import strategy guarantees predictable convergence across distributed systems, solving rename detection and collision handling while maintaining data integrity during multi-stage imports.


Wait for CI

Monitor GitHub Actions for release completion.

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

Expected time: 5-10 minutes

Watch for:
- Build artifacts (all platforms)
- Test suite pass
- npm publish
- PyPI publish


bd mol update: Check and update installed formulas

Check for newer versions of installed formulas and update them.

## Usage
```bash
bd mol update                    # Update all
bd mol update mol-code-review    # Update specific formula
bd mol update --check            # Just check, don't update
```

## Implementation
1. Read .beads/installed.json
2. For each installed formula:
   - Fetch latest tag from GitHub API
   - Compare with installed version
   - If newer: download, cook, update installed.json
3. Report what was updated

## Flags
- `--check` - Only check for updates, don't install
- `--force` - Reinstall even if up to date
- `--json` - Machine-readable output


bd prime should mention when beads is redirected

## Problem

Agents running in a redirected clone don't know they're sharing beads with other clones. This can cause confusion when molecules or issues seem to 'appear' or 'disappear'.

## Proposed Solution

When `bd prime` runs and detects a redirect, include it in the output:

```
Beads: /Users/stevey/gt/beads/mayor/rig/.beads
       (redirected from crew/dave - you share issues with other clones)
```

## Why

Visibility over magic. If agents can see the redirect, they can reason about it.

## Related

- bd where command (shows this on demand)
- gt redirect following (ensures gt matches bd behavior)


Add test files for internal/storage

The internal/storage package has no test files at all. This package provides the storage interface abstraction.

Current coverage: N/A (no test files)
Target: Add basic interface tests


Restart daemons

bd daemons killall


Commit release

Stage and commit all version changes.

```bash
git add -A
git commit -m "chore: Bump version to 0.39.0"
```

Review the commit to ensure all expected files are included.


Update .claude-plugin/marketplace.json to 0.30.4

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

```verify
jq -e '.plugins[0].version == "0.30.4"' .claude-plugin/marketplace.json
```


> bd sync --no-daemon
→ Exporting pending changes to JSONL...
→ Committing changes to sync branch 'beads-sync'...
Error committing to sync branch: failed to create worktree: failed to create worktree parent directory: mkdir /var/home/matt/dev/beads/fix-ci/.git: not a directory

**Problem Diagnosed**: The `bd sync` command was failing with "mkdir /var/home/matt/dev/beads/fix-ci/.git: not a directory" because it was being executed from the wrong directory.

**Root Cause**: The command was run from `/var/home/matt/dev/beads` (where the `fix-ci` worktree exists) instead of the main repository directory `/var/home/matt/dev/beads/main`. Since `fix-ci` is a git worktree with a `.git` file (not directory), the worktree creation logic failed when trying to create `<current_dir>/.git/beads-worktrees/<branch>`.

**Solution Verified**: Execute `bd sync` from the main repository directory:
```bash
cd main && bd sync --dry-run
```


Design molecule step hooks

Hooks that fire between molecule steps. When a bead in a molecule closes, trigger hook that can spawn agent attention to prompts/requests. This enables reactive orchestration - the molecule drives, hooks respond. Gas Town feature built on Beads data plane.


Merge: bd-d28c

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


Upgrade beads-mcp to {{version}}

Upgrade the MCP server via pip:

```bash
pip install --upgrade beads-mcp
pip show beads-mcp | grep Version  # Verify {{version}}
```

Note: Restart Claude Code or MCP session to use new version.


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.


Correction: Pinned field already in v0.31.0

Quick correction - the Pinned field is already in the current bd v0.31.0:

```go
// In beads internal/types/types.go
Pinned bool `json:"pinned,omitempty"`
```

So you just need to:
1. Add `Pinned bool `json:"pinned,omitempty"`` to BeadsMessage in types.go
2. Sort pinned messages first in listBeads() after fetching

No migration needed - the field is already there.

-- Mayor


Merge: bd-au0.5

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


Phase 1.3: Basic TOON read/write operations

Add basic TOON read/write operations to bdt executable. Implement create, list, and show commands that use the internal/toon package for encoding/decoding to TOON format.

## Subtasks
1. Implement bdt create command - Create issues and serialize to TOON format
2. Implement bdt list command - Read issues.toon and display all issues
3. Implement bdt show command - Display single issue by ID
4. Add file I/O operations for issues.toon
5. Integrate internal/toon package (EncodeTOON, DecodeJSON)
6. Write tests for create, list, show operations

## Files to Create/Modify
- cmd/bdt/create.go - Create command
- cmd/bdt/list.go - List command
- cmd/bdt/show.go - Show command
- cmd/bdt/storage.go - File I/O helper

## Success Criteria
- bdt create "Issue title" creates and saves to issues.toon
- bdt list displays all issues in human-readable format
- bdt list --json shows JSON output
- bdt show <id> displays single issue
- Issues round-trip correctly: create → list → show
- All tests passing with >80% coverage


Add tests for helper functions (GetDirtyIssueHash, GetAllDependencyRecords, export hashes)

Several utility functions have 0% coverage:
- GetDirtyIssueHash (dirty.go)
- GetAllDependencyRecords (dependencies.go)
- GetExportHash, SetExportHash, ClearAllExportHashes (hash.go)

These are lower priority but should have basic coverage.


Pinned issues: persistent context markers

Add ability to pin issues so they remain visible and are excluded from work-finding commands. Pinned issues serve as persistent context markers (handoffs, architectural notes, recovery instructions) that should not be claimed as work items.

Use Cases:
1. Handoff messages - Pin session handoffs so new agents always see them
2. Architecture decisions - Pin ADRs or design notes for reference
3. Recovery context - Pin amnesia-cure notes that help agents orient

Core commands: bd pin, bd unpin, bd list --pinned/--no-pinned


Verify CI is green

Check that CI is passing before starting release:
```bash
gh run list --limit 3
```
All recent runs should show 'success'. If not, fix issues first.


Refactor: Extract shared getEpicChildren helper for swarm commands

## Context
`getSwarmStatus` and `analyzeEpicForSwarm` in cmd/bd/swarm.go have nearly identical code for:
- Getting epic dependents via GetDependents
- Filtering to parent-child relationships
- Building childIDSet map
- Building dependency maps

## Implementation
1. Extract `getEpicChildren(ctx, store, epicID)` that returns:
   - `[]*types.Issue` - child issues
   - `map[string]bool` - child ID set
   - `map[string][]string` - dependency map (within children)
   - `error`

2. Refactor both `analyzeEpicForSwarm` and `getSwarmStatus` to use it

3. Consider defining a named interface for the store methods:
   ```go
   type SwarmStore interface {
       GetIssue(context.Context, string) (*types.Issue, error)
       GetDependents(context.Context, string) ([]*types.Issue, error)
       GetDependencyRecords(context.Context, string) ([]*types.Dependency, error)
   }
   ```

## Files
- cmd/bd/swarm.go (lines 150-248, 616-682)

## Acceptance
- No duplicated code for fetching epic children
- Both commands produce identical results as before


Update local binary

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


Run tests and linting

Run the full test suite and linter:

```bash
TMPDIR=/tmp go test -short ./...
golangci-lint run ./...
```

Fix any failures. Linting warnings acceptable (see LINTING.md).


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.


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

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


Update CHANGELOG.md for 0.33.2

In CHANGELOG.md:

1. Change `## [Unreleased]` section header to `## [0.33.2] - 2025-12-21`
2. Add new empty `## [Unreleased]` section above it
3. Review and clean up the changes list

Format:
```markdown
## [Unreleased]

## [0.33.2] - 2025-12-21

### Added
- ...

### Changed
- ...

### Fixed
- ...
```


Implement subgraph cloning with variable substitution

Core implementation of template instantiation:

1. Add `bd template instantiate <template-id> [--var key=value]...` command
2. Implement subgraph loading:
   - Load template epic
   - Recursively load all children (and their children)
   - Load all dependencies between issues in the subgraph
3. Implement variable substitution:
   - Scan titles and descriptions for `{{name}}` patterns
   - Replace with provided values
   - Error on missing required variables (or prompt interactively)
4. Implement cloning:
   - Generate new IDs for all issues
   - Create cloned issues with substituted text
   - Remap and create dependencies
5. Return the new epic ID

Consider adding `--dry-run` flag to preview what would be created.


Thread Test 2

Testing direct mode


bd swarm create command

Add bd swarm create to create a swarm molecule from an epic.

## Context
Swarms ARE persistent molecules - not separate JSON state. This command creates
a swarm molecule that:
- Links to the epic it orchestrates
- Has mol_type=swarm
- Specifies a coordinator
- Can be discovered by any agent

## Core Principle: Discovery Over Tracking
The swarm molecule doesn't track step-by-step state. Instead:
- Query bd ready --parent=<epic> to find the ready front
- Query bd list --parent=<epic> --status=closed to find completed
- Derive progress from children's statuses

## Implementation
1. New command: bd swarm create <epic-id> [--coordinator=<addr>]
2. Validate epic structure first (call bd swarm validate)
3. Create molecule bead:
   - mol_type: swarm
   - epic: <epic-id>
   - coordinator: <addr>
   - status: open
4. Return the swarm molecule ID

## Single-Issue Wrapping
If given a single issue (not epic), auto-wrap:
- Create an epic with that issue as child
- Then create swarm molecule

## Reference
~/gt/docs/swarm-architecture.md - 'Swarm Structure' section

## Acceptance
- bd swarm create <epic> creates a swarm molecule
- Molecule has mol_type=swarm
- Links to epic via epic field
- Validates structure before creation


GH#403: bd doctor --fix circular error message

bd doctor --fix suggests running bd doctor --fix for deletions manifest issue. Fix to provide actual resolution. See GitHub issue #403.


Time-dependent tests may be flaky near TTL boundary

Several tombstone merge tests use time.Now() to create test data: time.Now().Add(-24 * time.Hour), time.Now().Add(-60 * 24 * time.Hour), etc. While these work reliably in practice (24h vs 30d TTL has large margin), they could theoretically be flaky if: 1) Tests run slowly, 2) System clock changes during test, 3) TTL constants change. Recommendation: Consider using a fixed reference time or time injection for deterministic tests. Lower priority since current margin is large. Files: internal/merge/merge_test.go:1337-1338, 1352-1353, 1548-1549, 1590-1591


Update documentation for CLI consolidation

## Task
Update all documentation to reflect CLI consolidation changes.

## Files requiring updates

### Primary docs
- docs/CLI_REFERENCE.md - Major updates
  - Add admin section (cleanup, compact, reset)
  - Update migrate section (subcommands)
  - Update formula section (add cook)
  - Remove/update standalone command references

### Secondary docs
- docs/DELETIONS.md - migrate-tombstones → migrate tombstones, compact → admin compact
- docs/FAQ.md - compact → admin compact
- docs/QUICKSTART.md - compact, cleanup → admin compact, admin cleanup
- docs/TROUBLESHOOTING.md - compact → admin compact
- docs/CONFIG.md - compact → admin compact
- docs/INSTALLING.md - quickstart reference
- docs/EXTENDING.md - quickstart reference

### Skills docs
- skills/beads/SKILL.md - compact, quickstart references
- skills/beads/references/CLI_REFERENCE.md - mirror main CLI_REFERENCE.md

### Other docs
- commands/quickstart.md - update or remove
- commands/compact.md - update to admin compact
- examples/compaction/README.md - update examples
- README.md - quickstart reference
- CHANGELOG.md - add consolidation changes section

## Implementation notes
- Keep backwards compatibility notices where aliases exist
- Update command examples to use new paths
- Consider adding deprecation warnings section


activity.go: Missing test coverage

The new activity.go command (from bd-xo1o.3) has no test coverage. At minimum, tests should cover:
- parseDurationString() for various formats (5m, 1h, 2d, invalid)
- filterEvents() for --mol and --type filtering
- formatEvent() and getEventDisplay() for all mutation types

Discovered during code review of bd-xo1o implementation.


Migrate sort.Slice to slices.SortFunc

Go 1.21+ provides slices.SortFunc which is cleaner and slightly faster than sort.Slice.

Found 15+ instances of sort.Slice in:
- cmd/bd/autoflush.go
- cmd/bd/count.go
- cmd/bd/daemon_sync.go
- cmd/bd/doctor.go
- cmd/bd/export.go
- cmd/bd/import.go
- cmd/bd/integrity.go
- cmd/bd/jira.go
- cmd/bd/list.go
- cmd/bd/migrate_hash_ids.go
- cmd/bd/rename_prefix.go
- cmd/bd/show.go

Example migration:
```go
// Before
sort.Slice(issues, func(i, j int) bool {
    return issues[i].Priority < issues[j].Priority
})

// After
slices.SortFunc(issues, func(a, b *types.Issue) int {
    return cmp.Compare(a.Priority, b.Priority)
})
```

Benefits:
- Cleaner 3-way comparison
- Slightly better performance
- Modern idiomatic Go


Test createTombstone and deleteIssue wrappers

Add tests for the createTombstone and deleteIssue wrapper functions in cmd/bd/delete.go.

## Functions under test
- createTombstone (cmd/bd/delete.go:335) - Wrapper around SQLite CreateTombstone
- deleteIssue (cmd/bd/delete.go:349) - Wrapper around SQLite DeleteIssue

## Test scenarios for createTombstone
1. Successful tombstone creation
2. Tombstone with reason and actor tracking
3. Error when issue doesn't exist
4. Verify tombstone status set correctly
5. Verify audit trail recorded
6. Rollback/error handling

## Test scenarios for deleteIssue
1. Successful issue deletion
2. Error on non-existent issue
3. Verify issue removed from database
4. Error handling when storage backend doesn't support delete

## Coverage target
Current: 0%
Target: >85%

## Related
- Parent epic: bd-kyll
- Original issue: bd-7z4


Merge: bd-bqcc

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


Test hooked styling


Add empty tasks validation in workflow create

workflow.go:321 will panic if wf.Tasks is empty. Add validation that len(wf.Tasks) > 0 before accessing wf.Tasks[0].


Version Bump: {{version}}

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


GH#402: Add --parent flag documentation to bd onboard

bd onboard output is missing --parent flag for epic subtasks. Agents guess wrong syntax (--deps parent:). See GitHub issue #402.


BondRef.ProtoID field name is misleading for mol+mol bonds

In bondMolMol, the BondRef.ProtoID field is used to store molecule IDs:

```go
BondedFrom: append(molA.BondedFrom, types.BondRef{
    ProtoID:   molB.ID,  // This is a molecule, not a proto
    ...
})
```

This is semantically confusing since ProtoID suggests it should only hold proto references.

**Options:**
1. Rename ProtoID to SourceID (breaking change, needs migration)
2. Add documentation clarifying ProtoID can hold molecule IDs in bond context
3. Leave as-is, accept the naming is imprecise

Low priority since it's just naming, not functionality.


CLI cleanup: Rename bd mol catalog to bd formula list

## Problem
`bd mol catalog` shows formulas, not molecules. This is confusing.

Current state:
- `bd formula list` - lists formulas
- `bd mol catalog` - ALSO lists formulas (duplicate!)

The "mol" namespace should be for molecules (instantiated work), not formulas (templates).

## Proposed Change
- Remove `bd mol catalog`
- Keep `bd formula list` as the canonical command
- Update docs to use `bd formula list`

## Alternative
If we want a "catalog" concept separate from "list", make it `bd formula catalog`.


Graph Link: relates_to for knowledge graph

Implement relates_to link type for loose associations.

New command:
- bd relate <id1> <id2> - creates bidirectional relates_to link

Query support:
- bd show <id> --related shows related issues
- bd list --related-to <id>

Storage:
- relates_to stored as JSON array of issue IDs
- Consider: separate junction table for efficiency at scale?

This enables 'see also' connections without blocking or hierarchy.


HANDOFF: Version 0.30.7 release in progress

## Context
Doing a 0.30.7 patch release with bug fixes.

## What's done
- Fixed #657: bd graph nil pointer crash (graph.go:102)
- Fixed #652: Windows npm installer file lock (postinstall.js)
- Updated CHANGELOG.md and info.go
- Pushed to main, CI running (run 20390861825)
- Created version-bump molecule template (bd-6s61) and instantiated for 0.30.7 (bd-8pyn)

## In progress
Molecule bd-8pyn has 3 remaining tasks:
  - bd-dxo7: Wait for CI to pass
  - bd-7l70: Verify release artifacts
  - bd-5c91: Update local installation

## Check CI
  gh run list --repo steveyegge/beads --limit 1
  gh run view 20390861825 --repo steveyegge/beads

## New feature filed
bd-n777: Timer beads for scheduled agent callbacks
Design for Deacon-managed timers that can interrupt agents via tmux

## Resume commands
  bd --no-daemon show bd-8pyn
  gh run list --repo steveyegge/beads --limit 1


Remove Storage Cache from Server Struct

Eliminate cache fields and use s.storage directly


Test pinned for stats


Update CHANGELOG.md

Write the [Unreleased] section with all changes for 0.39.0.

Format: Keep a Changelog (https://keepachangelog.com)

Sections:
- ### Added
- ### Changed
- ### Fixed
- ### Documentation

The bump script will stamp the date automatically.


sync branch not match config

./bd sync
→ Exporting pending changes to JSONL...
→ No changes to commit
→ Pulling from sync branch 'gh-386'...
Error pulling from sync branch: failed to create worktree: failed to create worktree parent directory: mkdir /var/home/matt/dev/beads/worktree-db-fail/.git: not a directory
matt@blufin-framation ~/d/b/worktree-db-fail (worktree-db-fail) [1]> bd config list

Configuration:
  auto_compact_enabled = false
  compact_batch_size = 50
  compact_model = claude-3-5-haiku-20241022
  compact_parallel_workers = 5
  compact_tier1_days = 30
  compact_tier1_dep_levels = 2
  compact_tier2_commits = 100
  compact_tier2_days = 90
  compact_tier2_dep_levels = 5
  compaction_enabled = false
  issue_prefix = worktree-db-fail
  sync.branch = worktree-db-fail


bd dep add: Auto-resolve cross-rig IDs using routes.jsonl

Currently, adding a dependency to an issue in another rig requires verbose external reference syntax:

```bash
# This fails - can't resolve bd-* from gastown context
bd dep add gt-xyz bd-abc

# This works but is verbose
bd dep add gt-xyz external:beads:bd-abc
```

The town-level routing (~/gt/.beads/routes.jsonl) already knows how to map prefixes to rigs:
```json
{"prefix": "gt-", "path": "gastown/mayor/rig"}
{"prefix": "bd-", "path": "beads/mayor/rig"}
```

Enhancement: When `bd dep add` encounters an ID with a foreign prefix, it should:
1. Check routes.jsonl for the prefix mapping
2. Auto-resolve to external:<project>:<id> internally
3. Allow the simpler `bd dep add gt-xyz bd-abc` syntax

This would make cross-rig dependencies much more ergonomic.


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.


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
- ...
```


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


Move cook to formula subcommand

## Task
Move `bd cook` → `bd formula cook`

## Implementation

### 1. Update formula.go
- Add `cookCmd` as subcommand of `formulaCmd`
- Import necessary packages from cook.go if not already present

### 2. Update cook.go
- Remove `rootCmd.AddCommand(cookCmd)` from init()
- Keep the command implementation as-is

### 3. Create hidden alias for backwards compatibility
- In main.go or aliases file, add:
  ```go
  aliasCmd := &cobra.Command{
    Use:    "cook",
    Hidden: true,
    Run: func(cmd *cobra.Command, args []string) {
      // Forward to formula cook
    },
  }
  ```

### 4. Update docs
- docs/MOLECULES.md - if `bd cook` mentioned
- CHANGELOG.md - add deprecation notice

## Files to modify
- cmd/bd/formula.go (add subcommand)
- cmd/bd/cook.go (change registration)
- cmd/bd/main.go (add hidden alias)


Consolidate maintenance commands into bd doctor --fix

Per rsnodgrass in GH#692:
> "The biggest improvement to beads from an ergonomics perspective would be to prune down commands. We have a lot of 'maintenance' commands that probably should just be folded into 'bd doctor --fix' automatically."

Current maintenance commands that could be consolidated:
- clean - Clean up temporary git merge artifacts
- cleanup - Delete closed issues and prune expired tombstones
- compact - Compact old closed issues
- detect-pollution - Detect and clean test issues
- migrate-* (5 commands) - Various migration utilities
- repair-deps - Fix orphaned dependency references
- validate - Database health checks

Proposal:
1. Make `bd doctor` the single entry point for health checks
2. Add `bd doctor --fix` to auto-fix common issues
3. Deprecate (but keep working) individual commands
4. Add `bd doctor --all` for comprehensive maintenance

This would reduce cognitive load for users - they just need to remember 'bd doctor'.

Note: This is higher impact but also higher risk - needs careful design to avoid breaking existing workflows.


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.


bd prime: AI context loading and Claude Code integration

Implement `bd prime` command and Claude Code hooks for context recovery. Hooks work with BOTH MCP server and CLI approaches - they solve the context memory problem (keeping bd workflow fresh after compaction) not the tool access problem (MCP vs CLI).


Update CHANGELOG header

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


Add unit tests for reset package

Comprehensive unit tests for internal/reset package.

## Test Cases

### ValidateState tests
- .beads/ exists → success
- .beads/ missing → appropriate error
- git dirty state detection

### CountImpact tests
- Empty .beads/ → zero counts
- With issues → correct count (open vs closed)
- With tombstones → correct count
- Returns HasUncommitted correctly

### Backup tests
- Creates backup with correct timestamp format
- Preserves all files and permissions
- Returns correct path
- Handles missing .beads/ gracefully
- Errors on pre-existing backup dir

### Git operation tests
- CheckGitState detects dirty, detached, not-a-repo
- GitRemoveBeads removes correct files
- GitCommitReset creates commit with message
- Operations skip gracefully when not in git repo

### Reset tests (with mocks/temp dirs)
- Soft reset removes files, calls init
- Hard reset includes git operations
- Dry run doesn't modify anything
- SkipInit flag prevents re-initialization
- Daemon killall is called
- Backup is created when requested

## Approach
- Can start with interface definitions (TDD style)
- Use testify for assertions
- Create temp directories for isolation
- Mock git operations where needed
- Test completion depends on implementation tasks

## File Location
`internal/reset/reset_test.go`
`internal/reset/backup_test.go`
`internal/reset/git_test.go`


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


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.


Add Validation type and validations field to Issue

Add Validation struct (Validator *EntityRef, Outcome string, Timestamp time.Time, Score *float32) and Validations []Validation field to Issue. Tracks who validated/approved work completion. Core to HOP proof-of-stake concept - validators stake reputation on approvals.


hq- prefix routing fails: '.' resolves relative to cwd, not town root

## Problem
The hq- prefix in routes.jsonl maps to '.' which is interpreted relative to the current working directory, not the town root.

## Reproduction
```bash
cd ~/gt && bd show hq-2cchm    # Works
cd ~/gt/beads/crew/emma && bd show hq-2cchm  # Fails: 'no issue found'
```

## Root Cause
routes.jsonl has: {"prefix": "hq-", "path": "."}

The '.' is resolved relative to cwd, so from crew/emma it looks for ~/gt/beads/crew/emma/.beads/ instead of ~/gt/.beads/

## Fix
The routing logic should resolve '.' as the town root, or the route should use an absolute path or a sentinel like 'TOWN_ROOT'.


Centralize error handling patterns in storage layer

80+ instances of inconsistent error handling across sqlite.go with mix of %w, %v, and no wrapping.

Location: internal/storage/sqlite/sqlite.go (throughout)

Problem:
- Some use fmt.Errorf("op failed: %w", err) - correct wrapping
- Some use fmt.Errorf("op failed: %v", err) - loses error chain
- Some return err directly - no context
- Hard to debug production issues
- Can't distinguish error types

Solution: Create internal/storage/sqlite/errors.go:
- Define sentinel errors (ErrNotFound, ErrInvalidID, etc.)
- Create wrapDBError(op string, err error) helper
- Convert sql.ErrNoRows to ErrNotFound
- Always wrap with operation context

Impact: Lost error context; inconsistent messages; hard to debug

Effort: 5-7 hours


bd close hooks: context check and notifications

Add hook system to bd close for notifications and custom actions.

## Scope (MVP)

Implement **command hooks only** for bd close. Deferred: notify, webhook types.

## Implementation

### 1. Config Schema

Add to internal/configfile/config.go:

```go
type HooksConfig struct {
    OnClose []HookEntry `yaml:"on_close,omitempty"`
}

type HookEntry struct {
    Command string `yaml:"command"`           // Shell command to run
    Name    string `yaml:"name,omitempty"`    // Optional display name
}
```

Add `Hooks HooksConfig` field to Config struct.

### 2. Hook Execution

Create internal/hooks/close_hooks.go:

```go
func RunCloseHooks(ctx context.Context, cfg *configfile.Config, issue *types.Issue) error {
    for _, hook := range cfg.Hooks.OnClose {
        cmd := exec.CommandContext(ctx, "sh", "-c", hook.Command)
        cmd.Env = append(os.Environ(),
            "BEAD_ID="+issue.ID,
            "BEAD_TITLE="+issue.Title,
            "BEAD_TYPE="+string(issue.IssueType),
            "BEAD_PRIORITY="+strconv.Itoa(issue.Priority),
            "BEAD_CLOSE_REASON="+issue.CloseReason,
        )
        cmd.Stdout = os.Stdout
        cmd.Stderr = os.Stderr
        if err := cmd.Run(); err \!= nil {
            // Log warning but dont fail the close
            fmt.Fprintf(os.Stderr, "Warning: close hook %q failed: %v\n", hook.Name, err)
        }
    }
    return nil
}
```

### 3. Integration Point

In cmd/bd/close.go, after successful close:

```go
// Run close hooks
if cfg := configfile.Load(); cfg \!= nil {
    hooks.RunCloseHooks(ctx, cfg, closedIssue)
}
```

### 4. Example Config

```yaml
# .beads/config.yaml
hooks:
  on_close:
    - name: show-next
      command: bd ready --limit 1
    - name: context-check
      command: echo "Issue $BEAD_ID closed. Check context if nearing limit."
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| BEAD_ID | Issue ID (e.g., bd-abc1) |
| BEAD_TITLE | Issue title |
| BEAD_TYPE | Issue type (task, bug, feature, etc.) |
| BEAD_PRIORITY | Priority (0-4) |
| BEAD_CLOSE_REASON | Close reason if provided |

## Testing

Add test in internal/hooks/close_hooks_test.go:
- Test hook execution with mock config
- Test env vars are set correctly
- Test hook failure doesnt block close

## Files to Create/Modify

1. **Create:** internal/hooks/close_hooks.go
2. **Create:** internal/hooks/close_hooks_test.go
3. **Modify:** internal/configfile/config.go (add HooksConfig)
4. **Modify:** cmd/bd/close.go (call RunCloseHooks)
5. **Modify:** docs/CONFIG.md (document hooks config)

## Out of Scope (Future)

- notify hook type (gt mail integration)
- webhook type (HTTP POST)
- on_create, on_update hooks
- Hook timeout configuration
- Parallel hook execution


GetBlockedIssues shows external deps as blocking even when satisfied

GetBlockedIssues (ready.go:385-493) shows external:* refs in the blocked_by list but doesn't check if they're actually satisfied using CheckExternalDep.

This can be confusing - an issue shows as blocked by external:project:capability even if that capability has been shipped (closed issue with provides: label exists).

Options:
1. Call CheckExternalDep for each external ref and filter satisfied ones from blocked_by
2. Add a note in output indicating external deps need lazy resolution
3. Document this is expected behavior (bd blocked shows all deps, bd ready shows resolved state)

Related: GetReadyWork correctly filters by external deps, but GetBlockedIssues doesn't.


Move pour/ephemeral under bd mol subcommand

For consistency, bd pour and bd ephemeral should become bd mol pour and bd mol ephemeral:

Current:
  bd mol list                  # Available protos
  bd mol show <id>             # Proto details
  bd pour <proto>              # Create mol ← sticks out
  bd ephemeral <proto>         # Create ephemeral ← sticks out
  bd mol bond <proto> <parent> # Attach to existing mol
  bd mol squash <id>           # Condense to digest
  bd mol burn <id>             # Discard

Proposed:
  bd mol list
  bd mol show <id>
  bd mol pour <proto>          # Moved under mol
  bd mol ephemeral <proto>     # Moved under mol
  bd mol bond <proto> <parent>
  bd mol squash <id>
  bd mol burn <id>

All molecule operations should be under bd mol for discoverability and consistency.


Test Agent


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 missing hook calls in mail reply and ack

The mail commands are missing hook calls:

1. runMailReply (mail.go:525-672) creates a message but doesn't call hookRunner.Run(hooks.EventMessage, ...) after creating the reply in direct mode (around line 640)

2. runMailAck (mail.go:432-523) closes messages but doesn't call hookRunner.Run(hooks.EventClose, ...) after closing each message (around line 487 for daemon mode, 493 for direct mode)

This means GGT hooks won't fire for replies or message acknowledgments.


Add tests for mol spawn --attach

Code review (bd-obep) found no tests for the spawn --attach functionality.

**Test cases needed:**
1. Basic attach - spawn proto with one --attach
2. Multiple attachments - spawn with --attach A --attach B
3. Attach types - verify sequential vs parallel bonding
4. Error case: attaching non-proto (missing template label)
5. Variable aggregation - vars from primary + attachments combined
6. Dry-run output includes attachment info

**Implementation notes:**
- Tests should use in-memory storage
- Create test protos, spawn with attachments, verify dependency structure
- Check that sequential uses 'blocks' type, parallel uses 'parent-child'


Commit release

git add -A && git commit -m 'release: v{{version}}'


Final release verification

Verify all release artifacts are accessible:

- [ ] `bd --version` shows 0.30.4
- [ ] `bd version --daemon` shows 0.30.4
- [ ] GitHub release exists: https://github.com/steveyegge/beads/releases/tag/v0.30.4
- [ ] `brew upgrade beads && bd --version` shows 0.30.4 (if using Homebrew)
- [ ] `pip show beads-mcp` shows 0.30.4
- [ ] npm package available at 0.30.4
- [ ] `bd info --whats-new` shows 0.30.4 notes

Run final checks:
```bash
bd --version
bd version --daemon
pip show beads-mcp | grep Version
bd info --whats-new
```


bd close --continue: auto-advance to next molecule step

Add --continue flag to bd close for seamless molecule step transitions.

## Usage

bd close <step-id> --continue [--no-auto]

## Behavior

1. Closes the specified step
2. Finds next ready step in same molecule (sibling/child)
3. By default, marks it in_progress (--no-auto to skip)
4. Outputs the transition

## Output

[done] Closed gt-abc.3: Implement feature

Next ready in molecule:
  gt-abc.4: Write tests

[arrow] Marked in_progress (use --no-auto to skip)

## If no next step

[done] Closed gt-abc.6: Exit decision

Molecule gt-abc complete! All steps closed.
Consider: bd mol squash gt-abc --summary '...'

## Key behaviors
- Detects parent molecule from closed step
- Finds next unblocked sibling
- Auto-claims by default (propulsion principle)
- Graceful handling when molecule is complete

## Gas Town integration
- gt-lz13: Update templates with nav workflow
- gt-um6q: Update docs with nav workflow


test pin issue