types

package
v0.62.1 Latest Latest
Warning

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

Go to latest
Published: Mar 13, 2026 License: MIT Imports: 8 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.

Package types defines core data structures for the bd issue tracker.

Index

Constants

View Source
const (
	WaitsForAllChildren = "all-children" // Wait for all dynamic children to complete
	WaitsForAnyChildren = "any-children" // Proceed when first child completes (future)
)

WaitsForGate 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 (
	IDPrefixMol  = "mol"  // Persistent molecules (bd-mol-xxx)
	IDPrefixWisp = "wisp" // Ephemeral wisps (bd-wisp-xxx)
)

ID prefix constants for molecule/wisp instantiation. These prefixes are inserted into issue IDs: <project>-<prefix>-<id> Used by: cmd/bd/pour.go, cmd/bd/wisp.go (ID generation)

View Source
const (
	ValidationAccepted          = "accepted"
	ValidationRejected          = "rejected"
	ValidationRevisionRequested = "revision_requested"
)

Validation outcome constants

View Source
const MaxHierarchyDepth = 3

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

Variables

View Source
var FailureCloseKeywords = []string{
	"failed",
	"rejected",
	"wontfix",
	"won't fix",
	"canceled",
	"cancelled",
	"abandoned",
	"blocked",
	"error",
	"timeout",
	"aborted",
}

FailureCloseKeywords are keywords that indicate an issue was closed due to failure. Used by conditional-blocks dependencies to determine if the condition is met.

Functions

func CheckHierarchyDepth

func CheckHierarchyDepth(parentID string, maxDepth int) error

CheckHierarchyDepth validates that adding a child to parentID won't exceed maxDepth. Returns an error if the depth would be exceeded. If maxDepth < 1, it defaults to MaxHierarchyDepth.

func ExtractPrefix

func ExtractPrefix(id string) string

ExtractPrefix returns the prefix portion of a bead ID (everything before the first hyphen, including the hyphen). For example, "sh-abc" returns "sh-". Returns empty string for IDs without a hyphen.

func GenerateChildID

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

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 IsFailureClose

func IsFailureClose(closeReason string) bool

IsFailureClose returns true if the close reason indicates the issue failed. This is used by conditional-blocks dependencies: B runs only if A fails. A "failure" close reason contains one of the FailureCloseKeywords (case-insensitive).

func ParseHierarchicalID

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 ParseWaitsForGateMetadata

func ParseWaitsForGateMetadata(metadata string) string

ParseWaitsForGateMetadata extracts the waits-for gate type from dependency metadata. Note: spawner identity comes from dependencies.depends_on_id in storage/query paths; metadata.spawner_id is parsed for compatibility/future explicit targeting. Returns WaitsForAllChildren on empty/invalid metadata for backward compatibility.

Types

type AgentState

type AgentState string

AgentState represents the self-reported state of an agent

const (
	StateIdle     AgentState = "idle"     // Agent is waiting for work
	StateSpawning AgentState = "spawning" // Agent is starting up
	StateRunning  AgentState = "running"  // Agent is executing (general)
	StateWorking  AgentState = "working"  // Agent is actively working on a task
	StateStuck    AgentState = "stuck"    // Agent is blocked and needs help
	StateDone     AgentState = "done"     // Agent completed its current work
	StateStopped  AgentState = "stopped"  // Agent has cleanly shut down
	StateDead     AgentState = "dead"     // Agent died without clean shutdown (timeout detection)
)

Agent state constants

func (AgentState) IsValid

func (s AgentState) IsValid() bool

IsValid checks if the agent state value is valid

type AttestsMeta

type AttestsMeta struct {
	// Skill is the identifier of the skill being attested (e.g., "go", "rust", "code-review")
	Skill string `json:"skill"`
	// Level is the proficiency level (e.g., "beginner", "intermediate", "expert", or numeric 1-5)
	Level string `json:"level"`
	// Date is when the attestation was made (RFC3339 format)
	Date string `json:"date"`
	// Evidence is optional reference to supporting evidence (e.g., issue ID, commit, PR)
	Evidence string `json:"evidence,omitempty"`
	// Notes is optional free-form notes about the attestation
	Notes string `json:"notes,omitempty"`
}

