When an issue is deleted, issues that depend on it were not being marked
dirty. This caused stale dependency references to persist in JSONL after
the target issue was deleted, because the dependent issues were never
re-exported.
This manifests as FK validation failures during multi-repo hydration:
"foreign key violation: issue X depends on non-existent issue Y"
The fix queries for dependent issues before deleting and marks them dirty
so they get re-exported without the stale dependency reference.
Adds test: TestDeleteIssueMarksDependentsDirty
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(create): Use prefix from routes.jsonl when creating issues with --rig
When using `bd create --rig <name>`, the prefix from routes.jsonl was
being discarded. This caused issues to be created with the target
database's default prefix instead of the route's prefix.
This is particularly problematic when using the redirect mechanism to
share a single database across multiple rigs - the redirect correctly
routes to the shared database, but the prefix was not being applied.
The fix:
1. Capture the prefix from routing.ResolveBeadsDirForRig()
2. Temporarily override the target database's issue_prefix config
3. Restore the original prefix after issue creation
Example scenario that now works:
- routes.jsonl: {"prefix": "aops-", "path": "src/academicOps"}
- src/academicOps/.beads/redirect points to ~/writing/.beads
- `bd create --rig aops "Test"` now creates aops-xxx instead of ns-xxx
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(create): pass prefix via struct field instead of mutating config
The previous approach temporarily mutated the database's issue_prefix
config during cross-rig issue creation, then restored it afterward.
This was fragile in multi-user scenarios where concurrent operations
could see the wrong prefix.
New approach:
- Add PrefixOverride field to types.Issue
- CreateIssue checks PrefixOverride first, uses it if set
- createInRig sets issue.PrefixOverride instead of mutating config
This passes state as a parameter rather than mutating shared state,
making it safe for concurrent multi-user access.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
RenameDependencyPrefix updates issue IDs in the dependencies table but
was not rebuilding the blocked_issues_cache, leaving stale IDs in the
cache that no longer exist in the issues table.
Add invalidateBlockedCache() call at the end of RenameDependencyPrefix
to rebuild the cache with the new issue IDs.
Fixes: GH#1016
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds crystallizes column for work economics (compounds vs evaporates)
per Decision 006. Includes migration 036 and updates to all INSERT/SELECT
queries in issues.go, queries.go, dependencies.go, and transaction.go.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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
Root cause: CreateIssue used INSERT OR IGNORE which could silently skip
the insert (e.g., on duplicate ID from hash collision), then fail with
FOREIGN KEY constraint error when trying to record the creation event.
Fix: Add insertIssueStrict() that uses plain INSERT (fails on duplicates)
and use it for CreateIssue in both queries.go and transaction.go. The
existing insertIssue() with INSERT OR IGNORE is preserved for import
scenarios where duplicates are expected.
Added test TestCreateIssueDuplicateID to verify duplicate IDs are properly
rejected instead of silently ignored.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove Gas Town-specific issue types (agent, role, rig, convoy, slot)
from beads core. These types are now identified by labels instead:
- gt:agent, gt:role, gt:rig, gt:convoy, gt:slot
Changes:
- internal/types/types.go: Remove TypeAgent, TypeRole, TypeRig, TypeConvoy, TypeSlot constants
- cmd/bd/agent.go: Create agents with TypeTask + gt:agent label
- cmd/bd/merge_slot.go: Create slots with TypeTask + gt:slot label
- internal/storage/sqlite/queries.go, transaction.go: Query convoys by gt:convoy label
- internal/rpc/server_issues_epics.go: Check gt:agent label for role_type/rig label auto-add
- cmd/bd/create.go: Check gt:agent label for role_type/rig label auto-add
- internal/ui/styles.go: Remove agent/role/rig type colors
- cmd/bd/export_obsidian.go: Remove agent/role/rig/convoy type tag mappings
- Update all affected tests
This enables beads to be a generic issue tracker while Gas Town
uses labels for its specific type semantics.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: beads/crew/dave
Rig: beads
Role: crew
Add types.custom config key mirroring the status.custom pattern:
- Add CustomTypeConfigKey constant and GetCustomTypes() to storage interface
- Add IssueType.IsValidWithCustom() method for validation
- Add ValidateWithCustom() to Issue for combined status/type validation
- Update all validation call sites to use GetCustomTypes()
- Rename parseCustomStatuses to parseCommaSeparated for reuse
This enables Gas Town to register custom types like agent/role/rig/convoy
without hardcoding them in beads core, supporting the type extraction epic.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: beads/crew/dave
Rig: beads
Role: crew
Implements automatic discovery of GitHub workflow run IDs for gates
awaiting CI/CD completion. This enables the Refinery patrol to
auto-populate await_id for gh:run gates that were created without one.
Changes:
- Add `bd gate discover` command that:
- Finds open gh:run gates without await_id
- Queries recent GitHub workflow runs via gh CLI
- Matches runs to gates using heuristics (branch, commit, time)
- Updates gates with discovered run IDs
- Add `--await-id` flag to `bd update` for manual setting
- Add AwaitID to UpdateArgs in RPC protocol
- Add await_id to allowedUpdateFields in storage layer
Matching heuristics (scored, highest match wins):
- Commit SHA match: +100 points
- Branch match: +50 points
- Time proximity (<5min: +30, <10min: +20, <30min: +10)
- In-progress/queued status: +5 points
Usage:
bd gate discover # Auto-discover for all matching gates
bd gate discover --dry-run # Preview without updating
bd gate discover --branch main --limit 10
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* 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.
This implements Phase 1 of the Step.Gate feature (bd-7zka.2):
- bd cook now creates gate issues for steps with gate fields
- Gate issues have type=gate and block the gated step via dependency
- bd list filters out gate issues by default (use --include-gates to show)
- New bd gate command with list and resolve subcommands
Gate types supported in Phase 1:
- human: Manual closure via bd close or bd gate resolve
Implementation details:
- createGateIssue() in cook.go creates gate issues with proper metadata
- collectSteps() creates gate dependencies when processing gated steps
- IssueFilter.ExcludeTypes added to storage layer for type-based filtering
- Gate command provides dedicated UX for gate management
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds closed_by_session tracking for entity CV building per Gas Town
decision 009-session-events-architecture.md.
Changes:
- Add ClosedBySession field to Issue struct
- Add closed_by_session column to issues table (migration 034)
- Add --session flag to bd close command
- Support CLAUDE_SESSION_ID env var as fallback
- Add --session flag to bd update for status=closed
- Display closed_by_session in bd show output
- Update Storage interface to include session parameter in CloseIssue
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: beads/crew/dave
Rig: beads
Role: crew
Adds TypeEvent issue type for recording operational state changes as
immutable beads. Events capture:
- event_category: namespaced category (e.g., patrol.muted, agent.started)
- event_actor: entity URI who caused the event
- event_target: entity URI or bead ID affected
- event_payload: event-specific JSON data
Changes:
- Add TypeEvent constant and IsValid() support in types.go
- Add event fields to Issue struct with ComputeContentHash support
- Add --event-category/actor/target/payload flags to bd create
- Add event fields to RPC CreateArgs and UpdateArgs
- Add migration 033_event_fields to add columns to issues table
- Update insertIssue and queries to include event fields
- Fix migrations_test.go for new column requirements
This enables:
- bd activity --follow showing events
- bd list --type=event --target=agent:deacon
- Full audit trail for operational state
- HOP-compatible transaction records
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds support for event beads that capture operational state transitions
as immutable records. Events are a new issue type with fields:
- event_kind: namespaced category (patrol.muted, agent.started)
- actor: entity URI who caused the event
- target: entity URI or bead ID affected
- payload: event-specific JSON data
This enables:
- bd activity --follow showing events
- bd list --type=event --target=agent:deacon
- Full audit trail for operational state
- HOP-compatible transaction records
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: beads/crew/dave
Rig: beads
Role: crew
- Add TypeConvoy to issue types for cross-project tracking
- Implement reactive completion: when all tracked issues close,
convoy auto-closes with reason "All tracked issues completed"
- Uses 'tracks' dependency type (non-blocking, cross-prefix capable)
- Update help text for --type flag in list/create commands
- Add test for convoy reactive completion behavior
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Executed-By: beads/crew/dave
Rig: beads
Role: crew
Changes:
- Default to excluding closed issues (use --all to include)
- Default limit of 50 issues (use --limit 0 for unlimited)
- --all flag now overrides the closed filter
This addresses agent context blowout from seeing hundreds of closed issues.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
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>
Add slot management commands:
- bd slot set <agent> <slot> <bead> - set slot (error if occupied)
- bd slot clear <agent> <slot> - clear slot
- bd slot show <agent> - show all slots
These enforce cardinality constraints for agent bead slots.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
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>
Changed prefix logic to combine the database prefix with the type prefix:
- bd-wisp-xxx (was: wisp-xxx)
- bd-mol-xxx (was: mol-xxx)
This ensures IDs like hq-wisp-xxx at town level and gt-mol-xxx for gastown,
maintaining database namespace while adding type recognition.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added type-specific ID prefixes for better visual recognition:
- `bd pour` now generates IDs with "mol-" prefix
- `bd wisp create` now generates IDs with "wisp-" prefix
- Regular issues continue using the configured prefix
Implementation:
- Added IDPrefix field to types.Issue (internal, not exported to JSONL)
- Added Prefix field to CloneOptions for spawning operations
- Added IDPrefix to RPC CreateArgs for daemon communication
- Updated storage layer to use issue.IDPrefix when generating IDs
- Updated pour.go and wisp.go to pass appropriate prefixes
This enables instant visual recognition of entity types and prevents
accidental modification of templates.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When creating issues with explicit hierarchical IDs (e.g., bd-test.1, bd-test.2
via --id flag or import), the child_counters table was not being updated.
This caused GetNextChildID to return colliding IDs when later called with
--parent.
Changes:
- Add ensureChildCounterUpdatedWithConn() to update counter on explicit child creation
- Add ParseHierarchicalID() to extract parent and child number from IDs
- Update CreateIssue to call counter update after hierarchical ID validation
- Update EnsureIDs to call counter update when parent exists
- Add post-insert phase in batch operations to update counters after FK
constraint can be satisfied
- Update tests to reflect new behavior where counter is properly initialized
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
Filters issues by parent issue ID using parent-child dependencies.
Example: bd list --parent=bd-xyz --status=open
Changes:
- Add ParentID field to IssueFilter type
- Add --parent flag to list command
- Forward parent filter through RPC
- Implement filtering in SQLite and memory storage
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
Ephemeral issues should never be exported to issues.jsonl. They exist only
in SQLite and are shared via .beads/redirect pointers. This prevents
"zombie" issues from resurrecting after mol squash deletes them.
Changes:
- Filter ephemeral issues in autoflush, export, and multirepo_export
- Add --summary flag to bd mol squash for agent-provided summaries
- Fix DeleteIssue to also remove comments (missing cascade)
- Add tests for ephemeral filtering and comment deletion
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The 'bd pin' command was failing with "invalid field for update: pinned"
because the pinned field was missing from allowedUpdateFields.
Fixes:
- Add 'pinned' to allowedUpdateFields in queries.go
- Update importer to include pinned field in updates during import
- Add equalBool comparator for IssueDataChanged to detect pinned changes
- Fix stats query to count pinned=1 instead of status='pinned'
- Fix pinIndicator in list.go to check issue.Pinned instead of status
This unblocks gt mail --pinned functionality.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
* fix(storage): implement RenameDependencyPrefix to update dependency records
RenameDependencyPrefix was previously a no-op that returned nil without
updating any records. This caused dependencies to break after using
bd rename-prefix, as the issue_id and depends_on_id columns in the
dependencies table still referenced the old prefix.
The fix updates both columns in the dependencies table to use the new
prefix, ensuring all dependency relationships are preserved.
Fixes#630
* test(storage): add regression tests for RenameDependencyPrefix
Add tests verifying that RenameDependencyPrefix:
- Executes without error when no dependencies exist
- Can be called with various prefix combinations
These tests ensure the fix for GH#630 doesn't regress.
---------
Co-authored-by: Charles P. Cross <cpdata@users.noreply.github.com>
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>
Change reconnectMu from sync.Mutex to sync.RWMutex so read operations
can hold RLock during database access. This prevents reconnect() from
closing the connection while queries are in progress.
- GetIssue and SearchIssues now hold RLock during database operations
- Close() acquires write lock to coordinate with reconnect
- Add TestConcurrentReadsWithReconnect to verify the fix
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
When issue fields (replies_to, relates_to, duplicate_of, superseded_by)
are set during CreateIssue or UpdateIssue, we now ALSO create the
corresponding dependency edges. This enables gradual migration to
edge-based storage while maintaining backward compatibility.
Changes:
- createGraphEdgesFromIssueFields: handles CreateIssue dual-write
- createGraphEdgesFromUpdates: handles UpdateIssue dual-write
- Replies-to edges include thread_id for efficient thread queries
- Uses INSERT OR IGNORE to handle idempotency
The dual-write ensures both field and dependency stay in sync during
the migration period.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add bd cleanup --ephemeral flag for transient message cleanup (bd-kwro.9)
- Add Ephemeral filter to IssueFilter type
- Add ephemeral filtering to SQLite storage queries
Tests (bd-kwro.10):
- Add internal/hooks/hooks_test.go for hook system
- Add cmd/bd/mail_test.go for mail commands
- Add internal/storage/sqlite/graph_links_test.go for graph links
Documentation (bd-kwro.11):
- Add docs/messaging.md for full messaging reference
- Add docs/graph-links.md for graph link types
- Update AGENTS.md with inter-agent messaging section
- Update CHANGELOG.md with all bd-kwro features
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>
When git merge replaces the .beads/beads.db file, the daemon's
SQLite connection becomes stale (still reading deleted inode).
This adds FreshnessChecker that detects file replacement via
inode/mtime comparison and triggers automatic reconnection.
Implementation:
- freshness.go: monitors db file for replacement
- store.go: adds EnableFreshnessChecking() and reconnect()
- queries.go: calls checkFreshness() on GetIssue/SearchIssues
- daemon.go: enables freshness checking at startup
- freshness_test.go: comprehensive tests including merge scenario
Code quality (per review):
- Extract configureConnectionPool() helper to reduce duplication
- Handle Close() error in reconnect() (log but continue)
- Use t.Cleanup() pattern in tests per project conventions
- Rename setupFreshnessTest() per naming conventions
Overhead: ~2.6μs per read op (~0.8% of total query time)
Signed-off-by: Alessandro De Blasis <alex@deblasis.net>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The orphan detection was incorrectly flagging issues with dots in their
prefix (e.g., "my.project-abc123") as orphans because it was looking for
any dot in the ID, treating everything before the first dot as the
parent ID.
The fix:
- Add IsHierarchicalID() helper that correctly detects hierarchical IDs
by checking if the ID ends with .{digits} (e.g., "bd-abc.1")
- Update SQL query in orphan detection migration to use GLOB patterns
that only match IDs ending with numeric suffixes
- Update all Go code that checks for hierarchical IDs to use the new
helper function
Test cases added:
- Unit tests for IsHierarchicalID covering normal, dotted prefix, and
edge cases
- Integration test verifying dotted prefixes do not trigger false
positives
Fixes: #508