hc

package
v0.45.0 Latest Latest
Warning

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

Go to latest
Published: Mar 30, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrCyclicDependency = errors.New("cyclic dependency")

ErrCyclicDependency is returned when an AddBlocker call would create a cycle.

View Source
var ErrInvalidItemType = fmt.Errorf("not a valid ItemType, try [%s]", strings.Join(_ItemTypeNames, ", "))
View Source
var ErrInvalidStatus = fmt.Errorf("not a valid Status, try [%s]", strings.Join(_StatusNames, ", "))
View Source
var ErrNotFound = errors.New("not found")

ErrNotFound is returned when a requested item does not exist.

Functions

func GenerateCommentID

func GenerateCommentID() string

GenerateCommentID returns a short unique ID for an HC comment.

func GenerateID

func GenerateID() string

GenerateID returns a short unique ID for an HC item.

func ItemTypeNames

func ItemTypeNames() []string

ItemTypeNames returns a list of possible string values of ItemType.

func StatusNames

func StatusNames() []string

StatusNames returns a list of possible string values of Status.

func WouldCycle added in v0.39.0

func WouldCycle(edges [][2]string, from, to string) bool

WouldCycle reports whether adding the edge from → to would introduce a cycle in the blocker graph. It performs a DFS from 'to' following existing edges; if 'from' is reachable, adding the edge would close a cycle.

Types

type Comment

type Comment struct {
	ID        string    `json:"id"`
	ItemID    string    `json:"item_id"`
	Message   string    `json:"message"`
	CreatedAt time.Time `json:"created_at"`
}

Comment records a note attached to an item. Comments are used for two purposes: capturing design decisions made during implementation, and leaving context for handoffs when stopping mid-implementation.

type ContextBlock

type ContextBlock struct {
	Epic         Item              `json:"epic"`
	Counts       TaskCounts        `json:"counts"`
	MyTasks      []TaskWithComment `json:"my_tasks"`
	AllOpenTasks []Item            `json:"all_open_tasks"`
}

ContextBlock is the assembled context view for an epic.

func (ContextBlock) String

func (c ContextBlock) String() string

String returns a markdown representation of the context block suitable for display in the CLI or consumption by an AI agent.

type CreateInput

type CreateInput struct {
	Ref      string        `json:"ref,omitempty"` // optional local reference for blocker wiring
	Title    string        `json:"title"`
	Desc     string        `json:"desc,omitempty"`
	Type     ItemType      `json:"type"`
	Children []CreateInput `json:"children,omitempty"`
	Blockers []string      `json:"blockers,omitempty"` // refs of items that must complete before this one
}

CreateInput represents a node in a hierarchical task tree for bulk creation. The tree is walked BFS and IDs are generated in the service layer.

type CreateItemInput

type CreateItemInput struct {
	Title    string
	Desc     string
	Type     ItemType
	ParentID string
}

CreateItemInput describes a single-item create request.

type Item

type Item struct {
	ID         string    `json:"id"`
	RepoKey    string    `json:"repo_key"`   // "owner/repo" or ""
	EpicID     string    `json:"epic_id"`    // "" for epics themselves
	ParentID   string    `json:"parent_id"`  // "" for root items
	SessionID  string    `json:"session_id"` // assigned agent session, may be ""
	Title      string    `json:"title"`
	Desc       string    `json:"desc"`
	Type       ItemType  `json:"type"`
	Status     Status    `json:"status"`
	Blocked    bool      `json:"-"`                     // computed at read time: true when the item has open/in_progress children or open/in_progress explicit blockers
	BlockerIDs []string  `json:"blocker_ids,omitempty"` // explicit blocker item IDs (open/in_progress only)
	Depth      int       `json:"depth"`                 // 0 for epics/roots
	CreatedAt  time.Time `json:"created_at"`
	UpdatedAt  time.Time `json:"updated_at"`
}

Item represents a single unit of work tracked by hc.

func (Item) IsEpic

func (i Item) IsEpic() bool

IsEpic reports whether the item is an epic.

func (Item) IsRoot

func (i Item) IsRoot() bool

IsRoot reports whether the item has no parent.

func (Item) Validate

func (i Item) Validate() error

Validate checks that an Item has internally consistent required fields.

type ItemType

type ItemType string

ItemType categorizes an item as an epic or a task.

ENUM(

epic
task

)

const (
	// ItemTypeEpic is a ItemType of type epic.
	ItemTypeEpic ItemType = "epic"
	// ItemTypeTask is a ItemType of type task.
	ItemTypeTask ItemType = "task"
)

func ParseItemType

func ParseItemType(name string) (ItemType, error)

ParseItemType attempts to convert a string to a ItemType.

func (*ItemType) AppendText

func (x *ItemType) AppendText(b []byte) ([]byte, error)

AppendText appends the textual representation of itself to the end of b (allocating a larger slice if necessary) and returns the updated slice.

Implementations must not retain b, nor mutate any bytes within b[:len(b)].

func (ItemType) IsValid

func (x ItemType) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (ItemType) MarshalText

func (x ItemType) MarshalText() ([]byte, error)

MarshalText implements the text marshaller method.

func (ItemType) String

func (x ItemType) String() string

String implements the Stringer interface.

func (*ItemType) UnmarshalText

func (x *ItemType) UnmarshalText(text []byte) error

UnmarshalText implements the text unmarshaller method.