AttestsMeta holds metadata for attests dependencies (skill attestations). Stored as JSON in the Dependency.Metadata field. Enables: Entity X attests that Entity Y has skill Z at level N.

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

type BondRef struct {
	SourceID  string `json:"source_id"`            // Source proto or 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. When protos or molecules are bonded together, BondRefs record which sources were combined and how they were attached.

type Comment

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 CompactionCandidate

type CompactionCandidate struct {
	IssueID        string
	ClosedAt       time.Time
	OriginalSize   int
	EstimatedSize  int
	DependentCount int
}

CompactionCandidate represents an issue eligible for compaction. Used by the compact subsystem to identify and process closed issues that can have their description/notes summarized to save space.

type DeleteIssuesResult

type DeleteIssuesResult struct {
	DeletedCount      int
	DependenciesCount int
	LabelsCount       int
	EventsCount       int
	OrphanedIssues    []string
}

DeleteIssuesResult contains statistics from a batch delete operation. Used when deleting multiple issues with cascade/force options.

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,omitempty"`
	// 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

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"
	DepConditionalBlocks DependencyType = "conditional-blocks" // B runs only if A fails
	DepWaitsFor          DependencyType = "waits-for"          // Fanout gate: wait for dynamic children

	// Association types
	DepRelated        DependencyType = "related"
	DepDiscoveredFrom DependencyType = "discovered-from"

	// Graph link types
	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
	DepAttests    DependencyType = "attests"     // Skill attestation: X attests Y has skill Z

	// Convoy tracking (non-blocking cross-project references)
	DepTracks DependencyType = "tracks" // Convoy → issue tracking (non-blocking)

	// Reference types (cross-referencing without blocking)
	DepUntil     DependencyType = "until"     // Active until target closes (e.g., muted until issue resolved)
	DepCausedBy  DependencyType = "caused-by" // Triggered by target (audit trail)
	DepValidates DependencyType = "validates" // Approval/validation relationship

	// Delegation types (work delegation chains)
	DepDelegatedFrom DependencyType = "delegated-from" // Work delegated from parent; completion cascades up
)

Dependency type constants

func (DependencyType) AffectsReadyWork

func (d DependencyType) AffectsReadyWork() bool

AffectsReadyWork returns true if this dependency type blocks work. Only blocking types 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

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 EntityRef

type EntityRef struct {
	// Name is the human-readable identifier (e.g., "polecat/Nux", "mayor")
	Name string `json:"name,omitempty"`

	// Platform identifies the execution context (e.g., "gastown", "github")
	Platform string `json:"platform,omitempty"`

	// Org identifies the organization (e.g., "steveyegge", "anthropics")
	Org string `json:"org,omitempty"`

	// ID is the unique identifier within the platform/org (e.g., "polecat-nux")
	ID string `json:"id,omitempty"`
}

EntityRef is a structured reference to an entity (human, agent, or org). This is the foundation for HOP entity tracking and CV chains. Can be rendered as a URI: hop://<platform>/<org>/<id>

Example usage:

ref := &EntityRef{
    Name:     "polecat/Nux",
    Platform: "gastown",
    Org:      "steveyegge",
    ID:       "polecat-nux",
}
uri := ref.URI() // "hop://gastown/steveyegge/polecat-nux"

func ParseEntityURI

func ParseEntityURI(uri string) (*EntityRef, error)

ParseEntityURI parses a HOP entity URI into an EntityRef. Format: hop://<platform>/<org>/<id> Also accepts legacy entity://hop/<platform>/<org>/<id> for backward compatibility. Returns nil and error if the URI is invalid.

func (*EntityRef) IsEmpty

func (e *EntityRef) IsEmpty() bool

IsEmpty returns true if all fields are empty.

func (*EntityRef) String

func (e *EntityRef) String() string

