wfdot

package
v0.0.175 Latest Latest
Warning

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

Go to latest
Published: Jul 10, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package wfdot parses a workflow's fenced ```dot block into a neutral spec — the SINGLE DOT-to-spec path shared by the web diagram, the reviewer gater, and the commit/edit hooks (so the grammar is defined once, never copied). The model is node-centric: each DOT node is a step/state carrying an `agent`, each edge a transition, and the edge INTO a reviewer node (whose gate is prompt="@skill:NAME") carries that skill — so a story's status walks the nodes and entry to a reviewer node is the gated transition. See the satelle-agent-model principle.

Index

Constants

View Source
const DefaultDoneGate = "satelle-story-done-review"

DefaultDoneGate is satelle's conventional close gate. It is no longer MANDATED by Validate (sty_9a139c78): the done gate is whatever the workflow's `done` node declares, transparently — a workflow may name it, name another, or omit it entirely ("if the user breaks the process, so be it"). The name remains the convention init seeds and the docs reference.

View Source
const StepSummarySkill = "satelle-step-summary"

StepSummarySkill is the conventional step-review/summary skill. A workflow opts into per-transition step summaries by declaring a node whose gate is this skill (transparently, in the DOT), optionally marked mandatory=true. There is no hidden always-on summariser — the flow declares it (sty_9a139c78).

Variables

This section is empty.

Functions

func ToDOT

func ToDOT(body string) (string, bool)

ToDOT normalizes a workflow body to the DOT standard — the conversion satelle runs at ingest (create/upload). A body that already carries a fenced ```dot block is returned unchanged (changed=false). A body in the inline-YAML grammar is parsed and re-emitted: its `states:`/`transitions:` block is replaced by an equivalent ```dot graph (edge-centric — each gated transition keeps its gate as a reviewer_skill attribute), and the frontmatter, prose, and any other YAML block (e.g. guardrails) are preserved. ToDOT is idempotent.

func Validate

func Validate(spec Spec) []string

Validate checks a parsed workflow Spec for structural soundness, returning human-readable problems (empty = valid):

  • at least one state;
  • every transition endpoint is a declared state (no dangling edge);
  • at least one terminal state (a state with no outgoing edge);
  • a state named "done", if present, is terminal.

The done gate is NOT mandated: it is whatever the workflow declares (sty_9a139c78).

Types

type Spec

type Spec struct {
	States      []State
	Transitions []Transition
}

Spec is the parsed lifecycle: states and gated transitions.

func Parse

func Parse(body string) (Spec, bool)

Parse extracts the Spec from a workflow body's fenced ```dot block. ok is false when the body carries no dot block, so callers fall back to the inline-YAML grammar.

func (Spec) ExecutorPathToDoneSkills added in v0.0.12

func (s Spec) ExecutorPathToDoneSkills() []string

ExecutorPathToDoneSkills returns the `@skill:` prompts of PERFORMING nodes that lie on a path which can still reach "done", deduped and sorted. These are the rubrics that perform a step. Unlike reviewer gates — which degrade to advisory when their rubric is absent — a missing performer skill leaves the step unperformable, so its absence is the genuine wasted-work trap to catch at engagement. Empty when no "done".

func (Spec) IsPerformingState added in v0.0.134

func (s Spec) IsPerformingState(name string) bool

IsPerformingState reports whether the named state exists and performs work. An unknown name is not performing (false). Used by the dispatch lock-guard to verify a named agent's FROM state is genuinely engaged.

func (Spec) NonTerminalEngagingStates added in v0.0.150

func (s Spec) NonTerminalEngagingStates() []string

NonTerminalEngagingStates returns all states that are neither the start state (shape=Mdiamond) nor a terminal state (shape=Msquare), nor a cancel/exception sink (agent=reviewer with no outgoing edges). This reads the DOT shape markers directly — no hardcoded state names — so the hook's engagement check is configuration-over-code (sty_f3d5d4b8).

