Skip to content

Concepts: Graph Resolution

Understanding how CUTIP resolves and validates the artifact graph is useful when debugging ref errors or building complex multi-group workspaces.


The pipeline

cutip/              WorkspaceDiscovery       CutipRegistry
*.yaml files   ──▶  parse + dispatch    ──▶  in-memory store
                    (by kind)                keyed by prefix/name

CutipRegistry       RefResolver              GraphValidator
                ──▶ resolve refs         ──▶ full graph walk
                    on demand                non-failing error collection

WorkspaceDiscovery

WorkspaceDiscovery walks the cutip/ directory, reads every .yaml / .yml file, and dispatches to the right model based on the kind field:

kind Model Registry prefix
ImageCard ImageCard images/
ContainerCard ContainerCard containers/
NetworkCard NetworkCard networks/
Unit Unit unit registry
Group Group group registry

Parse errors are non-fatal warnings — a malformed file is skipped and logged, not a hard crash. This lets you add work-in-progress YAMLs without breaking cutip tree.


CutipRegistry

The registry is an in-memory store with three namespaces:

  • cards — keyed by <prefix>/<name>, e.g. images/app, containers/db
  • units — keyed by unit name
  • groups — keyed by group name

The registry also stores _sources — a mapping from registry key to the source file path, used by cutip show and cutip tree to display file locations.


RefResolver

RefResolver is a thin lookup layer on top of CutipRegistry. It parses ref strings ("images/app", "containers/db"), maps the prefix to an expected model class, and returns the registered artifact or raises CutipRefError.

resolver.resolve("images/app")                # → ImageCard
resolver.resolve_card("containers/db", ContainerCard)   # → ContainerCard (type-checked)
resolver.resolve_unit("my-unit")              # → Unit

GraphValidator

GraphValidator performs a full semantic walk of the graph and collects all errors before reporting:

For each Unit:
  resolve containerRef → ContainerCard
    resolve imageRef   → ImageCard
    resolve networkRef → NetworkCard    (skipped when network_mode is set)

For each Group:
  resolve each unit ref → Unit
  check workflow.py exists on disk

Errors are collected into a ValidationResult(ok: bool, errors: list[str]). All errors are reported in one pass — you never fix one error only to discover the next.


Error types

Exception When raised
CutipParseError YAML file fails Pydantic validation
CutipRefError A ref: string points to a non-existent artifact
CutipValidationError Graph validation fails
CutipWorkflowError workflow.py raises an exception during execution

Full exception hierarchy: reference/exceptions.md