String returns a human-readable representation. Prefers Name if set, otherwise returns URI or ID.

func (*EntityRef) URI

func (e *EntityRef) URI() string

URI returns the entity as a HOP URI. Format: hop://<platform>/<org>/<id> Returns empty string if Platform, Org, or ID is missing.

type EpicStatus

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 Issue

type Issue struct {
	// ===== Core Identification =====
	ID          string `json:"id"`
	ContentHash string `json:"-"` // Internal: SHA256 of canonical content

	// ===== Issue Content =====
	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"`
	SpecID             string `json:"spec_id,omitempty"`

	// ===== Status & Workflow =====
	Status    Status    `json:"status,omitempty"`
	Priority  int       `json:"priority"` // No omitempty: 0 is valid (P0/critical)
	IssueType IssueType `json:"issue_type,omitempty"`

	// ===== Assignment =====
	Assignee         string `json:"assignee,omitempty"`
	Owner            string `json:"owner,omitempty"` // Human owner for CV attribution (git author email)
	EstimatedMinutes *int   `json:"estimated_minutes,omitempty"`

	// ===== Timestamps =====
	CreatedAt       time.Time  `json:"created_at"`
	CreatedBy       string     `json:"created_by,omitempty"` // Who created this issue (GH#748)
	UpdatedAt       time.Time  `json:"updated_at"`
	ClosedAt        *time.Time `json:"closed_at,omitempty"`
	CloseReason     string     `json:"close_reason,omitempty"`      // Reason provided when closing
	ClosedBySession string     `json:"closed_by_session,omitempty"` // Claude Code session that closed this issue

	// ===== Time-Based Scheduling (GH#820) =====
	DueAt      *time.Time `json:"due_at,omitempty"`      // When this issue should be completed
	DeferUntil *time.Time `json:"defer_until,omitempty"` // Hide from bd ready until this time

	// ===== External Integration =====
	ExternalRef  *string `json:"external_ref,omitempty"`  // e.g., "gh-9", "jira-ABC"
	SourceSystem string  `json:"source_system,omitempty"` // Adapter/system that created this issue (federation)

	// ===== Custom Metadata =====
	// Metadata holds arbitrary JSON data for extension points (tool annotations, file lists, etc.)
	// Validated as well-formed JSON on create/update. See GH#1406.
	Metadata json.RawMessage `json:"metadata,omitempty"`

	// ===== Compaction Metadata =====
	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"`

	// ===== Internal Routing (not synced via git) =====
	SourceRepo     string `json:"-"` // Which repo owns this issue (multi-repo support)
	IDPrefix       string `json:"-"` // Override prefix for ID generation (appends to config prefix)
	PrefixOverride string `json:"-"` // Completely replace config prefix (for cross-rig creation)

	// ===== Relational Data (populated for export/import) =====
	Labels       []string      `json:"labels,omitempty"`
	Dependencies []*Dependency `json:"dependencies,omitempty"`
	Comments     []*Comment    `json:"comments,omitempty"`

	// ===== Messaging Fields (inter-agent communication) =====
	Sender    string   `json:"sender,omitempty"`    // Who sent this (for messages)
	Ephemeral bool     `json:"ephemeral,omitempty"` // If true, not synced via git
	WispType  WispType `json:"wisp_type,omitempty"` // Classification for TTL-based compaction (gt-9br)

	// ===== Context Markers =====
	Pinned     bool `json:"pinned,omitempty"`      // Persistent context marker, not a work item
	IsTemplate bool `json:"is_template,omitempty"` // Read-only template molecule

	// ===== Bonding Fields (compound molecule lineage) =====
	BondedFrom []BondRef `json:"bonded_from,omitempty"` // For compounds: constituent protos

	// ===== HOP Fields (entity tracking for CV chains) =====
	Creator      *EntityRef   `json:"creator,omitempty"`       // Who created (human, agent, or org)
	Validations  []Validation `json:"validations,omitempty"`   // Who validated/approved
	QualityScore *float32     `json:"quality_score,omitempty"` // Aggregate quality (0.0-1.0), set by Refineries on merge
	Crystallizes bool         `json:"crystallizes,omitempty"`  // Work that compounds (true: code, features) vs evaporates (false: ops, support) - affects CV weighting per Decision 006

	// ===== Gate Fields (async coordination primitives) =====
	AwaitType string        `json:"await_type,omitempty"` // Condition type: gh:run, gh:pr, timer, human, mail
	AwaitID   string        `json:"await_id,omitempty"`   // Condition identifier (run ID, PR number, etc.)
	Timeout   time.Duration `json:"timeout,omitempty"`    // Max wait time before escalation
	Waiters   []string      `json:"waiters,omitempty"`    // Mail addresses to notify when gate clears

	// ===== Slot Fields (exclusive access primitives) =====
	Holder string `json:"holder,omitempty"` // Who currently holds the slot (empty = available)

	// ===== Source Tracing Fields (formula cooking origin) =====
	SourceFormula  string `json:"source_formula,omitempty"`  // Formula name where step was defined
	SourceLocation string `json:"source_location,omitempty"` // Path: "steps[0]", "advice[0].after"

	// ===== Agent Identity Fields (agent-as-bead support) =====
	HookBead     string     `json:"hook_bead,omitempty"`     // Current work on agent's hook (0..1)
	RoleBead     string     `json:"role_bead,omitempty"`     // Role definition bead (required for agents)
	AgentState   AgentState `json:"agent_state,omitempty"`   // Agent state: idle|running|stuck|stopped
	LastActivity *time.Time `json:"last_activity,omitempty"` // Updated on each action (timeout detection)
	RoleType     string     `json:"role_type,omitempty"`     // Agent role type (application-defined)
	Rig          string     `json:"rig,omitempty"`           // Rig name (empty for town-level agents)

	// ===== Molecule Type Fields (swarm coordination) =====
	MolType MolType `json:"mol_type,omitempty"` // Molecule type: swarm|patrol|work (empty = work)

	// ===== Work Type Fields (assignment model - Decision 006) =====
	WorkType WorkType `json:"work_type,omitempty"` // Work type: mutex|open_competition (empty = mutex)

	// ===== Event Fields (operational state changes) =====
	EventKind string `json:"event_kind,omitempty"` // Namespaced event type: patrol.muted, agent.started
	Actor     string `json:"actor,omitempty"`      // Entity URI who caused this event
	Target    string `json:"target,omitempty"`     // Entity URI or bead ID affected
	Payload   string `json:"payload,omitempty"`    // Event-specific JSON data
}