func (Spec) PerformingStates added in v0.0.134

func (s Spec) PerformingStates() []string

PerformingStates returns the names of every performing node (see IsPerforming), in declaration order — the workflow's engaged states.

func (Spec) ScopedReviewers added in v0.0.12

func (s Spec) ScopedReviewers(toStatus string) []string

ScopedReviewers returns the skills of DECLARED, edge-less reviewer nodes that gate the transition into toStatus — a reviewer node whose `on=` list includes toStatus or the wildcard "*". These are the workflow-declared always-on gates, replacing the old reviewer:always skill-tag scan so the DOT is the sole gating authority. The step-summary node is excluded: it is a post-transition summariser (run via Summarise), not a blocking gate. Sorted for a deterministic order.

func (Spec) Start added in v0.0.12

func (s Spec) Start() string

Start returns the workflow's initial state — the first declared state with no incoming transition (the Mdiamond entry, e.g. "backlog"). Empty when every state has an incoming edge (no clear start). The engagement edge leaves Start.

func (Spec) StepSummary added in v0.0.12

func (s Spec) StepSummary() (declared, mandatory bool)

StepSummary reports whether the workflow declares a step-summary node (a node whose gate skill is StepSummarySkill) and whether it is marked mandatory. The summariser runs only when declared — there is no hidden always-on summariser (sty_9a139c78).

type State

type State struct {
	Name     string
	Agent    string
	Terminal bool
	// Skill is the node's own `@skill:NAME` prompt — the executor rubric an
	// executor step performs, or the gate a reviewer node judges by (empty when
	// the node carries no prompt). Populated from the DOT grammar.
	Skill string
	// Mandatory is the node's `mandatory=true` attribute. For a step-summary node
	// it means the step summary is required (a failure is surfaced, not swallowed);
	// for other nodes it is advisory metadata. Populated from the DOT grammar.
	Mandatory bool
	// On is the node's `on="s1,s2"` (or `on="*"`) attribute — the target states a
	// declared, edge-less reviewer node gates as a blocking gate. Empty for an
	// ordinary node. `*` means every transition. This is the declarative
	// replacement for the old reviewer:always tag layer: the DOT, not a skill tag,
	// is the sole authority for which always-on gates run. Populated from the grammar.
	On []string
	// Shape is the node's DOT shape attribute — the visual classification the
	// authored DOT uses to mark start/terminal states (Mdiamond=start,
	// Msquare=terminal). Populated from the DOT grammar.
	Shape string
}

State is one workflow node. Terminal is true when no transition leaves it.

func (State) IsPerforming added in v0.0.134

func (st State) IsPerforming() bool

IsPerforming reports whether a node PERFORMS work — any node carrying a non-reviewer agent (the in-loop `executor` OR a named isolated agent a node allocates a step to, e.g. planner/coder/commit-push). A reviewer node judges, it does not perform; an agent-less node (a terminal marker) performs nothing. This is the dispatch lock-guard's predicate (internal/agentstep uses IsPerformingState to verify a named agent's FROM state is genuinely engaged) — NOT the edit-gate's engaged check, which has its own independent shape-derived predicate (NonTerminalEngagingStates, sty_f3d5d4b8). The two are deliberately separate: PerformingStates answers "which nodes dispatch work"; NonTerminalEngagingStates answers "which statuses count as in-flight for the edit gate" (non-start, non-terminal).

type Transition

type Transition struct {
	From   string
	To     string
	Skill  string
	Skills []string
}

Transition is a directed edge. Skills are the reviewer gates admitting entry to the target node, in order (empty = ungated); Skill mirrors the first for single-reviewer back-compat. An edge declares its gate(s) either edge-centric (`reviewer_skill="a,b"`) or in the NODE-CONSISTENT form (`agent=reviewer, prompt="@skill:a"`) — the same vocabulary a reviewer node uses (sty_be67919a); reviewer_skill wins when both are present.

Jump to

Keyboard shortcuts

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