Skip to content

Schema and stage specifications

The pipeline JSON Schema and the specifications of registered stages:

from stageflow.docs import generate_pipeline_schema, generate_stages_json, load_pipeline_schema
from stageflow import get_stages

schema = generate_pipeline_schema(get_stages())   # schema with the stage-name enum
stages = generate_stages_json(get_stages())       # stage specs for an editor

load_pipeline_schema() returns the schema without the injected enum; it is the one Pipeline.validate() uses. These two functions supply everything an external tool needs: an editor, a CI validator, a documentation generator.

The editor is one such tool. It holds no stages of its own: it asks a backend for the specs and draws the palette, the cards and the argument forms from them.

The prose in those specs — a stage's description and the description of each of its arguments and outputs — comes out in every language the build has, as a {locale: text} mapping, and the tool drawing it picks one. So a single dump serves every reader, and a language is not a reason to generate the file again. generate_stages_json(registry, locale="ru") collapses the prose to one language for a file meant to be read rather than drawn from — see Localization.

What this build can do

An editor is written against one version of the core and then pointed at whatever backend is running. The question it needs answered is not "which release is this" but "may I offer a map node here", so the core answers that one directly:

from stageflow import capabilities, __version__

capabilities()
# {"stageflow": "0.13.0",
#  "node_types": ["condition", "entry", "map", "parallel", "stage",
#                 "subpipeline", "switch", "terminal", "try"],
#  "stages": 17}

With a policy the answer narrows to what that caller may use, which is what a backend should serve rather than a description of itself:

capabilities(basic_plan)
# {"stageflow": "0.13.0",
#  "node_types": ["condition", "entry", "stage", "switch", "terminal"],
#  "stages": 5}

node_types is the registry itself, not a list written down beside it: a type registered by a plugin appears here too, and a name missing from it is exactly a name Pipeline.from_dict will reject with Unknown node type. That makes it something a client can branch on, which a version range is not — a build with a custom node type belongs to no range.

A backend is expected to hand this to its clients. The example backend serves it at GET /api/meta, together with the version of its own HTTP contract:

{ "api": 1, "stageflow": "0.13.0", "node_types": ["condition", "…"], "stages": 17 }

__version__ is read from the installed distribution. In a source checkout that was never installed it reads 0.0.0+unknown — deliberately not a plausible number, so that nobody compares it with one.

The editor working off a backend's specs