coordinate

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: 16 Imported by: 0

Documentation

Overview

Package coordinate provides multi-file change coordination for Trace.

Description

This package enables planning, validating, and previewing coordinated changes across multiple files. It is READ-ONLY - it analyzes and generates plans but does not modify files. The agent uses Edit tools after approval.

Thread Safety

All types in this package are safe for concurrent use after initialization.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidInput indicates invalid input parameters.
	ErrInvalidInput = errors.New("invalid input")

	// ErrSymbolNotFound indicates the target symbol was not found.
	ErrSymbolNotFound = errors.New("symbol not found")

	// ErrGraphNotReady indicates the graph is not frozen or not available.
	ErrGraphNotReady = errors.New("graph not ready")

	// ErrContextCanceled indicates the context was canceled.
	ErrContextCanceled = errors.New("context canceled")

	// ErrUnsupportedChangeType indicates the change type is not supported.
	ErrUnsupportedChangeType = errors.New("unsupported change type")

	// ErrPlanNotFound indicates a referenced plan was not found.
	ErrPlanNotFound = errors.New("plan not found")

	// ErrValidationFailed indicates the change plan failed validation.
	ErrValidationFailed = errors.New("validation failed")
)

Sentinel errors for the coordinate package.

Functions

This section is empty.

Types

type CRSRecorder

type CRSRecorder interface {
	// RecordToolStep records a tool execution step in the CRS.
	RecordToolStep(ctx context.Context, toolName string, resultCount int, duration time.Duration, err error)
}

CRSRecorder abstracts CRS step recording for coordinate tool implementations.

Description

CRSRecorder provides a simplified interface for coordinate analysis tools to record their executions in the CRS. This interface mirrors reason.CRSRecorder and patterns.CRSRecorder — Go duck typing means any implementation satisfying one automatically satisfies the others.

Thread Safety

Implementations must be safe for concurrent use.

type ChangePlan

type ChangePlan struct {
	// ID is a unique identifier for this plan.
	ID string `json:"plan_id"`

	// GraphID is the ID of the graph this plan was created for.
	GraphID string `json:"graph_id,omitempty"`

	// Description explains the overall change.
	Description string `json:"description"`

	// PrimaryChange is the original change request.
	PrimaryChange ChangeRequest `json:"primary_change"`

	// FileChanges lists all changes needed across files.
	FileChanges []FileChange `json:"file_changes"`

	// Order lists file paths in the order changes should be applied.
	// Target file first, then dependent files.
	Order []string `json:"order"`

	// TotalFiles is the number of files affected.
	TotalFiles int `json:"total_files"`

	// TotalChanges is the total number of individual changes.
	TotalChanges int `json:"total_changes"`

	// RiskLevel is the overall risk assessment.
	RiskLevel RiskLevel `json:"risk_level"`

	// Confidence is how confident we are in the plan (0.0-1.0).
	Confidence float64 `json:"confidence"`

	// Warnings contains important warnings about the plan.
	Warnings []string `json:"warnings,omitempty"`

	// Limitations lists what we couldn't analyze.
	Limitations []string `json:"limitations,omitempty"`

	// CreatedAt is when the plan was created (Unix milliseconds UTC).
	CreatedAt int64 `json:"created_at"`
}

ChangePlan is the coordinated plan for all files.

func (*ChangePlan) GetGraphID

func (p *ChangePlan) GetGraphID() string

GetGraphID returns the graph ID this plan was created for.

Description:

Returns the graph ID for plan retrieval and validation.

Thread Safety:

This method is safe for concurrent use.

func (*ChangePlan) GetID

func (p *ChangePlan) GetID() string

GetID returns the plan's unique identifier.

Description:

Returns the plan ID for storage and retrieval.

Thread Safety:

This method is safe for concurrent use.

type ChangeRequest