Issue represents a trackable work item. Fields are organized into logical groups for maintainability.

func (*Issue) ComputeContentHash

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

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

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

func (*Issue) IsCompound

func (i *Issue) IsCompound() bool

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

func (*Issue) SetDefaults

func (i *Issue) SetDefaults()

SetDefaults applies default values for fields that may be omitted during deserialization. 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

func (*Issue) Validate

func (i *Issue) Validate() error

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

func (*Issue) ValidateForImport

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

ValidateForImport validates the issue for multi-repo import (federation trust model). Built-in types are validated (to catch typos). Non-built-in types are trusted since the source repo already validated them when the issue was created. This implements "trust the chain below you" from the HOP federation model.

func (*Issue) ValidateWithCustom

func (i *Issue) ValidateWithCustom(customStatuses, customTypes []string) error

ValidateWithCustom checks if the issue has valid field values, allowing custom statuses and types in addition to built-in ones.

func (*Issue) ValidateWithCustomStatuses

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 IssueDetails

type IssueDetails struct {
	Issue
	Labels       []string                       `json:"labels,omitempty"`
	Dependencies []*IssueWithDependencyMetadata `json:"dependencies,omitempty"`
	Dependents   []*IssueWithDependencyMetadata `json:"dependents,omitempty"`
	Comments     []*Comment                     `json:"comments,omitempty"`
	Parent       *string                        `json:"parent,omitempty"`

	// Epic progress fields (populated only for issue_type=epic with children)
	EpicTotalChildren  *int  `json:"epic_total_children,omitempty"`
	EpicClosedChildren *int  `json:"epic_closed_children,omitempty"`
	EpicCloseable      *bool `json:"epic_closeable,omitempty"`
}

