spec

package
v0.1.97 Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package spec defines resource envelopes, MVP kind structs (§6–§7), YAML loading, project-level defaults (NormalizeProjectGraph), reference resolution (ResolveReferences), and graph validation (ValidateProjectGraph, §9.1–§9.5 MVP subset). Environment-specific overrides (§7.6) are applied by ApplyEnvironment. after NormalizeProjectGraph in CLI and local-runtime flows.

Tool resources may declare spec.safety (trusted, sideEffects, requiresApproval) for fail-closed policy derivation when explicit Policy rules do not apply (issue #103). spec.operations names per-operation effects (issue #188); undeclared tools are fail-closed in ResolveToolEffects and do not change runtime CheckToolCall.

Built-in policy presets (strict, permissive, shell_safe) are defined in this package and expanded during NormalizeProjectGraph via ExpandPresetsInGraph (issue #104).

Index

Constants

View Source
const (
	DefaultMaxToolInputBytes  = 256 << 10 // 256 KiB
	DefaultMaxToolOutputBytes = 256 << 10 // 256 KiB
	DefaultMaxCheckpointBytes = 1 << 20   // 1 MiB
	// DefaultMaxWorkflowNesting is the maximum workflow: call depth (issue #194).
	// Top-level run is depth 0; the first subworkflow is depth 1.
	DefaultMaxWorkflowNesting = 8
	// DefaultMaxLoopIterations caps how many elements a single `.agent` loop or
	// dynamic fan-out may iterate (issue #199). The surface has no unbounded
	// (`while`) loop, so every loop is bounded by its collection; this cap bounds
	// that collection so a runtime list cannot make termination unbounded. A loop
	// whose collection exceeds it fails loudly rather than fanning out without
	// limit.
	DefaultMaxLoopIterations = 1000
)

Default byte limits for execution bounds (issue #117). Values use binary KiB/MiB.

View Source
const (
	PresetStrict     = "strict"
	PresetPermissive = "permissive"
	PresetShellSafe  = "shell_safe"
)

Built-in policy preset names (issue #104).

View Source
const (
	MCPMetaTrustedKey          = "trusted"
	MCPMetaSideEffectsKey      = "side_effects"
	MCPMetaRequiresApprovalKey = "requires_approval"
)

MCP meta.mcp_flags field names (snake_case per MCP descriptor convention).

View Source
const (
	KindProject     = "Project"
	KindAgent       = "Agent"
	KindTool        = "Tool"
	KindWorkflow    = "Workflow"
	KindPolicy      = "Policy"
	KindEnvironment = "Environment"
)

Kind names for MVP resources (design doc §6.2).

View Source
const APIVersionV0 = "agentic.dev/v0"

API version for MVP resources (design doc §6.1).

View Source
const ApprovalStepUses = "workflow.approval"

ApprovalStepUses is the sentinel uses string stored on workflow-level HITL checkpoints (issue #195). It is not a tool identity; switch is not applicable.

View Source
const DefaultApprovalStepDescription = "Workflow step requires approval"

DefaultApprovalStepDescription is shown when an approval step omits description.

View Source
const DefaultHitlDescriptionPrefix = "Tool execution requires approval"

DefaultHitlDescriptionPrefix is shown before per-call review text when policy omits descriptionPrefix.

View Source
const EffectDestructive = "destructive"

EffectDestructive is the only reserved effect identifier (issue #188, ADR 002). It may feed ToolSafety sideEffects derivation when the author omitted spec.safety.sideEffects.

View Source
const EffectIdentPattern = `[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*`

EffectIdentPattern is the tight dotted identifier for named effects: [a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)* Operation map keys use the same pattern. Effect identifiers must not begin with "tool.".

View Source
const MCPMetaFlagsKey = "mcp_flags"

MCPMetaFlagsKey is the MCP tool descriptor meta key for safety flags (issue #125).

View Source
const MaxSuggestEditDistance = 2

MaxSuggestEditDistance is the maximum Levenshtein distance for YAML field typo suggestions.

Variables

View Source
var (
	ErrMultipleDocuments = errors.New("expected exactly one YAML document")
	ErrUnknownKind       = errors.New("unknown resource kind")
)

Sentinel errors for resource loading.

AllHitlDecisionKinds lists every supported decision in stable order.

View Source
var ErrUnknownField = fmt.Errorf("unknown field")

ErrUnknownField is returned when strict YAML decoding encounters an unrecognized key.

View Source
var ShellCommandOperations = []string{"command.run", "run", "exec", "shell"}

Shell command operation names for native tools (single source of truth, issue #104).

Functions

func ApprovalPermissive

func ApprovalPermissive(a *PolicyApprovals) bool

ApprovalPermissive reports whether merged approvals enable permissive mode.

func ApprovalRequireAllTools

func ApprovalRequireAllTools(a *PolicyApprovals) bool

ApprovalRequireAllTools reports whether merged approvals gate every tool call.

func ApprovalStepDescription

func ApprovalStepDescription(st WorkflowStep) string

ApprovalStepDescription returns review text for an approval step.

func BoolPtr

func BoolPtr(b bool) *bool

BoolPtr returns a pointer to b (for optional YAML bool fields).

func BuiltinPresetNames

func BuiltinPresetNames() []string

BuiltinPresetNames returns sorted built-in preset identifiers.

func ClosestTag

func ClosestTag(candidates []string, wrong string) string

ClosestTag returns the nearest candidate tag within MaxSuggestEditDistance, or "".

func CollectWithStringValues

func CollectWithStringValues(with map[string]any) []string

CollectWithStringValues walks workflow step "with" values and yields string forms for interpolation scanning (maps and slices recurse shallowly).

func EffectCovers

func EffectCovers(declared, candidate string) bool

EffectCovers reports membership or dotted-prefix coverage: declared "github" covers "github.read"; "github.read" covers "github.read" and "github.read.pr".

func ExpandPresetsInGraph

func ExpandPresetsInGraph(g *ProjectGraph)

ExpandPresetsInGraph materializes built-in policy presets referenced by Project defaults, agents, workflows, and Policy.spec.preset (issue #104). User-defined Policy resources with the same metadata.name override built-ins. Mutates g in place.

func ExtractShellCommand

func ExtractShellCommand(with map[string]any) string

ExtractShellCommand reads a command string from a workflow step input map.

func FirstShellToken

func FirstShellToken(command string) string

FirstShellToken returns the first whitespace-delimited token from a shell command string.

func FormatStrictYAMLError

func FormatStrictYAMLError(path string, err error) string

FormatStrictYAMLError turns yaml.v3 strict decode failures into path-qualified messages with optional "did you mean" hints (issue #112).

func InterpolationStepRefs

func InterpolationStepRefs(s string) []string

func IsBuiltinPreset

func IsBuiltinPreset(name string) bool

IsBuiltinPreset reports whether name is a built-in preset identifier.

func IsShellCommandOperation

func IsShellCommandOperation(operation string) bool

IsShellCommandOperation reports whether operation is a shell command carrier for shell_safe.

func IsValidHitlDecisionKind

func IsValidHitlDecisionKind(k HitlDecisionKind) bool

IsValidHitlDecisionKind reports whether k is a known decision kind.

func Levenshtein

func Levenshtein(a, b string) int

Levenshtein returns the edit distance between a and b.

func NormalizeExecutionLimits

func NormalizeExecutionLimits(l *ExecutionLimits)

NormalizeExecutionLimits merges maxStateBytes into maxCheckpointBytes when the latter is unset.

func NormalizePolicyEffects

func NormalizePolicyEffects(pol *PolicySpec)

NormalizePolicyEffects trims and unique-sorts permit identifiers, keeping Pos aligned.

func NormalizeProjectGraph

func NormalizeProjectGraph(g *ProjectGraph)

NormalizeProjectGraph applies Project.spec.defaults to resources that omit matching fields, materializes Tool safety defaults (issue #103), expands built-in policy presets (issue #104), and performs trivial string canonicalization (trim surrounding ASCII space).

MCP tool safety from server meta.mcp_flags is merged earlier in the config pipeline via [tools.ApplyMCPSafetyDiscovery] before this function runs (issue #125).

Default application (§7.1 → effective config):

  • Agent.spec.model ← defaults.model when the agent omits model (empty / whitespace-only).
  • Agent.spec.policy ← defaults.policy when the agent omits policy.
  • Agent.spec.runtime ← defaults.runtime when the agent omits runtime (issue #76).
  • Workflow.spec.policy ← defaults.policy when the workflow omits policy.
  • Workflow.spec.runtime ← defaults.runtime when the workflow omits runtime (issue #76).

Environment overlays (design doc §7.6) are not applied here. Typical pipelines load the graph, run NormalizeProjectGraph, then apply the selected environment with spec.ApplyEnvironment in the control plane before handing an immutable snapshot to runtime.Runtime, then validate. Mutates g in place.

func NormalizeToolEffects

func NormalizeToolEffects(spec *ToolSpec)

NormalizeToolEffects trims operation keys and effect identifiers and sorts unique effects. EffectsPos is kept aligned with Effects (first occurrence wins; empty strings are dropped).

func NormalizeToolSafety

func NormalizeToolSafety(spec *ToolSpec)

NormalizeToolSafety mutates spec.Safety so resolved bools are materialized for stable plan output. Idempotent when called on an already-normalized safety block.

func ParseToolUses

func ParseToolUses(uses string) (toolName string, ok bool)

ParseToolUses extracts the Tool metadata.name from a workflow step "uses" value of the form tool.<toolName>.<operation...> (design doc §7.4, issue #6).

func ParseUnknownFieldLine

func ParseUnknownFieldLine(line string) (field, typeName string, ok bool)

ParseUnknownFieldLine extracts the unknown field and type name from a yaml.v3 strict decode line.

func RelocateFile

func RelocateFile(res any, file string)

RelocateFile rewrites File on every Pos attached to res (project-relative paths).

func ResolveMaxWorkflowNesting

func ResolveMaxWorkflowNesting(project *ProjectSpec, workflow *WorkflowSpec) int

ResolveMaxWorkflowNesting is the effective workflow: nesting cap (issue #194). Zero/omitted YAML uses DefaultMaxWorkflowNesting.

func ResolveReferences

func ResolveReferences(g *ProjectGraph) error

ResolveReferences checks symbolic references and workflow step rules (§9.4). Multiple problems are combined with errors.Join.

func ResolvedPresetName

func ResolvedPresetName(pol *PolicySpec) string

ResolvedPresetName returns the effective preset mode for a policy spec.

func ShellCommandRequiresApproval

func ShellCommandRequiresApproval(command string) bool

ShellCommandRequiresApproval reports whether a command string must be gated under shell_safe.

This is a first-token heuristic with metacharacter fail-closed checks — not a sandbox. Commands containing shell composition syntax (;|&$`, newlines, $(…)) always require approval.

func StepAncestorIDs

func StepAncestorIDs(steps []WorkflowStep, i int) map[string]struct{}

StepAncestorIDs returns the transitive predecessor set of steps[i] (not including itself).

func StepIsApproval

func StepIsApproval(st WorkflowStep) bool

StepIsApproval reports whether st is an approval graph node (issue #195).

func StepNeedsIDs

func StepNeedsIDs(steps []WorkflowStep, i int) []string

StepNeedsIDs returns the declared or implicit predecessor IDs for steps[i].

func SuggestYAMLField

func SuggestYAMLField(typeName, wrong string) string

SuggestYAMLField returns the closest known yaml tag for wrong within typeName, or "".

func TelemetryEnabled

func TelemetryEnabled(g *ProjectGraph) bool

TelemetryEnabled reports whether spec.telemetry.enabled is true on the merged project graph.

func TraceRetentionDays

func TraceRetentionDays(g *ProjectGraph) int

TraceRetentionDays returns spec.traces.retentionDays from the merged project graph, or 0 when unset or non-positive (no pruning; issue #75). Tracing config is project-global (not overridden per Environment in MVP).

func ValidateEffectIdent

func ValidateEffectIdent(id string) error

ValidateEffectIdent reports whether id is a legal effect identifier.

func ValidateExecutionLimits

func ValidateExecutionLimits(l *ExecutionLimits) error

ValidateExecutionLimits returns an error when limits or policies are invalid.

func ValidateOperationName

func ValidateOperationName(name string) error

ValidateOperationName reports whether name is a legal spec.operations map key.

func ValidateProjectGraph

func ValidateProjectGraph(g *ProjectGraph, projectRoot string) error

ValidateProjectGraph runs MVP validation rules from design doc §9.1–§9.5 on a merged graph. projectRoot is used to resolve Agent/Workflow input and output schema paths (§9.2), load those schemas onto the graph, and check step interpolation wiring (§13.1, issue #193).

Multiple violations are combined with errors.Join. Callers (e.g. terfyn validate) should treat a non-nil return as exit code 2 per §11.2.

func WorkflowUsesExplicitNeeds

func WorkflowUsesExplicitNeeds(steps []WorkflowStep) bool

WorkflowUsesExplicitNeeds reports whether any step opts the workflow into graph mode (issue #192). A workflow with no `needs:` keys keeps implicit sequential semantics: YAML order is an implicit chain (step i waits for step i-1).

Types

type AdvertisedAgentTool

type AdvertisedAgentTool struct {
	Name string
	Uses string
}

AdvertisedAgentTool is one ToolDef-name → uses binding for an agent loop (issue #160).

func ResolveAgentAdvertisedTools

func ResolveAgentAdvertisedTools(agent *AgentResource, tools map[string]*ToolResource) ([]AdvertisedAgentTool, error)

ResolveAgentAdvertisedTools maps agent.spec.tools onto one uses string per Tool name. Entries may be a Tool metadata name or a pinned uses string tool.<name>.<operation>. Native names advertise echo; mock/mcp advertise default; HTTP requires a method.path pin.

type AgentConstraints

type AgentConstraints struct {
	MaxIterations           int     `yaml:"maxIterations,omitempty" json:"maxIterations,omitempty"`
	TimeoutSeconds          int     `yaml:"timeoutSeconds,omitempty" json:"timeoutSeconds,omitempty"`
	Temperature             float64 `yaml:"temperature,omitempty" json:"temperature,omitempty"`
	RequireStructuredOutput bool    `yaml:"requireStructuredOutput,omitempty" json:"requireStructuredOutput,omitempty"`
}

type AgentIO

type AgentIO struct {
	Schema string `yaml:"schema,omitempty" json:"schema,omitempty"`
	// Resolved is the compiled JSON Schema loaded from Schema during validate (issue #193).
	// Diagnostic/derived; not identity. Omitted from hashes.
	Resolved *schema.Document `yaml:"-" json:"-"`
}

type AgentMemory

type AgentMemory struct {
	Type        string `yaml:"type,omitempty" json:"type,omitempty"`
	MaxMessages int    `yaml:"maxMessages,omitempty" json:"maxMessages,omitempty"`
}

type AgentOverride

type AgentOverride struct {
	Model       string            `yaml:"model,omitempty" json:"model,omitempty"`
	Constraints *AgentConstraints `yaml:"constraints,omitempty" json:"constraints,omitempty"`
}

type AgentResource

type AgentResource = Resource[AgentSpec]

MVP resource envelopes with concrete spec types.

type AgentSpec

type AgentSpec struct {
	Description  string   `yaml:"description,omitempty" json:"description,omitempty"`
	Model        string   `yaml:"model,omitempty" json:"model,omitempty"`
	Runtime      string   `yaml:"runtime,omitempty" json:"runtime,omitempty"`
	Instructions string   `yaml:"instructions,omitempty" json:"instructions,omitempty"`
	Tools        []string `yaml:"tools,omitempty" json:"tools,omitempty"`
	// ToolsPos is diagnostic metadata aligned with Tools (issue #187). Not YAML/JSON identity.
	ToolsPos    []Pos             `yaml:"-" json:"-"`
	Policy      string            `yaml:"policy,omitempty" json:"policy,omitempty"`
	Memory      *AgentMemory      `yaml:"memory,omitempty" json:"memory,omitempty"`
	Constraints *AgentConstraints `yaml:"constraints,omitempty" json:"constraints,omitempty"`
	Input       *AgentIO          `yaml:"input,omitempty" json:"input,omitempty"`
	Output      *AgentIO          `yaml:"output,omitempty" json:"output,omitempty"`
}

type Decoded

type Decoded struct {
	Path     string
	Resource any // *ProjectResource | *AgentResource | *ToolResource | *WorkflowResource | *PolicyResource | *EnvironmentResource
}

Decoded is one parsed MVP resource from a single YAML document.

func LoadResourceFile

func LoadResourceFile(path string) (*Decoded, error)

LoadResourceFile reads path and decodes exactly one YAML MVP resource.

func ParseResourceFromBytes

func ParseResourceFromBytes(data []byte, path string) (*Decoded, error)

ParseResourceFromBytes decodes exactly one YAML document from data with strict unknown-key rejection. path is used only for error messages (e.g. when data did not come from a file).

func (*Decoded) APIVersion

func (d *Decoded) APIVersion() string

APIVersion returns apiVersion from the typed envelope.

func (*Decoded) Kind

func (d *Decoded) Kind() string

Kind returns the resource kind from the typed envelope.

func (*Decoded) ResourceID

func (d *Decoded) ResourceID() ResourceID

ResourceID returns kind and metadata.name for the decoded resource.

type EnvironmentOverrides

type EnvironmentOverrides struct {
	Agents   map[string]AgentOverride  `yaml:"agents,omitempty" json:"agents,omitempty"`
	Policies map[string]PolicyOverride `yaml:"policies,omitempty" json:"policies,omitempty"`
}

type EnvironmentResource

type EnvironmentResource = Resource[EnvironmentSpec]

MVP resource envelopes with concrete spec types.

type EnvironmentSpec

type EnvironmentSpec struct {
	Overrides *EnvironmentOverrides `yaml:"overrides,omitempty" json:"overrides,omitempty"`
}

type ErrUnknownPreset

type ErrUnknownPreset struct {
	Name string
}

ErrUnknownPreset is returned when a policy references an unrecognized preset name.

func (*ErrUnknownPreset) Error

func (e *ErrUnknownPreset) Error() string

type ExecutionLimits

type ExecutionLimits struct {
	MaxToolInputBytes      int               `yaml:"maxToolInputBytes,omitempty" json:"maxToolInputBytes,omitempty"`
	MaxToolOutputBytes     int               `yaml:"maxToolOutputBytes,omitempty" json:"maxToolOutputBytes,omitempty"`
	MaxCheckpointBytes     int               `yaml:"maxCheckpointBytes,omitempty" json:"maxCheckpointBytes,omitempty"`
	MaxStateBytes          int               `yaml:"maxStateBytes,omitempty" json:"maxStateBytes,omitempty"`
	MaxWorkflowNesting     int               `yaml:"maxWorkflowNesting,omitempty" json:"maxWorkflowNesting,omitempty"`
	MaxLoopIterations      int               `yaml:"maxLoopIterations,omitempty" json:"maxLoopIterations,omitempty"`
	ToolInputExceedPolicy  LimitExceedPolicy `yaml:"toolInputExceedPolicy,omitempty" json:"toolInputExceedPolicy,omitempty"`
	ToolOutputExceedPolicy LimitExceedPolicy `yaml:"toolOutputExceedPolicy,omitempty" json:"toolOutputExceedPolicy,omitempty"`
	CheckpointExceedPolicy LimitExceedPolicy `yaml:"checkpointExceedPolicy,omitempty" json:"checkpointExceedPolicy,omitempty"`
}

ExecutionLimits bounds tool I/O and checkpoint/state size. Project YAML may set defaults; Workflow and Tool resources may override individual fields (issue #117).

func MergeExecutionLimits

func MergeExecutionLimits(base ExecutionLimits, override *ExecutionLimits) ExecutionLimits

MergeExecutionLimits overlays override onto base; non-zero override fields win.

type HitlDecisionKind

type HitlDecisionKind string

HitlDecisionKind names an operator resolution at an approval gate (issue #106).

const (
	HitlDecisionApprove HitlDecisionKind = "approve"
	HitlDecisionReject  HitlDecisionKind = "reject"
	HitlDecisionEdit    HitlDecisionKind = "edit"
	HitlDecisionSwitch  HitlDecisionKind = "switch"
)

func ParseHitlDecisionKind

func ParseHitlDecisionKind(s string) (HitlDecisionKind, error)

ParseHitlDecisionKind normalizes a CLI decision string.

type HitlInterruptConfig

type HitlInterruptConfig struct {
	AllowedDecisions []HitlDecisionKind  `yaml:"allowedDecisions,omitempty" json:"allowedDecisions,omitempty"`
	Description      string              `yaml:"description,omitempty" json:"description,omitempty"`
	AllowedEditArgs  []string            `yaml:"allowedEditArgs,omitempty" json:"allowedEditArgs,omitempty"`
	DeniedEditArgs   []string            `yaml:"deniedEditArgs,omitempty" json:"deniedEditArgs,omitempty"`
	AllowedEditPaths []string            `yaml:"allowedEditPaths,omitempty" json:"allowedEditPaths,omitempty"`
	DeniedEditPaths  []string            `yaml:"deniedEditPaths,omitempty" json:"deniedEditPaths,omitempty"`
	AllowedEditTools []string            `yaml:"allowedEditTools,omitempty" json:"allowedEditTools,omitempty"`
	SwitchMap        map[string][]string `yaml:"switchMap,omitempty" json:"switchMap,omitempty"`
	RedactKeys       []string            `yaml:"redactKeys,omitempty" json:"redactKeys,omitempty"`
}

HitlInterruptConfig is per-tool review configuration at an approval gate.

type HitlInterruptValue

type HitlInterruptValue struct {
	Enabled bool
	Config  *HitlInterruptConfig
}

HitlInterruptValue is either enabled-with-defaults (true) or an explicit HitlInterruptConfig.

func (HitlInterruptValue) MarshalYAML

func (v HitlInterruptValue) MarshalYAML() (any, error)

MarshalYAML encodes as true or the config object.

func (*HitlInterruptValue) UnmarshalYAML

func (v *HitlInterruptValue) UnmarshalYAML(value *yaml.Node) error

UnmarshalYAML accepts `true` or a mapping for interruptOn entries.

type HitlPolicy

type HitlPolicy struct {
	// InterruptOn maps Tool metadata.name to true (defaults) or per-tool review config.
	// Does not gate tools by itself; see [HitlPolicy] package comment.
	InterruptOn map[string]HitlInterruptValue `yaml:"interruptOn,omitempty" json:"interruptOn,omitempty"`
	// InterruptOnPos is diagnostic metadata for interruptOn keys (issue #187).
	InterruptOnPos map[string]Pos `yaml:"-" json:"-"`
	// DescriptionPrefix prefixes every approval prompt (default [DefaultHitlDescriptionPrefix]).
	DescriptionPrefix string `yaml:"descriptionPrefix,omitempty" json:"descriptionPrefix,omitempty"`
	// ToolSwitchMap maps source operation to allowed target operations for switch decisions.
	ToolSwitchMap map[string][]string `yaml:"toolSwitchMap,omitempty" json:"toolSwitchMap,omitempty"`
	// RedactKeys masks top-level arg keys in approval prompts (merged with per-call redactKeys).
	RedactKeys []string `yaml:"redactKeys,omitempty" json:"redactKeys,omitempty"`
}

HitlPolicy configures human-in-the-loop approval gates (issue #106).

interruptOn keys are Tool metadata.name values. They do not independently gate tools; they supply per-tool review configuration (allowed decisions, edit rules, switchMap) when a call already requires approval via approvals.requiredFor or safety metadata.

type LimitExceedPolicy

type LimitExceedPolicy string

LimitExceedPolicy controls behavior when a byte limit is exceeded.

const (
	// LimitExceedTruncate shortens payload fields in-place (engine truncateMapInPlace) and records a limit-hit trace event.
	LimitExceedTruncate LimitExceedPolicy = "truncate"
	// LimitExceedFail aborts the step or run with a clear error.
	LimitExceedFail LimitExceedPolicy = "fail"
)

type LimitKind

type LimitKind string

LimitKind identifies which execution limit was evaluated (trace events, issue #117).

const (
	LimitKindToolInput  LimitKind = "tool_input"
	LimitKindToolOutput LimitKind = "tool_output"
	LimitKindCheckpoint LimitKind = "checkpoint"
)

type LoadError

type LoadError struct {
	Path   string
	Line   int // 1-based; 0 if unknown
	Column int // 1-based; 0 if unknown
	Msg    string
	Err    error
}

LoadError records a resource load or decode failure with file context (issue #3). Line/Column are set from yaml.Node when available; syntax errors with no Node are Path-only (issue #187 — no regex scraping of yaml.v3 error text).

func (*LoadError) Error

func (e *LoadError) Error() string

func (*LoadError) Unwrap

func (e *LoadError) Unwrap() error

Unwrap returns the underlying error for errors.Is / errors.As.

type MCPProviderConfig

type MCPProviderConfig struct {
	Enabled bool `yaml:"enabled,omitempty" json:"enabled,omitempty"`
}

type Metadata

type Metadata struct {
	Name        string            `yaml:"name" json:"name"`
	Labels      map[string]string `yaml:"labels,omitempty" json:"labels,omitempty"`
	Annotations map[string]string `yaml:"annotations,omitempty" json:"annotations,omitempty"`
}

Metadata is shared resource metadata (design doc §6.1).

type MissingRefError

type MissingRefError struct {
	Referrer ResourceID
	Missing  ResourceID
	Pos      Pos
}

MissingRefError reports a reference from Referrer to a missing resource (§9.1).

func (*MissingRefError) Error

func (e *MissingRefError) Error() string

type ModelProviderConfig

type ModelProviderConfig struct {
	Type       string `yaml:"type" json:"type"`
	APIKeyFrom string `yaml:"apiKeyFrom,omitempty" json:"apiKeyFrom,omitempty"`
}

type PolicyApprovals

type PolicyApprovals struct {
	RequiredFor []string `yaml:"requiredFor,omitempty" json:"requiredFor,omitempty"`
	// RequiredForPos is diagnostic metadata aligned with RequiredFor (issue #187).
	RequiredForPos []Pos `yaml:"-" json:"-"`
	// RequireAllTools gates every tool call when true (strict preset). Pointer preserves tri-state merge.
	RequireAllTools *bool `yaml:"requireAllTools,omitempty" json:"requireAllTools,omitempty"`
	// Permissive skips tool-call approval when true (permissive preset). Pointer preserves tri-state merge.
	Permissive *bool `yaml:"permissive,omitempty" json:"permissive,omitempty"`
}

type PolicyEffects

type PolicyEffects struct {
	Permit                []string `yaml:"permit,omitempty" json:"permit,omitempty"`
	PermitWithApproval    []string `yaml:"permitWithApproval,omitempty" json:"permitWithApproval,omitempty"`
	PermitPos             []Pos    `yaml:"-" json:"-"`
	PermitWithApprovalPos []Pos    `yaml:"-" json:"-"`
}

PolicyEffects lists effect identifiers a Policy permits (issue #190, ADR 002). permit is unattended allow; permitWithApproval is allowed only subject to approval. A missing or empty block permits nothing once any Tool declares spec.operations effects.

type PolicyExecution

type PolicyExecution struct {
	MaxWallClockSeconds     int     `yaml:"maxWallClockSeconds,omitempty" json:"maxWallClockSeconds,omitempty"`
	MaxTotalCostUsd         float64 `yaml:"maxTotalCostUsd,omitempty" json:"maxTotalCostUsd,omitempty"`
	RequireStructuredOutput bool    `yaml:"requireStructuredOutput,omitempty" json:"requireStructuredOutput,omitempty"`
}

type PolicyOverride

type PolicyOverride struct {
	Execution *PolicyExecution `yaml:"execution,omitempty" json:"execution,omitempty"`
	// Approvals merges extra requiredFor entries onto the named Policy (issue #171).
	// Overlay entries are unioned with the base list; empty overlay requiredFor is a no-op.
	Approvals *PolicyApprovals `yaml:"approvals,omitempty" json:"approvals,omitempty"`
}

type PolicyResource

type PolicyResource = Resource[PolicySpec]

MVP resource envelopes with concrete spec types.

type PolicySecurity

type PolicySecurity struct {
	NetworkAccess string `yaml:"networkAccess,omitempty" json:"networkAccess,omitempty"`
	SecretAccess  string `yaml:"secretAccess,omitempty" json:"secretAccess,omitempty"`
}

type PolicySpec

type PolicySpec struct {
	// Preset references a built-in policy preset (strict, permissive, shell_safe) as a base
	// for this Policy resource; local spec fields layer on top (issue #104).
	Preset string `yaml:"preset,omitempty" json:"preset,omitempty"`
	// ResolvedPreset is populated during [NormalizeProjectGraph] when a preset is expanded; not author YAML.
	ResolvedPreset string           `yaml:"-" json:"-"`
	Execution      *PolicyExecution `yaml:"execution,omitempty" json:"execution,omitempty"`
	Tools          *PolicyTools     `yaml:"tools,omitempty" json:"tools,omitempty"`
	Approvals      *PolicyApprovals `yaml:"approvals,omitempty" json:"approvals,omitempty"`
	// Effects is the static permit set for transitive tool effects (issue #190).
	Effects *PolicyEffects `yaml:"effects,omitempty" json:"effects,omitempty"`
	// Hitl configures human-in-the-loop approval gates for gated tool calls (issue #106).
	Hitl     *HitlPolicy     `yaml:"hitl,omitempty" json:"hitl,omitempty"`
	Security *PolicySecurity `yaml:"security,omitempty" json:"security,omitempty"`
}

func BuildPreset

func BuildPreset(name string) (PolicySpec, error)

BuildPreset returns a fresh PolicySpec for a built-in preset name.

func MergePolicySpec

func MergePolicySpec(base, overlay PolicySpec) PolicySpec

MergePolicySpec layers local policy fields on top of a preset base (issue #104).

func ResolvePolicySpec

func ResolvePolicySpec(pol *PolicySpec) (*PolicySpec, error)

ResolvePolicySpec expands Preset (when set) and returns the effective merged policy.

type PolicyTools

type PolicyTools struct {
	ForbidUnknownTools bool `yaml:"forbidUnknownTools,omitempty" json:"forbidUnknownTools,omitempty"`
}

type Pos

type Pos struct {
	File   string `json:"file,omitempty" yaml:"file,omitempty"`
	Line   int    `json:"line,omitempty" yaml:"line,omitempty"`
	Column int    `json:"column,omitempty" yaml:"column,omitempty"`
}

Pos is diagnostic source location on IR nodes (issue #187, ADR 003). It is metadata only — never identity. Fields on resources and steps use `json:"-" yaml:"-"` so Pos is stripped from canonicalResourceJSON, SpecHash, WorkflowSpecHash, and ResolvedGraphDigest. Zero value means unknown (machine-constructed resources).

func WorkflowCallPos

func WorkflowCallPos(st WorkflowStep) Pos

WorkflowCallPos is the diagnostic location of a workflow: field.

func (Pos) Errorf

func (p Pos) Errorf(format string, args ...any) error

Errorf prefixes format with p when p has a location; otherwise it is a plain formatted error.

func (Pos) IsZero

func (p Pos) IsZero() bool

IsZero reports whether p has no line or column (file-only is still unknown for underlining).

func (Pos) String

func (p Pos) String() string

String formats file:line:col for diagnostics. Empty if nothing useful is set.

type ProjectDefaults

type ProjectDefaults struct {
	Runtime string `yaml:"runtime,omitempty" json:"runtime,omitempty"`
	Model   string `yaml:"model,omitempty" json:"model,omitempty"`
	Policy  string `yaml:"policy,omitempty" json:"policy,omitempty"`
}

type ProjectGraph

type ProjectGraph struct {
	Meta         Metadata `yaml:"-" json:"-"`
	Pos          Pos      `yaml:"-" json:"-"`
	Spec         ProjectSpec
	Agents       map[string]*AgentResource
	Tools        map[string]*ToolResource
	Workflows    map[string]*WorkflowResource
	Policies     map[string]*PolicyResource
	Environments map[string]*EnvironmentResource
}

ProjectGraph is the merged in-memory view keyed by resource name (design doc §12.2).

func ApplyEnvironment

func ApplyEnvironment(g *ProjectGraph, envName string) (*ProjectGraph, error)

ApplyEnvironment returns a shallow copy of g with Environment overrides applied (design doc §7.6 MVP). Call after NormalizeProjectGraph so Project.spec.defaults are merged first; terfyn and [Runtime.Invoke] and [Runtime.Resume] receive a resolved config snapshot from the control plane.

func CloneProjectGraph

func CloneProjectGraph(g *ProjectGraph) (*ProjectGraph, error)

CloneProjectGraph returns a deep copy of g via JSON round-trip for snapshot isolation.

type ProjectProviders

type ProjectProviders struct {
	Models map[string]ModelProviderConfig `yaml:"models,omitempty" json:"models,omitempty"`
	Tools  *ProjectToolsProviders         `yaml:"tools,omitempty" json:"tools,omitempty"`
}

type ProjectResource

type ProjectResource = Resource[ProjectSpec]

MVP resource envelopes with concrete spec types.

type ProjectSpec

type ProjectSpec struct {
	Imports   []string                `yaml:"imports,omitempty" json:"imports,omitempty"`
	Defaults  *ProjectDefaults        `yaml:"defaults,omitempty" json:"defaults,omitempty"`
	Providers *ProjectProviders       `yaml:"providers,omitempty" json:"providers,omitempty"`
	State     *ProjectStateConfig     `yaml:"state,omitempty" json:"state,omitempty"`
	Traces    *ProjectTracesConfig    `yaml:"traces,omitempty" json:"traces,omitempty"`
	Telemetry *ProjectTelemetryConfig `yaml:"telemetry,omitempty" json:"telemetry,omitempty"`
	// Limits bounds tool I/O and checkpoint bytes for all workflows (issue #117).
	Limits *ExecutionLimits `yaml:"limits,omitempty" json:"limits,omitempty"`
}

type ProjectStateConfig

type ProjectStateConfig struct {
	Backend string `yaml:"backend,omitempty" json:"backend,omitempty"`
	DSN     string `yaml:"dsn,omitempty" json:"dsn,omitempty"`
}

type ProjectTelemetryConfig

type ProjectTelemetryConfig struct {
	Enabled       bool   `yaml:"enabled,omitempty" json:"enabled,omitempty"`
	ServiceName   string `yaml:"serviceName,omitempty" json:"serviceName,omitempty"`
	Endpoint      string `yaml:"endpoint,omitempty" json:"endpoint,omitempty"`
	ConsoleExport bool   `yaml:"consoleExport,omitempty" json:"consoleExport,omitempty"`
}

ProjectTelemetryConfig enables optional OpenTelemetry trace export (issue #108). SQLite traces remain the local source of truth; OTLP export is additive.

type ProjectToolsProviders

type ProjectToolsProviders struct {
	MCP *MCPProviderConfig `yaml:"mcp,omitempty" json:"mcp,omitempty"`
}

type ProjectTracesConfig

type ProjectTracesConfig struct {
	Backend         string                     `yaml:"backend,omitempty" json:"backend,omitempty"`
	RetentionDays   int                        `yaml:"retentionDays,omitempty" json:"retentionDays,omitempty"`
	RedactKeys      []string                   `yaml:"redactKeys,omitempty" json:"redactKeys,omitempty"`
	MaxPayloadBytes int                        `yaml:"maxPayloadBytes,omitempty" json:"maxPayloadBytes,omitempty"`
	Redaction       *ProjectTracesRedactionCfg `yaml:"redaction,omitempty" json:"redaction,omitempty"`
}

type ProjectTracesRedactionCfg

type ProjectTracesRedactionCfg struct {
	RedactKeys      []string `yaml:"redactKeys,omitempty" json:"redactKeys,omitempty"`
	MaxDepth        int      `yaml:"maxDepth,omitempty" json:"maxDepth,omitempty"`
	MaxBytes        int      `yaml:"maxBytes,omitempty" json:"maxBytes,omitempty"`
	MaxStringChars  int      `yaml:"maxStringChars,omitempty" json:"maxStringChars,omitempty"`
	MaxPayloadBytes int      `yaml:"maxPayloadBytes,omitempty" json:"maxPayloadBytes,omitempty"`
}

ProjectTracesRedactionCfg tunes sanitize/redact/truncate for trace payloads (issue #110).

type RefIndex

type RefIndex struct {
	AgentTools        map[string][]string
	AgentPolicies     map[string]string
	WorkflowAgents    map[string][]string
	WorkflowTools     map[string][]string
	WorkflowWorkflows map[string][]string
	WorkflowPolicies  map[string]string
}

RefIndex summarizes symbolic references between resources (issue #6, §9.1).

func BuildRefIndex

func BuildRefIndex(g *ProjectGraph) *RefIndex

BuildRefIndex scans ProjectGraph resources and builds RefIndex lookup tables.

type ResolvedExecutionLimits

type ResolvedExecutionLimits struct {
	MaxToolInputBytes      int
	MaxToolOutputBytes     int
	MaxCheckpointBytes     int
	MaxWorkflowNesting     int
	MaxLoopIterations      int
	ToolInputExceedPolicy  LimitExceedPolicy
	ToolOutputExceedPolicy LimitExceedPolicy
	CheckpointExceedPolicy LimitExceedPolicy
}

ResolvedExecutionLimits holds fully merged limits after precedence resolution.

func DefaultExecutionLimits

func DefaultExecutionLimits() ResolvedExecutionLimits

DefaultExecutionLimits returns built-in limits when project config omits a limits block.

func ResolveExecutionLimits

func ResolveExecutionLimits(project *ProjectSpec, workflow *WorkflowSpec, tool *ToolSpec) ResolvedExecutionLimits

ResolveExecutionLimits merges project, workflow, and tool limits with built-in defaults. Precedence (highest wins): tool > workflow > project > defaults.

type ResolvedOpEffects

type ResolvedOpEffects struct {
	Effects []string
	Unknown bool
}

ResolvedOpEffects is the fail-closed effect set of one operation.

func ResolveOperationEffects

func ResolveOperationEffects(toolName, operation string, spec *ToolSpec) ResolvedOpEffects

ResolveOperationEffects returns the fail-closed effect set for one operation. Unknown operations on a tool that declared others are still unknown (not empty-allow).

type ResolvedToolEffects

type ResolvedToolEffects struct {
	// ByOperation maps operation name to declared effect identifiers (sorted, unique).
	// Nil when Unknown is true.
	ByOperation map[string][]string
	// Unknown is true when the tool declared no effects. An empty effect set must not
	// be treated as "no effects / allow"; no policy permits this tool unless it opts in.
	Unknown bool
	// Message names the tool when Unknown is true.
	Message string
}

ResolvedToolEffects is the fail-closed effect model for a Tool (issue #188). It is independent of runtime CheckToolCall (ToolSafety + Policy until #190).

func ResolveToolEffects

func ResolveToolEffects(toolName string, spec *ToolSpec) ResolvedToolEffects

ResolveToolEffects applies fail-closed undeclared-effect semantics (issue #188). A tool with no declared effects carries an unknown effect that no policy permits.

type ResolvedToolSafety

type ResolvedToolSafety struct {
	Trusted          bool
	SideEffects      bool
	RequiresApproval bool
}

ResolvedToolSafety holds fully resolved safety flags after defaults and derivation.

func ResolveToolSafety

func ResolveToolSafety(s *ToolSafety) ResolvedToolSafety

ResolveToolSafety applies fail-closed defaults and derives requiresApproval when unset.

Derivation when requiresApproval is omitted:

  • trusted → does not require approval
  • untrusted and no side effects → does not require approval (read-only)
  • otherwise → requires approval

type Resource

type Resource[T any] struct {
	APIVersion string   `yaml:"apiVersion" json:"apiVersion"`
	Kind       string   `yaml:"kind" json:"kind"`
	Metadata   Metadata `yaml:"metadata" json:"metadata"`
	Spec       T        `yaml:"spec" json:"spec"`
	// Pos is diagnostic source location (issue #187). Never identity; omitted from hashes.
	Pos Pos `yaml:"-" json:"-"`
}

Resource is the apiVersion/kind/metadata/spec envelope for a typed spec (design doc §6.1).

type ResourceID

type ResourceID struct {
	Kind string `yaml:"kind" json:"kind"`
	Name string `yaml:"name" json:"name"`
}

ResourceID identifies a resource by kind and metadata name (design doc §12.2).

func (ResourceID) String

func (r ResourceID) String() string

String returns a stable identifier for logs and display (e.g. "Agent/reviewer").

type ShellTokenClass

type ShellTokenClass int

ShellTokenClass classifies the first token of a shell command for shell_safe policy.

const (
	ShellTokenUnknown ShellTokenClass = iota
	ShellTokenReadOnly
	ShellTokenGate
)

func ClassifyShellToken

func ClassifyShellToken(token string) ShellTokenClass

ClassifyShellToken maps the first command token to read-only, gate, or unknown (fail-closed → gate).

type ToolHTTP

type ToolHTTP struct {
	BaseURL string            `yaml:"baseUrl,omitempty" json:"baseUrl,omitempty"`
	Headers map[string]string `yaml:"headers,omitempty" json:"headers,omitempty"`
}

type ToolMCP

type ToolMCP struct {
	Transport string            `yaml:"transport,omitempty" json:"transport,omitempty"`
	Command   string            `yaml:"command,omitempty" json:"command,omitempty"`
	Args      []string          `yaml:"args,omitempty" json:"args,omitempty"`
	URL       string            `yaml:"url,omitempty" json:"url,omitempty"`
	Headers   map[string]string `yaml:"headers,omitempty" json:"headers,omitempty"`
}

type ToolOperation

type ToolOperation struct {
	Effects []string `yaml:"effects,omitempty" json:"effects,omitempty"`
	// Schema is a JSON Schema ref for this operation's input (the manifest's "operation → effects →
	// schema", completing #204). When set, a tool call's input is validated against it before
	// dispatch; absent means gradual (any input). Part of the capability manifest and identity.
	Schema string `yaml:"schema,omitempty" json:"schema,omitempty"`
	// Pos is the YAML map-key location of this operation (issue #187). Not identity.
	Pos Pos `yaml:"-" json:"-"`
	// EffectsPos is diagnostic metadata aligned with Effects (issue #187).
	EffectsPos []Pos `yaml:"-" json:"-"`
	// SchemaPos is diagnostic metadata for Schema (issue #187). Not identity.
	SchemaPos Pos `yaml:"-" json:"-"`
}

ToolOperation is one named operation on a Tool and the effects it may produce.

type ToolPermissions

type ToolPermissions struct {
	Allow []string `yaml:"allow,omitempty" json:"allow,omitempty"`
	Deny  []string `yaml:"deny,omitempty" json:"deny,omitempty"`
}

type ToolResource

type ToolResource = Resource[ToolSpec]

MVP resource envelopes with concrete spec types.

type ToolRetry

type ToolRetry struct {
	MaxAttempts int    `yaml:"maxAttempts,omitempty" json:"maxAttempts,omitempty"`
	Backoff     string `yaml:"backoff,omitempty" json:"backoff,omitempty"`
}

type ToolSafety

type ToolSafety struct {
	Trusted          *bool `yaml:"trusted,omitempty" json:"trusted,omitempty"`
	SideEffects      *bool `yaml:"sideEffects,omitempty" json:"sideEffects,omitempty"`
	RequiresApproval *bool `yaml:"requiresApproval,omitempty" json:"requiresApproval,omitempty"`
}

ToolSafety describes trust and side effects for policy fallback when no explicit Policy rule matches. Omitted fields resolve to fail-closed defaults via ResolveToolSafety.

func MergeMCPToolSafetyFlags

func MergeMCPToolSafetyFlags(flags ...*ToolSafety) *ToolSafety

MergeMCPToolSafetyFlags combines safety parsed from multiple MCP tool descriptors on one server. The merge is conservative (fail-closed): any untrusted, side-effecting, or approval-required descriptor makes the aggregate restrictive for that dimension. Returns nil when no recognized flags are present in any descriptor.

func MergeToolSafety

func MergeToolSafety(author, mcp *ToolSafety) *ToolSafety

MergeToolSafety combines author-set safety with MCP-discovered flags. Precedence: author (base) wins over MCP for each field that base sets explicitly.

func SafetyFromMCPMeta

func SafetyFromMCPMeta(meta map[string]any) *ToolSafety

SafetyFromMCPMeta maps MCP tool descriptor meta[MCPMetaFlagsKey] onto ToolSafety. Returns nil when meta is nil or carries no recognized flags.

type ToolSpec

type ToolSpec struct {
	Type        string           `yaml:"type,omitempty" json:"type,omitempty"`
	MCP         *ToolMCP         `yaml:"mcp,omitempty" json:"mcp,omitempty"`
	HTTP        *ToolHTTP        `yaml:"http,omitempty" json:"http,omitempty"`
	Permissions *ToolPermissions `yaml:"permissions,omitempty" json:"permissions,omitempty"`
	Retry       *ToolRetry       `yaml:"retry,omitempty" json:"retry,omitempty"`
	// Safety carries blast-radius metadata for fail-closed policy derivation (issue #103).
	Safety *ToolSafety `yaml:"safety,omitempty" json:"safety,omitempty"`
	// Operations declares per-operation named effects (issue #188, ADR 002). Additive to Safety.
	Operations map[string]ToolOperation `yaml:"operations,omitempty" json:"operations,omitempty"`
	// OperationsDeclared is true when the mapping included an `operations` key (even if empty). It
	// is the presence bit for the closed-world capability manifest (issue #204): an empty
	// `operations: {}` is a *closed* manifest that denies every operation, distinct from an omitted
	// `operations` (an open callable set, backward compatible). Because `Operations` is omitempty an
	// empty map serializes away, so this bit carries closedness — and it is **part of identity**
	// (`json:"operationsDeclared"`), not merely diagnostic: it flows into the normalized spec hash,
	// plan diffs, `NormalizedSpecJSON`, and `graphFromApplied`, so deleting `operations:` from a
	// locked tool is a visible plan change rather than a silent reopen, and the deployed manifest
	// reconstructed from applied spec (and the #207 snapshot) sees the same closed world runtime
	// enforces. Not author-settable (`yaml:"-"`); it is derived from key presence during load.
	// `omitempty` keeps the field absent (JSON unchanged) for the common open tool.
	OperationsDeclared bool `yaml:"-" json:"operationsDeclared,omitempty"`
	// Limits optionally overrides project execution byte limits for this tool (issue #117).
	Limits *ExecutionLimits `yaml:"limits,omitempty" json:"limits,omitempty"`
}

func (ToolSpec) MarshalYAML added in v0.1.93

func (s ToolSpec) MarshalYAML() (any, error)

MarshalYAML preserves the closed-empty capability manifest across YAML interchange (issue #204, ADR 003). Operations is yaml:"omitempty", so an empty operations map is dropped by the encoder, and OperationsDeclared is not a YAML field — so a plain marshal of a locked tool would emit no operations key and a reload would reopen the callable set. When the manifest is declared but empty, emit an explicit operations: {} so terfyn export → load round-trips to the same closed world that plan/apply identity and CheckToolCall enforce. A non-empty or undeclared manifest marshals exactly as the default encoder would (this only ever adds the empty mapping).

type WorkflowApprovalConfig

type WorkflowApprovalConfig struct {
	Description string   `yaml:"description,omitempty" json:"description,omitempty"`
	RedactKeys  []string `yaml:"redactKeys,omitempty" json:"redactKeys,omitempty"`
}

WorkflowApprovalConfig is optional review presentation on an approval step. These fields are not policy: they do not decide whether the step pauses.

type WorkflowApprovalValue

type WorkflowApprovalValue struct {
	Enabled bool
	Config  *WorkflowApprovalConfig
}

WorkflowApprovalValue is either enabled-with-defaults (true) or an explicit WorkflowApprovalConfig.

func (WorkflowApprovalValue) MarshalYAML

func (v WorkflowApprovalValue) MarshalYAML() (any, error)

MarshalYAML encodes as true or the config object.

func (*WorkflowApprovalValue) UnmarshalYAML

func (v *WorkflowApprovalValue) UnmarshalYAML(value *yaml.Node) error

UnmarshalYAML accepts `true` or a mapping for approval:.

type WorkflowInput

type WorkflowInput struct {
	Schema string `yaml:"schema,omitempty" json:"schema,omitempty"`
	// Resolved is the compiled JSON Schema loaded from Schema during validate (issue #193).
	Resolved *schema.Document `yaml:"-" json:"-"`
}

type WorkflowOutput

type WorkflowOutput struct {
	Value map[string]any `yaml:"value,omitempty" json:"value,omitempty"`
}

type WorkflowResource

type WorkflowResource = Resource[WorkflowSpec]

MVP resource envelopes with concrete spec types.

type WorkflowSpec

type WorkflowSpec struct {
	Description string           `yaml:"description,omitempty" json:"description,omitempty"`
	Runtime     string           `yaml:"runtime,omitempty" json:"runtime,omitempty"`
	Trigger     *WorkflowTrigger `yaml:"trigger,omitempty" json:"trigger,omitempty"`
	Input       *WorkflowInput   `yaml:"input,omitempty" json:"input,omitempty"`
	Policy      string           `yaml:"policy,omitempty" json:"policy,omitempty"`
	Steps       []WorkflowStep   `yaml:"steps,omitempty" json:"steps,omitempty"`
	Output      *WorkflowOutput  `yaml:"output,omitempty" json:"output,omitempty"`
	// Limits optionally overrides project execution byte limits for this workflow (issue #117).
	Limits *ExecutionLimits `yaml:"limits,omitempty" json:"limits,omitempty"`
}

type WorkflowStep

type WorkflowStep struct {
	ID    string `yaml:"id,omitempty" json:"id,omitempty"`
	Uses  string `yaml:"uses,omitempty" json:"uses,omitempty"`
	Agent string `yaml:"agent,omitempty" json:"agent,omitempty"`
	// Workflow names another Workflow resource in the project graph (issue #194, ADR 002).
	// The callee is statically named; with: maps to the callee's input and the callee's
	// output.value becomes this step's output. Exactly one of uses, agent, workflow, or approval.
	Workflow string `yaml:"workflow,omitempty" json:"workflow,omitempty"`
	// Approval marks a graph-node human pause (issue #195, ADR 002). true or a mapping
	// with optional description/redactKeys. Policy still gates tool-call approvals;
	// this field only says where the workflow suspends. XOR with uses, agent, workflow.
	Approval *WorkflowApprovalValue `yaml:"approval,omitempty" json:"approval,omitempty"`
	With     map[string]any         `yaml:"with,omitempty" json:"with,omitempty"`
	// Needs lists step IDs that must complete before this step runs (issue #192, ADR 002).
	// Edges are static and author-declared. Empty/omitted means:
	//   - if no step in the workflow declares needs, YAML order is an implicit chain
	//     (backward compatible sequential execution);
	//   - if any step declares needs, omitted needs means this step is a root
	//     (ready immediately, may run concurrently with other roots).
	Needs []string `yaml:"needs,omitempty" json:"needs,omitempty"`
	// Pos, UsesPos, AgentPos, WorkflowPos, ApprovalPos, and NeedsPos are diagnostic metadata only (issue #187).
	Pos         Pos   `yaml:"-" json:"-"`
	UsesPos     Pos   `yaml:"-" json:"-"`
	AgentPos    Pos   `yaml:"-" json:"-"`
	WorkflowPos Pos   `yaml:"-" json:"-"`
	ApprovalPos Pos   `yaml:"-" json:"-"`
	NeedsPos    []Pos `yaml:"-" json:"-"`
	// NeedsDeclared is true when the mapping included a `needs` key (even if empty). Because `Needs`
	// is omitempty, an empty declared list would serialize away, so this bit is **part of identity**
	// (`json:"needsDeclared"`), not merely diagnostic: it is the DAG-mode signal
	// ([WorkflowUsesExplicitNeeds]) — an empty `needs:` opts the whole workflow into graph mode /
	// concurrent roots — and a deployment snapshot (#207) must reproduce graph vs sequential
	// execution on resume. Mirrors [ToolSpec.OperationsDeclared]. Not author-settable (`yaml:"-"`);
	// derived from key presence during load. `omitempty` keeps JSON unchanged for the common
	// implicit-sequential step.
	NeedsDeclared bool `yaml:"-" json:"needsDeclared,omitempty"`
}

func (WorkflowStep) MarshalYAML added in v0.1.94

func (s WorkflowStep) MarshalYAML() (any, error)

MarshalYAML preserves the DAG-mode signal across YAML interchange (issue #207, ADR 003). Needs is yaml:"omitempty" and NeedsDeclared is not a YAML field, so a step whose only graph-mode signal is an empty declared `needs:` (a parallel root, or an .agent `parallel { }` root the lowerer sets NeedsDeclared on with empty Needs) would export without a needs key and reload as implicit sequential — silently switching concurrent roots to a chain. When needs is declared but empty, emit an explicit `needs: []` so terfyn export → load round-trips to the same graph mode (WorkflowUsesExplicitNeeds). A non-empty or undeclared needs marshals exactly as the default encoder would (this only ever adds the empty sequence). Mirrors ToolSpec.MarshalYAML.

type WorkflowTrigger

type WorkflowTrigger struct {
	Type string `yaml:"type,omitempty" json:"type,omitempty"`
}

Jump to

Keyboard shortcuts

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