Commit Graph

66 Commits

Author SHA1 Message Date
aleiby
0b6df198a5 fix(ready): exclude molecule steps from bd ready by default (#1246)
* fix(ready): exclude molecule steps from bd ready by default (GH#1239)

Add ID prefix constants (IDPrefixMol, IDPrefixWisp) to types.go as single
source of truth. Update pour.go and wisp.go to use these constants.

GetReadyWork now excludes issues with -mol- in their ID when no explicit
type filter is specified. Users can still see mol steps with --type=task.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(ready): config-driven ID pattern exclusion (GH#1239)

Add ready.exclude_id_patterns config for excluding IDs from bd ready.
Default patterns: -mol-, -wisp- (molecule steps and wisps).

Changes:
- Add IncludeMolSteps to WorkFilter for internal callers
- Update findGateReadyMolecules and getMoleculeCurrentStep to use it
- Make exclusion patterns config-driven via ready.exclude_id_patterns
- Remove hardcoded MolStepIDPattern() in favor of config
- Add test for custom patterns (e.g., gastown's -role-)

Usage: bd config set ready.exclude_id_patterns "-mol-,-wisp-,-role-"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: remove -role- example from ready.go comments

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: remove GH#1239 references from code comments

Issue references belong in commit messages, not code.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 19:30:15 -08:00
beads/crew/collins
458fb7197a fix(sqlite): handle text timestamps in scan for cross-driver compatibility
The ncruces/go-sqlite3 driver does not always auto-convert TEXT columns
to time.Time. This caused scan errors on updated_at/created_at fields,
blocking witness startup.

Fix: Scan timestamps into sql.NullString and parse with parseTimeString()
helper that handles RFC3339Nano, RFC3339, and SQLite native formats.

Fixes: bd-4dqmy

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 20:48:08 -08:00
Daniel Sauer
4fffdb7fae fix(sqlite): add missing agent fields to scanIssues and related queries (#1176)
The scanIssues() function and multiple SQL queries were not selecting or
scanning agent-related fields (hook_bead, role_bead, agent_state, last_activity,
role_type, rig, mol_type) and time-based scheduling fields (due_at, defer_until).

This caused bd list --json to return null for last_activity even when the
database contained valid timestamps, preventing proper agent health monitoring.

Updated files:
- dependencies.go: scanIssues() variable declarations, scan calls, assignments
- queries.go: SearchIssues query
- labels.go: GetIssuesByLabel query
- ready.go: GetReadyWork and GetNewlyUnblockedByClose queries
- transaction.go: GetIssue query, SearchIssues query, scanIssueRow()

Fixes steveyegge/beads#1175
2026-01-19 10:11:03 -08:00
aleiby
490e9f695f fix: exclude role and rig types from bd ready (#1105)
Role and rig beads are reference metadata that should never be closed
or appear as actionable work. They are similar to agent beads which
are already excluded.

- Add 'role' and 'rig' to the issue type exclusion list in GetReadyWork
- Update comments to document the excluded types

Fixes confusion where role/rig beads appeared in bd ready output,
leading agents to try to close them as regular work items.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 19:20:58 -08:00
dennis
f703237c3d fix(ready): prevent wisps from appearing in bd ready
Add multiple layers of defense against misclassified wisps:
- Importer auto-detects -wisp- pattern and sets ephemeral flag
- GetReadyWork excludes -wisp- IDs via SQL LIKE clause
- Doctor check 26d detects misclassified wisps in JSONL

This addresses recurring issue where wisps with missing ephemeral
flag would pollute bd ready output after JSONL import.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 00:14:12 -08:00
beads/crew/fang
0de6b10ac0 fix: add missing crystallizes column to SELECT queries and remove duplicate
- Remove duplicate crystallizes column from schema.go
- Add crystallizes to SELECT in transaction.go SearchIssues
- Add crystallizes to SELECT in ready.go GetReadyWork and GetNewlyUnblockedByClose
- Add crystallizes to SELECT in labels.go GetIssuesByLabel
- Add missing placeholder in issues.go INSERT VALUES
- Update migrations_test.go schema to include crystallizes column

Fixes test failures caused by schema/query column count mismatches.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 23:55:16 -08:00
beads/crew/dave
ceb5769c75 feat: add owner field for human attribution in HOP CV chains
Add 'owner' field to Issue struct for tracking the human responsible
for the issue, distinct from 'created_by' which tracks the executor.
Owner is populated from git author email (GIT_AUTHOR_EMAIL or git
config user.email), per Decision 008 for CV accumulation.

Changes:
- Add Owner field to types.Issue with omitempty JSON tag
- Include Owner in content hash computation
- Add owner column migration (036_owner_column.go)
- Update all SQL queries to include owner field
- Add getOwner() helper using git author email fallback chain
- Populate owner in bd create command
- Add owner to RPC CreateArgs protocol

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Executed-By: beads/crew/dave
Rig: beads
Role: crew
2026-01-10 19:28:08 -08:00
fang
a851104203 fix: prevent closing issues with open blockers (GH#962)
Added IsBlocked method to Storage interface that checks if an issue is
in the blocked_issues_cache and returns the blocking issue IDs.

The close command now checks for blockers before allowing an issue to
be closed:
- If an issue has open blockers, closing is blocked with an error message
- The --force flag overrides this check
- Works in both daemon mode (RPC) and direct storage mode
- Also handles cross-rig routed IDs

This addresses the bug where agents could close a bead even when it
depends on an open bug/issue.

Closes #962

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 22:57:07 -08:00
beads/crew/grip
32a4a9e060 perf: batch external dep checks by project (bd-687v)
Optimize CheckExternalDeps to group refs by project and open each
external DB only once, checking all capabilities in a single query.

Before: If 10 issues depend on external:gastown:cap1, we opened
gastown's DB 10 times.

After: We open each external project's DB once, query for all
capabilities needed from that project, then close.

Also added deduplication in filterByExternalDeps to collect all
unique refs before checking, avoiding redundant checks for the
same ref across multiple issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 17:17:47 -08:00
Peter Chanthamynavong
d371baf2ca feat(dates): add --due and --defer timestamp options with natural language parsing (#847)
* feat(dates): add due date schema and --due flag

- Add due_at and defer_until columns to issues table via migration 035
- Implement --due flag on create command with ISO date parsing
- Extend RPC protocol and daemon to pass DueAt from CLI to storage
- Display DueAt and DeferUntil in show command output
- Update Issue type with new date fields

Users can now set due dates when creating issues, enabling deadline-based
task management.

* feat(dates): add compact duration parser (+6h, +1d, +2w)

- Create internal/timeparsing package with layered parser architecture
- Implement parseCompactDuration with regex pattern [+-]?\d+[hdwmy]
- Add comprehensive test suite (22 cases) for duration parsing
- Integrate into create.go with fallback to ISO format

Supports hours (h), days (d), weeks (w), months (m), and years (y).
Negative values allowed for past dates.

* feat(dates): add NLP parsing for natural language dates

Integrate olebedev/when library for natural language time expressions.
The layered parser now handles: compact duration → absolute formats → NLP.

Changes:
- Add olebedev/when dependency for NLP parsing
- Implement ParseNaturalLanguage and ParseRelativeTime functions
- Reorder layers: absolute formats before NLP to avoid misinterpretation
- Simplify create.go to use unified ParseRelativeTime
- Add comprehensive NLP test coverage (22 test cases)

Supports: tomorrow, next monday, in 3 days, 3 days ago

* feat(dates): add --defer flag to create/update/defer commands

Add time-based deferral support alongside existing status-based defer.
Issues can now be hidden from bd ready until a specific time.

Changes:
- Add --defer flag to bd create (sets defer_until on creation)
- Add --due and --defer flags to bd update (modify existing issues)
- Add --until flag to bd defer (combines status=deferred with defer_until)
- Add DueAt/DeferUntil fields to UpdateArgs in protocol.go

Supports: +1h, tomorrow, next monday, 2025-01-15

* feat(dates): add defer_until filtering to ready command

Add time-based deferral support to bd ready:

- Add --include-deferred flag to show issues with future defer_until
- Filter out issues where defer_until > now by default
- Update undefer to clear defer_until alongside status change
- Add IncludeDeferred to WorkFilter and RPC ReadyArgs

Part of GH#820: Relative Date Parsing (Phase 5)

* feat(dates): add polish and tests for relative date parsing

Add user-facing warnings when defer date is in the past to help catch
common mistakes. Expand help text with format examples and document
the olebedev/when September parsing quirk.

Tests:
- TestCreateSuite/WithDueAt, WithDeferUntil, WithBothDueAndDefer
- TestReadyWorkDeferUntil (ExcludesFutureDeferredByDefault, IncludeDeferredShowsAll)

Docs:
- CLAUDE.md quick reference updated with new flags
- Help text examples for --due, --defer on create/update

Closes: Phase 6 of beads-820-relative-dates spec

* feat(list): add time-based query filters for defer/due dates

Add --deferred, --defer-before, --defer-after, --due-before, --due-after,
and --overdue flags to bd list command. All date filters now support
relative time expressions (+6h, tomorrow, next monday) via the
timeparsing package.

Filters:
- --deferred: issues with defer_until set
- --defer-before/after: filter by defer_until date range
- --due-before/after: filter by due_at date range
- --overdue: due_at in past AND status != closed

Existing date filters (--created-after, etc.) now also support relative
time expressions through updated parseTimeFlag().

* build(nix): update vendorHash for olebedev/when dependency

The olebedev/when library was added for natural language date parsing
(GH#820). This changes go.sum, requiring an updated vendorHash in the
Nix flake configuration.
2026-01-01 20:06:13 -08:00
Steve Yegge
b919c47fd8 Exclude agent type from bd ready by default
Agent beads are identity/state tracking beads for agents, not actionable work items.
2025-12-30 18:13:12 -08:00
Steve Yegge
7d1ee6d3e9 feat: Add 'hooked' status for GUPP work assignment (bd-s00m)
Separates semantics of 'pinned' (identity records) from work-on-hook:
- 'pinned' = domain table / identity record (agents, roles) - non-blocking
- 'hooked' = work on agent's hook (GUPP-driven) - blocks dependents

Changes:
- Add StatusHooked constant to types.go
- Update all blocking queries to include 'hooked' status
- Add cyan styling for 'hooked' in UI output
- Create migration 032 to convert pinned work items to hooked

Generated with Claude Code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 22:37:04 -08:00
Steve Yegge
f3dcafca66 feat: Add mol_type schema field for molecule type classification (bd-oxgi)
Add mol_type field to beads for swarm coordination:
- Values: 'swarm' (multi-polecat), 'patrol' (recurring ops), 'work' (default)
- Nullable, defaults to empty string (treated as 'work')

Changes:
- Add mol_type column to SQLite schema and migration 031
- Add MolType type with IsValid() validation in types.go
- Update insertIssue/GetIssue to handle mol_type
- Add --mol-type flag to create command
- Add mol_type filtering to list and ready commands
- Update RPC protocol for daemon mode support
- Update test schema in migrations_test.go

🤝 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 19:52:51 -08:00
Steve Yegge
f46cc2e798 chore: remove issue ID references from comments and changelogs
Strip (bd-xxx), (gt-xxx) suffixes from code comments and changelog
entries. The descriptions remain meaningful without the ephemeral
issue IDs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 10:05:16 -08:00
Steve Yegge
1611f16751 refactor: remove unused bd pin/unpin/hook commands (bd-x0zl)
Analysis found these commands are dead code:
- gt never calls `bd pin` - uses `bd update --status=pinned` instead
- Beads.Pin() wrapper exists but is never called
- bd hook functionality duplicated by gt mol status
- Code comment says "pinned field is cosmetic for bd hook visibility"

Removed:
- cmd/bd/pin.go
- cmd/bd/unpin.go
- cmd/bd/hook.go

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 16:02:15 -08:00
Steve Yegge
c8b912cbe6 bd sync: 2025-12-27 15:56:42 2025-12-27 15:56:42 -08:00
Steve Yegge
ea8ae11002 feat: Rename 'wisp' to 'ephemeral' in beads API (bd-o18s)
BREAKING CHANGE: API field and CLI command renamed

- types.Issue.Wisp → types.Issue.Ephemeral
- JSON field: "wisp" → "ephemeral"
- CLI: bd wisp → bd ephemeral
- Flags: --wisp → --ephemeral
- ID prefix: wisp → eph

The SQLite column already uses 'ephemeral' so no schema migration needed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 21:07:37 -08:00
Steve Yegge
05b84c3925 fix: bd ready excludes ephemeral (wisp) issues (hq-t15s)
Wisps are ephemeral issues used for patrol/operational cycles and should
not appear in `bd ready` output as trackable work items. Added ephemeral
exclusion filter to both the GetReadyWork() function and ready_issues VIEW.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 20:51:51 -08:00
Steve Yegge
c3ef1c3f38 feat: Add created_by field to issues (GH#748)
Add a created_by field to track who created each issue, similar to how
comments have an author field.

- Add CreatedBy string field to Issue struct
- Add migration 029 to add created_by column to issues table
- Update all SELECT/INSERT/Scan statements across storage layer
- Populate created_by in bd create from actor chain
- Display created_by in bd show output

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 13:33:54 -08:00
Aarya Reddy
bd5fc214c3 feat(ready,blocked): Add --parent flag for scoping by epic/bead desce… (#743)
* feat(ready,blocked): Add --parent flag for scoping by epic/bead descendants

Add --parent flag to `bd ready` and `bd blocked` CLI commands and MCP tools
to filter results to all descendants of a specific epic or bead.

## Backward Compatibility

- CLI: New optional --parent flag; existing usage unchanged
- RPC: New `blocked` operation added (was missing); existing operations unchanged
- MCP: New optional `parent` parameter; existing calls work as before
- Storage interface: GetBlockedIssues signature changed to accept WorkFilter
  - All callers updated to pass empty filter for existing behavior
  - Empty WorkFilter{} returns identical results to previous implementation

## Implementation Details

SQLite uses recursive CTE to traverse parent-child hierarchy:

    WITH RECURSIVE descendants AS (
        SELECT issue_id FROM dependencies
        WHERE type = 'parent-child' AND depends_on_id = ?
        UNION ALL
        SELECT d.issue_id FROM dependencies d
        JOIN descendants dt ON d.depends_on_id = dt.issue_id
        WHERE d.type = 'parent-child'
    )
    SELECT issue_id FROM descendants

MemoryStorage implements equivalent recursive traversal with visited-set
cycle protection via collectDescendants helper.

Parent filter composes with existing filters (priority, labels, assignee, etc.)
as an additional WHERE clause - all filters are AND'd together.

## RPC Blocked Support

MCP beads_blocked() existed but daemon client raised NotImplementedError.
Added OpBlocked and handleBlocked to enable daemon RPC path, which was
previously broken. Now both CLI and daemon clients work for blocked queries.

## Changes

- internal/types/types.go: Add ParentID *string to WorkFilter
- internal/storage/sqlite/ready.go: Add recursive CTE for parent filtering
- internal/storage/memory/memory.go: Add getAllDescendants/collectDescendants
- internal/storage/storage.go: Update GetBlockedIssues interface signature
- cmd/bd/ready.go: Add --parent flag to ready and blocked commands
- internal/rpc/protocol.go: Add OpBlocked constant and BlockedArgs type
- internal/rpc/server_issues_epics.go: Add handleBlocked RPC handler
- internal/rpc/client.go: Add Blocked client method
- integrations/beads-mcp/: Add BlockedParams model and parent parameter

## Usage

  bd ready --parent bd-abc              # All ready descendants
  bd ready --parent bd-abc --priority 1 # Combined with other filters
  bd blocked --parent bd-abc            # All blocked descendants

## Testing

Added 4 test cases for parent filtering:
- TestParentIDFilterDescendants: Verifies recursive traversal (grandchildren)
- TestParentIDWithOtherFilters: Verifies composition with priority filter
- TestParentIDWithBlockedDescendants: Verifies blocked issues excluded from ready
- TestParentIDEmptyParent: Verifies empty result for childless parent

* fix: Correct blockedCmd indentation and suppress gosec false positive

- Fix syntax error from incorrect indentation in blockedCmd Run function
- Add nolint:gosec comment for GetBlockedIssues SQL formatting (G201)
  The filterSQL variable contains only parameterized WHERE clauses with
  ? placeholders, not user input
2025-12-25 21:11:58 -08:00
Steve Yegge
f3a5e02a35 feat(close): Add --suggest-next flag to show newly unblocked issues (GH#679)
When closing an issue, the new --suggest-next flag returns a list of
issues that became unblocked (ready to work on) as a result of the close.

This helps agents and users quickly identify what work is now available
after completing a blocker.

Example:
  $ bd close bd-5 --suggest-next
  ✓ Closed bd-5: Completed

  Newly unblocked:
    • bd-7 "Implement feature X" (P1)
    • bd-8 "Write tests for X" (P2)

Implementation:
- Added GetNewlyUnblockedByClose to storage interface
- Implemented efficient single-query for SQLite using blocked_issues_cache
- Added SuggestNext field to CloseArgs in RPC protocol
- Added CloseResult type for structured response
- CLI handles both daemon and direct modes

Thanks to @kraitsura for the detailed feature request and design.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 20:05:04 -08:00
Steve Yegge
e67f27c092 bd sync: 2025-12-23 23:38:57 2025-12-24 00:06:41 -08:00
Steve Yegge
2de1695615 bd sync: 2025-12-23 22:33:32 2025-12-23 22:33:33 -08:00
Steve Yegge
cf9e5a597b bd sync: 2025-12-23 20:50:50 2025-12-23 20:50:50 -08:00
Steve Yegge
9c8761abc9 bd sync: 2025-12-23 20:45:19 2025-12-23 20:45:19 -08:00
Steve Yegge
fe2ac97597 fix: Exclude workflow types from bd ready by default (gt-7xtn)
merge-request, gate, molecule, and message types are internal workflow
items processed by Refinery/Deacon, not work for polecats to claim.
These are now excluded from bd ready unless explicitly requested via
--type flag.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 15:05:51 -08:00
Steve Yegge
47b86b35d8 feat: add gate issue type and CLI commands for async coordination (bd-udsi)
Add async gates - coordination primitives for agents to wait on external events
like CI completion, PR merges, timers, or human approval.

Changes:
- Add 'gate' issue type to types.go with gate-specific fields:
  - AwaitType: condition type (gh:run, gh:pr, timer, human, mail)
  - AwaitID: condition identifier
  - Timeout: max wait duration
  - Waiters: mail addresses to notify when gate clears
- Add SQLite migration 027_gate_columns for new fields
- Update all SQLite storage queries to handle gate fields
- Add bd gate commands: create, show, list, close, wait
- All commands support --json output and --no-daemon mode

Closes: bd-2v0f, bd-lz49, bd-u66e

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 12:06:42 -08:00
Steve Yegge
340417f393 fix: filter satisfied external deps from GetBlockedIssues (bd-396j)
GetBlockedIssues was showing external deps as blocking even when they
were satisfied (had a closed issue with provides:capability label).

Added filterBlockedByExternalDeps() which:
- Collects all external refs from blocked issues
- Checks each with CheckExternalDeps() in batch
- Filters satisfied refs from BlockedBy lists
- Updates BlockedByCount accordingly
- Removes issues with no remaining blockers (unless status=blocked/deferred)

This matches the behavior of GetReadyWork which already filters by
external deps correctly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 21:48:55 -08:00
Ryan
a11b20960a fix(doctor): UX improvements for diagnostics and daemon (#687)
* fix(doctor): UX improvements for diagnostics and daemon

- Add Repo Fingerprint check to detect when database belongs to a
  different repository (copied .beads dir or git remote URL change)
- Add interactive fix for repo fingerprint with options: update repo ID,
  reinitialize database, or skip
- Add visible warning when daemon takes >5s to start, recommending
  'bd doctor' for diagnosis
- Detect install method (Homebrew vs script) and show only relevant
  upgrade command
- Improve WARNINGS section:
  - Add icons (⚠ or ✖) next to each item
  - Color numbers by severity (yellow for warnings, red for errors)
  - Render entire error lines in red
  - Sort by severity (errors first)
  - Fix alignment with checkmarks above
- Use heavier fail icon (✖) for better visibility
- Add integration and validation tests for doctor fixes

* fix(lint): address errcheck and gosec warnings

- mol_bond.go: explicitly ignore ephStore.Close() error
- beads.go: add nosec for .gitignore file permissions (0644 is standard)
2025-12-22 01:25:23 -08:00
Steve Yegge
1cfb23487b feat: bd ready filters by external dep satisfaction (bd-zmmy)
GetReadyWork now lazily resolves external dependencies at query time:
- External refs (external:project:capability) checked against target DB
- Issues with unsatisfied external deps are filtered from ready list
- Satisfaction = closed issue with provides:<capability> label in target

Key changes:
- Remove FK constraint on depends_on_id to allow external refs
- Add migration 025 to drop FK and recreate views
- Filter external deps in GetReadyWork, not in blocked_issues_cache
- Add application-level validation for orphaned local deps
- Comprehensive tests for external dep resolution

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 23:41:44 -08:00
Steve Yegge
e7f09660c0 feat: add cross-project dependency support - config and external: prefix (bd-66w1, bd-om4a)
Config (bd-66w1):
- Add external_projects config for mapping project names to paths
- Add GetExternalProjects() and ResolveExternalProjectPath() functions
- Add config documentation and tests

External deps (bd-om4a):
- bd dep add accepts external:project:capability syntax
- External refs stored as-is in dependencies table
- GetBlockedIssues includes external deps in blocked_by list
- blocked_issues_cache includes external dependencies
- Add validation and parsing helpers for external refs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 23:08:00 -08:00
Steve Yegge
358d076fde refactor: rename Ephemeral → Wisp (Steam Engine metaphor)
Wisp = ephemeral vapor produced by the Steam Engine (Gas Town).
This aligns with the metaphor:
- Claude = Fire
- Claude Code = Steam
- Gas Town = Steam Engine
- Wisps = ephemeral vapor it produces

Changes:
- types.Issue.Ephemeral → types.Issue.Wisp
- types.IssueFilter.Ephemeral → types.IssueFilter.Wisp
- JSON field: "ephemeral" → "wisp"
- CLI flag: --ephemeral → --wisp (bd cleanup)
- All tests updated

Note: SQLite column remains "ephemeral" (no migration needed).
This is a breaking change for JSON consumers using 0.33.0.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 15:22:45 -08:00
Steve Yegge
e778b3f648 feat(status): add deferred status for icebox issues (bd-4jr)
Add 'deferred' as a valid issue status for issues that are deliberately
put on ice - not blocked by dependencies, just postponed for later.

Changes:
- Add StatusDeferred constant and update IsValid() validation
- Add DeferredIssues to Statistics struct with counting in both SQLite
  and memory storage
- Add 'bd defer' command to set status to deferred
- Add 'bd undefer' command to restore status to open
- Update help text across list, search, count, dep, stale, and config
- Update MCP server models and tools to accept deferred status
- Add deferred to blocker status checks (schema, cache, ready, compact)
- Add StatusDeferred to public API exports (beads.go, internal/beads)
- Add snowflake styling for deferred in dep tree and graph views

Semantics:
- deferred vs blocked: deferred is a choice, blocked is forced
- deferred vs closed: deferred will be revisited, closed is done
- Deferred issues excluded from 'bd ready' (already works since
  default filter only includes open/in_progress)
- Deferred issues still block dependents (they are not done!)
- Deferred issues visible in 'bd list' and 'bd stale'

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 14:24:48 -08:00
Steve Yegge
52135d0370 feat(types): add template molecules infrastructure for beads-1ra
Add support for template molecules (is_template field and TypeMolecule type):

- Add IsTemplate field to Issue type with JSON support
- Add TypeMolecule constant to IssueType constants
- Add IsTemplate filter to IssueFilter for querying
- Update all SQL queries to include is_template column
- Add migration 024 for is_template column
- Add FindMoleculesJSONLInDir helper for molecules.jsonl path detection

This enables treating certain issues as read-only templates that can be
instantiated to create work items. The template flag allows separating
template molecules from regular work items in queries and exports.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 22:03:22 -08:00
Steve Yegge
c84a2404b7 feat(ready): add --type flag for filtering by issue type (gt-ktf3)
Enables bd ready --type=merge-request for MQ integration.
The Engineer can now query for ready merge-requests.

Files changed:
- cmd/bd/ready.go: Add -t/--type flag
- internal/types/types.go: Add Type field to WorkFilter
- internal/rpc/protocol.go: Add Type to ReadyArgs
- internal/storage/sqlite/ready.go: Filter by issue_type column
2025-12-19 15:09:30 -08:00
Steve Yegge
c78347c4c4 Merge polecat/Morsov: exclude pinned from bd ready 2025-12-19 01:28:26 -08:00
Steve Yegge
44f87dc1a2 Merge polecat/Nux: exclude pinned from bd blocked 2025-12-19 01:27:41 -08:00
Steve Yegge
5aacff4423 feat(ready): exclude pinned issues from bd ready (beads-92u)
Pinned issues are persistent anchors that should not appear in ready
work lists. This adds:

- Pinned bool field to Issue struct
- pinned INTEGER DEFAULT 0 column to schema
- Migration 023 to add pinned column to existing databases
- WHERE i.pinned = 0 filter in GetReadyWork query

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 00:47:50 -08:00
Steve Yegge
9e85aa9f9a feat(blocked): exclude pinned issues from bd blocked output
- Add Pinned field to Issue struct in types.go
- Create migration 023 to add pinned column with partial index
- Update SQLite GetBlockedIssues to filter WHERE pinned = 0
- Update Memory GetBlockedIssues to skip pinned issues
- Update schema.go with pinned column definition

Pinned issues are tracked but excluded from the blocked list to
reduce noise for issues that are intentionally parked.

Closes: beads-ei4

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 00:37:16 -08:00
Steve Yegge
b1ba1c5315 feat(storage): add pinned field to issues schema
Add pinned column to the issues table to support persistent context markers
that should not be treated as work items (bd-7h5).

Changes:
- Add pinned column to schema.go CREATE TABLE
- Add migration 023_pinned_column.go for existing databases
- Update all issue queries to include pinned column
- Update scanIssues and scanIssuesWithDependencyType to handle pinned field
- Add Pinned field to types.Issue struct with JSON serialization
- Fix migrations_test.go to include pinned in legacy schema test

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 00:08:32 -08:00
Steve Yegge
7c8b69f5b3 Phase 4: Remove deprecated edge fields from Issue struct (Decision 004)
This is the final phase of the Edge Schema Consolidation. It removes
the deprecated edge fields (RepliesTo, RelatesTo, DuplicateOf, SupersededBy)
from the Issue struct and all related code.

Changes:
- Remove edge fields from types.Issue struct
- Remove edge field scanning from queries.go and transaction.go
- Update graph_links_test.go to use dependency API exclusively
- Update relate.go to use AddDependency/RemoveDependency
- Update show.go with helper functions for thread traversal via deps
- Update mail_test.go to verify thread links via dependencies
- Add migration 022 to drop columns from issues table
- Fix cycle detection to allow bidirectional relates-to links
- Fix migration 022 to disable foreign keys before table recreation

All edge relationships now use the dependencies table exclusively.
The old Issue fields are fully removed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 02:48:13 -08:00
Steve Yegge
0aea2d93c6 feat(schema): add messaging fields for bd-kwro epic
- Add TypeMessage issue type for inter-agent communication
- Add 6 new Issue fields: Sender, Ephemeral, RepliesTo, RelatesTo,
  DuplicateOf, SupersededBy
- Add 4 new dependency types: replies-to, relates-to, duplicates, supersedes
- Create migration 019_messaging_fields with indexes
- Update all CRUD operations across storage layer
- Fix reset_test.go to use correct function names
- Fix redundant newline lint error in sync.go

Closes: bd-kwro.1

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-16 13:06:47 -08:00
Steve Yegge
8e58c306a7 fix(sync,blocked): add safety guards for issue deletion and include status=blocked in bd blocked
GH#464: Add safety guards to prevent deletion of open/in_progress issues during sync:
- Safety guard in git-history-backfill (importer.go)
- Safety guard in deletions manifest processing
- Warning when uncommitted changes detected before pull (daemon_sync.go)
- Enhanced repo ID mismatch error message

GH#545: Fix bd blocked to show status=blocked issues (sqlite/ready.go):
- Changed from INNER JOIN to LEFT JOIN to include issues without dependencies
- Added WHERE clause to include both status=blocked AND dependency-blocked issues

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 23:07:54 -08:00
Steve Yegge
18b1eb2e07 fix(sqlite): handle deleted_at TEXT column scanning properly
The deleted_at column was defined as TEXT in the schema but code was
trying to scan into sql.NullTime. The ncruces/go-sqlite3 driver only
auto-converts TEXT to time.Time for columns declared as DATETIME/DATE/
TIME/TIMESTAMP. For TEXT columns, it returns raw strings which
sql.NullTime.Scan() cannot handle.

Added parseNullableTimeString() helper that manually parses time strings
and changed all deletedAt variables from sql.NullTime to sql.NullString.

Fixes import failure: "sql: Scan error on column index 22, name
deleted_at: unsupported Scan, storing driver.Value type string into
type *time.Time"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 07:13:40 -08:00
Steve Yegge
08e43d9fc7 feat(types): add tombstone support for inline soft-delete (bd-fbj)
Add tombstone types and schema migration as foundation for the tombstone
epic (bd-vw8) which replaces deletions.jsonl with inline tombstones.

Changes:
- Add tombstone fields to Issue struct: DeletedAt, DeletedBy, DeleteReason, OriginalType
- Add StatusTombstone constant and IsTombstone() helper method
- Update Status.IsValid() to accept tombstone status
- Create migration 018_tombstone_columns.go for new database columns
- Update schema.go with tombstone columns: deleted_at, deleted_by, delete_reason, original_type
- Update all issue insert/update/scan operations across:
  - issues.go (insertIssue, insertIssues)
  - queries.go (GetIssue, GetIssueByExternalRef, SearchIssues)
  - dependencies.go (scanIssues, scanIssuesWithDependencyType)
  - transaction.go (scanIssueRow, GetIssue, SearchIssues)
  - multirepo.go (import operations)
  - ready.go (GetReadyWork, GetStaleIssues)
  - labels.go (GetIssuesByLabel)
- Add test for IsTombstone() helper
- Update migration test to include tombstone columns

Unblocks: bd-olt (TTL logic), bd-3b4 (delete command), bd-0ih (merge updates), bd-dve (import/export)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 15:29:42 -08:00
Steve Yegge
09fffa4eaf fix(db): add close_reason column to issues table (bd-uyu)
- Add migration 017_close_reason_column.go to create the column
- Update all INSERT statements to include close_reason
- Update all SELECT statements to include close_reason
- Update doctor.go to check for close_reason in schema validation
- Remove workaround code that batch-loaded close reasons from events table
- Fix migrations_test.go to include close_reason in test table schema

This fixes sync loops where close_reason values were silently dropped
because the DB lacked the column despite the struct having the field.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 21:56:41 -08:00
Steve Yegge
64771a28d2 feat(ready): add --unassigned filter for bd ready
Add -u/--unassigned flag to bd ready command to show only issues
with no assignee. This supports the SCAVENGE protocol where polecats
query the 'Salvage Yard' for unassigned ready work.

Changes:
- Add NoAssignee field to WorkFilter struct
- Update SQLite GetReadyWork to filter by empty/null assignee
- Add --unassigned/-u flag to ready command
- Update RPC protocol and daemon handler
- Add test for NoAssignee filter functionality

Fixes: gt-3rp

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 00:38:57 -08:00
Steve Yegge
53342732b5 feat: add --unassigned flag to bd ready command
Adds the ability to filter ready work for issues with no assignee,
which is useful for the SCAVENGE protocol in Gas Town where polecats
need to query the "Salvage Yard" for unclaimed work.

Changes:
- Add Unassigned bool field to types.WorkFilter
- Add --unassigned/-u flag to bd ready command
- Update SQL query in GetReadyWork to filter for NULL/empty assignee
- Add Unassigned field to RPC ReadyArgs for daemon support
- Add tests for the new functionality

Closes: gt-3rp

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 00:37:12 -08:00
Steve Yegge
fcd6ca694e Document blocked_issues_cache architecture and behavior
Add comprehensive documentation for the blocked_issues_cache optimization
that improved GetReadyWork performance from 752ms to 29ms (25x speedup).

Documentation locations:
- blocked_cache.go: Detailed package comment covering architecture,
  invalidation strategy, transaction safety, edge cases, and future
  optimizations
- ready.go: Enhanced comment at query site explaining the optimization
  and maintenance triggers
- ARCHITECTURE.md: New section with diagrams, blocking semantics,
  performance characteristics, and testing instructions

Closes bd-1w6i

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 01:14:21 -08:00
Steve Yegge
ed23f8f4fe Optimize GetReadyWork to use blocked_issues_cache
Replaces expensive recursive CTE query with simple cache lookup,
achieving 96% performance improvement on 10K databases (bd-5qim).

Performance results:
- Before: ~752ms (recursive CTE on every call)
- After: ~29ms (cache lookup + filters)
- Target: <50ms ✓

The query now uses a simple NOT EXISTS check against the
blocked_issues_cache table instead of computing the full
blocked issue tree on every call.

Cache is maintained by invalidateBlockedCache() called on
dependency and status changes (added in next commit).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 19:29:30 -05:00