IssueDetails extends Issue with labels, dependencies, dependents, and comments. Used for JSON serialization in bd show and RPC responses.

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
	LabelPattern string   // Glob pattern for label matching (e.g., "tech-*")
	LabelRegex   string   // Regex pattern for label matching (e.g., "tech-(debt|legacy)")
	TitleSearch  string
	IDs          []string // Filter by specific issue IDs
	IDPrefix     string   // Filter by ID prefix (e.g., "bd-" to match "bd-abc123")
	SpecIDPrefix string   // Filter by spec_id prefix
	Limit        int

	// Pattern matching
	TitleContains       string
	DescriptionContains string
	NotesContains       string
	ExternalRefContains 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

	// Source repo filtering (for multi-repo support)
	SourceRepo *string // Filter by source_repo field (nil = any)

	// Ephemeral filtering
	Ephemeral *bool // Filter by ephemeral flag (nil = any, true = only ephemeral, false = only persistent)

	// Pinned filtering
	Pinned *bool // Filter by pinned flag (nil = any, true = only pinned, false = only non-pinned)

	// Template filtering
	IsTemplate *bool // Filter by template flag (nil = any, true = only templates, false = exclude templates)

	// Parent filtering: filter children by parent issue ID
	ParentID *string // Filter by parent issue (via parent-child dependency)
	NoParent bool    // Exclude issues that are children of another issue

	// Molecule type filtering
	MolType *MolType // Filter by molecule type (nil = any, swarm/patrol/work)

	// Wisp type filtering (TTL-based compaction classification)
	WispType *WispType // Filter by wisp type (nil = any, heartbeat/ping/patrol/gc_report/recovery/error/escalation)

	// Status exclusion (for default non-closed behavior)
	ExcludeStatus []Status // Exclude issues with these statuses

	// Type exclusion (for hiding internal types like gates)
	ExcludeTypes []IssueType // Exclude issues with these types

	// Time-based scheduling filters (GH#820)
	Deferred    bool       // Filter issues with defer_until set (any value)
	DeferAfter  *time.Time // Filter issues with defer_until > this time
	DeferBefore *time.Time // Filter issues with defer_until < this time
	DueAfter    *time.Time // Filter issues with due_at > this time
	DueBefore   *time.Time // Filter issues with due_at < this time
	Overdue     bool       // Filter issues where due_at < now AND status != closed

	// Metadata field filtering (GH#1406)
	MetadataFields map[string]string // Top-level key=value equality; AND semantics (all must match)
	HasMetadataKey string            // Existence check: issue has this top-level key set (non-null)
}

IssueFilter is used to filter issue queries

type IssueProvider

type IssueProvider interface {
	// GetOpenIssues returns issues that are open or in_progress.
	// Should return empty slice (not error) if no issues exist.
	GetOpenIssues(ctx context.Context) ([]*Issue, error)

	// GetIssuePrefix returns the configured prefix (e.g., "bd", "TEST").
	// Should return "bd" as default if not configured.
	GetIssuePrefix() string
}

IssueProvider abstracts issue storage for orphan detection. Implementations may be backed by Dolt or mocks.

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"
	TypeDecision IssueType = "decision"
	TypeMessage  IssueType = "message"
	TypeMolecule IssueType = "molecule" // Molecule type for swarm coordination (internal use)
)

Core work type constants - these are the built-in types that beads validates. All other types require configuration via types.custom in config.yaml.

const TypeEvent IssueType = "event"

