Documentation
¶
Overview ¶
Package engine implements the v1 workflow engine core: procedure specs parsed from kind: procedure graph entries, a typed variable store per running instance, guards as boolean combinations of named Go predicates, a closed function registry (predicates, queries, commands), gate-transition cascade with chooser stops, and append-only JSONL session persistence.
Everything semantic lives in named Go functions composed by name in the procedure spec — the spec language has no expressions, no literals, no assignment. See the v1 surface spec (plan 20260702-220449-d-tac-ry0) and the engine directive (20260702-174833-d-cpt-3yw).
Index ¶
- Constants
- func ComposeInstructions(unitText string, diagnostics []string) string
- func IsEndTarget(to string) bool
- type BaseType
- type ChooserKind
- type ChooserOption
- type ChooserServe
- type CollectField
- type Command
- type CommandFunc
- type Context
- type ContextualGraphs
- type Dispatch
- type Engine
- type EngineOption
- type Event
- type EventSink
- type EventType
- type ExportedValue
- type FactIndex
- type FailedPredicate
- type FuncClass
- type FuncDoc
- type Graphs
- type GuardExpr
- type InjectCall
- type Instance
- type InstanceStatus
- type Involvement
- type Option
- type PartSize
- type Predicate
- type PredicateFunc
- type PresencePair
- type Provenance
- type Query
- type QueryBound
- type QueryFunc
- type QueryResolver
- type ReadDepth
- type Ref
- type Registry
- func (r *Registry) Command(name string) (*Command, bool)
- func (r *Registry) Docs(class FuncClass) []FuncDoc
- func (r *Registry) Predicate(name string) (*Predicate, bool)
- func (r *Registry) Query(name string) (*Query, bool)
- func (r *Registry) RegisterCommand(c Command) error
- func (r *Registry) RegisterPredicate(p Predicate) error
- func (r *Registry) RegisterQuery(q Query) error
- type Serve
- type ServeLane
- type Session
- func (s *Session) Abandon(instanceID, reason string) error
- func (s *Session) Answer(instanceID, chooser, choice string, fields map[string]any, userWords string) (*Serve, error)
- func (s *Session) Inject(instanceID string, call InjectCall) (any, *truncate.Cut, error)
- func (s *Session) Instance(id string) (*Instance, bool)
- func (s *Session) Instances() []*Instance
- func (s *Session) LogRead(tool string, full, summary []string)
- func (s *Session) Park(instanceID, note string) error
- func (s *Session) ReadDepthOf(id string) ReadDepth
- func (s *Session) Report(instanceID string, fields map[string]any) (*Serve, error)
- func (s *Session) Serve(instanceID string) (*Serve, error)
- func (s *Session) SetLabel(label string)
- func (s *Session) SinkErr() error
- func (s *Session) Start(spec *Spec, params map[string]any, parent string) (*Serve, error)
- type SessionOption
- type Spec
- func (s *Spec) AnswerSchemaForStep(step *Step) map[string]any
- func (s *Spec) EffectiveTotal(budget serveview.Budget) int
- func (s *Spec) OverBudget(budget serveview.Budget, resolver QueryResolver) []StepSize
- func (s *Spec) ReportSchemaForStep(step *Step) map[string]any
- func (s *Spec) Validate(reg *Registry) []string
- func (s *Spec) WorstCaseServeBytes(budget serveview.Budget, resolver QueryResolver) []StepSize
- type SpecResolver
- type StaticGraphs
- type Step
- type StepSize
- type Store
- func (s *Store) Clone() *Store
- func (s *Store) Collected() map[string]any
- func (s *Store) Export() map[string]ExportedValue
- func (s *Store) Get(name string) (any, bool)
- func (s *Store) Has(name string) bool
- func (s *Store) SetParams(params map[string]any) error
- func (s *Store) SetStart(inputs map[string]any) error
- func (s *Store) StateSnapshot() string
- func (s *Store) TemplateContext() map[string]any
- func (s *Store) WriteEngine(name string, v any) error
- func (s *Store) WriteState(fields map[string]any) ([]string, error)
- type Transition
- type Unit
- type UnitLane
- type VarDecl
- type VarType
- type When
- type WriterSink
Constants ¶
const ( EndCompleted = "end(completed)" EndAbandoned = "end(abandoned)" )
Terminal transition targets. A procedure ends by transitioning to one of these instead of a step ID.
const ExampleSpecFrontmatter = `` /* 1759-byte string literal not displayed */
ExampleSpecFrontmatter is the worked example the procedure spec reference fact serves: a small review move written for width — optional param and optional collect, two injects with differently shaped args, multi-clause infix guards, a user chooser looping back for correction, a dispatch seed on the confirming option, and a closing gate on the field the dispatched recording hands back. Authored beside the engine so its own tests load it — the served example cannot drift from what the engine accepts.
const LogVersion = 1
LogVersion stamps every event line. A session generally does not survive an sdd upgrade mid-flight — replay rejects unknown versions rather than guessing (accepted per the surface spec). Exported for shells that append terminal events to a parked log without replaying it (teardown by handle).
Variables ¶
This section is empty.
Functions ¶
func ComposeInstructions ¶
ComposeInstructions joins a rendered unit (or a shell-substituted reminder) with stall diagnostics — the one composition rule for the Instructions field, shared by the engine's serve and shells recomposing around served-instruction memory.
func IsEndTarget ¶
IsEndTarget reports whether a transition target is a terminal rather than a step ID.
Types ¶
type BaseType ¶
type BaseType string
BaseType is one of the closed set of domain types a procedure variable can declare. Adding a domain type means adding it here, once, with its validation — no other types exist.
const ( TypeText BaseType = "text" TypeBool BaseType = "bool" TypeEntryID BaseType = "entry-id" TypeRef BaseType = "ref" TypeLabel BaseType = "label" TypeParticipant BaseType = "participant" TypeEntryKind BaseType = "entry-kind" TypeLayer BaseType = "layer" TypeConfidence BaseType = "confidence" TypeIntent BaseType = "intent" TypeAttachmentHandle BaseType = "attachment-handle" TypeProcedureSpec BaseType = "procedure-spec" TypeFactIndex BaseType = "fact-index" TypePreflightFindings BaseType = "preflight-findings" TypeGuideFindings BaseType = "guide-findings" TypeInvolvement BaseType = "involvement" TypeInvolvementWhen BaseType = "involvement-when" TypeSearchReplace BaseType = "search-replace" // TypeProse validates exactly like text; the distinct declaration tells // serve-side rendering to treat changes as content diffs rather than // whole-value re-serves (20260826-120330-d-tac-8f8). TypeProse BaseType = "prose" )
func BaseTypeValues ¶ added in v0.17.0
func BaseTypeValues() []BaseType
BaseTypeValues lists the domain types in canonical order, for surfaces that render or generate from the enumeration instead of restating it.
func (BaseType) Description ¶ added in v0.17.0
Description returns the type's served meaning; empty for an unknown type.
type ChooserKind ¶
type ChooserKind string
ChooserKind classifies who advances a step: the engine (gate, auto-advance on guards), the agent (advisory pick, logged with evidence), or the user (dialogue-presence made structural).
const ( ChooserGate ChooserKind = "gate" ChooserAgent ChooserKind = "agent" ChooserUser ChooserKind = "user" )
type ChooserOption ¶
type ChooserOption struct {
Choice string
Collect []CollectField
}
ChooserOption is one selectable choice in a served chooser.
type ChooserServe ¶
type ChooserServe struct {
Chooser string
Kind ChooserKind
Options []ChooserOption
}
ChooserServe is the pending-chooser part of a serve: which step's chooser is pending, who answers, and what the options are. Chooser is the step ID the caller must name in a chooser answer — carried here so the value the answer requires appears in the payload it answers.
type CollectField ¶
CollectField names a state field a report may write at a step; Optional fields don't gate the cascade.
type Command ¶
type Command struct {
Doc FuncDoc
Fn CommandFunc
// MutatesGraph declares that running this command changes the on-disk graph
// (a new entry, a rewritten summary). The engine invalidates the graph
// provider after such a command so later reads in the same advance reload
// and see the write — post-write freshness driven by the command's own
// declaration, replacing the shell's hand-maintained refresh calls.
MutatesGraph bool
}
Command is a registered command.
type CommandFunc ¶
CommandFunc executes a side effect (gate ops and chooser calls only). Its store writes go through Store.WriteEngine per the declared contract.
type Context ¶
type Context struct {
Store *Store
Graph *model.Graph
// Step is the step the function runs at — commands like confirmPlayback
// record it (the reopen target when a confirmation goes stale).
Step string
// Reads is the session's folded read set — the deepest depth each entry
// was served at (refsInspected evaluates it). Nil means nothing was
// served; reading a nil map is safe.
Reads map[string]ReadDepth
}
Context is what registry functions see: the running instance's store and the graph, read-only by convention for predicates and queries. Commands additionally reach their side-effect dependencies through the closures they were registered with — the registry itself stays dependency-free.
type ContextualGraphs ¶ added in v0.17.0
ContextualGraphs optionally resolves the graph for one procedure store. The engine does not interpret store fields: application shells use this hook when a move carries an explicit graph authority that differs from the session's ordinary read graph. Procedure loading still uses Graphs.Current.
type Dispatch ¶
type Dispatch struct {
// Procedure optionally names the child canonical this option dispatches.
// When set, it guards the handoff — the seed applies only to a child of
// that procedure. Omit it for a generic junction whose child is chosen at
// runtime (e.g. engage's move), where the seed applies to whatever is
// dispatched next.
Procedure string
// Seed maps child field ← parent field: the key is the field the child
// declares as state, the value is this parent's own declared field carrying
// the evidence. Required — a Dispatch with no seed has nothing to carry.
Seed map[string]string
}
Dispatch is a junction option's declaration of the grounding it seeds into a child dispatched after this option is answered. The seeding contract (d-tac-tlo) keeps the declaration entirely in the parent's spec: answering an option carrying a Dispatch stashes its Seed on the parent instance, and the next child started under that parent inherits exactly that mapping. There is no engine-wide default — a handoff happens only where a junction declares one, so every inheritance is readable at the junction that grants it.
type Engine ¶
Engine executes procedure instances against a graph provider and a registry. It is pure Go over data — shells (MCP, webapp) sit on top; side-effectful commands come in through the registry with their own dependencies. The graph is not held as a mutable field: the engine reads it through Graphs, so ownership of "what the current graph is" stays on the read side.
func New ¶
func New(registry *Registry, graphs Graphs, opts ...EngineOption) *Engine
New creates an engine reading the current graph through graphs.
func (*Engine) NewSession ¶
func (e *Engine) NewSession(id, participant string, sink EventSink, opts ...SessionOption) *Session
NewSession creates an empty session appending to sink.
func (*Engine) ReplaySession ¶
func (e *Engine) ReplaySession(id, participant string, events []Event, resolve SpecResolver, sink EventSink, opts ...SessionOption) (*Session, error)
ReplaySession reconstructs a session by folding its event log: state is applied directly from the logged values — reports, op results, and transitions — never by re-running commands, so replay is free of side effects. The returned session continues appending to sink.
type EngineOption ¶ added in v0.17.0
type EngineOption func(*Engine)
EngineOption configures an engine.
func WithTemplateValues ¶ added in v0.17.0
func WithTemplateValues(values map[string]any) EngineOption
WithTemplateValues adds read-only values available to procedure templates and inject-argument templates.
type Event ¶
type Event struct {
V int `json:"v"`
TS time.Time `json:"ts"`
Session string `json:"session"`
Seq int `json:"seq"`
Instance string `json:"instance,omitempty"`
Event EventType `json:"event"`
Data map[string]any `json:"data,omitempty"`
}
Event is one line of the append-only session log. Memory is the runtime source of truth; the log is the persistence, the session protocol, and the forensic record — transition reports are the trajectory evidence.
type EventSink ¶
EventSink receives events as they happen. The shell wires it to an append-only JSONL file; tests use an in-memory sink.
type EventType ¶
type EventType string
EventType is one of the closed set of session-log events.
const ( // EventSessionMeta is the session-level header line (no instance): // participant identity, so a log is self-describing for list_sessions // descriptors without resolving any procedure spec. EventSessionMeta EventType = "session_meta" // EventLabeled carries a human-meaningful session label (no instance): // the dialogue's subject, agent-supplied and updatable as it sharpens. // Last one wins on fold and replay. EventLabeled EventType = "labeled" EventStarted EventType = "started" EventReport EventType = "report" EventChooserAnswer EventType = "chooser_answer" EventOpResult EventType = "op_result" EventServed EventType = "served" EventTransition EventType = "transition" EventCompleted EventType = "completed" EventAbandoned EventType = "abandoned" // EventRead records what a read surface served to the session: the tool, // the entry IDs, and the depth — metadata only, never payloads. Reads stay // free and ungated; tracking is logging, not gating (d-tac-dbk). No // instance — the read set is session-level, so evidence inspected by a // dispatching parent counts for its seeded children. EventRead EventType = "read" // EventParked records that a running move was deliberately parked back to // the session junction — state kept, resumable through next. Forensic // only: a resuming agent can tell a shelved move from one that drifted. EventParked EventType = "parked" )
type ExportedValue ¶
type ExportedValue struct {
Value any `json:"value"`
Provenance Provenance `json:"provenance"`
}
ExportedValue is the persisted form of one store value.
type FailedPredicate ¶
FailedPredicate names a predicate that held a gate, with its registered failure message — the message becomes the served instruction.
type FuncDoc ¶
FuncDoc is a registry function's documented contract: what it reads from and writes into the store. YAML never maps fields — it only names functions; these contracts are what spec authors consult (registryList, the MCP registry tool) and what load-time collision checks enforce.
type Graphs ¶ added in v0.14.1
Graphs is the engine's read-through to the current graph. The read side owns loading and freshness (a finders.GraphSource); the engine only reads through this value — Current returns the current graph (memoized by the source), Invalidate drops that memo after a graph write so the next read reloads. Declared here as an interface so the engine takes no finders import.
type GuardExpr ¶
type GuardExpr struct {
// contains filtered or unexported fields
}
GuardExpr is a parsed guard expression.
func ParseGuard ¶
ParseGuard parses a guard expression. Whitespace (including newlines from folded YAML scalars) separates tokens.
func (*GuardExpr) Eval ¶
Eval evaluates the expression against a predicate evaluator. Predicates are pure, so full evaluation (no short-circuit) is safe and keeps stall diagnostics complete.
func (*GuardExpr) Predicates ¶
Predicates returns the distinct predicate names the expression references, in first-appearance order. Used by spec validation (every name must exist in the registry) and by stall diagnostics.
type InjectCall ¶
type InjectCall struct {
// Id is the stable identifier the unit template references the result
// under. Optional — it falls back to Fn — but required to distinguish two
// injects of the same fn on one step (d-tac-87o).
Id string
Fn string
Args map[string]any
// Cap is the author's size override for this inject's result; the zero
// value defers to the query's registration default (d-tac-qwc).
Cap serveview.Cap
}
InjectCall is a query op the engine runs before serving a step's unit. Args are literals or Go templates rendered against the store.
func (InjectCall) EffectiveID ¶ added in v0.17.0
func (c InjectCall) EffectiveID() string
EffectiveID is the template-context key an inject's result lands under.
type Instance ¶
type Instance struct {
ID string
Spec *Spec
Store *Store
Step string
Status InstanceStatus
// Outcome is the end(...) label the instance finished with.
Outcome string
// Parent is the spawning instance's ID for sub-procedures, empty at the
// top level.
Parent string
// contains filtered or unexported fields
}
Instance is one running procedure — a spec, its typed store, and a step position. Instances belong to a session; sub-procedures carry a parent link.
type InstanceStatus ¶
type InstanceStatus string
InstanceStatus is a procedure instance's lifecycle state.
const ( StatusRunning InstanceStatus = "running" StatusCompleted InstanceStatus = "completed" StatusAbandoned InstanceStatus = "abandoned" )
type Involvement ¶ added in v0.17.0
Involvement is the engine-side value of an involvement-typed variable: one target a focus advances, with optional per-target actors and when, before it becomes a model.Involvement at the write gate. ActorsSet keeps the model's unset (inherit focus default) versus explicit-empty (pull-available) distinction across the JSON round-trip through the session log.
func (Involvement) MarshalJSON ¶ added in v0.17.0
func (i Involvement) MarshalJSON() ([]byte, error)
MarshalJSON emits actors only when set, so the replay round-trip through map[string]any reconstructs ActorsSet from the key's presence — omitempty cannot tell an explicit empty list from an unset one.
func (Involvement) String ¶ added in v0.17.0
func (i Involvement) String() string
type Option ¶
type Option struct {
Choice string
Call string // command run on selection, per its Go contract
Collect []CollectField
To string
// Dispatch declares the grounding this junction option seeds into a child
// dispatched after it is answered (child field ← parent field, named in the
// parent's own spec). Nil means this option hands nothing down.
Dispatch *Dispatch
}
Option is one choice on an agent or user chooser step.
type PartSize ¶ added in v0.17.0
PartSize is defined in pkg/application/types — the exported surface names it, so the definition lives in the cycle-free public leaf (s-tac-ah2).
type Predicate ¶
type Predicate struct {
Doc FuncDoc
Fn PredicateFunc
FailMessage string
// FailDetail, when set, renders the failure message against the live
// context — for gates whose rejection must name the offending values
// (refsInspected naming the un-inspected IDs). Empty results fall back
// to FailMessage.
FailDetail func(ctx *Context) string
}
Predicate is a registered predicate with its contract and failure text — the message served as instruction when the predicate stalls a gate.
type PredicateFunc ¶
PredicateFunc is a pure check over the store (and graph): no side effects, deterministic for a given state.
type PresencePair ¶ added in v0.17.0
PresencePair is one gateable field with the presence predicate that reads it — the pairing surfaces render instead of restating.
func PresencePairs ¶ added in v0.17.0
func PresencePairs() []PresencePair
PresencePairs lists the presence predicates and the store field each reads, sorted by field — the closed gateable vocabulary.
type Provenance ¶
type Provenance string
Provenance classifies who wrote a store value. The split carries the trust property from the surface spec: reports can only write declared state fields; params are fixed at start; everything trust-bearing (created IDs, findings, confirmation records) is engine-written via ops and chooser calls, structurally out of a report's reach.
const ( ProvenanceParam Provenance = "param" ProvenanceState Provenance = "state" ProvenanceEngine Provenance = "engine" )
type Query ¶
type Query struct {
Doc FuncDoc
Fn QueryFunc
// ServeSafe marks the query as a pure read with no side effects — it writes
// nothing to the session log or graph. Only serve-safe queries may be
// declared as shell framing lanes: framing renders on every serve, and a
// serve must not write (I7). A query that logs its reads (LogRead) or
// mutates is not serve-safe and is rejected as a framing lane at spec load.
ServeSafe bool
// Bound declares the query's serving knowledge at its one authoritative
// site: what part kind the result is, its default cap (a spec-declared
// cap overrides it), and how to compose a pull expression for a cut's
// remainder (d-tac-qwc).
Bound QueryBound
}
Query is a registered query.
type QueryBound ¶ added in v0.17.0
type QueryBound struct {
Part serveview.PartKind
Cap serveview.Cap
// Pull composes a ready-to-run expression for what a cut dropped, from
// the rendered inject args and the cut's accounting. Nil when no pull is
// expressible.
Pull func(args map[string]any, cut truncate.Cut) string
}
QueryBound is a query's declared serving knowledge; see Query.Bound.
type QueryFunc ¶
QueryFunc serves data for dynamic injection: pure read, result enters the template context (not the store).
type QueryResolver ¶ added in v0.17.0
QueryResolver resolves a query's registration by name — what the arithmetic sizes inject caps against. *Registry implements it. A resolver miss means the spec names an unknown query, which Validate rejects before the arithmetic runs; the arithmetic skips such injects.
type ReadDepth ¶
type ReadDepth string
ReadDepth classifies how deeply an entry was served: full means the body was served (a show primary, an injected chain's primary, or a same-session write); summary covers chain bullets, search headers, and snippets.
type Ref ¶
type Ref struct {
ID string `json:"id"`
Kind string `json:"kind"`
Desc string `json:"desc,omitempty"`
}
Ref is the engine-side value of a ref-typed variable: the same closed-kind reference shape entries carry, before it becomes a model.Ref at the write gate.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry is the closed set of Go functions a procedure spec may name. All semantics live here, composed by name in YAML — the spec language itself carries no logic. Enumerable so spec authors and lint can check every referenced name.
func NewRegistry ¶
func NewRegistry() *Registry
NewRegistry returns a registry pre-populated with the built-in predicates (largely the mechanical pre-flight checks re-exposed — single path, no duplicated validation). Queries and commands with side-effect dependencies are registered by the shell that owns those dependencies.
func (*Registry) Docs ¶
Docs enumerates registered function contracts, optionally filtered by class, sorted by name — the registryList query's data.
func (*Registry) RegisterCommand ¶
RegisterCommand adds a command. Names are unique across all classes.
func (*Registry) RegisterPredicate ¶
RegisterPredicate adds a predicate. Names are unique across all classes.
func (*Registry) RegisterQuery ¶
RegisterQuery adds a query. Names are unique across all classes.
type Serve ¶
type Serve struct {
Instance string
Procedure string
Status InstanceStatus
Outcome string
Step string
// Goal is a one-line statement of what advances the instance from here.
Goal string
// Instructions is the step's instruction unit rendered against the
// store, with stall diagnostics appended when a gate is held.
Instructions string
// Unit names the instruction unit rendered into Instructions (empty when
// the step has none). Shells key their served-instruction memory on it.
Unit string
// UnitText is the rendered unit alone, without diagnostics — what a
// shell replaces with a one-line reminder once the unit was served.
UnitText string
// Lanes are the unit's rendered lanes in declaration order (empty
// rendered lanes dropped), the blocks a host dedups independently
// (d-tac-87o). UnitText is their join.
Lanes []ServeLane
// Diagnostics are the stall messages appended to Instructions ("Gate
// held" lines), kept separate so shells can recompose around UnitText.
Diagnostics []string
// Missing names the current step's required collect fields not yet in
// the store.
Missing []string
// Failing lists predicates currently holding the gate.
Failing []FailedPredicate
// ReportSchema is the JSON Schema for the current step's report.
ReportSchema map[string]any
// Chooser is set when the step awaits an agent or user choice.
Chooser *ChooserServe
// Produced carries the engine-written results on completion (e.g. the
// created entry ID), excluding internal trust machinery.
Produced map[string]any
// Sizes is the per-part byte accounting of this serve — inject results,
// rendered lanes, schema, diagnostics, produced (d-tac-qwc).
Sizes []PartSize
// Cuts records every bound that fired on this serve; the engine-owned
// cuts lane renders them and the measurement harness reads them.
Cuts []truncate.Cut
}
Serve is what the engine returns after every advance — the current step's rendered instructions, the report schema, chooser material when one is pending, and stall diagnostics naming exactly what's missing.
type ServeLane ¶ added in v0.17.0
ServeLane is defined in pkg/application/types — the exported surface names it, so the definition lives in the cycle-free public leaf (s-tac-ah2).
type Session ¶
type Session struct {
ID string
Participant string
// Label is the session's human-meaningful subject line — what a user
// picks a parked dialogue by. Agent-supplied via SetLabel, updatable;
// empty until supplied.
Label string
// contains filtered or unexported fields
}
Session is one dialogue session: N procedure instances interleaved serially, one append-only event log. Per-participant; the shell owns file placement and lifecycle.
func (*Session) Abandon ¶
Abandon explicitly discards a running instance, logged as an abandonment transition. It never cleans up implicitly — anything the instance holds (a WIP marker, staged attachments) is left standing for resume or groom.
func (*Session) Answer ¶
func (s *Session) Answer(instanceID, chooser, choice string, fields map[string]any, userWords string) (*Serve, error)
Answer resolves the pending chooser at the instance's current step: the named chooser must be the current step (no early, late, or double answers), the choice must be one of its options, and any carried fields are limited to the option's collect list. User answers carry the user's words verbatim for the auditable-relay record.
func (*Session) Inject ¶ added in v0.17.0
Inject runs one registered query against an instance's live context — the same path renderUnit uses for a step's inject, exposed so a shell can render declared framing lanes (which live outside any step unit) through the one query mechanism. Args templates render against the instance store. The result arrives bounded by the call's effective cap; a non-nil cut says what the bound dropped, for the caller's surface to render in its own register.
func (*Session) LogRead ¶
LogRead records what a read surface served to the session: entry IDs at full depth (body served) and summary depth (headers, chain bullets, snippets), attributed to the serving tool. Every call appends a read event — re-reads are part of the forensic record — and folds into the session's read set, where full depth never downgrades. Empty calls append nothing.
func (*Session) Park ¶
Park records that a running move was deliberately parked back to the session junction: state kept, position kept, resumable through the normal advance path. The event is forensic — nothing about the instance changes — but it makes the shelving auditable and legible to a resuming agent.
func (*Session) ReadDepthOf ¶
ReadDepthOf returns the deepest depth the entry was served to this session at (empty when never served).
func (*Session) Report ¶
Report applies state fields from a transition report, re-evaluates, and cascades. Reports can only write declared state fields; batched fields for later steps are accepted. A report does not answer a pending chooser.
func (*Session) Serve ¶
Serve re-serves the instance's current position without advancing it — shells use it to rehydrate an agent after resume_session. Draft (serveDelta) fields serve whole here: a rehydrating agent holds no earlier base, and the full serve resets the delta base for the rounds that follow.
func (*Session) SetLabel ¶
SetLabel records the session's subject label. Idempotent per value — a resent identical label appends nothing, so agents may safely carry the label on every call.
func (*Session) SinkErr ¶ added in v0.17.0
checkSink surfaces a deferred log-append failure before advancing. SinkErr returns a stashed durable-append failure without clearing it, so the operation that caused it can surface the typed error synchronously while subsequent operations still refuse through checkSink.
type SessionOption ¶
type SessionOption func(*Session)
SessionOption configures a session.
func WithClock ¶
func WithClock(now func() time.Time) SessionOption
WithClock injects the timestamp source (tests use a fixed clock).
type Spec ¶
type Spec struct {
// EntryID is the graph entry the spec was loaded from.
EntryID string
// Canonical is the procedure's stable identity (capture, engage, …).
Canonical string
// Class is the procedure's execution role: a move is started through the
// loop, a shell is a session base auto-started by the session door.
Class model.ProcedureClass
// Params are the typed inputs accepted at start_procedure.
Params map[string]VarDecl
// State is the report-writable variable store declaration. Engine-
// written values are deliberately not declared — they enter the store
// per the Go contracts of the functions the spec names, and collisions
// with these declarations are rejected at load.
State map[string]VarDecl
// Steps is the state graph, in declaration order. The first step is the
// entry step.
Steps []*Step
// ServeBudget is the spec's declared worst-case serve total in bytes;
// zero defers to the engine's default budget. Read only by the advisory
// authoring arithmetic (WorstCaseServeBytes) — never at load or runtime.
ServeBudget int
// StepByID indexes Steps.
StepByID map[string]*Step
// Units are the body's instruction units by name (`## unit: <name>`
// sections), rendered as Go templates against the store at serve time.
Units map[string]Unit
// Framing declares a shell's session-framing lanes: inject query calls the
// shell renders into its serve alongside the engine-supplied info block,
// through the same query mechanism a step's inject uses. Empty on moves and
// on shells that declare none (which then serve info-only framing).
Framing []InjectCall
}
Spec is the typed, validated form of a procedure entry's state machine — what the engine executes. Parsed from the raw YAML the model retains on kind: procedure entries (structural validation happens here, at engine load time, per the type-system revision contract) plus the body's per-step instruction units.
func LoadSpec ¶
LoadSpec parses and fully validates a procedure entry against the registry — the one-call path the engine and lint use.
func ParseSpec ¶
ParseSpec parses a procedure entry into a typed Spec: variable declarations, the step graph with parsed guards, and the body's instruction units. Registry-independent validation happens here (types, step wiring, guard syntax, collect declarations); function existence and write-collision checks need the registry and run in Validate.
func (*Spec) AnswerSchemaForStep ¶
AnswerSchemaForStep generates the JSON Schema for a chooser step's answer: the chooser to name (its step id), the choice to pick, the user's verbatim words for a user chooser, and the option-collected fields nested under `fields`. A flat report schema at a chooser step misled callers into placing collected fields at the top level (rejected); this envelope makes the required nesting explicit. `fields` unions every option's collect fields — each option enforces its own required set at answer time, so the envelope marks none of them required.
func (*Spec) EffectiveTotal ¶ added in v0.17.0
EffectiveTotal is the total the arithmetic checks against: the spec's declared serveBudget when set — the author's recorded trade — else the budget's default Total.
func (*Spec) OverBudget ¶ added in v0.17.0
func (s *Spec) OverBudget(budget serveview.Budget, resolver QueryResolver) []StepSize
OverBudget returns the steps whose worst case exceeds the effective total.
func (*Spec) ReportSchemaForStep ¶
ReportSchemaForStep generates the JSON Schema for a step's report from the spec's variable declarations: the step's collect fields are the named, described properties (required unless marked optional), and every other declared state field is accepted too — reports may batch fields for later steps, and the cascade rule makes the one-shot full draft as fast as today. The same desc that feeds instruction text feeds the schema.
func (*Spec) Validate ¶
Validate runs the registry-dependent load checks: every function a spec names exists in the right class, and no named command writes into a declared param or state field (engine-written values must stay structurally out of the report-writable surface). Returns all problems.
func (*Spec) WorstCaseServeBytes ¶ added in v0.17.0
func (s *Spec) WorstCaseServeBytes(budget serveview.Budget, resolver QueryResolver) []StepSize
WorstCaseServeBytes sizes every step's automatic serve at its declared worst: the unit's lane skeleton (authored template text as written), each inject at its effective cap, each referenced declared field at its typed slot allowance, and the draft lane's cap when the step serves a delta. Individually capped parts can still sum past a host budget — this is the check that moved from runtime to authoring surfaces.
type SpecResolver ¶
SpecResolver resolves a procedure canonical to its loaded spec — replay uses it to rebind logged instances to their procedure definitions.
type StaticGraphs ¶ added in v0.14.1
StaticGraphs is a Graphs backed by a fixed in-memory graph — for tests and callers with no reload need. Invalidate is a no-op: there is nothing behind the value to re-read.
func (StaticGraphs) Current ¶ added in v0.14.1
func (s StaticGraphs) Current() (*model.Graph, error)
Current returns the fixed graph.
func (StaticGraphs) Invalidate ¶ added in v0.14.1
func (s StaticGraphs) Invalidate()
Invalidate is a no-op for a static graph.
type Step ¶
type Step struct {
ID string
Collect []CollectField
Inject []InjectCall
Render string
Chooser ChooserKind
Options []Option
Guard *GuardExpr
Op string
Transitions []Transition
// Goal overrides the serve's generic per-chooser goal line for this
// step. Built for resident steps whose standing posture the generic
// wording would misstate (a session shell's junction is "dialogue
// freely", not "put the choice to the user").
Goal string
// ServeDelta names the state fields the engine renders as a draft block
// on this step's serves: whole on the first serve (and on resume), only
// what changed after — prose fields as content diffs, lists item-level,
// scalars whole (20260826-120330-d-tac-8f8).
ServeDelta []string
}
Step is one node of the state graph.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is the typed variable store of one procedure instance. Declared params and state come from the spec; engine-written values enter through command contracts (their Writes set) and are validated against declaration collisions at spec load time, not here.
func NewStore ¶
NewStore creates an empty store bound to the spec that declares its params and state fields.
func (*Store) Clone ¶ added in v0.17.0
Clone creates an isolated store for candidate mutation. Every stored value is a normalized JSON document, so a container-recursion copy fully isolates the candidate — a rejected batch leaves the source untouched.
func (*Store) Collected ¶ added in v0.17.0
Collected returns the param- and state-provenance values that are present and non-empty, excluding internal trust machinery. It is a resuming agent's view of what this instance has already gathered — the anchor, chosen scope, and reported judgments that persist across a handover and must not be re-derived. Engine-produced trust records are structurally excluded by the provenance filter; the explicit trust-machinery skip keeps that guarantee even if such a field were ever param- or state-declared.
func (*Store) Export ¶
func (s *Store) Export() map[string]ExportedValue
Export returns all values with provenance for session-log persistence.
func (*Store) Has ¶
Has reports whether the field is present and non-empty. Empty strings, empty lists, and nil don't count as present — a presence predicate asking hasBody wants substance, not a key.
func (*Store) SetParams ¶
SetParams validates and writes the start-time params. Required params must be present; unknown params are rejected.
func (*Store) SetStart ¶
SetStart applies the start-time input map, the shared seeding primitive (d-tac-tlo): a key naming a declared param sets that param (fixed at start), a key naming a declared state field seeds it — a start-time state write, equivalent to an immediate report, so an entry gate reading it is satisfied on entry. Move dispatch and direct start share this: a caller passing an anchor a procedure declares as state seeds the resolver, and the parent handoff seeds the same fields from the parent's store. Unknown keys are rejected.
func (*Store) StateSnapshot ¶
StateSnapshot returns a deterministic fingerprint over the report-writable state values. confirmPlayback binds a confirmation to this fingerprint; playbackConfirmed compares it — any state edit after confirmation changes the snapshot and reopens playback.
func (*Store) TemplateContext ¶
TemplateContext exposes every store value by name for instruction-unit and inject-arg template rendering.
func (*Store) WriteEngine ¶
WriteEngine writes an engine-produced value (an op result or chooser-call effect) per the producing function's Go contract. Never reachable from a report. The value is normalized to its JSON document form so pre-restart reads match the replayed form; a value that cannot marshal is a loud write-time error, leaving the store unchanged.
type Transition ¶
Transition is one ordered {when, to} entry; the final entry may be an otherwise fallback (When nil).
type Unit ¶ added in v0.17.0
type Unit struct {
Lanes []UnitLane
}
Unit is one named instruction unit, as ordered lanes rendered independently so a host can dedup each on its own (d-tac-87o). A unit body without lane markers is one implicit lane named after the unit.
type UnitLane ¶ added in v0.17.0
UnitLane is one declared slice of a unit's instruction text (`### lane: <name>` sections inside a unit).
type VarDecl ¶
type VarDecl struct {
Type VarType
Optional bool
Desc string
// Default is an optional start-time value applied to a state field the
// caller leaves unset — the one place the spec carries a literal, and only
// a declaration attribute, not an expression in the step language. It lets
// a procedure carry a constant it seeds into every child it dispatches
// (bootstrap's recognitionMode flag). Validated against Type at load; nil
// means no default. Applied at store start on state only.
Default any
// PatchOf names a text state field this field edits in place: a reported
// value is an ordered list of search-replace pairs applied atomically to
// the target, and the target's new value is what lands and logs — the
// patch field itself is never stored (20260826-120330-d-tac-8f8). Requires
// an optional list<search-replace> declaration; validated at load.
PatchOf string
}
VarDecl declares one typed variable. The desc seeds both the generated report schema and the "provide the following" instruction text — one declaration, both surfaces.
type VarType ¶
VarType is a declared variable type: a base domain type, optionally wrapped as list<T>.
func ParseVarType ¶
ParseVarType parses a type string from a variable declaration: a base domain type name or list<T> around one.
type When ¶ added in v0.17.0
When is the engine-side value of an involvement-when: a temporal range that becomes a model.FocusWhen at the write gate. At least one end is set.
type WriterSink ¶
type WriterSink struct {
// contains filtered or unexported fields
}
WriterSink appends events as JSON lines to an io.Writer.
func NewWriterSink ¶
func NewWriterSink(w io.Writer) *WriterSink
NewWriterSink wraps a writer as an EventSink emitting one JSON line per event.
func (*WriterSink) Append ¶
func (s *WriterSink) Append(e Event) error
Append writes the event as one JSON line.