Documentation
¶
Overview ¶
Package types defines core data structures for the bd issue tracker.
Package types defines core data structures for the bd issue tracker.
Index ¶
- Constants
- func GenerateChildID(parentID string, childNumber int) string
- func GenerateHashID(prefix, title, description string, created time.Time, workspaceID string) string
- func IsProcessAlive(pid int, hostname string) bool
- func ParseHierarchicalID(id string) (rootID, parentID string, depth int)
- func ShouldSkipDatabase(beadsDir string) (skip bool, holder string, err error)
- type BlockedIssue
- type BondRef
- type Comment
- type Dependency
- type DependencyCounts
- type DependencyType
- type EpicStatus
- type Event
- type EventType
- type ExclusiveLock
- type Issue
- func (i *Issue) ComputeContentHash() string
- func (i *Issue) GetConstituents() []BondRef
- func (i *Issue) IsCompound() bool
- func (i *Issue) IsExpired(ttl time.Duration) bool
- func (i *Issue) IsTombstone() bool
- func (i *Issue) SetDefaults()
- func (i *Issue) Validate() error
- func (i *Issue) ValidateWithCustomStatuses(customStatuses []string) error
- type IssueFilter
- type IssueType
- type IssueWithCounts
- type IssueWithDependencyMetadata
- type Label
- type SortPolicy
- type StaleFilter
- type Statistics
- type Status
- type TreeNode
- type WorkFilter
Constants ¶
const ( BondTypeSequential = "sequential" // B runs after A completes BondTypeParallel = "parallel" // B runs alongside A BondTypeConditional = "conditional" // B runs only if A fails BondTypeRoot = "root" // Marks the primary/root component )
Bond type constants for compound molecules
const ClockSkewGrace = 1 * time.Hour
ClockSkewGrace is added to TTL to handle clock drift between machines
const DefaultTombstoneTTL = 30 * 24 * time.Hour
DefaultTombstoneTTL is the default time-to-live for tombstones (30 days)
const MaxHierarchyDepth = 3
MaxHierarchyDepth is the maximum nesting level for hierarchical IDs. Prevents over-decomposition and keeps IDs manageable.
const MinTombstoneTTL = 7 * 24 * time.Hour
MinTombstoneTTL is the minimum allowed TTL (7 days) to prevent data loss
Variables ¶
This section is empty.
Functions ¶
func GenerateChildID ¶ added in v0.20.0
GenerateChildID creates a hierarchical child ID. Format: parent.N (e.g., "bd-af78e9a2.1", "bd-af78e9a2.1.2")
Max depth: 3 levels (prevents over-decomposition) Max breadth: Unlimited (tested up to 347 children)
func GenerateHashID ¶ added in v0.20.0
func GenerateHashID(prefix, title, description string, created time.Time, workspaceID string) string
GenerateHashID creates a deterministic content-based hash ID. Format: prefix-{6-8-char-hex} with progressive extension on collision Examples: bd-a3f2dd (6), bd-a3f2dda (7), bd-a3f2dda8 (8)
The hash is computed from: - Title (primary identifier) - Description (additional context) - Created timestamp (RFC3339Nano for precision) - Workspace ID (prevents cross-workspace collisions)
Returns the full 64-char hash for progressive collision handling. Caller extracts hash[:6] initially, then hash[:7], hash[:8] on collisions.
Collision probability with 6 chars (24 bits): - 1,000 issues: ~2.94% chance (most extend to 7 chars) - 10,000 issues: ~94.9% chance (most extend to 7-8 chars)
Progressive strategy optimizes for common case: 97% stay at 6 chars.
func IsProcessAlive ¶ added in v0.17.7
IsProcessAlive checks if a process with the given PID is alive on the given hostname. If hostname doesn't match the current host, it returns true (cannot verify remote, assume alive). If hostname matches the current host, it checks if the PID exists. Permission errors are treated as "alive" (fail-safe: better to skip than wrongly remove a lock).
func ParseHierarchicalID ¶ added in v0.20.0
ParseHierarchicalID extracts the parent ID and depth from a hierarchical ID. Returns: (rootID, parentID, depth)
Examples:
"bd-af78e9a2" → ("bd-af78e9a2", "", 0)
"bd-af78e9a2.1" → ("bd-af78e9a2", "bd-af78e9a2", 1)
"bd-af78e9a2.1.2" → ("bd-af78e9a2", "bd-af78e9a2.1", 2)
func ShouldSkipDatabase ¶ added in v0.17.7
ShouldSkipDatabase checks if the given beads directory has an exclusive lock file. It returns true if the database should be skipped (lock is valid and holder is alive), false otherwise. It also returns the lock holder name if skipping, and any error encountered.
The function will: - Return false if no lock file exists (proceed with database) - Return true if lock exists and holder process is alive (skip database) - Remove stale locks (dead process) and return false (proceed with database) - Return true on malformed locks (fail-safe, skip database)
Types ¶
type BlockedIssue ¶
type BlockedIssue struct {
Issue
BlockedByCount int `json:"blocked_by_count"`
BlockedBy []string `json:"blocked_by"`
}
BlockedIssue extends Issue with blocking information
type BondRef ¶ added in v0.33.0
type BondRef struct {
ProtoID string `json:"proto_id"` // Source proto/molecule ID
BondType string `json:"bond_type"` // sequential, parallel, conditional
BondPoint string `json:"bond_point,omitempty"` // Attachment site (issue ID or empty for root)
}
BondRef tracks compound molecule lineage (bd-rnnr). When protos or molecules are bonded together, BondRefs record which sources were combined and how they were attached.
type Comment ¶ added in v0.9.11
type Comment struct {
ID int64 `json:"id"`
IssueID string `json:"issue_id"`
Author string `json:"author"`
Text string `json:"text"`
CreatedAt time.Time `json:"created_at"`
}
Comment represents a comment on an issue
type Dependency ¶
type Dependency struct {
IssueID string `json:"issue_id"`
DependsOnID string `json:"depends_on_id"`
Type DependencyType `json:"type"`
CreatedAt time.Time `json:"created_at"`
CreatedBy string `json:"created_by"`
// Metadata contains type-specific edge data (JSON blob)
// Examples: similarity scores, approval details, skill proficiency
Metadata string `json:"metadata,omitempty"`
// ThreadID groups conversation edges for efficient thread queries
// For replies-to edges, this identifies the conversation root
ThreadID string `json:"thread_id,omitempty"`
}
Dependency represents a relationship between issues
type DependencyCounts ¶ added in v0.21.4
type DependencyCounts struct {
DependencyCount int `json:"dependency_count"` // Number of issues this issue depends on
DependentCount int `json:"dependent_count"` // Number of issues that depend on this issue
}
DependencyCounts holds counts for dependencies and dependents
type DependencyType ¶
type DependencyType string
DependencyType categorizes the relationship
const ( // Workflow types (affect ready work calculation) DepBlocks DependencyType = "blocks" DepParentChild DependencyType = "parent-child" // Association types DepRelated DependencyType = "related" DepDiscoveredFrom DependencyType = "discovered-from" // Graph link types (bd-kwro) DepRepliesTo DependencyType = "replies-to" // Conversation threading DepRelatesTo DependencyType = "relates-to" // Loose knowledge graph edges DepDuplicates DependencyType = "duplicates" // Deduplication link DepSupersedes DependencyType = "supersedes" // Version chain link // Entity types (HOP foundation - Decision 004) DepAuthoredBy DependencyType = "authored-by" // Creator relationship DepAssignedTo DependencyType = "assigned-to" // Assignment relationship DepApprovedBy DependencyType = "approved-by" // Approval relationship )
Dependency type constants
func (DependencyType) AffectsReadyWork ¶ added in v0.30.6
func (d DependencyType) AffectsReadyWork() bool
AffectsReadyWork returns true if this dependency type blocks work. Only "blocks" and "parent-child" relationships affect the ready work calculation.
func (DependencyType) IsValid ¶
func (d DependencyType) IsValid() bool
IsValid checks if the dependency type value is valid. Accepts any non-empty string up to 50 characters. Use IsWellKnown() to check if it's a built-in type.
func (DependencyType) IsWellKnown ¶ added in v0.30.6
func (d DependencyType) IsWellKnown() bool
IsWellKnown checks if the dependency type is a well-known constant. Returns false for custom/user-defined types (which are still valid).
type EpicStatus ¶ added in v0.9.10
type EpicStatus struct {
Epic *Issue `json:"epic"`
TotalChildren int `json:"total_children"`
ClosedChildren int `json:"closed_children"`
EligibleForClose bool `json:"eligible_for_close"`
}
EpicStatus represents an epic with its completion status
type Event ¶
type Event struct {
ID int64 `json:"id"`
IssueID string `json:"issue_id"`
EventType EventType `json:"event_type"`
Actor string `json:"actor"`
OldValue *string `json:"old_value,omitempty"`
NewValue *string `json:"new_value,omitempty"`
Comment *string `json:"comment,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
Event represents an audit trail entry
type EventType ¶
type EventType string
EventType categorizes audit trail events
const ( EventCreated EventType = "created" EventUpdated EventType = "updated" EventStatusChanged EventType = "status_changed" EventCommented EventType = "commented" EventClosed EventType = "closed" EventReopened EventType = "reopened" EventDependencyAdded EventType = "dependency_added" EventDependencyRemoved EventType = "dependency_removed" EventLabelAdded EventType = "label_added" EventLabelRemoved EventType = "label_removed" EventCompacted EventType = "compacted" )
Event type constants for audit trail
type ExclusiveLock ¶ added in v0.17.7
type ExclusiveLock struct {
Holder string `json:"holder"` // Name of lock holder (e.g., "vc-executor")
PID int `json:"pid"` // Process ID
Hostname string `json:"hostname"` // Hostname where process is running
StartedAt time.Time `json:"started_at"` // When lock was acquired
Version string `json:"version"` // Version of lock holder
}
ExclusiveLock represents the lock file format for external tools to claim exclusive management of a beads database. When this lock is present, the bd daemon will skip the database in its sync cycle.
func NewExclusiveLock ¶ added in v0.17.7
func NewExclusiveLock(holder, version string) (*ExclusiveLock, error)
NewExclusiveLock creates a new exclusive lock for the current process
func (*ExclusiveLock) MarshalJSON ¶ added in v0.17.7
func (e *ExclusiveLock) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler
func (*ExclusiveLock) UnmarshalJSON ¶ added in v0.17.7
func (e *ExclusiveLock) UnmarshalJSON(data []byte) error
UnmarshalJSON implements json.Unmarshaler
func (*ExclusiveLock) Validate ¶ added in v0.17.7
func (e *ExclusiveLock) Validate() error
Validate checks if the lock has valid field values
type Issue ¶
type Issue struct {
ID string `json:"id"`
ContentHash string `json:"-"` // Internal: SHA256 hash of canonical content (excludes ID, timestamps) - NOT exported to JSONL
Title string `json:"title"`
Description string `json:"description,omitempty"`
Design string `json:"design,omitempty"`
AcceptanceCriteria string `json:"acceptance_criteria,omitempty"`
Notes string `json:"notes,omitempty"`
Status Status `json:"status,omitempty"`
Priority int `json:"priority,omitempty"`
IssueType IssueType `json:"issue_type,omitempty"`
Assignee string `json:"assignee,omitempty"`
EstimatedMinutes *int `json:"estimated_minutes,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
ClosedAt *time.Time `json:"closed_at,omitempty"`
CloseReason string `json:"close_reason,omitempty"` // Reason provided when closing the issue
ExternalRef *string `json:"external_ref,omitempty"` // e.g., "gh-9", "jira-ABC"
CompactionLevel int `json:"compaction_level,omitempty"`
CompactedAt *time.Time `json:"compacted_at,omitempty"`
CompactedAtCommit *string `json:"compacted_at_commit,omitempty"` // Git commit hash when compacted
OriginalSize int `json:"original_size,omitempty"`
SourceRepo string `json:"-"` // Internal: Which repo owns this issue (multi-repo support) - NOT exported to JSONL
Labels []string `json:"labels,omitempty"` // Populated only for export/import
Dependencies []*Dependency `json:"dependencies,omitempty"` // Populated only for export/import
Comments []*Comment `json:"comments,omitempty"` // Populated only for export/import
// Tombstone fields (bd-vw8): inline soft-delete support
DeletedAt *time.Time `json:"deleted_at,omitempty"` // When the issue was deleted
DeletedBy string `json:"deleted_by,omitempty"` // Who deleted the issue
DeleteReason string `json:"delete_reason,omitempty"` // Why the issue was deleted
OriginalType string `json:"original_type,omitempty"` // Issue type before deletion (for tombstones)
// Messaging fields (bd-kwro): inter-agent communication support
Sender string `json:"sender,omitempty"` // Who sent this (for messages)
Ephemeral bool `json:"ephemeral,omitempty"` // Can be bulk-deleted when closed
// Pinned field (bd-7h5): persistent context markers
Pinned bool `json:"pinned,omitempty"` // If true, issue is a persistent context marker, not a work item
// Template field (beads-1ra): template molecule support
IsTemplate bool `json:"is_template,omitempty"` // If true, issue is a read-only template molecule
// Bonding fields (bd-rnnr): compound molecule lineage
BondedFrom []BondRef `json:"bonded_from,omitempty"` // For compounds: constituent protos
}
Issue represents a trackable work item
func (*Issue) ComputeContentHash ¶ added in v0.19.0
ComputeContentHash creates a deterministic hash of the issue's content. Uses all substantive fields (excluding ID, timestamps, and compaction metadata) to ensure that identical content produces identical hashes across all clones.
func (*Issue) GetConstituents ¶ added in v0.33.0
GetConstituents returns the BondRefs for this compound's constituent protos. Returns nil for non-compound issues.
func (*Issue) IsCompound ¶ added in v0.33.0
IsCompound returns true if this issue is a compound (bonded from multiple sources).
func (*Issue) IsExpired ¶ added in v0.30.0
IsExpired returns true if the tombstone has exceeded its TTL. Non-tombstone issues always return false. ttl is the configured TTL duration:
- If zero, DefaultTombstoneTTL (30 days) is used
- If negative, the tombstone is immediately expired (for --hard mode)
- If positive, ClockSkewGrace is added only for TTLs > 1 hour
func (*Issue) IsTombstone ¶ added in v0.30.0
IsTombstone returns true if the issue has been soft-deleted (bd-vw8)
func (*Issue) SetDefaults ¶ added in v0.30.7
func (i *Issue) SetDefaults()
SetDefaults applies default values for fields omitted during JSONL import. Call this after json.Unmarshal to ensure missing fields have proper defaults:
- Status: defaults to StatusOpen if empty
- Priority: defaults to 2 if zero (note: P0 issues must explicitly set priority=0)
- IssueType: defaults to TypeTask if empty
This enables smaller JSONL output by using omitempty on these fields.
func (*Issue) Validate ¶
Validate checks if the issue has valid field values (built-in statuses only)
func (*Issue) ValidateWithCustomStatuses ¶ added in v0.26.1
ValidateWithCustomStatuses checks if the issue has valid field values, allowing custom statuses in addition to built-in ones.
type IssueFilter ¶
type IssueFilter struct {
Status *Status
Priority *int
IssueType *IssueType
Assignee *string
Labels []string // AND semantics: issue must have ALL these labels
LabelsAny []string // OR semantics: issue must have AT LEAST ONE of these labels
TitleSearch string
IDs []string // Filter by specific issue IDs
Limit int
// Pattern matching
TitleContains string
DescriptionContains string
NotesContains string
// Date ranges
CreatedAfter *time.Time
CreatedBefore *time.Time
UpdatedAfter *time.Time
UpdatedBefore *time.Time
ClosedAfter *time.Time
ClosedBefore *time.Time
// Empty/null checks
EmptyDescription bool
NoAssignee bool
NoLabels bool
// Numeric ranges
PriorityMin *int
PriorityMax *int
// Tombstone filtering (bd-1bu)
IncludeTombstones bool // If false (default), exclude tombstones from results
// Ephemeral filtering (bd-kwro.9)
Ephemeral *bool // Filter by ephemeral flag (nil = any, true = only ephemeral, false = only non-ephemeral)
// Pinned filtering (bd-7h5)
Pinned *bool // Filter by pinned flag (nil = any, true = only pinned, false = only non-pinned)
// Template filtering (beads-1ra)
IsTemplate *bool // Filter by template flag (nil = any, true = only templates, false = exclude templates)
}
IssueFilter is used to filter issue queries
type IssueType ¶
type IssueType string
IssueType categorizes the kind of work
const ( TypeBug IssueType = "bug" TypeFeature IssueType = "feature" TypeTask IssueType = "task" TypeEpic IssueType = "epic" TypeChore IssueType = "chore" TypeMessage IssueType = "message" // Ephemeral communication between workers TypeMergeRequest IssueType = "merge-request" // Merge queue entry for refinery processing TypeMolecule IssueType = "molecule" // Template molecule for issue hierarchies (beads-1ra) )
Issue type constants
type IssueWithCounts ¶ added in v0.21.4
type IssueWithCounts struct {
*Issue
DependencyCount int `json:"dependency_count"`
DependentCount int `json:"dependent_count"`
}
IssueWithCounts extends Issue with dependency relationship counts
type IssueWithDependencyMetadata ¶ added in v0.21.4
type IssueWithDependencyMetadata struct {
Issue
DependencyType DependencyType `json:"dependency_type"`
}
IssueWithDependencyMetadata extends Issue with dependency relationship type Note: We explicitly include all Issue fields to ensure proper JSON marshaling
type SortPolicy ¶ added in v0.17.2
type SortPolicy string
SortPolicy determines how ready work is ordered
const ( // SortPolicyHybrid prioritizes recent issues by priority, older by age // Recent = created within 48 hours // This is the default for backwards compatibility SortPolicyHybrid SortPolicy = "hybrid" // SortPolicyPriority always sorts by priority first, then creation date // Use for autonomous execution, CI/CD, priority-driven workflows SortPolicyPriority SortPolicy = "priority" // SortPolicyOldest always sorts by creation date (oldest first) // Use for backlog clearing, preventing issue starvation SortPolicyOldest SortPolicy = "oldest" )
Sort policy constants
func (SortPolicy) IsValid ¶ added in v0.17.2
func (s SortPolicy) IsValid() bool
IsValid checks if the sort policy value is valid
type StaleFilter ¶ added in v0.21.1
type StaleFilter struct {
Days int // Issues not updated in this many days
Status string // Filter by status (open|in_progress|blocked), empty = all non-closed
Limit int // Maximum issues to return
}
StaleFilter is used to filter stale issue queries
type Statistics ¶
type Statistics struct {
TotalIssues int `json:"total_issues"`
OpenIssues int `json:"open_issues"`
InProgressIssues int `json:"in_progress_issues"`
ClosedIssues int `json:"closed_issues"`
BlockedIssues int `json:"blocked_issues"`
DeferredIssues int `json:"deferred_issues"` // Issues on ice (bd-4jr)
ReadyIssues int `json:"ready_issues"`
TombstoneIssues int `json:"tombstone_issues"` // Soft-deleted issues (bd-nyt)
PinnedIssues int `json:"pinned_issues"` // Persistent issues (bd-6v2)
EpicsEligibleForClosure int `json:"epics_eligible_for_closure"`
AverageLeadTime float64 `json:"average_lead_time_hours"`
}
Statistics provides aggregate metrics
type Status ¶
type Status string
Status represents the current state of an issue
const ( StatusOpen Status = "open" StatusInProgress Status = "in_progress" StatusBlocked Status = "blocked" StatusDeferred Status = "deferred" // Deliberately put on ice for later (bd-4jr) StatusClosed Status = "closed" StatusTombstone Status = "tombstone" // Soft-deleted issue (bd-vw8) StatusPinned Status = "pinned" // Persistent bead that stays open indefinitely (bd-6v2) )
Issue status constants
func (Status) IsValidWithCustom ¶ added in v0.26.1
IsValidWithCustom checks if the status is valid, including custom statuses. Custom statuses are user-defined via bd config set status.custom "status1,status2,..."
type TreeNode ¶
type TreeNode struct {
Issue
Depth int `json:"depth"`
ParentID string `json:"parent_id"`
Truncated bool `json:"truncated"`
}
TreeNode represents a node in a dependency tree
type WorkFilter ¶
type WorkFilter struct {
Status Status
Type string // Filter by issue type (task, bug, feature, epic, merge-request, etc.)
Priority *int
Assignee *string
Unassigned bool // Filter for issues with no assignee
Labels []string // AND semantics: issue must have ALL these labels
LabelsAny []string // OR semantics: issue must have AT LEAST ONE of these labels
Limit int
SortPolicy SortPolicy
}
WorkFilter is used to filter ready work queries