type ChangeRequest struct {
	// TargetID is the symbol ID to change.
	TargetID string `json:"target_id"`

	// ChangeType categorizes the change.
	ChangeType ChangeType `json:"change_type"`

	// NewSignature is the proposed new signature (for signature changes).
	NewSignature string `json:"new_signature,omitempty"`

	// NewName is the proposed new name (for renames).
	NewName string `json:"new_name,omitempty"`

	// NewPackage is the target package (for moves).
	NewPackage string `json:"new_package,omitempty"`

	// Description explains the change in human terms.
	Description string `json:"description,omitempty"`
}

ChangeRequest describes a single change the user wants to make.

type ChangeSet

type ChangeSet struct {
	// PrimaryChange is the main change being requested.
	PrimaryChange ChangeRequest `json:"primary_change"`

	// Description explains the overall change set.
	Description string `json:"description"`
}

ChangeSet is a collection of related changes to coordinate.

type ChangeType

type ChangeType string

ChangeType categorizes the kind of change being made.

const (
	// ChangeAddParameter adds a new parameter to a function.
	ChangeAddParameter ChangeType = "add_parameter"

	// ChangeRemoveParameter removes a parameter from a function.
	ChangeRemoveParameter ChangeType = "remove_parameter"

	// ChangeAddReturn adds a new return value.
	ChangeAddReturn ChangeType = "add_return"

	// ChangeRemoveReturn removes a return value.
	ChangeRemoveReturn ChangeType = "remove_return"

	// ChangeAddMethod adds a new method to an interface.
	ChangeAddMethod ChangeType = "add_method"

	// ChangeRenameSymbol renames a function, type, or variable.
	ChangeRenameSymbol ChangeType = "rename_symbol"

	// ChangeChangeType changes a field or parameter type.
	ChangeChangeType ChangeType = "change_type"

	// ChangeMoveSymbol moves a symbol to a different package.
	ChangeMoveSymbol ChangeType = "move_symbol"
)

type FileChange

type FileChange struct {
	// FilePath is the relative path to the file.
	FilePath string `json:"file_path"`

	// SymbolID is the symbol being changed (if applicable).
	SymbolID string `json:"symbol_id,omitempty"`

	// ChangeType categorizes how this file is affected.
	ChangeType FileChangeType `json:"change_type"`

	// CurrentCode is the current code that will be replaced.
	CurrentCode string `json:"current_code"`

	// ProposedCode is the new code to use.
	ProposedCode string `json:"proposed_code"`

	// StartLine is the 1-indexed starting line of the change.
	StartLine int `json:"start_line"`

	// EndLine is the 1-indexed ending line of the change.
	EndLine int `json:"end_line"`

	// Reason explains why this change is needed.
	Reason string `json:"reason"`
}

FileChange describes changes needed for a single file.

type FileChangeType

type FileChangeType string

FileChangeType categorizes how a file is affected.

const (
	// FileChangePrimary is the file containing the primary change target.
	FileChangePrimary FileChangeType = "primary"

	// FileChangeCallerUpdate updates a caller to match new signature.
	FileChangeCallerUpdate FileChangeType = "caller_update"

	// FileChangeImportUpdate updates import statements.
	FileChangeImportUpdate FileChangeType = "import_update"

	// FileChangeImplementerUpdate updates interface implementations.
	FileChangeImplementerUpdate FileChangeType = "implementer_update"

	// FileChangeReferenceUpdate updates type or variable references.
	FileChangeReferenceUpdate FileChangeType = "reference_update"
)

type FileDiff

type FileDiff struct {
	// FilePath is the relative path to the file.
	FilePath string `json:"file_path"`

	// Hunks contains the diff sections.
	Hunks []Hunk `json:"hunks"`

	// LinesAdded is the total lines added.
	LinesAdded int `json:"lines_added"`

	// LinesRemoved is the total lines removed.
	LinesRemoved int `json:"lines_removed"`

	// ChangeType is how this file is affected.
	ChangeType FileChangeType `json:"change_type"`

	// Reason explains why this file is changing.
	Reason string `json:"reason"`
}

FileDiff represents a unified diff for a single file.

type Hunk

type Hunk struct {
	// StartLine is the 1-indexed starting line in the old file.
	StartLine int `json:"start_line"`

	// OldLines are the lines being removed (with - prefix).
	OldLines []string `json:"old_lines"`

	// NewLines are the lines being added (with + prefix).
	NewLines []string `json:"new_lines"`

	// Context contains context lines around the change.
	Context []string `json:"context,omitempty"`
}

Hunk represents a section of changed lines in a diff.

type MultiFileChangeCoordinator

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

MultiFileChangeCoordinator plans, validates, and previews coordinated changes.

Description

MultiFileChangeCoordinator handles multi-file change coordination for the agent. It analyzes a proposed change to one symbol and generates a complete plan for all files that need to be updated together. This is READ-ONLY analysis - actual file editing is done by the agent using Edit tools after user approval.

Thread Safety

This type is safe for concurrent use.

func NewMultiFileChangeCoordinator

func NewMultiFileChangeCoordinator(
	g *graph.Graph,
	idx *index.SymbolIndex,
	breaking *reason.BreakingChangeAnalyzer,
	blast *analysis.BlastRadiusAnalyzer,
	validator *reason.ChangeValidator,
) *MultiFileChangeCoordinator

NewMultiFileChangeCoordinator creates a new coordinator.

Description

Creates a coordinator that uses the provided graph, index, and analyzers to generate multi-file change plans.

Inputs

  • g: Code graph. Must be frozen before PlanChanges().
  • idx: Symbol index for lookups.
  • breaking: Breaking change analyzer.
  • blast: Blast radius analyzer.
  • validator: Change validator.

Outputs

  • *MultiFileChangeCoordinator: Configured coordinator.

Example

coordinator := NewMultiFileChangeCoordinator(
    graph, index,
    reason.NewBreakingChangeAnalyzer(graph, index),
    analysis.NewBlastRadiusAnalyzer(graph, index, nil),
    reason.NewChangeValidator(index),
)

func (*MultiFileChangeCoordinator) GetPlan

func (c *MultiFileChangeCoordinator) GetPlan(planID string) (*ChangePlan, bool)

GetPlan retrieves a previously created plan by ID.

Inputs

  • planID: The plan ID returned from PlanChanges.

Outputs

  • *ChangePlan: The plan, or nil if not found.
  • bool: True if the plan was found.

func (*MultiFileChangeCoordinator) PlanChanges

func (c *MultiFileChangeCoordinator) PlanChanges(
	ctx context.Context,
	changes ChangeSet,
	opts *PlanOptions,
) (*ChangePlan, error)

PlanChanges creates a coordinated change plan.

Description

Analyzes the primary change and generates a complete plan covering all files that need to be updated. Uses blast radius to find affected callers and generates specific code changes for each file.

Inputs

  • ctx: Context for cancellation.
  • changes: The change set to plan.
  • opts: Optional configuration.

Outputs

  • *ChangePlan: Complete plan with all file changes.
  • error: Non-nil on validation failure or if symbol not found.

Example

plan, err := coordinator.PlanChanges(ctx, ChangeSet{
    PrimaryChange: ChangeRequest{
        TargetID:     "order/service.go:10:ProcessOrder",
        ChangeType:   ChangeAddParameter,
        NewSignature: "func (s *Service) ProcessOrder(ctx context.Context, order *Order) error",
    },
    Description: "Add context parameter to ProcessOrder",
}, nil)

func (*MultiFileChangeCoordinator) PreviewChanges

func (c *MultiFileChangeCoordinator) PreviewChanges(
	ctx context.Context,
	plan *ChangePlan,
) ([]FileDiff, error)

PreviewChanges generates unified diffs for review.

Description

Generates a unified diff for each file in the change plan, suitable for showing the user before applying changes.

Inputs

  • ctx: Context for cancellation.
  • plan: The change plan to preview.

Outputs

  • []FileDiff: Unified diffs for all affected files.
  • error: Non-nil on failure.

Example

