How to Perform Semantic Checks on Archify Workflow Diagrams: A Complete Guide

Archify validates workflow diagrams against a semantic contract declared in the diagram's JSON source under the semanticChecks property, which supports allowedRoots, allowedTerminals, requiredEdges, and requiredPaths rules.

Archify's workflow renderer lets you enforce architectural correctness directly in your diagram definitions. By adding a semanticChecks block to your workflow JSON, you can prevent accidental orphan nodes, mandate critical dependencies, and guarantee reachability conditions—before the compiler ever produces an SVG.

What Are Semantic Checks in Archify?

Semantic checks in Archify are declarative constraints that validate the structure of your workflow graph. Unlike syntactic validation (which ensures your JSON is well-formed), semantic checks verify that the topology matches your intended design.

The contract is evaluated by semanticContractDiagnostics in archify/renderers/workflow/workflow‑compiler.mjs. This function runs automatically when you invoke archify compile workflow … and will abort rendering if any constraint is violated.

The Four Semantic Contract Fields

Your semanticChecks object can contain any combination of these optional fields:

  • allowedRoots — Node IDs permitted to have no incoming edge. Use this to declare intentional start nodes like "CI-trigger" or "Git Push".

  • allowedTerminals — Node IDs permitted to have no outgoing edge. Use this to declare intentional end nodes like "Deploy" or "Archive".

  • requiredEdges — Array of { from, to } objects that must exist exactly as authored edges. Use this to force direct dependencies.

  • requiredPaths — Array of { from, to } objects requiring a directed path (with any number of intermediate hops). Use this to enforce reachability without dictating the route.

How Semantic Validation Works

According to the Archify source code, semanticContractDiagnostics executes five validation passes:

  1. Collect node IDs and build adjacency maps from the nodes and edges arrays.

  2. Validate references — Any ID in the contract missing from the diagram triggers workflow/semantic-node-reference.

  3. Check unexpected roots/terminals — Unlisted nodes without incoming/outgoing edges raise workflow/unexpected-root or workflow/unexpected-terminal.

  4. Ensure required edges exist exactly as specified; missing edges produce workflow/required-edge.

  5. Verify required paths using breadth-first search; unreachable pairs generate workflow/required-path.

All failures are emitted as machine-readable diagnostics containing: code, message, subject (with path), evidence, and supportedFixes.

Writing a Workflow with Semantic Checks

Here is a complete, valid workflow JSON that uses all four contract fields:

{
  "schema_version": 2,
  "diagram_type": "workflow",
  "lanes": [{ "id": "dev", "label": "Dev" }],
  "nodes": [
    { "id": "trigger", "label": "Git Push", "lane": "dev", "col": 1 },
    { "id": "build",   "label": "Build",    "lane": "dev", "col": 2 },
    { "id": "test",    "label": "Test",     "lane": "dev", "col": 3 },
    { "id": "deploy",  "label": "Deploy",   "lane": "dev", "col": 4 }
  ],
  "edges": [
    { "id": "e1", "from": "trigger", "to": "build", "label": "" },
    { "id": "e2", "from": "build",   "to": "test",   "label": "" },
    { "id": "e3", "from": "test",    "to": "deploy", "label": "" }
  ],
  "semanticChecks": {
    "allowedRoots": ["trigger"],
    "allowedTerminals": ["deploy"],
    "requiredEdges": [{ "from": "build", "to": "test" }],
    "requiredPaths": [{ "from": "trigger", "to": "deploy" }]
  }
}

Compile with:

node archify/bin/archify.mjs compile workflow my.json out.html

This succeeds because:

  • Only trigger lacks an incoming edge (per allowedRoots)
  • Only deploy lacks an outgoing edge (per allowedTerminals)
  • The edge build → test exists (per requiredEdges)
  • A path exists from trigger to deploy (per requiredPaths)

Interpreting Semantic Check Failures

When a contract is violated, Archify produces detailed diagnostics. For example, omitting the build → test edge while keeping its requirement yields:

{
  "code": "workflow/required-edge",
  "message": "Workflow semantic contract requires edge \"build\" -> \"test\", but no authored edge matches it.",
  "subject": { "diagramType":"workflow", "from":"build", "to":"test", "path":"/semanticChecks/requiredEdges/0" },
  "evidence": { "authoredEdgeCount":3 },
  "supportedFixes": ["add an edge from \"build\" to \"test\" without deleting the semantic requirement"]
}

Fix options are explicit: add the missing edge, or remove the contract entry if the requirement is no longer valid.

Testing Semantic Contracts Programmatically

Archify's test suite in archify/test/workflow-semantic-contract.test.mjs demonstrates how to validate contracts in your own tests:

test('semanticChecks rejects an undeclared root', () => {
  const workflow = { /* … nodes/edges … */ };
  const result = compileWorkflow({ workflow, discoverFixes: false });
  assert.equal(result.diagnostics[0].code, 'workflow/unexpected-root');
});

Use this pattern to gate CI pipelines: compile workflows and assert diagnostics.length === 0 before allowing deployment.

Key Source Files for Semantic Checks

File Purpose
workflow‑compiler.mjs Contains semanticContractDiagnostics (lines 638–652), the core validation engine
workflow-semantic-contract.test.mjs Comprehensive test suite showing valid and invalid contract configurations
[workflow/README.md](https://github.com/tt-a1i/archify/blob/main/archify/renderers/workflow/README.md) Renderer documentation with field descriptions and examples
[examples/workflow-agent-tool-call.html](https://github.com/tt-a1i/archify/blob/main/examples/workflow-agent-tool-call.html) Live example demonstrating semantic contracts in production diagrams

Summary

  • Semantic checks in Archify are declared via the semanticChecks property in workflow JSON.

  • Four constraint types cover start nodes (allowedRoots), end nodes (allowedTerminals), direct dependencies (requiredEdges), and reachability (requiredPaths).

  • Validation runs at compile time via semanticContractDiagnostics in workflow‑compiler.mjs, blocking rendering on any violation.

  • Diagnostics are machine-readable with structured evidence and suggested fixes, enabling automated CI/CD integration.

  • Testability is built-in through the compileWorkflow API, letting you assert contract compliance programmatically.

Frequently Asked Questions

What happens if a node ID in my semantic contract doesn't exist?

Archify emits a workflow/semantic-node-reference diagnostic with the invalid ID and its location in the contract. The compiler treats this as a hard error and aborts rendering until the reference is corrected or removed.

Can I use semantic checks without lanes?

Yes. The semanticChecks contract operates on the graph structure formed by nodes and edges. Lanes are a visual organization feature and do not affect semantic validation logic.

How do requiredPaths differ from requiredEdges?

requiredEdges demands a direct, single-hop connection between two nodes, while requiredPaths only requires that a directed path exists—any number of intermediate nodes and edges may appear between the start and end. Use requiredEdges to enforce immediate dependencies; use requiredPaths to guarantee overall reachability without prescribing the route.

Will semantic checks slow down compilation?

No. According to the implementation in workflow‑compiler.mjs, validation uses efficient adjacency maps and BFS for path queries. The overhead is negligible for typical workflow sizes, and checks can be disabled for development if needed by omitting the semanticChecks property entirely.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →