Documentation
¶
Overview ¶
Package workflow provides workflow state management and node implementations for AI-powered development workflows.
Core types:
- State: Workflow execution state with git, spec, implementation, and review data
- NodeFunc: Function signature for workflow nodes
- NodeConfig: Configuration for node behavior (retries, transcripts, etc.)
- Ticket: External ticket reference (Jira, GitHub issue, etc.)
Workflow nodes:
- CreateWorktreeNode: Creates git worktree for isolated work
- GenerateSpecNode: Generates feature specification from ticket
- ImplementNode: Implements code based on specification
- ReviewNode: Reviews implementation for issues
- FixFindingsNode: Fixes issues found during review
- RunTestsNode: Executes test suite
- CheckLintNode: Runs linting checks
- CreatePRNode: Creates pull request
- NotifyNode: Sends workflow notifications
Example usage:
state := workflow.NewState("ticket-to-pr")
state.SetTicket(workflow.Ticket{ID: "TK-421", Title: "Add feature"})
result, err := workflow.CreateWorktreeNode(ctx, state)
Index ¶
- Constants
- func DefaultReviewRouter(state State) string
- func ReviewRouter(state State, maxAttempts int) string
- type FileChange
- type GitState
- type ImplementState
- type LintState
- type MetricsState
- type NodeConfig
- type NodeFunc
- type PullRequestState
- type ReviewState
- type SpecState
- type State
- func CheckLintNode(ctx flowgraph.Context, state State) (State, error)
- func CleanupNode(ctx flowgraph.Context, state State) (State, error)
- func CreatePRNode(ctx flowgraph.Context, state State) (State, error)
- func CreateWorktreeNode(ctx flowgraph.Context, state State) (State, error)
- func FixFindingsNode(ctx flowgraph.Context, state State) (State, error)
- func GenerateSpecNode(ctx flowgraph.Context, state State) (State, error)
- func ImplementNode(ctx flowgraph.Context, state State) (State, error)
- func NewState(flowID string) State
- func NotifyNode(ctx flowgraph.Context, state State) (State, error)
- func ReviewNode(ctx flowgraph.Context, state State) (State, error)
- func RunTestsNode(ctx flowgraph.Context, state State) (State, error)
- func (s *State) AddTokens(in, out int)
- func (s *State) AddTokensWithCost(in, out int, cost float64)
- func (s State) CanRetryReview(maxAttempts int) bool
- func (s *State) FinalizeDuration()
- func (s State) HasError() bool
- func (s State) NeedsReviewFix() bool
- func (s *State) SetError(err error)
- func (s State) ShouldCreateDraftPR(maxAttempts int) bool
- func (s State) Summary() string
- func (s State) Validate(requirements ...StateRequirement) error
- func (s State) ValidateStrings(requirements ...string) error
- func (s State) WithBaseBranch(branch string) State
- func (s State) WithRunID(runID string) State
- func (s State) WithTicket(ticket *Ticket) State
- func (s State) WithTicketID(ticketID string) State
- type StateRequirement
- type TestState
- type Ticket
Constants ¶
const DefaultLintCommand = "go vet ./..."
DefaultLintCommand is the default command used to run linting.
const DefaultTestCommand = "go test -race ./..."
DefaultTestCommand is the default command used to run tests.
Variables ¶
This section is empty.
Functions ¶
func DefaultReviewRouter ¶
DefaultReviewRouter uses 3 max attempts
func ReviewRouter ¶
ReviewRouter returns the next node based on review results. Used with flowgraph conditional edges.
Types ¶
type FileChange ¶
type FileChange struct {
Path string `json:"path"`
Operation string `json:"operation"` // "create", "modify", "delete"
Content string `json:"content,omitempty"`
}
FileChange represents a file modification during implementation
type GitState ¶
type GitState struct {
Worktree string `json:"worktree,omitempty"`
Branch string `json:"branch,omitempty"`
BaseBranch string `json:"baseBranch,omitempty"`
}
GitState tracks git workspace state
type ImplementState ¶
type ImplementState struct {
Implementation string `json:"implementation,omitempty"`
Files []FileChange `json:"files,omitempty"`
ImplementTokensIn int `json:"implementTokensIn,omitempty"`
ImplementTokensOut int `json:"implementTokensOut,omitempty"`
}
ImplementState tracks implementation progress
type LintState ¶
type LintState struct {
LintOutput *artifact.LintOutput `json:"lintOutput,omitempty"`
LintPassed bool `json:"lintPassed,omitempty"`
LintRunAt time.Time `json:"lintRunAt,omitempty"`
}
LintState tracks lint/type check execution
type MetricsState ¶
type MetricsState struct {
TotalTokensIn int `json:"totalTokensIn"`
TotalTokensOut int `json:"totalTokensOut"`
TotalCost float64 `json:"totalCost"`
StartTime time.Time `json:"startTime"`
TotalDuration time.Duration `json:"totalDuration"`
}
MetricsState tracks execution metrics
type NodeConfig ¶
type NodeConfig struct {
MaxReviewAttempts int // Max review/fix cycles (default: 3)
TestCommand string // Test command (default: "go test ./...")
LintCommand string // Lint command (default: "go vet ./...")
BaseBranch string // Default base branch (default: "main")
}
NodeConfig configures node behavior
func DefaultNodeConfig ¶
func DefaultNodeConfig() NodeConfig
DefaultNodeConfig returns sensible defaults
type NodeFunc ¶
NodeFunc is a function that processes state and returns updated state. This signature is compatible with flowgraph's NodeFunc[State].
func WithTiming ¶
WithTiming wraps a node with timing metrics
func WithTranscript ¶
WithTranscript wraps a node with transcript recording
type PullRequestState ¶
type PullRequestState struct {
PR *pr.PullRequest `json:"pr,omitempty"`
PRCreated time.Time `json:"prCreated,omitempty"`
}
PullRequestState tracks pull request creation Named to avoid collision with pr.State (open/closed/merged)
type ReviewState ¶
type ReviewState struct {
Review *artifact.ReviewResult `json:"review,omitempty"`
ReviewAttempts int `json:"reviewAttempts,omitempty"`
ReviewTokensIn int `json:"reviewTokensIn,omitempty"`
ReviewTokensOut int `json:"reviewTokensOut,omitempty"`
}
ReviewState tracks code review
type SpecState ¶
type SpecState struct {
Spec string `json:"spec,omitempty"`
SpecTokensIn int `json:"specTokensIn,omitempty"`
SpecTokensOut int `json:"specTokensOut,omitempty"`
SpecGeneratedAt time.Time `json:"specGeneratedAt,omitempty"`
}
SpecState tracks specification generation
type State ¶
type State struct {
// Identification
RunID string `json:"runId"`
FlowID string `json:"flowId"`
TicketID string `json:"ticketId,omitempty"`
// Input
Ticket *Ticket `json:"ticket,omitempty"`
// Embedded state components
GitState
SpecState
ImplementState
ReviewState
PullRequestState
TestState
LintState
MetricsState
// Error tracking
Error string `json:"error,omitempty"`
}
State is the complete state for dev workflows
func CheckLintNode ¶
CheckLintNode runs linting and type checks.
Prerequisites: state.Worktree must be set Updates: state.LintOutput, state.LintPassed, state.LintRunAt
The node uses CommandRunner from context if available, otherwise falls back to ExecRunner. This allows for easy testing with MockRunner.
func CleanupNode ¶
CleanupNode cleans up the worktree.
Prerequisites: state.Worktree must be set Updates: clears state.Worktree
func CreatePRNode ¶
CreatePRNode creates a pull request.
Prerequisites: state.Branch must be set and pushed Updates: state.PR, state.PRCreated
func CreateWorktreeNode ¶
CreateWorktreeNode creates an isolated git worktree for the task.
Prerequisites: state.TicketID or state.Branch must be set Updates: state.Worktree, state.Branch
func FixFindingsNode ¶
FixFindingsNode fixes issues found in review.
Prerequisites: state.Review with findings, state.Worktree Updates: state.Implementation, state.Files
func GenerateSpecNode ¶
GenerateSpecNode generates a technical specification from the ticket.
Prerequisites: state.Ticket must be set Updates: state.Spec, state.SpecTokensIn/Out, state.SpecGeneratedAt
func ImplementNode ¶
ImplementNode implements code based on the specification.
Prerequisites: state.Spec, state.Worktree must be set Updates: state.Implementation, state.Files, state.ImplementTokensIn/Out
func NotifyNode ¶
NotifyNode sends a notification based on current state.
This node is typically placed at the end of a workflow to notify interested parties of completion or failure. If no notifier is configured in the context, this is a no-op.
Updates: None (only sends notification)
func ReviewNode ¶
ReviewNode reviews implementation for issues.
Prerequisites: state.Spec or state.Implementation must be set Updates: state.Review, state.ReviewAttempts, state.ReviewTokensIn/Out
func RunTestsNode ¶
RunTestsNode runs the test suite.
Prerequisites: state.Worktree must be set Updates: state.TestOutput, state.TestPassed, state.TestRunAt
The node uses CommandRunner from context if available, otherwise falls back to ExecRunner. This allows for easy testing with MockRunner.
func (*State) AddTokensWithCost ¶
AddTokensWithCost updates token metrics with explicit cost
func (State) CanRetryReview ¶
CanRetryReview returns true if we haven't exceeded review attempts
func (*State) FinalizeDuration ¶
func (s *State) FinalizeDuration()
FinalizeDuration sets total duration from start time
func (State) NeedsReviewFix ¶
NeedsReviewFix returns true if review found issues that need fixing
func (State) ShouldCreateDraftPR ¶
ShouldCreateDraftPR returns true if we should create a draft PR (review found issues but we've hit max attempts)
func (State) Validate ¶
func (s State) Validate(requirements ...StateRequirement) error
Validate checks if state has required fields
func (State) ValidateStrings ¶
ValidateStrings validates using string requirements (for flexibility)
func (State) WithBaseBranch ¶
WithBaseBranch sets the base branch for the workflow
func (State) WithTicket ¶
WithTicket adds ticket information to state
func (State) WithTicketID ¶
WithTicketID sets just the ticket ID (for when full ticket isn't needed)
type StateRequirement ¶
type StateRequirement string
StateRequirement defines a state prerequisite
const ( RequireTicket StateRequirement = "ticket" RequireWorktree StateRequirement = "worktree" RequireSpec StateRequirement = "spec" RequireImplementation StateRequirement = "implementation" RequireReview StateRequirement = "review" RequireBranch StateRequirement = "branch" RequireFiles StateRequirement = "files" )
type TestState ¶
type TestState struct {
TestOutput *artifact.TestOutput `json:"testOutput,omitempty"`
TestPassed bool `json:"testPassed,omitempty"`
TestRunAt time.Time `json:"testRunAt,omitempty"`
}
TestState tracks test execution
type Ticket ¶
type Ticket struct {
ID string `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
Priority string `json:"priority,omitempty"`
Type string `json:"type,omitempty"` // bug, feature, task, etc.
Labels []string `json:"labels,omitempty"`
Assignee string `json:"assignee,omitempty"`
Reporter string `json:"reporter,omitempty"`
URL string `json:"url,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
Ticket represents input ticket data from an issue tracker