phases

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Mar 11, 2026 License: AGPL-3.0 Imports: 37 Imported by: 0

Documentation

Overview

Package phases implements the agent state machine phases.

Package phases implements the individual phases of the agent state machine.

Each phase handles a specific stage of agent execution:

  • INIT: Initialize the session, load graph
  • PLAN: Assemble initial context, prepare for execution
  • EXECUTE: Main tool execution loop
  • REFLECT: Evaluate progress and decide next steps
  • CLARIFY: Request user input for ambiguous situations

Thread Safety:

Phase implementations must be safe for concurrent use.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrSymbolIndexNotAvailable indicates the symbol index is not initialized.
	ErrSymbolIndexNotAvailable = errors.New("symbol index not available")

	// ErrSymbolNotFound indicates no symbol matched the search criteria.
	ErrSymbolNotFound = errors.New("symbol not found")
)

CB-31d: Typed errors for better error handling (M-R-1)

Functions

func CleanupUCB1Context

func CleanupUCB1Context(sessionID string)

CleanupUCB1Context removes the UCB1 context for a session. This is the exported version for use by the agent loop during session cleanup.

Description:

Removes all UCB1-related state (scorer, selection counts, cache, key builder)
for the specified session. Should be called when a session is definitively
closed (not just completed, as sessions can be continued with follow-up questions).

Inputs:

sessionID - The session ID to clean up.

Thread Safety: Safe for concurrent use.

func ClearSemanticCorrectionCache

func ClearSemanticCorrectionCache()

ClearSemanticCorrectionCache clears the cache (for testing).

func ValidateToolQuerySemantics

func ValidateToolQuerySemantics(query, selectedTool string) (correctedTool string, wasChanged bool, reason string)

ValidateToolQuerySemantics checks if the selected tool matches the query semantics.

Description:

GR-Phase1: Post-router validation to catch obvious semantic mismatches.
Specifically designed to detect find_callers vs find_callees confusion.

Inputs:

query - The user's query string.
selectedTool - The tool selected by the router.

Outputs:

correctedTool - The validated/corrected tool name.
wasChanged - True if the tool was changed from the original selection.
reason - Explanation if the tool was changed.

Types

type BatchFilterer

type BatchFilterer interface {
	// FilterBatch evaluates a batch of tool calls and returns filter decisions.
	//
	// Inputs:
	//   ctx - Context for cancellation/timeout.
	//   prompt - The filter prompt containing tools and similarity scores.
	//
	// Outputs:
	//   string - Response with KEEP/SKIP decisions.
	//   error - Non-nil if the filter call fails.
	FilterBatch(ctx context.Context, prompt string) (string, error)
}

BatchFilterer is an interface for components that can filter tool call batches.

Description:

Components implementing this interface can classify/filter tool calls
using a fast model. The primary implementation is the router model
(granite4:micro-h) which is optimized for fast classification.

Thread Safety: Implementations must be safe for concurrent use.

type ClarifyPhase

type ClarifyPhase struct {
	// contains filtered or unexported fields
}

ClarifyPhase handles user clarification requests.

This phase is responsible for:

  • Generating clarification prompts for the user
  • Processing user clarification responses
  • Updating context with clarified information

When to Use CLARIFY State

The CLARIFY state should ONLY be used when the agent genuinely cannot proceed without user input. It should NOT be used as a lazy fallback for broad questions.

APPROPRIATE uses of CLARIFY:

  • Project root not provided or invalid path
  • User request contains contradictory requirements
  • Multiple mutually exclusive interpretations exist (e.g., "fix the bug" when multiple bugs exist)
  • Required information is truly missing (e.g., API keys, credentials)

INAPPROPRIATE uses of CLARIFY (agent should explore instead):

  • "Which file should I look at?" - explore the codebase
  • "Which function do you mean?" - search for matches
  • "What security concerns?" - analyze the code and report findings
  • "Trace data flow" - start from entry points and explore

The agent should be proactive: use tools to explore the codebase and provide comprehensive answers rather than asking the user to narrow the scope.

Thread Safety: ClarifyPhase is safe for concurrent use.

func NewClarifyPhase

func NewClarifyPhase(opts ...ClarifyPhaseOption) *ClarifyPhase

NewClarifyPhase creates a new clarification phase.

Inputs:

opts - Configuration options.

Outputs:

*ClarifyPhase - The configured phase.

func (*ClarifyPhase) ClearClarificationInput

func (p *ClarifyPhase) ClearClarificationInput()

ClearClarificationInput clears any pending clarification input.

Thread Safety: This method is safe for concurrent use.

func (*ClarifyPhase) Execute

func (p *ClarifyPhase) Execute(ctx context.Context, deps *Dependencies) (agent.AgentState, error)

Execute implements Phase.

Description:

Processes the clarification state. If clarification input is available,
adds it to the context and transitions back to PLAN. Otherwise,
the phase signals that clarification is needed (returning an error
that indicates the session is awaiting user input).

Inputs:

ctx - Context for cancellation and timeout.
deps - Phase dependencies.

Outputs:

agent.AgentState - PLAN after clarification received, or CLARIFY if awaiting.
error - ErrAwaitingClarification if input needed, other errors on failure.

Thread Safety: This method is safe for concurrent use.

func (*ClarifyPhase) GetClarificationPrompt

func (p *ClarifyPhase) GetClarificationPrompt(deps *Dependencies) string

GetClarificationPrompt returns the prompt to show the user.

Description:

Returns the appropriate clarification prompt based on context.
Should be called when the session enters CLARIFY state to get
the message to display to the user.

Inputs:

deps - Phase dependencies (optional, used for context).

Outputs:

string - The clarification prompt.

Thread Safety: This method is safe for concurrent use.

func (*ClarifyPhase) Name

func (p *ClarifyPhase) Name() string

Name implements Phase.

Outputs:

string - "clarify"

func (*ClarifyPhase) SetClarificationInput

func (p *ClarifyPhase) SetClarificationInput(input string)

SetClarificationInput sets the user's clarification response.

Description:

Called by the agent loop when the user provides clarification.
This should be called before Execute() when processing a clarification.

Inputs:

input - The user's clarification text.

Thread Safety: This method is safe for concurrent use.

type ClarifyPhaseOption

type ClarifyPhaseOption func(*ClarifyPhase)

ClarifyPhaseOption configures a ClarifyPhase.

func WithDefaultPrompt

func WithDefaultPrompt(prompt string) ClarifyPhaseOption

WithDefaultPrompt sets the default clarification prompt.

Inputs:

prompt - The default prompt.

Outputs:

ClarifyPhaseOption - The configuration function.

type ContextManager

type ContextManager = agentcontext.Manager

ContextManager is the interface for context management.

type DefaultForcingPolicy

type DefaultForcingPolicy struct {
	// contains filtered or unexported fields
}

DefaultForcingPolicy implements ToolForcingPolicy with standard behavior.

Description:

Uses a QueryClassifier to identify analytical queries that require
tool exploration. Forces tool usage when:
- The query is analytical (requires codebase exploration)
- We haven't exceeded max retries
- We're within the early steps where forcing applies

Thread Safety: This type is safe for concurrent use after initialization.

func NewDefaultForcingPolicy

func NewDefaultForcingPolicy() *DefaultForcingPolicy

NewDefaultForcingPolicy creates a policy with a regex-based classifier.

Description:

Creates a DefaultForcingPolicy using RegexClassifier for query
classification. The classifier uses word-boundary patterns to
minimize false positives.

Outputs:

*DefaultForcingPolicy - A ready-to-use forcing policy.

Example:

policy := NewDefaultForcingPolicy()
if policy.ShouldForce(ctx, req) { ... }

Thread Safety: The returned policy is safe for concurrent use.

func NewDefaultForcingPolicyWithClassifier

func NewDefaultForcingPolicyWithClassifier(c classifier.QueryClassifier) *DefaultForcingPolicy

NewDefaultForcingPolicyWithClassifier creates a policy with a custom classifier.

Description:

Allows injecting a custom QueryClassifier for testing or
specialized classification logic.

Inputs:

c - The query classifier to use. Must not be nil.

Outputs:

*DefaultForcingPolicy - A policy using the provided classifier.

Example:

mockClassifier := &MockClassifier{isAnalytical: true}
policy := NewDefaultForcingPolicyWithClassifier(mockClassifier)

Thread Safety: The returned policy is safe for concurrent use if the classifier is safe for concurrent use.

func (*DefaultForcingPolicy) BuildHint

func (p *DefaultForcingPolicy) BuildHint(ctx context.Context, req *ForcingRequest) string

BuildHint creates the forcing hint message with targeted search instructions.

Description:

Generates a user message that prompts the LLM to use tools.
Uses SuggestToolWithHint to provide specific search instructions,
not just which tool to use but WHAT patterns to search for.
This implements Fix 2 (Targeted Exploration) from CB-28d-6.

Inputs:

ctx - Context for tracing. Must not be nil.
req - The forcing request. Must not be nil.

Outputs:

string - The hint message to inject with specific search instructions.

Example:

hint := policy.BuildHint(ctx, &ForcingRequest{
    Query: "What tests exist?",
    AvailableTools: []string{"find_entry_points"},
})
// hint contains "find_entry_points with type='test'" and search patterns

Thread Safety: This method is safe for concurrent use.

func (*DefaultForcingPolicy) ShouldForce

func (p *DefaultForcingPolicy) ShouldForce(ctx context.Context, req *ForcingRequest) bool

ShouldForce determines if tool usage should be forced.

Description:

