types

package
v0.33.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 21, 2025 License: MIT Imports: 10 Imported by: 0

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

View Source
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

View Source
const ClockSkewGrace = 1 * time.Hour

ClockSkewGrace is added to TTL to handle clock drift between machines

View Source
const DefaultTombstoneTTL = 30 * 24 * time.Hour

DefaultTombstoneTTL is the default time-to-live for tombstones (30 days)

View Source
const MaxHierarchyDepth = 3

MaxHierarchyDepth is the maximum nesting level for hierarchical IDs. Prevents over-decomposition and keeps IDs manageable.

View Source
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

func GenerateChildID(parentID string, childNumber int) string

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

func IsProcessAlive(pid int, hostname string) bool

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

func ParseHierarchicalID(id string) (rootID, parentID string, depth int)

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

func ShouldSkipDatabase(beadsDir string) (skip bool, holder string, err error)

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

func (i *Issue) ComputeContentHash() string

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

func (i *Issue) GetConstituents() []BondRef

GetConstituents returns the BondRefs for this compound's constituent protos. Returns nil for non-compound issues.

func (*Issue) IsCompound added in v0.33.0

func (i *Issue) IsCompound() bool

IsCompound returns true if this issue is a compound (bonded from multiple sources).

func (*Issue) IsExpired added in v0.30.0

func (i *Issue) IsExpired(ttl time.Duration) bool

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

func (i *Issue) IsTombstone() bool

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

func (i *Issue) Validate() error

Validate checks if the issue has valid field values (built-in statuses only)

func (*Issue) ValidateWithCustomStatuses added in v0.26.1

func (i *Issue) ValidateWithCustomStatuses(customStatuses []string) error

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

func (IssueType) IsValid

func (t IssueType) IsValid() bool

IsValid checks if the issue type value is valid

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 Label

type Label struct {
	IssueID string `json:"issue_id"`
	Label   string `json:"label"`
}

Label represents a tag on an issue

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) IsValid

func (s Status) IsValid() bool

IsValid checks if the status value is valid (built-in statuses only)

func (Status) IsValidWithCustom added in v0.26.1

func (s Status) IsValidWithCustom(customStatuses []string) bool

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL