Documentation
¶
Overview ¶
Package planning provides goal-directed state planning as an Agent execution strategy. Goal, Condition, WorldState, Action, and Plan belong exclusively to this package; the Agent kernel sees only opaque Execution state and Effects.
Planning separates predicted Action semantics from external execution. A Planner is a pure, deterministic search over a Problem. A managed Planning Execution reads the real world through a Sensor and executes selected Actions outside its Step through a Deployment-bound dispatcher or a child Process, then senses again before accepting that the prediction became true. A Sensor supplies decision input; it has no role in execution telemetry.
Attempt facts determine which Actions remain eligible. An Action reported as successful remains current until sensing confirms its predicted effects; failed or unconfirmed Actions are excluded from subsequent planning. Restore reconstructs those decisions from the same facts used during live execution. A delegated Action waits for its child subtree to drain before reobserving the world. A child start or execution failure records a failed attempt; it does not bypass sensing or directly establish the Action's effects.
Index ¶
- Variables
- func NewActionSettlement(effectID agent.EffectID, result ActionResult) (agent.Settlement, error)
- type Action
- func (a Action) Applicable(state WorldState) bool
- func (a Action) Apply(source WorldState) (WorldState, error)
- func (a Action) Cost(source WorldState) (cost float64, err error)
- func (a Action) Description() string
- func (a Action) Effects() []Condition
- func (a Action) Name() string
- func (a Action) Preconditions() []Condition
- func (a Action) Valid() bool
- type ActionBinding
- type ActionConfig
- type ActionExecutor
- type ActionExecutorFunc
- type ActionRequest
- type ActionResult
- type Attempt
- type AttemptStatus
- type ChildBindingConfig
- type ChildInputFunc
- type Condition
- type CostFunc
- type Definition
- type DefinitionConfig
- type Dispatcher
- type DispatcherBindingConfig
- type DispatcherConfig
- type Goal
- type GoalConfig
- type Outcome
- type Output
- type Plan
- type PlannedAction
- type Planner
- type PlannerFunc
- type Problem
- type SenseRequest
- type Sensor
- type SensorFunc
- type Truth
- type WorldState
- func (w WorldState) Apply(effects ...Condition) (WorldState, error)
- func (w WorldState) Conditions() []Condition
- func (WorldState) JSONSchemaAlias() any
- func (w WorldState) Key() string
- func (w WorldState) MarshalJSON() ([]byte, error)
- func (w WorldState) Satisfies(requirements ...Condition) bool
- func (w WorldState) Truth(key string) Truth
- func (w *WorldState) UnmarshalJSON(data []byte) error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( 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") ErrInvalidExecutionState = errors.New("planning: invalid execution state") ErrInvalidProtocol = errors.New("planning: invalid protocol payload") )
Functions ¶
func NewActionSettlement ¶
func NewActionSettlement(effectID agent.EffectID, result ActionResult) (agent.Settlement, error)
NewActionSettlement converts an executor result into the kernel settlement that closes the effect. Going through this constructor is what keeps an executor from encoding planning vocabulary into a payload the kernel would then have to understand.
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)
NewAction builds the predictive half of an action — preconditions, effects, and cost — with no executable body. Keeping execution out means the planner can search over actions without the risk of running one, and the same action can be bound to different executors.
func (Action) Applicable ¶
func (a Action) Applicable(state WorldState) bool
Applicable reports whether state establishes every Action precondition.
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 ¶
Description returns the human-readable predicted behavior.
func (Action) Preconditions ¶
Preconditions returns an independently owned, key-sorted requirement set.
type ActionBinding ¶
type ActionBinding struct {
// contains filtered or unexported fields
}
ActionBinding is an immutable association between predictive Action semantics and exactly one external execution mechanism.
func NewChildBinding ¶
func NewChildBinding(config ChildBindingConfig) (ActionBinding, error)
NewChildBinding attaches an action to a child Deployment, so a plan step becomes a real Process with its own identity, budget, and recovery instead of an opaque call inside the parent.
func NewDispatcherBinding ¶
func NewDispatcherBinding(config DispatcherBindingConfig) (ActionBinding, error)
NewDispatcherBinding attaches an action to an external executor. Binding is separate from the action itself so the same predictive model can be planned against in tests without an executor present.
func (ActionBinding) Action ¶
func (a ActionBinding) Action() Action
Action returns the immutable predictive Action owned by the binding.
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 explains what the Action is expected to accomplish.
Description string
// Preconditions are truths required in the source WorldState.
Preconditions []Condition
// Effects are truths predicted in the successor WorldState after success.
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 performs one dispatcher-bound Action. A valid ActionResult is a definite success or failure. A non-nil error means the external outcome is unknown, so Dispatcher returns an unknown Effect settlement and never retries it implicitly.
type ActionExecutorFunc ¶
type ActionExecutorFunc func(ctx context.Context, request ActionRequest) (ActionResult, error)
ActionExecutorFunc adapts a plain function to the executor interface, so a single action does not require a named type to be made runnable.
func (ActionExecutorFunc) Execute ¶
func (a ActionExecutorFunc) Execute( ctx context.Context, request ActionRequest, ) (ActionResult, error)
type ActionRequest ¶
type ActionRequest struct {
// EffectID is the stable identity of the prepared Action attempt.
EffectID agent.EffectID
// Input is the original immutable Planning Process input.
Input agent.Input
// ActionName is the exact frozen Action identity.
ActionName string
// ActionDescription is the human-readable description of the exact bound Action.
ActionDescription string
// WorldState is the complete observation against which the Action was selected.
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)
ActionFailed constructs a definite failed Action result with a bounded diagnostic suitable for a portable Planning attempt record.
func ActionSucceeded ¶
func ActionSucceeded() ActionResult
ActionSucceeded returns a definite successful Action result.
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
Succeeded reports whether the definite Action result succeeded.
func (ActionResult) Valid ¶
func (a ActionResult) Valid() bool
type Attempt ¶
type Attempt struct {
// ActionName is the exact Action identity selected for this attempt.
ActionName string `json:"action_name" jsonschema:"pattern=^[a-z][a-z0-9._-]{0\\,127}$"`
// Status is the observed semantic outcome of this attempt.
Status AttemptStatus `json:"status" jsonschema:"enum=succeeded,enum=failed,enum=unconfirmed"`
// Diagnostic explains failed or unconfirmed attempts and is empty on success.
Diagnostic string `json:"diagnostic,omitempty" jsonschema:"minLength=1,maxLength=4096"`
}
Attempt is one final, portable Action-attempt fact. Diagnostic is empty only for a succeeded attempt.
type AttemptStatus ¶
type AttemptStatus string
AttemptStatus records the observed result of one selected Action attempt.
const ( // 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) Valid ¶
func (a AttemptStatus) Valid() bool
type ChildBindingConfig ¶
type ChildBindingConfig struct {
// Action is the immutable predictive behavior delegated to a child Process.
Action Action
// DeploymentRef identifies the exact child behavior binding.
DeploymentRef agent.DeploymentRef
// Input deterministically derives child input; nil reuses Process input.
Input ChildInputFunc
// Budget is permanently allocated to each child attempt.
Budget agent.Budget
// Capabilities is the attenuated authority granted to each child attempt.
Capabilities agent.CapabilitySet
}
ChildBindingConfig binds a predictive Action to one exact child Deployment. Every attempt starts a new child Process with a stable Engine-derived identity, explicit budget, and attenuated capabilities.
type ChildInputFunc ¶
ChildInputFunc derives a child Process input from the parent input and the current world state, so a plan step can be parameterized by facts discovered during execution rather than only by what the plan was started with.
type Condition ¶
type Condition struct {
// contains filtered or unexported fields
}
Condition is one immutable known truth requirement or prediction. Unknown is represented by absence from a WorldState and therefore cannot be stored in a Condition.
func NewCondition ¶
NewCondition names one fact the planner reasons over. Conditions are keys with a truth value rather than arbitrary predicates, because the planner has to compare and combine them without executing anything.
func (Condition) JSONSchemaAlias ¶
JSONSchemaAlias returns the typed JSON wire model owned by Condition.
func (Condition) MarshalJSON ¶
func (*Condition) UnmarshalJSON ¶
type CostFunc ¶
type CostFunc func(source WorldState) (float64, error)
CostFunc lets an action's cost depend on the world state it would run in, which is what allows a planner to prefer a cheap path under current facts rather than a fixed ordering. Returning an error keeps an uncomputable cost from being silently treated as zero, which would make that action always win. The callback must be pure, deterministic, concurrency-safe, and bounded; a Planner cannot interrupt a callback that does not return.
type Definition ¶
type Definition struct {
// contains filtered or unexported fields
}
Definition is an immutable Planning Strategy definition. It contains no Sensor or ActionExecutor; those I/O capabilities belong to its Deployment-bound Dispatcher. Failed and unconfirmed Action names remain excluded for this Definition's entire execution, including after WorldState changes. Restore enforces this admission policy; portable Output validation only checks attempt facts.
func NewDefinition ¶
func NewDefinition(config DefinitionConfig) (*Definition, error)
NewDefinition freezes the goal, actions, and planner into one immutable behavior. The planner is chosen here rather than at run time so that a restored Execution searches with the same algorithm that produced the plan it is resuming.
func (*Definition) Descriptor ¶
func (d *Definition) Descriptor() agent.Descriptor
Descriptor returns the immutable managed Planning contract.
func (*Definition) Restore ¶
func (d *Definition) Restore(state agent.ExecutionState) (agent.Execution, error)
Restore recreates a Planning Execution solely from its opaque state and this exact Definition. A completed outcome must agree with the observed Goal satisfaction.
type DefinitionConfig ¶
type DefinitionConfig struct {
// Name is the stable qualified Definition name.
Name string
// Description states the managed goal-directed behavior for discovery.
Description string
// InputSchema is the authoritative schema for opaque task input passed to
// Sensor, ActionExecutor, and child input functions.
InputSchema agent.Schema
// Goal is the immutable target state.
Goal Goal
// Actions binds every predictive Action to exactly one execution mechanism.
Actions []ActionBinding
// Planner selects Actions from each newly observed WorldState.
Planner Planner
// MaxActionAttempts bounds external Action attempts. It must be positive.
MaxActionAttempts uint32
}
DefinitionConfig contains one immutable managed Planning behavior. Goal, Planner, and Action bindings are fixed for the exact Deployment; only Input varies per Process.
type Dispatcher ¶
type Dispatcher struct {
// contains filtered or unexported fields
}
Dispatcher executes sensing and dispatcher Action Effects emitted by one Planning Definition. It is immutable after construction and may serve Processes concurrently when Sensor and ActionExecutors are concurrent-safe.
func NewDispatcher ¶
func NewDispatcher(definition *Definition, config DispatcherConfig) (*Dispatcher, error)
NewDispatcher binds a definition to the executors that carry out its effects. It is constructed against an exact definition so an effect cannot be routed to an executor the planner never planned against.
func (*Dispatcher) Dispatch ¶
func (d *Dispatcher) Dispatch( ctx context.Context, request agent.EffectRequest, _ agent.DeltaEmitter, ) (agent.Settlement, error)
Dispatch executes one validated Planning protocol operation. Sensor errors and valid ActionResult failures are definite failed settlements; an ActionExecutor error leaves the Effect outcome unknown. Action Effects must declare every capability required by the frozen binding before execution.
func (*Dispatcher) ReplayPolicy ¶
func (*Dispatcher) ReplayPolicy(effect agent.Effect) agent.ReplayPolicy
ReplayPolicy permits same-identity replay only for side-effect-free sensing. Action Effects may have irreversible external consequences and always require explicit resolution after an unknown attempt.
type DispatcherBindingConfig ¶
type DispatcherBindingConfig struct {
// Action is the immutable predictive behavior bound to a dispatcher target.
Action Action
// RequiredCapabilities is the authority required before dispatch.
RequiredCapabilities []agent.Capability
}
DispatcherBindingConfig binds a predictive Action to the Planning Dispatcher. RequiredCapabilities are enforced by Engine before dispatch.
type DispatcherConfig ¶
type DispatcherConfig struct {
// Sensor supplies each complete WorldState observation.
Sensor Sensor
// ActionExecutors maps dispatcher-bound Action names to exact executors.
ActionExecutors map[string]ActionExecutor
}
DispatcherConfig binds side-effect-free sensing and the exact set of dispatcher-targeted Action executors required by a Definition. Child-bound Actions must not appear in ActionExecutors.
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)
NewGoal states the target as conditions rather than as a procedure, which is what lets the planner decide the route and re-plan when observed facts change.
func (Goal) Conditions ¶
Conditions returns an independently owned, key-sorted requirement set.
func (Goal) Description ¶
Description returns the human-readable desired state.
func (Goal) SatisfiedBy ¶
func (g Goal) SatisfiedBy(state WorldState) bool
SatisfiedBy reports whether state establishes every goal condition.
type GoalConfig ¶
type GoalConfig struct {
// Name is the stable lower-case qualified goal identity.
Name string
// Description explains the desired state to a human consumer.
Description string
// Conditions are the known truths the final WorldState must establish.
Conditions []Condition
}
GoalConfig contains the complete immutable description of a Planning goal.
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 ( // 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 attempts or the Action limit were exhausted without // reaching the Goal. OutcomeStuck Outcome = "stuck" )
type Output ¶
type Output struct {
// Outcome is the Planning-owned semantic completion reason.
Outcome Outcome `json:"outcome" jsonschema:"enum=achieved,enum=unreachable,enum=stuck"`
// WorldState is the final complete observation.
WorldState WorldState `json:"world_state"`
// Attempts preserves Action-attempt order.
Attempts []Attempt `json:"attempts"`
// PlanningPasses counts calls to Planner.
PlanningPasses uint32 `json:"planning_passes" jsonschema:"maximum=4294967295"`
}
Output is the final semantic Planning result. WorldState is the last complete observation, Attempts preserve selection order, and PlanningPasses counts calls to Planner. No field is derived from Event or Delta history.
type Plan ¶
type Plan struct {
// contains filtered or unexported fields
}
Plan is an immutable ordered Action sequence and its predicted total cost. An empty Plan with zero cost is valid and represents an already-satisfied Goal; Planner's separate found result distinguishes it from no solution.
func NewPlan ¶
func NewPlan(actions []PlannedAction, totalCost float64) (Plan, error)
NewPlan carries the total cost alongside the steps so an operator can compare two plans without re-running the search that produced them.
func (Plan) Actions ¶
func (p Plan) Actions() []PlannedAction
Actions returns independently owned Action references in execution order.
func (Plan) MarshalJSON ¶
func (*Plan) UnmarshalJSON ¶
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)
NewPlannedAction references an Action by name so the Plan remains portable. The Definition supplies the authoritative Action behavior and metadata.
func (PlannedAction) MarshalJSON ¶
func (p PlannedAction) MarshalJSON() ([]byte, error)
func (PlannedAction) Name ¶
func (p PlannedAction) Name() string
Name returns the referenced Action identity.
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 finds an ordered Action sequence for one immutable Problem. It must be deterministic and side-effect-free for the same Problem, safe for concurrent calls, and honor context cancellation. found=false with nil error means the search proved no plan within its algorithm's complete search space; resource exhaustion must be returned as an error instead.
type PlannerFunc ¶
PlannerFunc adapts a plain function to the planner interface. The separate found result distinguishes a completed search that proved no path exists from a search that failed, because the first is a legitimate planning answer and the second is an error.
type Problem ¶
type Problem struct {
// contains filtered or unexported fields
}
Problem is one immutable Planner input: a current observation, one Goal, and the available predictive Actions. It contains no dispatcher, Process, or application dependency.
func NewProblem ¶
func NewProblem(initial WorldState, goal Goal, actions ...Action) (Problem, error)
NewProblem binds the initial state, the goal, and the actions available to reach it into one value, so a planner cannot be handed a goal without the vocabulary it is expected to search over.
func (Problem) InitialState ¶
func (p Problem) InitialState() WorldState
InitialState returns the immutable starting observation.
func (Problem) ValidatePlan ¶
ValidatePlan verifies that every referenced Action exists and is applicable in sequence, the reported cost equals the evaluated path cost, and the predicted final state satisfies the Goal.
type SenseRequest ¶
type SenseRequest struct {
// EffectID is the stable identity of the prepared sensing attempt.
EffectID agent.EffectID
// Input is the original immutable Planning Process input.
Input agent.Input
}
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 ¶
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 produces one complete WorldState without externally visible side effects. A returned error is a definite sensing failure and terminates Planning; a Sensor must not use error to report an unknown side effect.
type SensorFunc ¶
type SensorFunc func(ctx context.Context, request SenseRequest) (WorldState, error)
SensorFunc adapts a plain function to the sensor interface. Sensing is an Effect rather than part of a Step, because reading the world is external I/O and its result must arrive as a settlement the Execution can be resumed from.
func (SensorFunc) Sense ¶
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. Unknown is not a synonym for False: it means the current WorldState does not establish either known value. The zero value is invalid; callers must choose explicitly.
const ( // Unknown means the current observation does not establish the condition. Unknown Truth = "unknown" // False means the current observation establishes that the condition is false. False Truth = "false" // True means the current observation establishes that the condition is true. True Truth = "true" )
func (Truth) MarshalJSON ¶
func (*Truth) UnmarshalJSON ¶
type WorldState ¶
type WorldState struct {
// contains filtered or unexported fields
}
WorldState is an immutable, canonical observation of known condition truths. Missing conditions read as Unknown. Its zero value is the empty state. Every value is valid: constructors and decoding establish invariants, and observations never expose mutable storage.
func NewWorldState ¶
func NewWorldState(conditions ...Condition) (WorldState, error)
NewWorldState collects the facts a plan is evaluated against. It is a validated set rather than a free-form map because the planner compares states for equality while searching, and duplicate or conflicting conditions would make that comparison meaningless.
Example ¶
package main
import (
"fmt"
"github.com/Tangerg/scope/agent/strategy/planning"
)
func main() {
ready, err := planning.NewCondition("service.ready", planning.True)
if err != nil {
panic(err)
}
state, err := planning.NewWorldState(ready)
if err != nil {
panic(err)
}
fmt.Println(state.Truth("service.ready"), state.Truth("service.cached"), state.Satisfies(ready))
}
Output: true unknown true
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) JSONSchemaAlias ¶
func (WorldState) JSONSchemaAlias() any
JSONSchemaAlias returns the typed JSON wire model owned by WorldState.
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
Satisfies reports whether w establishes every required condition.
func (WorldState) Truth ¶
func (w WorldState) Truth(key string) Truth
Truth returns the observed truth for key, or Unknown when key is absent.
func (*WorldState) UnmarshalJSON ¶
func (w *WorldState) UnmarshalJSON(data []byte) error