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
- func ToDOT(body string) (string, bool)
- func Validate(spec Spec) []string
- type Spec
- func (s Spec) ExecutorPathToDoneSkills() []string
- func (s Spec) IsPerformingState(name string) bool
- func (s Spec) NonTerminalEngagingStates() []string
- func (s Spec) PerformingStates() []string
- func (s Spec) ScopedReviewers(toStatus string) []string
- func (s Spec) Start() string
- func (s Spec) StepSummary() (declared, mandatory bool)
- type State
- type Transition
Constants ¶
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.
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 ¶
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 ¶
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 ¶
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
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
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
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
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
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
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
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
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 ¶
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.