Returns true when all of the following are true:
- The query is analytical (identified by classifier)
- StepNumber <= MaxStepForForcing (early enough to force)
- ForcingRetries < MaxRetries (haven't hit circuit breaker)

Inputs:

ctx - Context for tracing. Must not be nil.
req - The forcing request. Must not be nil.

Outputs:

bool - True if tool usage should be forced.

Example:

policy := NewDefaultForcingPolicy()
shouldForce := policy.ShouldForce(ctx, &ForcingRequest{
    Query: "What tests exist?",
    StepNumber: 1,
    MaxStepForForcing: 2,
    ForcingRetries: 0,
    MaxRetries: 2,
})
// shouldForce == true

Thread Safety: This method is safe for concurrent use.

type Dependencies

type Dependencies struct {
	// Session is the current agent session.
	Session *agent.Session

	// Query is the user's original query.
	Query string

	// Context is the assembled context (nil until PLAN phase completes).
	Context *agent.AssembledContext

	// ContextManager handles context assembly and updates.
	ContextManager *ContextManager

	// LLMClient sends requests to the language model.
	LLMClient LLMClient

	// ToolRegistry provides access to available tools.
	ToolRegistry *ToolRegistry

	// ToolExecutor executes tool invocations.
	ToolExecutor *ToolExecutor

	// SafetyGate validates proposed changes.
	SafetyGate SafetyGate

	// EventEmitter broadcasts agent events.
	EventEmitter *EventEmitter

	// GraphProvider initializes and provides the code graph.
	GraphProvider GraphProvider

	// ResponseGrounder validates LLM responses against project reality.
	// Optional - if nil, grounding validation is skipped.
	ResponseGrounder ResponseGrounder

	// AnchoredSynthesisBuilder builds tool-anchored synthesis prompts.
	// Optional - if nil, basic synthesis prompt is used.
	AnchoredSynthesisBuilder grounding.AnchoredSynthesisBuilder

	// DirtyTracker tracks files modified by tools for graph refresh.
	// Optional - if nil, graph freshness tracking is disabled.
	DirtyTracker *graph.DirtyTracker

	// GraphRefresher handles incremental graph updates.
	// Optional - if nil, graph refresh is disabled.
	GraphRefresher *graph.Refresher

	// Coordinator orchestrates MCTS activities in response to agent events.
	// Optional - if nil, MCTS activity coordination is disabled.
	// Use HandleEvent to emit events and trigger appropriate activities.
	Coordinator *integration.Coordinator

	// CRS is the Code Reasoning State for MCTS integration.
	// Optional - if nil, CRS-based reasoning is disabled.
	// Use for session restore, checkpoint management, and proof tracking.
	CRS crs.CRS

	// PersistenceManager handles CRS checkpoint storage.
	// Optional - if nil, CRS persistence is disabled.
	// GR-33/GR-36: Required for session restore and checkpoint save.
	PersistenceManager *crs.PersistenceManager

	// Journal stores CRS deltas for replay.
	// Optional - if nil, delta journaling is disabled.
	// GR-33/GR-36: Required for session restore to replay deltas.
	// CRS-27: Changed from *crs.BadgerJournal to crs.Journal interface
	// to support NATS JetStream and other journal backends.
	Journal crs.Journal

	// GraphAnalytics provides graph analysis operations (dominators, communities, etc).
	// Required for symbol resolution in parameter extraction (CB-31d).
	// Optional - if nil, parameter extraction falls back to raw symbol names.
	GraphAnalytics *graph.GraphAnalytics

	// SymbolIndex provides fast symbol lookup by ID, name, or fuzzy search.
	// Required for symbol resolution in parameter extraction (CB-31d).
	// Optional - if nil, parameter extraction falls back to raw symbol names.
	SymbolIndex *index.SymbolIndex

	// RAGResolver resolves query tokens against the code graph before param extraction.
	// CRS-25: Optional - if nil, param extraction runs without entity grounding.
	// When available, resolves entity names (packages, symbols) from the graph
	// and injects them into the extraction context for the LLM.
	// Accepts StructuralResolver (Layer 1 only) or CombinedResolver (Layers 1+2).
	RAGResolver rag.Resolver

	// SymbolStore handles Weaviate symbol index updates for incremental refresh.
	// CRS-25b: Optional - if nil, incremental RAG refresh is disabled.
	// When available, symbols are deleted/re-indexed when files change mid-session.
	SymbolStore *rag.SymbolStore

	// ParamExtractor uses a fast LLM to extract tool parameters from queries.
	// IT-08b: Optional - nil when LLM parameter extraction is not enabled.
	// When available, enhances regex-based extraction with semantic understanding.
	ParamExtractor agent.ParamExtractor

	// StalenessChecker detects if the code graph is stale relative to the working tree.
	// CRS-19: Optional - if nil, staleness detection is disabled.
	// When available, spot-checks file mtimes before graph tool dispatch.
	StalenessChecker *graph.StalenessChecker
}

Dependencies contains all dependencies needed by phases.

This struct provides phases with access to the session state, external services, and configuration without coupling phases to specific implementations.

type EventEmitter

type EventEmitter = events.Emitter

EventEmitter is the interface for event emission.

type ExecutePhase

type ExecutePhase struct {
	// contains filtered or unexported fields
}

ExecutePhase handles the main tool execution loop.

This phase is responsible for:

  • Sending requests to the LLM with current context
  • Parsing and executing tool calls from LLM responses
  • Running safety checks on proposed changes
  • Updating context with tool results
  • Forcing tool usage for analytical queries
  • Determining when to reflect or complete

Thread Safety: ExecutePhase is safe for concurrent use.

func NewExecutePhase

func NewExecutePhase(opts ...ExecutePhaseOption) *ExecutePhase

NewExecutePhase creates a new execution phase.

Inputs:

opts - Configuration options.

Outputs:

*ExecutePhase - The configured phase.

func (*ExecutePhase) Execute

func (p *ExecutePhase) Execute(ctx context.Context, deps *Dependencies) (agent.AgentState, error)

Execute implements Phase.

Description:

Runs a single step of the execution loop:
1. Build prompt with current context
2. Call LLM for response
3. Parse tool calls from response
4. For each tool call: run safety check, execute tool
5. Update context with results
6. Check if reflection is needed

Inputs:

ctx - Context for cancellation and timeout.
deps - Phase dependencies.

Outputs:

agent.AgentState - Next state (EXECUTE, REFLECT, COMPLETE, or ERROR).
error - Non-nil only for unrecoverable errors.

Thread Safety: This method is safe for concurrent use.

func (*ExecutePhase) Name

func (p *ExecutePhase) Name() string

Name implements Phase.

Outputs:

string - "execute"

type ExecutePhaseOption

type ExecutePhaseOption func(*ExecutePhase)

ExecutePhaseOption configures an ExecutePhase.

func WithMaxGroundingRetries

func WithMaxGroundingRetries(retries int) ExecutePhaseOption

WithMaxGroundingRetries sets the maximum grounding validation retries.

Inputs:

retries - Maximum retry count (circuit breaker threshold).

Outputs:

ExecutePhaseOption - The configuration function.

func WithMaxStepForForcing

func WithMaxStepForForcing(step int) ExecutePhaseOption

WithMaxStepForForcing sets the maximum step for tool forcing.

Inputs:

step - Maximum step number where forcing applies.

Outputs:

ExecutePhaseOption - The configuration function.

func WithMaxTokens

func WithMaxTokens(tokens int) ExecutePhaseOption

WithMaxTokens sets the maximum response tokens.

Inputs:

tokens - Maximum token count.

Outputs:

ExecutePhaseOption - The configuration function.

func WithMaxToolForcingRetries

func WithMaxToolForcingRetries(retries int) ExecutePhaseOption

WithMaxToolForcingRetries sets the maximum tool forcing retries.

Inputs:

retries - Maximum retry count (circuit breaker threshold).

Outputs:

ExecutePhaseOption - The configuration function.

func WithPreFilter

func WithPreFilter(pf *routing.PreFilter) ExecutePhaseOption

WithPreFilter sets the pre-filter for narrowing tool candidates (CB-38).

Description:

When set, the pre-filter runs before the LLM router to narrow
55+ tools to 5-10 candidates (or force a selection outright).
nil = disabled (backward compatible).

Inputs:

pf - The pre-filter instance. May be nil to disable.

Outputs:

ExecutePhaseOption - The configuration function.

func WithQueryClassifier

func WithQueryClassifier(c classifier.QueryClassifier) ExecutePhaseOption

WithQueryClassifier sets the query classifier for both tool forcing and tool choice selection.

Description:

Sets a custom QueryClassifier that will be used by both the forcing
policy (to determine when to force tool usage) and the tool choice
selector (to select API-level tool_choice parameter).

This enables using the LLMClassifier instead of the default RegexClassifier
for more accurate query classification.

Inputs:

c - The query classifier to use. If nil, defaults to RegexClassifier.

Outputs:

ExecutePhaseOption - The configuration function.

Example:

// Use LLM-based classifier
llmClassifier, _ := classifier.NewLLMClassifier(client, toolDefs, config)
phase := NewExecutePhase(WithQueryClassifier(llmClassifier))

Thread Safety: The option is safe for concurrent use if the classifier is.

func WithReflectionThreshold

func WithReflectionThreshold(steps int) ExecutePhaseOption

WithReflectionThreshold sets when to trigger reflection.

Inputs:

steps - Number of steps before reflection.

Outputs:

ExecutePhaseOption - The configuration function.

func WithSafetyCheck

func WithSafetyCheck(required bool) ExecutePhaseOption

WithSafetyCheck enables or disables safety checks.

Inputs:

required - Whether safety checks are required.

Outputs:

ExecutePhaseOption - The configuration function.

func WithToolForcingPolicy

func WithToolForcingPolicy(policy ToolForcingPolicy) ExecutePhaseOption

WithToolForcingPolicy sets the policy for forcing tool usage.

Inputs:

policy - The tool forcing policy. If nil, forcing is disabled.

Outputs:

ExecutePhaseOption - The configuration function.

type ForcingRequest

type ForcingRequest struct {
	// Query is the user's original query.
	Query string

	// StepNumber is the current execution step.
	StepNumber int

	// ForcingRetries is the number of tool forcing retries so far.
	ForcingRetries int

	// MaxRetries is the maximum allowed forcing retries.
	MaxRetries int

	// MaxStepForForcing is the maximum step number where forcing applies.
	MaxStepForForcing int

	// AvailableTools is the list of available tool names.
	AvailableTools []string
}

ForcingRequest contains the context for a tool forcing decision.

Thread Safety: This type is immutable and safe for concurrent read access.

type GraphProvider

type GraphProvider interface {
	// Initialize sets up the code graph for a project.
	//
	// Inputs:
	//   ctx - Context for cancellation.
	//   projectRoot - Path to the project root.
	//
	// Outputs:
	//   string - The graph ID.
	//   error - Non-nil if initialization fails.
	Initialize(ctx context.Context, projectRoot string) (string, error)

	// IsAvailable checks if the graph service is available.
	//
	// Outputs:
	//   bool - True if the service is available.
	IsAvailable() bool

	// EnrichmentTraceStep returns a TraceStep describing the LSP enrichment
	// quality of the cached graph. Returns nil if no graph is cached or
	// enrichment data is unavailable.
	//
	// Description:
	//
	//	GR-76: Called by InitPhase after SetGraphID to record enrichment
	//	quality in the CRS journal. The LLM uses this to calibrate trust
	//	in graph tool results.
	//
	// Inputs:
	//
	//	graphID - The graph ID to query.
	//
	// Outputs:
	//
	//	*crs.TraceStep - The enrichment TraceStep, or nil.
	//
	// Thread Safety: Safe for concurrent use.
	EnrichmentTraceStep(graphID string) *crs.TraceStep
}

GraphProvider initializes and provides access to the code graph.

type InitPhase

type InitPhase struct{}

InitPhase handles session initialization.

This phase is responsible for:

  • Initializing the code graph for the project
  • Setting up the session for execution
  • Handling degraded mode when services are unavailable

Thread Safety: InitPhase is safe for concurrent use.

func NewInitPhase

func NewInitPhase() *InitPhase

NewInitPhase creates a new initialization phase.

Outputs:

*InitPhase - The configured phase.

func (*InitPhase) Execute

func (p *InitPhase) Execute(ctx context.Context, deps *Dependencies) (agent.AgentState, error)

Execute implements Phase.

Description:

Initializes the code graph for the project. If the graph service
is unavailable, transitions to DEGRADED mode instead of failing.

Inputs:

ctx - Context for cancellation and timeout.
deps - Phase dependencies including the graph provider.

Outputs:

agent.AgentState - PLAN on success, DEGRADED if service unavailable, ERROR on failure.
error - Non-nil only for unrecoverable errors.

Thread Safety: This method is safe for concurrent use.

func (*InitPhase) Name

func (p *InitPhase) Name() string

Name implements Phase.

Outputs:

string - "init"

type LLMClient

type LLMClient = llm.Client

LLMClient is the interface for LLM completion.

type Phase

type Phase interface {
	// Name returns the phase name for logging and debugging.
	//
	// Outputs:
	//   string - The human-readable phase name.
	Name() string

	// Execute runs the phase logic.
	//
	// Description:
	//   Performs the phase-specific operations and returns the next state
	//   the agent should transition to.
	//
	// Inputs:
	//   ctx - Context for cancellation and timeout.
	//   deps - Dependencies required by the phase.
	//
	// Outputs:
	//   agent.AgentState - The next state to transition to.
	//   error - Non-nil if an unrecoverable error occurred.
	//
	// Thread Safety: Must be safe for concurrent use.
	Execute(ctx context.Context, deps *Dependencies) (agent.AgentState, error)
}

Phase defines the interface for agent phases.

Each phase represents a distinct stage in the agent's execution lifecycle. Phases are responsible for:

  • Performing their designated tasks
  • Determining the next state to transition to
  • Emitting relevant events
  • Handling errors appropriately

type PhaseResult

type PhaseResult struct {
	// NextState is the state to transition to.
	NextState agent.AgentState

	// UpdatedContext is the context after phase execution.
	UpdatedContext *agent.AssembledContext

	// Response is any response generated by the phase.
	Response string

	// ToolCalls are tool invocations requested by the LLM.
	ToolCalls []agent.ToolInvocation

	// ClarificationNeeded indicates if user input is required.
	ClarificationNeeded bool

	// ClarificationPrompt is the prompt to show the user.
	ClarificationPrompt string

	// Error contains any error that occurred.
	Error error
}

PhaseResult contains the result of phase execution.

type PlanPhase

type PlanPhase struct {
	// contains filtered or unexported fields
}

PlanPhase handles context assembly and execution preparation.

This phase is responsible for:

  • Assembling initial context for the user's query
  • Detecting ambiguous queries that need clarification
  • Preparing the context for the execution phase

Thread Safety: PlanPhase is safe for concurrent use.

func NewPlanPhase

func NewPlanPhase(opts ...PlanPhaseOption) *PlanPhase

NewPlanPhase creates a new planning phase.

Inputs:

opts - Configuration options.

Outputs:

*PlanPhase - The configured phase.

func (*PlanPhase) Execute

func (p *PlanPhase) Execute(ctx context.Context, deps *Dependencies) (agent.AgentState, error)

Execute implements Phase.

Description:

Assembles initial context for the user's query. If the query
is ambiguous or context assembly fails, may transition to
CLARIFY state to request user input.

Inputs:

ctx - Context for cancellation and timeout.
deps - Phase dependencies including context manager.

Outputs:

agent.AgentState - EXECUTE on success, CLARIFY if ambiguous, ERROR on failure.
error - Non-nil only for unrecoverable errors.

Thread Safety: This method is safe for concurrent use.

func (*PlanPhase) Name

func (p *PlanPhase) Name() string

Name implements Phase.

Outputs:

string - "plan"

type PlanPhaseOption

type PlanPhaseOption func(*PlanPhase)

PlanPhaseOption configures a PlanPhase.

func WithInitialBudget

func WithInitialBudget(budget int) PlanPhaseOption

WithInitialBudget sets the initial token budget.

Inputs:

budget - The token budget.

Outputs:

PlanPhaseOption - The configuration function.

type ReflectPhase

type ReflectPhase struct {
	// contains filtered or unexported fields
}

ReflectPhase handles progress evaluation and decision making.

This phase is responsible for:

  • Evaluating progress toward the goal
  • Deciding whether to continue, complete, or request clarification
  • Summarizing recent actions for context management

Thread Safety: ReflectPhase is safe for concurrent use.

func NewReflectPhase

func NewReflectPhase(opts ...ReflectPhaseOption) *ReflectPhase

NewReflectPhase creates a new reflection phase.

Inputs:

opts - Configuration options.

Outputs:

*ReflectPhase - The configured phase.

func (*ReflectPhase) Execute

func (p *ReflectPhase) Execute(ctx context.Context, deps *Dependencies) (agent.AgentState, error)

Execute implements Phase.

Description:

Evaluates the current progress and decides on the next action:
- EXECUTE: Continue with more steps
- COMPLETE: Task is done
- CLARIFY: Need user input

Inputs:

ctx - Context for cancellation and timeout.
deps - Phase dependencies.

Outputs:

agent.AgentState - Next state (EXECUTE, COMPLETE, or CLARIFY).
error - Non-nil only for unrecoverable errors.

Thread Safety: This method is safe for concurrent use.

func (*ReflectPhase) Name

func (p *ReflectPhase) Name() string

Name implements Phase.

Outputs:

string - "reflect"

type ReflectPhaseOption

type ReflectPhaseOption func(*ReflectPhase)

ReflectPhaseOption configures a ReflectPhase.

func WithMaxSteps

func WithMaxSteps(steps int) ReflectPhaseOption

WithMaxSteps sets the maximum allowed steps.

Inputs:

steps - Maximum step count.

Outputs:

ReflectPhaseOption - The configuration function.

func WithMaxTotalTokens

func WithMaxTotalTokens(tokens int) ReflectPhaseOption

WithMaxTotalTokens sets the maximum total tokens.

Inputs:

tokens - Maximum token count.

Outputs:

ReflectPhaseOption - The configuration function.

type ReflectionDecision

type ReflectionDecision string

ReflectionDecision represents the outcome of reflection.

const (
	// DecisionContinue indicates execution should continue.
	DecisionContinue ReflectionDecision = "continue"

	// DecisionComplete indicates the task is done.
	DecisionComplete ReflectionDecision = "complete"

	// DecisionClarify indicates user input is needed.
	DecisionClarify ReflectionDecision = "clarify"
)

type ReflectionInput

type ReflectionInput struct {
	// StepsCompleted is the number of steps executed so far.
	StepsCompleted int

	// TokensUsed is the total tokens consumed.
	TokensUsed int

	// ToolsInvoked is the number of tool invocations.
	ToolsInvoked int

	// LastResponse is the most recent LLM response.
	LastResponse string

	// RecentResults are the recent tool results.
	RecentResults []agent.ToolResult
}

ReflectionInput contains data for the reflection phase.

type ReflectionOutput

type ReflectionOutput struct {
	// Decision is what to do next.
	Decision ReflectionDecision

	// Reason explains the decision.
	Reason string

	// ClarificationPrompt is set if Decision is DecisionClarify.
	ClarificationPrompt string
}

ReflectionOutput contains the reflection decision.

type RepetitionDetector

type RepetitionDetector struct {
	// contains filtered or unexported fields
}

RepetitionDetector detects semantically repetitive tool calls.

Description:

Encapsulates semantic repetition detection with configurable options.
Uses simple Jaccard similarity for small term sets, and can optionally
use MinHash for larger sets (though this is rarely needed for queries).

Key Features:
- Configurable similarity threshold
- Configurable history depth
- Tracks alternative suggestions based on what's been tried
- OTel tracing built-in

Thread Safety: Safe for concurrent use. All mutable state is protected by mu.

func NewRepetitionDetector

func NewRepetitionDetector(opts ...RepetitionDetectorOption) *RepetitionDetector

NewRepetitionDetector creates a new RepetitionDetector with options.

Description:

Creates a detector with sensible defaults that can be overridden.
Default threshold is 0.7 (70% similarity), history is 5 steps.

Inputs:

opts - Optional configuration functions.

Outputs:

*RepetitionDetector - The configured detector.

func (*RepetitionDetector) IsSemanticallyRepetitive

func (d *RepetitionDetector) IsSemanticallyRepetitive(
	ctx context.Context,
	tool string,
	query string,
	steps []crs.TraceStep,
) (isRepetitive bool, similarity float64, similarQuery string)

IsSemanticallyRepetitive checks if a query is similar to recently tried queries.

Description:

Compares the proposed query against recent queries for the same tool.
Uses Jaccard similarity on extracted terms.

Inputs:

ctx - Context for tracing.
tool - The tool name.
query - The query string to check.
steps - Recent trace steps from session.

Outputs:

isRepetitive - True if above threshold.
similarity - The maximum similarity found.
similarQuery - The most similar previous query.

func (*RepetitionDetector) Record

func (d *RepetitionDetector) Record(tool, query string)

Record records a tool call for tracking tried queries.

Description:

Tracks what queries have been tried for each tool, enabling
the SuggestAlternative method to suggest different approaches.

Inputs:

tool - The tool that was called.
query - The query that was used.

Thread Safety: Safe for concurrent use.

func (*RepetitionDetector) Reset

func (d *RepetitionDetector) Reset()

Reset clears the detector's state for a new session.

Thread Safety: Safe for concurrent use.

func (*RepetitionDetector) SuggestAlternative

func (d *RepetitionDetector) SuggestAlternative(currentTool string) string

SuggestAlternative suggests a different tool or approach based on what's been tried.

Description:

Analyzes tried queries and suggests alternatives. For example, if
multiple Grep calls have been tried with similar patterns, might
suggest using find_callers or find_symbol instead.

Inputs:

currentTool - The tool being considered.

Outputs:

string - A suggestion, or empty if no suggestion.

Thread Safety: Safe for concurrent use.

type RepetitionDetectorOption

type RepetitionDetectorOption func(*RepetitionDetector)

RepetitionDetectorOption configures a RepetitionDetector.

func WithRepetitionHistory

func WithRepetitionHistory(maxHistory int) RepetitionDetectorOption

WithRepetitionHistory sets the history depth.

func WithRepetitionThreshold

func WithRepetitionThreshold(threshold float64) RepetitionDetectorOption

WithRepetitionThreshold sets the similarity threshold.

type ResponseGrounder

type ResponseGrounder = grounding.Grounder

ResponseGrounder is the interface for grounding validation.

type SafetyCheckResult

type SafetyCheckResult struct {
	// Blocked indicates if the operation should be blocked.
	Blocked bool

	// Result is the full safety check result.
	Result *safety.Result

	// ErrorMessage is the error message for learning.
	ErrorMessage string

	// Constraints are the extracted constraints for CDCL.
	Constraints []safety.SafetyConstraint
}

SafetyCheckResult holds the result of a safety check along with metadata for CDCL learning.

type SafetyGate

type SafetyGate = safety.Gate

SafetyGate is the interface for safety checks.

type SemanticCircuitBreaker

type SemanticCircuitBreaker struct {
	// contains filtered or unexported fields
}

SemanticCircuitBreaker extends circuit breaking with semantic awareness.

Description:

Groups semantically similar tool calls and breaks when either:
- A single tool is called too many times (any query)
- Semantically similar queries are called too many times (same intent)

This catches both direct repetition and paraphrased repetition:
- Direct: Grep("parseConfig") x 5
- Semantic: Grep("parseConfig"), Grep("parse_config"), Grep("ParseConfig")

Thread Safety: Safe for concurrent use. All mutable state is protected by mu.

func NewSemanticCircuitBreaker

func NewSemanticCircuitBreaker(opts ...SemanticCircuitBreakerOption) *SemanticCircuitBreaker

NewSemanticCircuitBreaker creates a new SemanticCircuitBreaker.

Description:

Creates a circuit breaker with sensible defaults.
Default: 5 max per tool, 3 max per semantic group.

Inputs:

opts - Optional configuration functions.

Outputs:

*SemanticCircuitBreaker - The configured circuit breaker.

func (*SemanticCircuitBreaker) AllowToolCall

func (cb *SemanticCircuitBreaker) AllowToolCall(ctx context.Context, tool, query string) bool

AllowToolCall checks if a tool call should be allowed.

Description:

Returns false if:
- Tool has been called maxPerTool times
- Semantic group has been called maxSemanticGroup times

Inputs:

ctx - Context for tracing.
tool - The tool name.
query - The query string (can be empty for non-search tools).

Outputs:

bool - True if allowed, false if blocked.

Thread Safety: Safe for concurrent use.

func (*SemanticCircuitBreaker) GetBlockReason

func (cb *SemanticCircuitBreaker) GetBlockReason() string

GetBlockReason returns the reason for the last blocked call.

Thread Safety: Safe for concurrent use.

func (*SemanticCircuitBreaker) RecordCall

func (cb *SemanticCircuitBreaker) RecordCall(tool, query string)

RecordCall records a tool call.

Description:

Updates tool counts and semantic groupings.

Inputs:

tool - The tool that was called.
query - The query string (can be empty).

Thread Safety: Safe for concurrent use.

func (*SemanticCircuitBreaker) Reset

func (cb *SemanticCircuitBreaker) Reset()

Reset clears the circuit breaker state.

Thread Safety: Safe for concurrent use.

type SemanticCircuitBreakerOption

type SemanticCircuitBreakerOption func(*SemanticCircuitBreaker)

SemanticCircuitBreakerOption configures a SemanticCircuitBreaker.

func WithMaxPerTool

func WithMaxPerTool(max int) SemanticCircuitBreakerOption

WithMaxPerTool sets the maximum calls per tool.

func WithMaxSemanticGroup

func WithMaxSemanticGroup(max int) SemanticCircuitBreakerOption

WithMaxSemanticGroup sets the maximum calls in a semantic group.

func WithSemanticThreshold

func WithSemanticThreshold(threshold float64) SemanticCircuitBreakerOption

WithSemanticThreshold sets the similarity threshold for grouping.

type SemanticInfo

type SemanticInfo struct {
	Similarity float64
	Status     string // "allowed", "penalized", or "blocked"
}

SemanticInfo holds semantic similarity information for trace step metadata. O1.3 Fix: Track semantic similarity in trace steps.

type SymbolResolution

type SymbolResolution struct {
	// SymbolID is the fully qualified symbol ID (e.g., "pkg/file.go:SymbolName").
	SymbolID string

	// Confidence is a strategy-based constant (0.0-1.0) indicating resolution quality.
	// IT-00a-1 Phase 4 note: These are hardcoded per-strategy constants, NOT computed
	// from match quality data (e.g., levenshtein distance, score margins). They provide
	// coarse ordering between strategies for observability but should not be used for
	// branching logic. If confidence-based branching is needed in the future, compute
	// from real signals (score margin, match count, edit distance).
	//
	// Current values:
	//   1.0  = exact match by ID
	//   0.95 = single exact name match
	//   0.8  = disambiguated name or substring match
	//   0.7  = fuzzy search match (function/method)
	//   0.6  = disambiguated name match (non-function)
	//   0.5  = fuzzy search match (non-function)
	Confidence float64

	// Strategy is the resolution strategy used ("exact", "name", "fuzzy").
	Strategy string
}

SymbolResolution holds a cached symbol resolution result.

Description:

Stores the result of resolving a symbol name to a qualified symbol ID,
along with a confidence score indicating resolution quality.

Thread Safety: This type is safe for concurrent use when stored in sync.Map.

type SynthesisQualityResult

type SynthesisQualityResult struct {
	// Score is the quality score from 0.0 to 1.0.
	//   1.0: Response references specific symbols from results
	//   0.5: Response mentions general findings but no specific symbols
	//   0.0: Response contradicts or ignores tool results
	Score float64

	// SymbolsExpected is the number of distinct symbols extracted from tool results.
	SymbolsExpected int

	// SymbolsFound is the number of expected symbols mentioned in the response.
	SymbolsFound int

	// HasResultCount indicates whether the response mentions result counts from tools.
	HasResultCount bool

	// MentionsScope indicates whether the response mentions scope when scope was applied.
	MentionsScope bool

	// ScopeRelevant indicates whether scope was applied to any tool result.
	ScopeRelevant bool

	// Reason is a short diagnostic string explaining the score.
	Reason string
}

SynthesisQualityResult holds the quality assessment of a synthesis response.

Description:

Contains the quality score and diagnostic details for observability.
Used by handleCompletion to record synthesis quality in trace steps
and Prometheus metrics.

Thread Safety: This struct is immutable after creation.

type TokenTracker

type TokenTracker struct {
	// contains filtered or unexported fields
}

TokenTracker tracks token usage and budget for a session.

Description:

Provides centralized token tracking with budget management.
Tracks prompt, response, and tool result tokens separately.
Can recommend synthesis when approaching budget limits.

Thread Safety: Safe for concurrent use. All mutable state is protected by mu.

func NewTokenTracker

func NewTokenTracker(opts ...TokenTrackerOption) *TokenTracker

NewTokenTracker creates a new TokenTracker with options.

Description:

Creates a tracker with default budget that can be overridden.

Inputs:

opts - Optional configuration functions.

Outputs:

*TokenTracker - The configured tracker.

func (*TokenTracker) AddLLMUsage

func (t *TokenTracker) AddLLMUsage(promptTokens, responseTokens int)

AddLLMUsage records prompt and response tokens from an LLM call.

Inputs:

promptTokens - Tokens in the prompt.
responseTokens - Tokens in the response.

Thread Safety: Safe for concurrent use.

func (*TokenTracker) AddToolResult

func (t *TokenTracker) AddToolResult(result string) int

AddToolResult estimates and adds token count for a tool result.

Description:

Uses tiered estimation based on content type.

Inputs:

result - The tool output string.

Outputs:

int - Estimated token count added.

Thread Safety: Safe for concurrent use.

func (*TokenTracker) GetBreakdown

func (t *TokenTracker) GetBreakdown() map[string]int

GetBreakdown returns a breakdown of token usage by category.

Thread Safety: Safe for concurrent use.

func (*TokenTracker) RemainingBudget

func (t *TokenTracker) RemainingBudget() int

RemainingBudget returns the remaining token budget.

Thread Safety: Safe for concurrent use.

func (*TokenTracker) Reset

func (t *TokenTracker) Reset()

Reset clears the tracker for a new session.

Thread Safety: Safe for concurrent use.

func (*TokenTracker) ShouldSynthesize

func (t *TokenTracker) ShouldSynthesize() bool

ShouldSynthesize returns true if synthesis is recommended based on budget.

Description:

Returns true when usage exceeds the synthesis threshold (default 85%).
This signals that the agent should synthesize an answer rather than
continue making tool calls.

Thread Safety: Safe for concurrent use.

func (*TokenTracker) TotalUsed

func (t *TokenTracker) TotalUsed() int

TotalUsed returns the total tokens used across all categories.

Thread Safety: Safe for concurrent use.

func (*TokenTracker) UsagePercent

func (t *TokenTracker) UsagePercent() float64

UsagePercent returns the percentage of budget used (0.0-1.0).

Thread Safety: Safe for concurrent use.

type TokenTrackerOption

type TokenTrackerOption func(*TokenTracker)

TokenTrackerOption configures a TokenTracker.

func WithTokenBudget

func WithTokenBudget(budget int) TokenTrackerOption

WithTokenBudget sets the token budget.

type ToolExecutor

type ToolExecutor = tools.Executor

ToolExecutor is the interface for tool execution.

type ToolForcingPolicy

type ToolForcingPolicy interface {
	// ShouldForce determines if tool usage should be forced.
	//
	// Description:
	//   Evaluates the request context to determine if the LLM should be
	//   prompted to use tools instead of answering directly.
	//
	// Inputs:
	//   ctx - Context for tracing and cancellation. Must not be nil.
	//   req - The forcing request context. Must not be nil.
	//
	// Outputs:
	//   bool - True if tool usage should be forced.
	//
	// Example:
	//   if policy.ShouldForce(ctx, &ForcingRequest{Query: "What tests exist?"}) {
	//       // Inject forcing hint
	//   }
	//
	// Thread Safety: This method is safe for concurrent use.
	ShouldForce(ctx context.Context, req *ForcingRequest) bool

	// BuildHint creates the forcing hint message to inject into conversation.
	//
	// Description:
	//   Generates a prompt that encourages the LLM to use tools before
	//   answering. The hint should include the suggested tool if available.
	//
	// Inputs:
	//   ctx - Context for tracing. Must not be nil.
	//   req - The forcing request context. Must not be nil.
	//
	// Outputs:
	//   string - The forcing hint to inject as a user message.
	//
	// Example:
	//   hint := policy.BuildHint(ctx, &ForcingRequest{
	//       Query: "What tests exist?",
	//       AvailableTools: []string{"find_entry_points"},
	//   })
	//
	// Thread Safety: This method is safe for concurrent use.
	BuildHint(ctx context.Context, req *ForcingRequest) string
}

ToolForcingPolicy determines when and how to force tool usage.

Description:

The policy is responsible for deciding when an LLM response should be
rejected in favor of forcing tool usage. This is used when the LLM
answers analytical questions without exploring the codebase first.

Thread Safety: Implementations must be safe for concurrent use.

type ToolRegistry

type ToolRegistry = tools.Registry

ToolRegistry is the interface for tool registration.

Jump to

Keyboard shortcuts

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