# How Archify Semantic Checks Enforce allowedRoots, allowedTerminals, and requiredEdges in Workflow Diagrams

> Learn how Archify semantic checks enforce allowedRoots, allowedTerminals, and requiredEdges for robust workflow diagrams. Ensure your workflows are valid and complete.

- Repository: [tt-a1i/archify](https://github.com/tt-a1i/archify)
- Tags: how-to-guide
- Published: 2026-08-31

---

**Archify validates workflow diagrams through deterministic semantic checks that require at least one root node, at least one terminal node, and enforce reachability for all required edges.**

Archify is a **Node.js-based rendering and validation system** that enables agents to generate polished, interactive system maps from plain-language descriptions or Mermaid diagrams. At the heart of this pipeline is a **typed JSON intermediate representation (IR)** that must pass strict semantic validation before any artifact can be delivered. This article examines how Archify semantic checks for workflows—specifically `allowedRoots`, `allowedTerminals`, and `requiredEdges`—guarantee logical graph integrity.

## The Three Core Semantic Rules

When processing a **workflow** diagram type, Archify applies a semantic contract defined in `archify/test/workflow-semantic-contract.test.mjs`【3†L34-L52】. This contract enforces three non-negotiable constraints on the graph structure:

### 1. allowedRoots: Required Entry Points

Every workflow must declare **at least one root node**—the designated entry point where execution begins. Nodes lacking a declared root are rejected as orphan recoveries.

In the JSON IR, root status is declared with the `"root": true` property:

```json
{
  "id": "start",
  "label": "Start",
  "root": true
}

```

The validator scans all nodes and fails if zero roots are detected, emitting a diagnostic with a path like `/semanticChecks/roots`.

### 2. allowedTerminals: Required End States

Every workflow must contain **at least one terminal node** representing a successful or failure end state. Undeclared terminals cause immediate validation failure.

Terminal declaration uses the `"terminal": true` property:

```json
{
  "id": "end",
  "label": "Success",
  "terminal": true
}

```

The absence of terminals produces diagnostics indicating exactly which nodes should be tagged.

### 3. requiredEdges: Enforced Reachability

Edges marked with `"required": true` must be **reachable from a root to a terminal following the authored direction**. Missing required edges or unreachable required paths trigger precise diagnostics that specify the exact endpoints.

Consider this required edge definition:

```json
{
  "from": "build",
  "to": "deploy",
  "required": true
}

```

Archify verifies that a valid path exists from any root node, through this edge, to some terminal node. If `build` is unreachable or `deploy` dead-ends without reaching a terminal, the validator reports: *"required path that is not reachable in authored direction"* with the exact `/semanticChecks/requiredEdges/0/from` path【3†L34-L51】.

## Implementation: How Archify Semantic Checks Work

The validation pipeline operates in distinct phases after initial schema validation:

- **Graph Construction** – Archify builds a directed graph from the `nodes` and `edges` arrays in the JSON IR
- **Depth-First Search** – Starting from each declared root, the system traverses outbound edges to map reachable nodes
- **Root/Terminal Verification** – Presence of `root: true` and `terminal: true` tags is confirmed through direct node inspection
- **Required Edge Reachability** – For each edge with `"required": true`, the system confirms that a complete path exists from any root through the edge to any terminal

All diagnostics are **machine-readable** with `--json` output and include `supportedFixes` fields indicating exactly which modification resolves the failure—such as adding a missing root, declaring a terminal, or correcting edge directionality.

## Validating Workflows with Archify Semantic Checks

### Command-Line Validation Workflow

```bash

# Generate a starter workflow IR

node bin/archify.mjs guide "CI/CD pipeline with approval and rollback" --json > workflow.json

# Run validation with semantic checks enabled

node bin/archify.mjs validate workflow workflow.json \
  --quality showcase \
  --json

```

Validation output follows this structure when semantic checks pass:

```json
{
  "valid": true,
  "receipts": {
    "workflow": {
      "sha256": "a1b2c3...",
      "bytes": 2847
    }
  }
}

```

Or when failing, with actionable diagnostics:

```json
{
  "valid": false,
  "diagnostics": [
    {
      "message": "required path that is not reachable in authored direction",
      "path": "/semanticChecks/requiredEdges/1/from",
      "subject": {
        "edge": { "from": "deploy", "to": "rollback" }
      },
      "supportedFixes": ["add_edge", "declare_terminal"]
    }
  ]
}

```

### Delivering Validated Artifacts

Once validation passes, generate the final HTML artifact:

```bash
node bin/archify.mjs deliver workflow workflow.json \
  workflow.html \
  --quality showcase \
  --json

```

The `deliver` command writes the final HTML, emits receipts with SHA-256 hashes and byte counts, and optionally runs visual containment checks【4†L29-L34】.

## Complete Workflow Example Satisfying All Semantic Checks

This minimal workflow JSON passes all three semantic validations—`allowedRoots`, `allowedTerminals`, and `requiredEdges`:

```json
{
  "schema_version": 2,
  "type": "workflow",
  "meta": { "quality_profile": "showcase" },
  "nodes": [
    { "id": "start", "label": "Start", "root": true },
    { "id": "build", "label": "Build" },
    { "id": "test", "label": "Test" },
    { "id": "deploy", "label": "Deploy" },
    { "id": "success", "label": "Success", "terminal": true },
    { "id": "failure", "label": "Failure", "terminal": true }
  ],
  "edges": [
    { "from": "start", "to": "build", "required": true },
    { "from": "build", "to": "test", "required": true },
    { "from": "test", "to": "deploy", "required": true },
    { "from": "deploy", "to": "success", "required": true },
    { "from": "test", "to": "failure", "required": false }
  ]
}

```

Key properties ensuring compliance:
- **One root**: `"start"` has `"root": true`
- **Two terminals**: `"success"` and `"failure"` both declare `"terminal": true`
- **Required edges reachable**: All `"required": true` edges form a continuous path from `start` to `success`

## Source Files and Architecture

| File | Purpose |
|------|---------|
| `archify/bin/archify.mjs` | Core CLI entry point for generate, validate, and deliver commands【2†L1-L2】 |
| `archify/test/workflow-semantic-contract.test.mjs` | Test suite enforcing semantic rules with cases like *"semanticChecks rejects a missing required edge with its exact endpoints"*【3†L34-L52】 |
| [`archify/schemas/workflow.schema.json`](https://github.com/tt-a1i/archify/blob/main/archify/schemas/workflow.schema.json) | JSON schema defining `root`, `terminal`, and `required` fields |
| [`archify/SKILL.md`](https://github.com/tt-a1i/archify/blob/main/archify/SKILL.md) | Formal skill definition documenting delivery contracts and receipt formats【4†L29-L34】 |

## Summary

- **Archify semantic checks for workflows** enforce three structural invariants: at least one root (`allowedRoots`), at least one terminal (`allowedTerminals`), and reachability for all required edges (`requiredEdges`)
- Validation occurs in `archify.mjs validate` and runs automatically before `deliver` generates artifacts
- Diagnostics are machine-readable with precise paths like `/semanticChecks/requiredEdges/0/from` and include `supportedFixes` for automated repair
- The semantic contract is tested in `workflow-semantic-contract.test.mjs` and defined in the workflow JSON schema

## Frequently Asked Questions

### What happens if a workflow lacks a root node?

Archify rejects the workflow with a diagnostic indicating missing roots. The JSON output includes a path like `/semanticChecks/roots` and suggests adding `"root": true` to an appropriate entry-point node.

### Can a workflow have multiple terminal nodes?

Yes. Archify requires **at least one** terminal, not exactly one. Multiple terminals representing success, failure, or different end states are valid and common in production workflows.

### What distinguishes required edges from optional edges?

**Required edges** (`"required": true`) must lie on at least one complete path from a root to a terminal. **Optional edges** may be unreachable or form disconnected subgraphs without triggering validation failures.