TypeEvent is a system-internal type used by set-state for audit trail beads. Originally a Gas Town type, promoted to built-in internal type. It is not a core work type (not in IsValid) but is accepted by IsValidWithCustom / ValidateWithCustom and treated as built-in for hydration trust (GH#1356).

func (IssueType) IsBuiltIn

func (t IssueType) IsBuiltIn() bool

IsBuiltIn returns true for core work types and system-internal types (i.e. TypeEvent). Used during multi-repo hydration to determine trust: - Built-in/internal types: validate (catch typos) - Custom types (!IsBuiltIn): trust from source repo

func (IssueType) IsValid

func (t IssueType) IsValid() bool

IsValid checks if the issue type is a core work type. Core work types (bug, feature, task, epic, chore, decision, message) and molecule type are built-in. Other types (gate, convoy, etc.) require types.custom configuration.

func (IssueType) IsValidWithCustom

func (t IssueType) IsValidWithCustom(customTypes []string) bool

IsValidWithCustom checks if the issue type is valid, including custom types. Custom types are user-defined via bd config set types.custom "type1,type2,..."

func (IssueType) Normalize

func (t IssueType) Normalize() IssueType

Normalize maps issue type aliases to their canonical form. For example, "enhancement" -> "feature". Case-insensitive to match util.NormalizeIssueType behavior.

func (IssueType) RequiredSections

func (t IssueType) RequiredSections() []RequiredSection

RequiredSections returns the recommended sections for this issue type. Returns nil for types with no specific section requirements.

type IssueWithCounts

type IssueWithCounts struct {
	*Issue
	DependencyCount int     `json:"dependency_count"`
	DependentCount  int     `json:"dependent_count"`
	CommentCount    int     `json:"comment_count"`
	Parent          *string `json:"parent,omitempty"` // Computed parent from parent-child dep (bd-ym8c)
}

IssueWithCounts extends Issue with dependency relationship counts

type IssueWithDependencyMetadata

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 MolType

type MolType string

MolType categorizes the molecule type for swarm coordination

const (
	MolTypeSwarm  MolType = "swarm"  // Swarm molecule: coordinated multi-polecat work
	MolTypePatrol MolType = "patrol" // Patrol molecule: recurring operational work (Witness, Deacon, etc.)
	MolTypeWork   MolType = "work"   // Work molecule: regular polecat work (default)
)

MolType constants

func (MolType) IsValid

func (m MolType) IsValid() bool

IsValid checks if the mol type value is valid

type MoleculeLastActivity

type MoleculeLastActivity struct {
	MoleculeID   string    `json:"molecule_id"`
	LastActivity time.Time `json:"last_activity"`
	Source       string    `json:"source"` // "step_closed", "step_updated", "molecule_updated"
	SourceStepID string    `json:"source_step_id,omitempty"`
}

MoleculeLastActivity holds the most recent activity timestamp for a molecule.

type MoleculeProgressStats

type MoleculeProgressStats struct {
	MoleculeID    string     `json:"molecule_id"`
	MoleculeTitle string     `json:"molecule_title"`
	Total         int        `json:"total"`           // Total steps (direct children)
	Completed     int        `json:"completed"`       // Closed steps
	InProgress    int        `json:"in_progress"`     // Steps currently in progress
	CurrentStepID string     `json:"current_step_id"` // First in_progress step ID (if any)
	FirstClosed   *time.Time `json:"first_closed,omitempty"`
	LastClosed    *time.Time `json:"last_closed,omitempty"`
}

MoleculeProgressStats provides efficient progress info for large molecules. This uses indexed queries instead of loading all steps into memory.

type RequiredSection

type RequiredSection struct {
	Heading string // Markdown heading, e.g., "## Steps to Reproduce"
	Hint    string // Guidance for what to include
}

RequiredSection describes a recommended section for an issue type. Used by bd lint and bd create --validate for template validation.

type SortPolicy

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

func (s SortPolicy) IsValid() bool

IsValid checks if the sort policy value is valid

type StaleFilter

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
	ReadyIssues             int     `json:"ready_issues"`
	PinnedIssues            int     `json:"pinned_issues"` // Persistent issues
	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
	StatusClosed     Status = "closed"
	StatusPinned     Status = "pinned" // Persistent bead that stays open indefinitely
	StatusHooked     Status = "hooked" // Work attached to an agent's hook (GUPP)
)

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

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 Validation