diffs, err := coordinator.PreviewChanges(ctx, plan)
for _, diff := range diffs {
    fmt.Printf("=== %s ===\n", diff.FilePath)
    for _, hunk := range diff.Hunks {
        for _, line := range hunk.OldLines {
            fmt.Println("-" + line)
        }
        for _, line := range hunk.NewLines {
            fmt.Println("+" + line)
        }
    }
}

func (*MultiFileChangeCoordinator) SetCRS

func (c *MultiFileChangeCoordinator) SetCRS(recorder CRSRecorder)

SetCRS sets the CRS recorder for CDCL clause generation.

Description

Replaces the default NopCRSRecorder with a real recorder that emits CRS tool steps for PlanChanges and ValidatePlan operations.

Inputs

  • recorder: The CRS recorder to use. Must not be nil.

Thread Safety

Must be called before any concurrent use of PlanChanges or ValidatePlan. Typically called once during initialization.

func (*MultiFileChangeCoordinator) ValidatePlan

func (c *MultiFileChangeCoordinator) ValidatePlan(
	ctx context.Context,
	plan *ChangePlan,
) (*ValidationResult, error)

ValidatePlan validates that a change plan would compile.

Description

Validates each file change for syntax errors, type reference existence, and import resolution. Reports all errors with file:line locations.

IMPORTANT: This performs syntactic validation only. Full type checking requires the compiler or LSP.

Inputs

  • ctx: Context for cancellation.
  • plan: The change plan to validate.

Outputs

  • *ValidationResult: Validation results including all errors.
  • error: Non-nil if validation itself fails.

Example

result, err := coordinator.ValidatePlan(ctx, plan)
if !result.Valid {
    for _, e := range result.SyntaxErrors {
        fmt.Printf("%s:%d: %s\n", e.FilePath, e.Line, e.Message)
    }
}

type NopCRSRecorder

type NopCRSRecorder struct{}

NopCRSRecorder is a no-op implementation for tests and standalone usage.

Thread Safety

This type is safe for concurrent use (stateless).

func (*NopCRSRecorder) RecordToolStep

func (n *NopCRSRecorder) RecordToolStep(_ context.Context, _ string, _ int, _ time.Duration, _ error)

RecordToolStep is a no-op.

type PlanOptions

type PlanOptions struct {
	// MaxCallers limits how many callers to update.
	MaxCallers int

	// MaxHops limits indirect caller depth.
	MaxHops int

	// IncludeTests includes test file updates.
	IncludeTests bool

	// GenerateStubs generates stub implementations for interface changes.
	GenerateStubs bool

	// ContextLines is the number of context lines in diffs.
	ContextLines int
}

PlanOptions configures change plan generation.

func DefaultPlanOptions

func DefaultPlanOptions() PlanOptions

DefaultPlanOptions returns sensible defaults.

type RiskLevel

type RiskLevel string

RiskLevel indicates the risk of a change plan.

const (
	RiskCritical RiskLevel = "CRITICAL"
	RiskHigh     RiskLevel = "HIGH"
	RiskMedium   RiskLevel = "MEDIUM"
	RiskLow      RiskLevel = "LOW"
)

type ValidationError

type ValidationError struct {
	// FilePath is the file containing the error.
	FilePath string `json:"file_path"`

	// Line is the 1-indexed line number.
	Line int `json:"line"`

	// Message describes the error.
	Message string `json:"message"`

	// Severity indicates how serious the error is.
	Severity string `json:"severity"` // "error", "warning"
}

ValidationError represents a validation failure.

type ValidationResult

type ValidationResult struct {
	// Valid indicates if the plan is valid.
	Valid bool `json:"valid"`

	// SyntaxErrors contains parsing errors.
	SyntaxErrors []ValidationError `json:"syntax_errors,omitempty"`

	// TypeErrors contains type-related errors.
	TypeErrors []ValidationError `json:"type_errors,omitempty"`

	// ImportErrors contains import resolution errors.
	ImportErrors []ValidationError `json:"import_errors,omitempty"`

	// Warnings contains non-fatal issues.
	Warnings []string `json:"warnings,omitempty"`
}

ValidationResult is the result of validating a change plan.

Jump to

Keyboard shortcuts

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