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. Drained child subtrees with unresolved Effects fail the Process before any further sensing or action. Join alone does not prove external outcomes.
Definitions reject unaddressed Host Signals through Descriptor.SignalSchema. Engine-owned settlements are consumed only at their matching protocol phase; Wait openings may share a window with the following completion. InputGate replies, when used as children, must address the child's current WaitID.
Index ¶
- Variables
- func NewActionSettlement(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 ( 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.
var ( ErrInvalidExecutionState = agent.NewClassifiedError( agent.FailureKindContract, "planning.state.invalid", "planning: invalid execution state", ) ErrInvalidProtocol = agent.NewClassifiedError( agent.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 NewActionSettlement ¶
func NewActionSettlement(result ActionResult) (agent.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 (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: a child Deployment when one is bound, and the planning Dispatcher otherwise.
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 agent.EffectID
Input agent.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 string `json:"action_name" jsonschema:"pattern=^[a-z][a-z0-9._-]{0\\,127}$"`
Status AttemptStatus `json:"status" jsonschema:"enum=succeeded,enum=failed,enum=unconfirmed"`
Diagnostic string `json:"diagnostic,omitempty" jsonschema:"minLength=1,maxLength=4096"`
}
Attempt is one final, portable Action-attempt fact. Only a failed attempt has a Diagnostic: an unconfirmed attempt is fully explained by its Status.
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) String ¶ added in v0.26.0
func (a AttemptStatus) String() string
func (AttemptStatus) Valid ¶
func (a AttemptStatus) Valid() bool
type ChildBindingConfig ¶
type ChildBindingConfig struct {
Action Action
// Deployment is the exact child behavior; the planning Definition owns it
// as one of its ChildDeployments.
Deployment agent.Deployment
// Input deterministically derives child input; nil reuses Process input.
Input ChildInputFunc
// Budget is permanently allocated to each child attempt.
Budget agent.Budget
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 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 (Condition) JSONSchemaAlias ¶
func (Condition) MarshalJSON ¶
func (*Condition) UnmarshalJSON ¶
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.
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)
func (*Definition) ChildDeployments ¶ added in v0.41.0
func (d *Definition) ChildDeployments() []agent.Deployment
ChildDeployments reports the child binding of every child Action.
func (*Definition) Descriptor ¶
func (d *Definition) Descriptor() agent.Descriptor
func (*Definition) Restore ¶
func (d *Definition) Restore(ctx context.Context, state agent.ExecutionState) (agent.Execution, error)
Restore recreates a Planning Execution solely from its opaque state and this exact Definition. A completed state is a bare marker: the Engine owns its Output.
type DefinitionConfig ¶
type DefinitionConfig struct {
Name string
Description string
// InputSchema is the authoritative schema for opaque task input passed to
// Sensor, ActionExecutor, and child input functions.
InputSchema agent.Schema
Goal Goal
Actions []ActionBinding
Planner Planner
// MaxActionAttempts bounds external Action attempts. Its zero value is
// unlimited; a finite zero is rejected because Planning must admit an Action.
// This is an execution limit, not a Planner path-length constraint. A lowest-cost
// plan may exceed the remaining attempts and finish Stuck even when a more
// expensive shorter plan could reach the Goal within that limit.
MaxActionAttempts agent.Quota
}
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, whose bindings own each Action's contract and required capabilities. 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)
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. The Engine enforces the capabilities Policy declares for each Action before dispatch. Input that violates the Definition schema or an Action whose binding does not admit the request's world state returns a Failed host_error settlement; Execution consumes it as a contract failure without another external attempt.
func (*Dispatcher) Policy ¶ added in v0.44.0
func (d *Dispatcher) Policy(effect agent.Effect) agent.EffectPolicy
Policy 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; each requires the capabilities its frozen binding declares.
type DispatcherBindingConfig ¶
type DispatcherBindingConfig struct {
Action Action
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 Sensor
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)
func (Goal) Conditions ¶
Conditions returns an independently owned, key-sorted requirement set.
func (Goal) Description ¶
func (Goal) SatisfiedBy ¶
func (g Goal) SatisfiedBy(state WorldState) bool
type GoalConfig ¶
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" )
type Output ¶
type Output struct {
Outcome Outcome `json:"outcome" jsonschema:"enum=achieved,enum=unreachable,enum=stuck,enum=exhausted"`
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 ¶
PlanningPasses counts calls to Planner: every attempt followed one pass, and an unreachable or stuck result followed one more pass that found no plan.
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 (*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)
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 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) EvaluatePlan ¶ added in v0.42.0
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) InitialState ¶
func (p Problem) InitialState() WorldState
type SenseRequest ¶
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 errors are definite sensing failures and terminate Planning.
type SensorFunc ¶
type SensorFunc func(ctx context.Context, request SenseRequest) (WorldState, error)
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. 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.
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 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)
Example ¶
package main
import (
"fmt"
"github.com/Tangerg/scope/agent/strategy/planning"
)
func main() {
ready, err := planning.NewCondition("service.ready", planning.TruthTrue)
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
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