type ItemUpdate

type ItemUpdate struct {
	Status    *Status
	SessionID *string
	Title     *string
	Desc      *string
}

ItemUpdate carries partial updates to an Item. Nil pointer fields are not changed.

type ListFilter

type ListFilter struct {
	RepoKey   string
	EpicID    string
	SessionID string
	Status    *Status
}

ListFilter controls which items are returned by ListItems.

func (ListFilter) Matches

func (f ListFilter) Matches(item Item) bool

Matches reports whether item satisfies all non-zero filter fields.

type NextFilter

type NextFilter struct {
	EpicID    string
	SessionID string
	RepoKey   string
}

NextFilter selects candidate items for NextItem.

type PruneOpts

type PruneOpts struct {
	OlderThan time.Duration
	Statuses  []Status
	RepoKey   string
	DryRun    bool
}

PruneOpts controls which items are removed by Prune.

type Status

type Status string

Status tracks the lifecycle of an hc item.

ENUM(

open
in_progress
done
cancelled

)

const (
	// StatusOpen is a Status of type open.
	StatusOpen Status = "open"
	// StatusInProgress is a Status of type in_progress.
	StatusInProgress Status = "in_progress"
	// StatusDone is a Status of type done.
	StatusDone Status = "done"
	// StatusCancelled is a Status of type cancelled.
	StatusCancelled Status = "cancelled"
)

func ParseStatus

func ParseStatus(name string) (Status, error)

ParseStatus attempts to convert a string to a Status.

func (*Status) AppendText

func (x *Status) AppendText(b []byte) ([]byte, error)

AppendText appends the textual representation of itself to the end of b (allocating a larger slice if necessary) and returns the updated slice.

Implementations must not retain b, nor mutate any bytes within b[:len(b)].

func (Status) IsValid

func (x Status) IsValid() bool

IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values

func (Status) MarshalText

func (x Status) MarshalText() ([]byte, error)

MarshalText implements the text marshaller method.

func (Status) String

func (x Status) String() string

String implements the Stringer interface.

func (*Status) UnmarshalText

func (x *Status) UnmarshalText(text []byte) error

UnmarshalText implements the text unmarshaller method.

type Store

type Store interface {
	// CreateItems persists one or more items atomically.
	CreateItems(ctx context.Context, items []Item) error
	// GetItem returns an item by ID.
	GetItem(ctx context.Context, id string) (Item, error)
	// UpdateItem applies a partial update and returns the updated item.
	UpdateItem(ctx context.Context, id string, update ItemUpdate) (Item, error)
	// ListItems returns items matching the filter.
	ListItems(ctx context.Context, filter ListFilter) ([]Item, error)
	// NextItem returns the next actionable leaf item for the filter.
	// Actionable means status is open/in_progress and no open/in_progress children.
	NextItem(ctx context.Context, filter NextFilter) (Item, bool, error)
	// DeleteItem removes an item by ID.
	// This is an internal maintenance path used by prune operations.
	DeleteItem(ctx context.Context, id string) error
	// AddComment records a comment on an item.
	AddComment(ctx context.Context, c Comment) error
	// ListComments returns all comments for an item in chronological order.
	ListComments(ctx context.Context, itemID string) ([]Comment, error)
	// Prune removes old items and related comments according to options.
	Prune(ctx context.Context, opts PruneOpts) (int, error)
	// ListRepoKeys returns all distinct, non-empty repo keys in sorted order.
	ListRepoKeys(ctx context.Context) ([]string, error)
	// CreateBulkWithEdges creates items and wires their explicit blocker edges atomically.
	// edges is a slice of [blockerID, blockedID] pairs. Cycle validation must be done
	// by the caller before invoking this method; this method only enforces FK constraints.
	CreateBulkWithEdges(ctx context.Context, items []Item, edges [][2]string) error
	// AddBlocker records that blockerID blocks blockedID atomically, including cycle detection.
	// Returns ErrCyclicDependency if the edge would create a cycle.
	AddBlocker(ctx context.Context, blockerID, blockedID string) error
	// RemoveBlocker removes the blocker relationship.
	RemoveBlocker(ctx context.Context, blockerID, blockedID string) error
	// ListBlockers returns IDs of open/in_progress items that explicitly block the given item.
	ListBlockers(ctx context.Context, itemID string) ([]string, error)
	// ListBlockerEdges returns all blocker edges as [blockerID, blockedID] pairs.
	// Used by callers that need the full graph (e.g. for pre-validation before bulk create).
	ListBlockerEdges(ctx context.Context) ([][2]string, error)
	// BulkUpdateStatus sets the status of all non-terminal descendants of the given
	// epic to the specified status. Items already in a terminal status (done, cancelled)
	// are not modified.
	BulkUpdateStatus(ctx context.Context, epicID string, status Status) error
}

Store persists hc items and comments to durable storage.

type TaskCounts

type TaskCounts struct {
	Open       int `json:"open"`
	InProgress int `json:"in_progress"`
	Done       int `json:"done"`
	Cancelled  int `json:"cancelled"`
}

TaskCounts holds counts of items by status.

type TaskWithComment

type TaskWithComment struct {
	Item          Item    `json:"item"`
	LatestComment Comment `json:"latest_comment"`
}

TaskWithComment pairs an item with its latest comment.

Jump to

Keyboard shortcuts

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