planning

package
v0.61.0 Latest Latest
Warning

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

Go to latest
Published: Nov 10, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package planning separates predicted action semantics from observed reality. Goal, Condition, WorldState, Action, and Plan belong to this strategy; the run kernel sees only opaque execution state and declared Effects.

Compile freezes the planning domain, action bindings, and limits using the Runtime's Compiler. Revision identifies the opaque Sensor, Planner, and action implementations. The definition retains only action declarations; its dispatcher owns the Sensor and ActionExecutors and shares the same immutable action index, so execution cannot diverge from the declared authority. A Planner performs deterministic search over a Problem. A Sensor reads actual world state through a dispatcher Effect. Actions execute through dispatcher Effects or exact child Programs, then the strategy senses again before accepting that their predicted effects became true.

Attempt facts determine eligibility. Successful actions remain current until sensing confirms their effects; failed or unconfirmed actions are excluded from later planning. Restore derives the same decisions from these facts. A child action is observed only through its drained Exit. Its admission or execution failure records a failed attempt and cannot establish world state.

Unknown external outcomes require explicit host resolution before planning advances. Cancellation and subtree drain remain Runtime-owned. Unaddressed Signals are rejected, and messages must match the outstanding action, sensing Effect, or child invocation.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidResult           = errors.New("planning: invalid result")
	ErrInvalidCondition        = errors.New("planning: invalid condition")
	ErrInvalidWorldState       = errors.New("planning: invalid world state")
	ErrInvalidGoal             = errors.New("planning: invalid goal")
	ErrInvalidAction           = errors.New("planning: invalid action")
	ErrInvalidActionCost       = errors.New("planning: invalid action cost")
	ErrInvalidPlan             = errors.New("planning: invalid plan")
	ErrInvalidProblem          = errors.New("planning: invalid problem")
	ErrInvalidDefinitionConfig = errors.New("planning: invalid definition configuration")
	ErrInvalidDispatcherConfig = errors.New("planning: invalid dispatcher configuration")
)

Invalid-value sentinels reject construction and domain values before execution, so they carry no Failure classification.

View Source
var (
	ErrInvalidExecutionState = run.NewClassifiedError(
		run.FailureKindContract,
		"planning.state.invalid",
		"planning: invalid execution state",
	)
	ErrInvalidProtocol = run.NewClassifiedError(
		run.FailureKindContract,
		"planning.protocol.invalid",
		"planning: invalid protocol payload",
	)
)

Execution sentinels own the Failure persisted when they reach Step. Wrapping one is the only way a Step error acquires its classification. Protocol and restored-state errors stay distinct because their recovery responsibilities differ.

Functions

func Compile added in v0.59.0

func Compile[I any](compiler *run.Compiler, cfg Config) (run.Program[I, Output], error)

func NewActionSettlement

func NewActionSettlement(result ActionResult) (run.Settlement, error)

NewActionSettlement closes an investigated action Effect with a definite result.

Types

type Action

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

Action is an immutable predictive operation used only by Planners. It does not execute I/O and is not a model Tool.

func NewAction

func NewAction(config ActionConfig) (Action, error)

func (Action) Applicable

func (a Action) Applicable(state WorldState) bool

func (Action) Apply

func (a Action) Apply(source WorldState) (WorldState, error)

Apply returns the Action's predicted successor state. It does not assert that external execution actually produced the prediction.

func (Action) Cost

func (a Action) Cost(source WorldState) (cost float64, err error)

Cost evaluates the Action's predicted edge cost against source. Panics, errors, negative values, and non-finite values are returned as ErrInvalidActionCost.

func (Action) Description

func (a Action) Description() string

func (Action) Effects

func (a Action) Effects() []Condition

Effects returns an independently owned, key-sorted prediction set.

func (Action) Name

func (a Action) Name() string

func (Action) Preconditions

func (a Action) Preconditions() []Condition

Preconditions returns an independently owned, key-sorted requirement set.

func (Action) Valid

func (a Action) Valid() bool

type ActionBinding

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

ActionBinding fixes one action's prediction, authority, and execution mechanism together, so a separate name-indexed registry cannot redirect it.

func NewChildBinding

func NewChildBinding(config ChildBindingConfig) (ActionBinding, error)

func NewDispatcherBinding

func NewDispatcherBinding(config DispatcherBindingConfig) (ActionBinding, error)

func (ActionBinding) Action

func (a ActionBinding) Action() Action

func (ActionBinding) Valid

func (a ActionBinding) Valid() bool

type ActionConfig

type ActionConfig struct {
	// Name is the stable lower-case qualified Action identity.
	Name string

	Description string

	Preconditions []Condition

	Effects []Condition

	// Cost computes the non-negative search edge cost. Nil defaults to 1.
	Cost CostFunc
}

ActionConfig contains one Action's complete predictive planning semantics. External execution is deliberately absent and is bound separately by a managed Planning definition.

type ActionExecutor

type ActionExecutor interface {
	// Execute attempts one selected Action against the observed WorldState. A
	// valid ActionResult is definite; a non-nil error means the external outcome
	// is unknown and must not be translated into an ordinary failed Action or
	// implicitly retried under a new identity.
	Execute(ctx context.Context, request ActionRequest) (ActionResult, error)
}

ActionExecutor reports definite results separately from unknown external outcomes.

type ActionExecutorFunc

type ActionExecutorFunc func(ctx context.Context, request ActionRequest) (ActionResult, error)

func (ActionExecutorFunc) Execute

func (a ActionExecutorFunc) Execute(
	ctx context.Context,
	request ActionRequest,
) (ActionResult, error)

type ActionRequest

type ActionRequest struct {
	EffectID          run.EffectID
	Input             run.Payload
	ActionName        string
	ActionDescription string
	WorldState        WorldState
}

ActionRequest is one external dispatcher Action invocation selected against an observed WorldState. Input and WorldState are immutable values.

type ActionResult

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

ActionResult is the definite external result reported by an ActionExecutor. Its zero value is invalid.

func ActionFailed

func ActionFailed(diagnostic string) (ActionResult, error)

func ActionSucceeded

func ActionSucceeded() ActionResult

func (ActionResult) Diagnostic

func (a ActionResult) Diagnostic() string

Diagnostic returns the definite failure explanation, or an empty string on success.

func (ActionResult) Succeeded

func (a ActionResult) Succeeded() bool

func (ActionResult) Valid

func (a ActionResult) Valid() bool

type Attempt

type Attempt struct {
	ActionName run.QualifiedName `json:"action_name"`
	Status     AttemptStatus     `json:"status"`
	Diagnostic string            `json:"diagnostic,omitempty"`
}

Attempt is one final, portable Action-attempt fact. Only a failed attempt has a Diagnostic: an unconfirmed attempt is fully explained by its Status.

func (Attempt) JSONSchemaConstraints added in v0.59.0

func (Attempt) JSONSchemaConstraints() jsonschema.Constraints

JSON Schema counts characters; Validate enforces the complete UTF-8 byte bound.

func (Attempt) Validate

func (a Attempt) Validate() error

type AttemptStatus

type AttemptStatus string

AttemptStatus records the observed result of one selected Action attempt.

const (
	AttemptInvalid AttemptStatus = ""
	// AttemptSucceeded means execution succeeded and reobservation established
	// every predicted effect.
	AttemptSucceeded AttemptStatus = "succeeded"
	// AttemptFailed means the dispatcher or child Process definitely failed.
	AttemptFailed AttemptStatus = "failed"
	// AttemptUnconfirmed means execution reported success but reobservation did
	// not establish every predicted effect.
	AttemptUnconfirmed AttemptStatus = "unconfirmed"
)

func (AttemptStatus) JSONSchemaEnum added in v0.59.0

func (AttemptStatus) JSONSchemaEnum() []string

func (AttemptStatus) String added in v0.59.0

func (a AttemptStatus) String() string

func (AttemptStatus) Valid

func (a AttemptStatus) Valid() bool

type ChildBindingConfig

type ChildBindingConfig struct {
	Action Action
	Child  run.ChildBinding
	// Input must be deterministic; nil reuses the process input.
	Input ChildInputFunc
}

type ChildInputFunc

type ChildInputFunc func(processInput run.Payload, worldState WorldState) (run.Payload, error)

ChildInputFunc derives a child Process input from the parent input and the WorldState observed when the Action is selected.

type Condition

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

Condition is one immutable known truth requirement or prediction. TruthUnknown is represented by absence from a WorldState and therefore cannot be stored in a Condition.

func NewCondition

func NewCondition(key string, truth Truth) (Condition, error)

func (Condition) JSONSchemaModel

func (Condition) JSONSchemaModel() any

func (Condition) Key

func (c Condition) Key() string

func (Condition) MarshalJSON

func (c Condition) MarshalJSON() ([]byte, error)

func (Condition) Truth

func (c Condition) Truth() Truth

func (*Condition) UnmarshalJSON

func (c *Condition) UnmarshalJSON(data []byte) error

func (Condition) Valid

func (c Condition) Valid() bool

type Config added in v0.59.0

type Config struct {
	Name        string
	Description string
	Goal        Goal
	Actions     []ActionBinding
	Planner     Planner
	Sensor      Sensor
	// MaxActionAttempts is unlimited by default; a finite zero cannot admit an action.
	MaxActionAttempts run.Quota
	Revision          string
}

Config binds a planner, its world sensor and executable actions. Revision identifies their opaque settings, including cost functions and child input conversion. The compiler hashes the declared planning domain.

type CostFunc

type CostFunc func(source WorldState) (float64, error)

CostFunc must be pure, deterministic, concurrency-safe, and bounded. A Planner cannot interrupt a callback that does not return. Invalid costs fail the search.

func FixedCost

func FixedCost(value float64) CostFunc

FixedCost defers validation until an Action evaluates the cost so fixed and dynamic costs share one error contract.

type DispatcherBindingConfig

type DispatcherBindingConfig struct {
	Action               Action
	Executor             ActionExecutor
	Replay               run.ReplayPolicy
	RequiredCapabilities []run.Capability
}

Replay is opt-in: SameIdentity requires the executor to honor EffectID even after an interrupted attempt. It does not promise concurrent safety or a deterministic result.

type Goal

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

Goal is an immutable set of desired condition truths.

func NewGoal

func NewGoal(config GoalConfig) (Goal, error)

func (Goal) Conditions

func (g Goal) Conditions() []Condition

Conditions returns an independently owned, key-sorted requirement set.

func (Goal) Description

func (g Goal) Description() string

func (Goal) Name

func (g Goal) Name() string

func (Goal) SatisfiedBy

func (g Goal) SatisfiedBy(state WorldState) bool

func (Goal) Valid

func (g Goal) Valid() bool

type GoalConfig

type GoalConfig struct {
	Name string

	Description string

	Conditions []Condition
}

type Outcome

type Outcome string

Outcome is the Planning-owned semantic reason a Goal-directed execution completed. It does not add states to the common Process lifecycle.

const (
	OutcomeInvalid Outcome = ""
	// OutcomeAchieved means the latest observed WorldState satisfies the Goal.
	OutcomeAchieved Outcome = "achieved"
	// OutcomeUnreachable means the initial complete planning search found no plan.
	OutcomeUnreachable Outcome = "unreachable"
	// OutcomeStuck means that after attempted Actions a further planning pass
	// found no plan to the Goal.
	OutcomeStuck Outcome = "stuck"
	// OutcomeExhausted means the Action attempt limit admitted no further
	// attempt, so no further planning pass ran.
	OutcomeExhausted Outcome = "exhausted"
)

func (Outcome) JSONSchemaEnum added in v0.59.0

func (Outcome) JSONSchemaEnum() []string

func (Outcome) String added in v0.59.0

func (o Outcome) String() string

func (Outcome) Valid

func (o Outcome) Valid() bool

type Output

type Output struct {
	Outcome    Outcome    `json:"outcome"`
	WorldState WorldState `json:"world_state"`
	Attempts   []Attempt  `json:"attempts"`
}

Output is the final semantic Planning result. WorldState is the last complete observation and Attempts preserve selection order. No field is derived from Event or Delta history.

func (Output) PlanningPasses

func (o Output) PlanningPasses() uint64

PlanningPasses counts calls to Planner: every attempt followed one pass, and an unreachable or stuck result followed one more pass that found no plan.

func (Output) Validate

func (o Output) Validate() error

Validate checks the outcome against the ordered attempt facts. Goal satisfaction, Action membership, and admission policy require the owning definition. A repeated Action name is a valid fact, even after a failed attempt.

type Plan

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

Plan is an immutable ordered Action sequence. Cost belongs to the Actions evaluated by Problem, never to the Planner's answer. An empty Plan is valid and represents an already-satisfied Goal; Planner's separate found result distinguishes it from no solution.

func NewPlan

func NewPlan(actions []PlannedAction) (Plan, error)

func (Plan) Actions

func (p Plan) Actions() []PlannedAction

Actions returns independently owned Action references in execution order.

func (Plan) MarshalJSON

func (p Plan) MarshalJSON() ([]byte, error)

jsonv2 encodes a nil slice as [], so the "actions":[] empty-set shape needs no defensive copy or nil normalization here.

func (*Plan) UnmarshalJSON

func (p *Plan) UnmarshalJSON(data []byte) error

type PlannedAction

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

PlannedAction is one immutable Action reference in Planner-selected order. It contains no executable capability or copied Action metadata.

func NewPlannedAction

func NewPlannedAction(name string) (PlannedAction, error)

func (PlannedAction) MarshalJSON

func (p PlannedAction) MarshalJSON() ([]byte, error)

func (PlannedAction) Name

func (p PlannedAction) Name() string

func (*PlannedAction) UnmarshalJSON

func (p *PlannedAction) UnmarshalJSON(data []byte) error

func (PlannedAction) Valid

func (p PlannedAction) Valid() bool

type Planner

type Planner interface {
	// Plan searches one immutable Problem without mutating it or performing I/O.
	// found=false with nil error is reserved for an exhausted complete search;
	// cancellation, resource limits, invalid costs, and internal failure return
	// errors. Equivalent Problems must produce an equivalent ordered Plan.
	Plan(ctx context.Context, problem Problem) (plan Plan, found bool, err error)
}

Planner searches deterministically without side effects and is safe for concurrent use.

type PlannerFunc

type PlannerFunc func(ctx context.Context, problem Problem) (plan Plan, found bool, err error)

func (PlannerFunc) Plan

func (p PlannerFunc) Plan(
	ctx context.Context,
	problem Problem,
) (Plan, bool, error)

type Problem

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

Problem is immutable and contains only predictive planning data.

func NewProblem

func NewProblem(initial WorldState, goal Goal, actions ...Action) (Problem, error)

func (Problem) Action

func (p Problem) Action(name string) (Action, bool)

func (Problem) Actions

func (p Problem) Actions() []Action

Actions returns an independently owned slice in declaration order.

func (Problem) EvaluatePlan added in v0.59.0

func (p Problem) EvaluatePlan(ctx context.Context, plan Plan) (float64, error)

EvaluatePlan returns the cost of an applicable Action sequence whose predicted final state satisfies the Goal. Cancellation is checked between actions and after each bounded Cost callback.

func (Problem) Goal

func (p Problem) Goal() Goal

func (Problem) InitialState

func (p Problem) InitialState() WorldState

func (Problem) Valid

func (p Problem) Valid() bool

type SenseRequest added in v0.16.0

type SenseRequest struct {
	EffectID run.EffectID
	Input    run.Payload
}

SenseRequest is one side-effect-free request for the current complete WorldState. Input is the original Planning Process input; EffectID is stable for the prepared attempt.

type Sensor added in v0.16.0

type Sensor interface {
	// Sense obtains one complete immutable WorldState for the original Process
	// input. It must honor ctx and must not cause externally visible side effects,
	// because the same EffectID may be replayed after an unknown sensing outcome.
	Sense(ctx context.Context, request SenseRequest) (WorldState, error)
}

Sensor errors are definite sensing failures and terminate Planning.

type SensorFunc added in v0.16.0

type SensorFunc func(ctx context.Context, request SenseRequest) (WorldState, error)

func (SensorFunc) Sense added in v0.16.0

func (s SensorFunc) Sense(
	ctx context.Context,
	request SenseRequest,
) (WorldState, error)

type Truth

type Truth string

Truth is the three-valued truth of one observed condition. TruthUnknown is not a synonym for TruthFalse: it means the current WorldState does not establish either known value. The zero value is invalid; callers must choose explicitly.

const (
	TruthUnknown Truth = "unknown"
	TruthFalse   Truth = "false"
	TruthTrue    Truth = "true"
)

func (Truth) JSONSchemaEnum added in v0.59.0

func (Truth) JSONSchemaEnum() []string

func (Truth) MarshalJSON

func (t Truth) MarshalJSON() ([]byte, error)

func (Truth) String

func (t Truth) String() string

func (*Truth) UnmarshalJSON

func (t *Truth) UnmarshalJSON(data []byte) error

func (Truth) Valid

func (t Truth) Valid() bool

type WorldState

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

WorldState is an immutable, canonical observation of known condition truths. Missing conditions read as TruthUnknown. Its zero value is the empty state. Every value is valid: constructors and decoding establish invariants, and observations never expose mutable storage. Its JSON representation requires an explicit conditions array, even when empty.

func NewWorldState

func NewWorldState(conditions ...Condition) (WorldState, error)

func (WorldState) Apply

func (w WorldState) Apply(effects ...Condition) (WorldState, error)

Apply returns a new state with predicted effects layered over this state. The receiver is never mutated. The last effect for a repeated key wins.

func (WorldState) Conditions

func (w WorldState) Conditions() []Condition

Conditions returns an independently owned, key-sorted snapshot.

func (WorldState) JSONSchemaModel

func (WorldState) JSONSchemaModel() any

func (WorldState) Key

func (w WorldState) Key() string

Key returns a stable identity derived only from canonical known truths.

func (WorldState) MarshalJSON

func (w WorldState) MarshalJSON() ([]byte, error)

func (WorldState) Satisfies

func (w WorldState) Satisfies(requirements ...Condition) bool

func (WorldState) Truth

func (w WorldState) Truth(key string) Truth

func (*WorldState) UnmarshalJSON

func (w *WorldState) UnmarshalJSON(data []byte) error

Directories

Path Synopsis
Package goap provides deterministic goal-oriented action planning over immutable planning.WorldState values.
Package goap provides deterministic goal-oriented action planning over immutable planning.WorldState values.

Jump to

Keyboard shortcuts

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