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
- Variables
- func ApprovalPermissive(a *PolicyApprovals) bool
- func ApprovalRequireAllTools(a *PolicyApprovals) bool
- func ApprovalStepDescription(st WorkflowStep) string
- func BoolPtr(b bool) *bool
- func BuiltinPresetNames() []string
- func ClosestTag(candidates []string, wrong string) string
- func CollectWithStringValues(with map[string]any) []string
- func EffectCovers(declared, candidate string) bool
- func ExpandPresetsInGraph(g *ProjectGraph)
- func ExtractShellCommand(with map[string]any) string
- func FirstShellToken(command string) string
- func FormatStrictYAMLError(path string, err error) string
- func InterpolationStepRefs(s string) []string
- func IsBuiltinPreset(name string) bool
- func IsShellCommandOperation(operation string) bool
- func IsValidHitlDecisionKind(k HitlDecisionKind) bool
- func Levenshtein(a, b string) int
- func NormalizeExecutionLimits(l *ExecutionLimits)
- func NormalizePolicyEffects(pol *PolicySpec)
- func NormalizeProjectGraph(g *ProjectGraph)
- func NormalizeToolEffects(spec *ToolSpec)
- func NormalizeToolSafety(spec *ToolSpec)
- func ParseToolUses(uses string) (toolName string, ok bool)
- func ParseUnknownFieldLine(line string) (field, typeName string, ok bool)
- func RelocateFile(res any, file string)
- func ResolveMaxWorkflowNesting(project *ProjectSpec, workflow *WorkflowSpec) int
- func ResolveReferences(g *ProjectGraph) error
- func ResolvedPresetName(pol *PolicySpec) string
- func ShellCommandRequiresApproval(command string) bool
- func StepAncestorIDs(steps []WorkflowStep, i int) map[string]struct{}
- func StepIsApproval(st WorkflowStep) bool
- func StepNeedsIDs(steps []WorkflowStep, i int) []string
- func SuggestYAMLField(typeName, wrong string) string
- func TelemetryEnabled(g *ProjectGraph) bool
- func TraceRetentionDays(g *ProjectGraph) int
- func ValidateEffectIdent(id string) error
- func ValidateExecutionLimits(l *ExecutionLimits) error
- func ValidateOperationName(name string) error
- func ValidateProjectGraph(g *ProjectGraph, projectRoot string) error
- func WorkflowUsesExplicitNeeds(steps []WorkflowStep) bool
- type AdvertisedAgentTool
- type AgentConstraints
- type AgentIO
- type AgentMemory
- type AgentOverride
- type AgentResource
- type AgentSpec
- type Decoded
- type EnvironmentOverrides
- type EnvironmentResource
- type EnvironmentSpec
- type ErrUnknownPreset
- type ExecutionLimits
- type HitlDecisionKind
- type HitlInterruptConfig
- type HitlInterruptValue
- type HitlPolicy
- type LimitExceedPolicy
- type LimitKind
- type LoadError
- type MCPProviderConfig
- type Metadata
- type MissingRefError
- type ModelProviderConfig
- type PolicyApprovals
- type PolicyEffects
- type PolicyExecution
- type PolicyOverride
- type PolicyResource
- type PolicySecurity
- type PolicySpec
- type PolicyTools
- type Pos
- type ProjectDefaults
- type ProjectGraph
- type ProjectProviders
- type ProjectResource
- type ProjectSpec
- type ProjectStateConfig
- type ProjectTelemetryConfig
- type ProjectToolsProviders
- type ProjectTracesConfig
- type ProjectTracesRedactionCfg
- type RefIndex
- type ResolvedExecutionLimits
- type ResolvedOpEffects
- type ResolvedToolEffects
- type ResolvedToolSafety
- type Resource
- type ResourceID
- type ShellTokenClass
- type ToolHTTP
- type ToolMCP
- type ToolOperation
- type ToolPermissions
- type ToolResource
- type ToolRetry
- type ToolSafety
- type ToolSpec
- type WorkflowApprovalConfig
- type WorkflowApprovalValue
- type WorkflowInput
- type WorkflowOutput
- type WorkflowResource
- type WorkflowSpec
- type WorkflowStep
- type WorkflowTrigger
Constants ¶
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.
const ( PresetStrict = "strict" PresetPermissive = "permissive" PresetShellSafe = "shell_safe" )
Built-in policy preset names (issue #104).
const ( MCPMetaTrustedKey = "trusted" MCPMetaSideEffectsKey = "side_effects" MCPMetaRequiresApprovalKey = "requires_approval" )
MCP meta.mcp_flags field names (snake_case per MCP descriptor convention).
const ( KindProject = "Project" KindAgent = "Agent" KindTool = "Tool" KindWorkflow = "Workflow" KindPolicy = "Policy" KindEnvironment = "Environment" )
Kind names for MVP resources (design doc §6.2).
const APIVersionV0 = "agentic.dev/v0"
API version for MVP resources (design doc §6.1).
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.
const DefaultApprovalStepDescription = "Workflow step requires approval"
DefaultApprovalStepDescription is shown when an approval step omits description.
const DefaultHitlDescriptionPrefix = "Tool execution requires approval"
DefaultHitlDescriptionPrefix is shown before per-call review text when policy omits descriptionPrefix.
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.
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.".
const MCPMetaFlagsKey = "mcp_flags"
MCPMetaFlagsKey is the MCP tool descriptor meta key for safety flags (issue #125).
const MaxSuggestEditDistance = 2
MaxSuggestEditDistance is the maximum Levenshtein distance for YAML field typo suggestions.
Variables ¶
var ( ErrMultipleDocuments = errors.New("expected exactly one YAML document") ErrUnknownKind = errors.New("unknown resource kind") )
Sentinel errors for resource loading.
var AllHitlDecisionKinds = []HitlDecisionKind{ HitlDecisionApprove, HitlDecisionReject, HitlDecisionEdit, HitlDecisionSwitch, }
AllHitlDecisionKinds lists every supported decision in stable order.
var ErrUnknownField = fmt.Errorf("unknown field")
ErrUnknownField is returned when strict YAML decoding encounters an unrecognized key.
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 BuiltinPresetNames ¶
func BuiltinPresetNames() []string
BuiltinPresetNames returns sorted built-in preset identifiers.
func ClosestTag ¶
ClosestTag returns the nearest candidate tag within MaxSuggestEditDistance, or "".
func CollectWithStringValues ¶
CollectWithStringValues walks workflow step "with" values and yields string forms for interpolation scanning (maps and slices recurse shallowly).
func EffectCovers ¶
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 ¶
ExtractShellCommand reads a command string from a workflow step input map.
func FirstShellToken ¶
FirstShellToken returns the first whitespace-delimited token from a shell command string.
func FormatStrictYAMLError ¶
FormatStrictYAMLError turns yaml.v3 strict decode failures into path-qualified messages with optional "did you mean" hints (issue #112).
func InterpolationStepRefs ¶
func IsBuiltinPreset ¶
IsBuiltinPreset reports whether name is a built-in preset identifier.
func IsShellCommandOperation ¶
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 ¶
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 ¶
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 ¶
ParseUnknownFieldLine extracts the unknown field and type name from a yaml.v3 strict decode line.
func RelocateFile ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 AgentMemory ¶
type AgentOverride ¶
type AgentOverride struct {
Model string `yaml:"model,omitempty" json:"model,omitempty"`
Constraints *AgentConstraints `yaml:"constraints,omitempty" json:"constraints,omitempty"`
}
type AgentResource ¶
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 ¶
LoadResourceFile reads path and decodes exactly one YAML MVP resource.
func ParseResourceFromBytes ¶
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 ¶
APIVersion returns apiVersion 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).
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).
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 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 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 ¶
Errorf prefixes format with p when p has a location; otherwise it is a plain formatted error.
type ProjectDefaults ¶
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 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 ¶
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 ¶
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 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 ToolResource ¶
MVP resource envelopes with concrete spec types.
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
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 WorkflowOutput ¶
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"`
}
Source Files
¶
- agent_tools.go
- approval.go
- clone.go
- defaults.go
- doc.go
- effects.go
- environment.go
- errors.go
- hitl.go
- kinds.go
- limits.go
- loader.go
- normalize.go
- parser.go
- policy_expand.go
- policy_presets.go
- pos.go
- refindex.go
- refs.go
- resolve.go
- safety.go
- shell_tokens.go
- stamp.go
- strict_decode.go
- telemetry.go
- tool_yaml.go
- traces.go
- types.go
- validator.go
- wiring.go
- workflow_calls.go
- workflow_graph.go
- workflow_yaml.go
- yamlhint.go