Documentation
¶
Overview ¶
Package orch is the planning and orchestration layer from spec 2080/ostres: a layer above the turn loop that turns a job into a plan, runs the plan's steps under a budget through the same gate, checks each against a grounded postcondition, and reports honestly. The turn loop (pkg/agent) is unchanged; orch only wraps it.
Index ¶
Constants ¶
const ( PostNone = "none" PostResultNonEmpty = "result_nonempty" PostResultContains = "result_contains" PostFileExists = "file_exists" PostFileContains = "file_contains" PostShellZero = "shell_zero" )
Postcondition kinds.
Variables ¶
This section is empty.
Functions ¶
func TriggerJob ¶
TriggerJob is the cheap, no-model structural signal from the spec: a request with an explicit multi-deliverable shape. Three signals fire it, in order of how unambiguous they are: an enumerated checklist of two or more items, an explicit job phrase ("do all of the following", "for each", "workflow"), or three or more distinct action verbs joined by conjunctions. It is deliberately biased toward "turn": a missed job just runs as one turn, while a false positive wastes planning tokens and can fragment a task that needed one context, so a single instruction with one or two verbs never fires (a bare "read X and write Y" stays a turn; the compound bar is three).
func Validate ¶
Validate checks a plan mechanically before it runs: every executor is known, every dependency and placeholder points strictly backward (which also makes the DAG acyclic), and every postcondition is one the orchestrator can evaluate. This is grounded plan-time validation, not asking a model if its plan is good.
Types ¶
type Leaf ¶
Leaf runs one step as a leaf executor: a turn, a single tool call, or a worker turn, selected by executor (`turn`, `tool:<name>`, `worker:<name>`). It is injected by the caller so orch stays decoupled from pkg/channel and the worker system, and so a leaf structurally has no handle to start a plan, which is the two-level bound from the spec enforced by construction.
type Orchestrator ¶
type Orchestrator struct {
Store *store.Store
Leaf Leaf
Workspace string
Concurrency int // ready steps run at most this many at once
MaxAttempts int // per-step attempt cap before it fails terminally
Report func(string) // optional progress sink for logs; the CLI polls the ledger for its live view
Now func() time.Time
}
Orchestrator drives a plan to a terminal state: it finds ready steps, runs them under a bounded pool, checks postconditions, repairs a failed step in place, and enforces the plan's budgets. It is the single writer to the plan's ledger rows.
func (*Orchestrator) Run ¶
func (o *Orchestrator) Run(ctx context.Context, planID string) error
Run drives the plan with the given id from its current step state to terminal. It is safe to call on a fresh plan or on resume: it schedules on whatever the ledger says, so a crash mid-job continues rather than restarting.
type Planner ¶
type Planner struct {
Provider provider.Provider
Model string
MaxTokens int
Tools []string // tool names a `tool:<name>` executor may reference
Workers []string // worker names a `worker:<name>` executor may reference
}
Planner decides whether a request is a job and, if so, turns it into a plan. It prefers a template (no model call, correct by construction), falls back to one planning model call for a novel job, and validates the result before it ever runs, since the model cannot be trusted to check its own plan.
type Postcondition ¶
type Postcondition struct {
// Kind selects the check. The zero value ("" or "none") always passes, for
// a step whose success genuinely cannot be checked mechanically.
Kind string `json:"kind"`
Path string `json:"path,omitempty"` // for file_exists, file_contains
Text string `json:"text,omitempty"` // for file_contains, result_contains
Cmd string `json:"cmd,omitempty"` // for shell_zero
}
Postcondition is a step's grounded success check. A step is done because a check holds, not because a model said so. The rungs are ordered from most grounded (a file parses, a command exits zero) to least (a produced result mentions a token); the design prefers the mechanical rungs and avoids leaning on the model to grade its own work.
func ParsePostcondition ¶
func ParsePostcondition(s string) Postcondition
ParsePostcondition reads a postcondition from its stored JSON. An empty or malformed value is treated as the always-passing none check rather than an error, so a step with no postcondition simply is not gated on one.
func (Postcondition) Eval ¶
Eval runs the check and returns whether it held and a one-line reason. All file paths resolve inside the workspace, and shell_zero runs in the workspace directory, so a postcondition cannot reach outside the job's working tree. result is the step's produced output, for the result_* rungs.
func (Postcondition) Evaluable ¶
func (p Postcondition) Evaluable() bool
Evaluable reports whether this postcondition is one the orchestrator knows how to check, used by plan validation so a plan cannot ship a check that will never evaluate.
func (Postcondition) JSON ¶
func (p Postcondition) JSON() string
JSON renders a postcondition to its stored form.
type Result ¶
Result is what a leaf executor returns: the produced text and an estimate of the tokens it spent, summed into the plan's budget.
type StepSpec ¶
type StepSpec struct {
Goal string `json:"goal"`
Deps []int `json:"deps"`
Inputs map[string]string `json:"inputs"`
Executor string `json:"executor"`
Post Postcondition `json:"postcondition"`
}
StepSpec is a planned step before it becomes ledger rows: the schema the planner produces and the orchestrator consumes. Idx is the step's position in the plan; Deps and #E<idx> placeholders reference earlier positions.