type Validation struct {
	// Validator is who approved/rejected the work
	Validator *EntityRef `json:"validator"`

	// Outcome is the validation result: accepted, rejected, revision_requested
	Outcome string `json:"outcome"`

	// Timestamp is when the validation occurred
	Timestamp time.Time `json:"timestamp"`

	// Score is an optional quality score (0.0-1.0)
	Score *float32 `json:"score,omitempty"`
}

Validation records who validated/approved work completion. This is core to HOP's proof-of-stake concept - validators stake their reputation on approvals.

func (*Validation) IsValidOutcome

func (v *Validation) IsValidOutcome() bool

IsValidOutcome checks if the outcome is a known validation outcome.

type WaitsForMeta

type WaitsForMeta struct {
	// Gate type: "all-children" (wait for all), "any-children" (wait for first)
	Gate string `json:"gate"`
	// SpawnerID identifies which step/issue spawns the children to wait for.
	// If empty, waits for all direct children of the depends_on_id issue.
	SpawnerID string `json:"spawner_id,omitempty"`
}

WaitsForMeta holds metadata for waits-for dependencies (fanout gates). Stored as JSON in the Dependency.Metadata field.

type WispType

type WispType string

WispType categorizes ephemeral wisps for TTL-based compaction (gt-9br)

const (
	// Category 1: High-churn, low forensic value (TTL: 6h)
	WispTypeHeartbeat WispType = "heartbeat" // Liveness pings
	WispTypePing      WispType = "ping"      // Health check ACKs

	// Category 2: Operational state (TTL: 24h)
	WispTypePatrol   WispType = "patrol"    // Patrol cycle reports
	WispTypeGCReport WispType = "gc_report" // Garbage collection reports

	// Category 3: Significant events (TTL: 7d)
	WispTypeRecovery   WispType = "recovery"   // Force-kill, recovery actions
	WispTypeError      WispType = "error"      // Error reports
	WispTypeEscalation WispType = "escalation" // Human escalations
)

WispType constants - see WISP-COMPACTION-POLICY.md for TTL assignments

func (WispType) IsValid

func (w WispType) IsValid() bool

IsValid checks if the wisp type value is valid

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
	LabelPattern string   // Glob pattern for label matching (e.g., "tech-*")
	LabelRegex   string   // Regex pattern for label matching (e.g., "tech-(debt|legacy)")
	Limit        int
	SortPolicy   SortPolicy

	// Parent filtering: filter to descendants of a bead/epic (recursive)
	ParentID *string // Show all descendants of this issue

	// Molecule type filtering
	MolType *MolType // Filter by molecule type (nil = any, swarm/patrol/work)

	// Wisp type filtering (TTL-based compaction classification)
	WispType *WispType // Filter by wisp type (nil = any, heartbeat/ping/patrol/gc_report/recovery/error/escalation)

	// Time-based deferral filtering (GH#820)
	IncludeDeferred bool // If true, include issues with future defer_until timestamps

	// Ephemeral issue filtering
	// By default, GetReadyWork excludes ephemeral issues (wisps).
	// Set to true to include them (e.g., for merge-request processing).
	IncludeEphemeral bool

	// Metadata field filtering (GH#1406)
	MetadataFields map[string]string // Top-level key=value equality; AND semantics (all must match)
	HasMetadataKey string            // Existence check: issue has this top-level key set (non-null)
}

WorkFilter is used to filter ready work queries

type WorkType

type WorkType string

WorkType categorizes how work assignment operates for a bead (Decision 006)

const (
	WorkTypeMutex           WorkType = "mutex"            // One worker, exclusive assignment (default)
	WorkTypeOpenCompetition WorkType = "open_competition" // Many submit, buyer picks
)

WorkType constants

func (WorkType) IsValid

func (w WorkType) IsValid() bool

IsValid checks if the work type value is valid

Jump to

Keyboard shortcuts

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