# How the Workflow Renderer Handles Schema Versions and Layout Contracts in Archify

> Discover how the Archify Workflow renderer manages schema versions and layout contracts with a migration layer for backward compatibility and semantic contracts for UI.

- Repository: [tt-a1i/archify](https://github.com/tt-a1i/archify)
- Tags: internals
- Published: 2026-09-01

---

**The Archify Workflow renderer decouples schema version detection from layout contract resolution, using a migration layer for backward compatibility and semantic contracts for UI structure.**

The `@archify/renderer` package implements a robust versioning system that allows workflow definitions to evolve without breaking existing implementations. This article examines how the renderer manages schema migrations and enforces layout contracts based on the source code architecture and test suite in `tt-a1i/archify`.

## Schema Version Detection and Migration

When a workflow JSON is loaded, the renderer first inspects the top-level `schemaVersion` field to determine the processing path.

**Current version workflows** (`schemaVersion: "2.0"`) proceed directly to validation.

**Legacy workflows** trigger an incremental migration pipeline. The migration logic is grounded in semantic contracts defined in the test suite, specifically `workflow-semantic-contract.test.mjs` and `workflow-migration.test.mjs`.

The migration layer applies transformations such as:

- Renaming deprecated fields
- Injecting default values for new required properties
- Restructuring nested objects to match current schema expectations

```javascript
// Migration hook illustrating the transformation pattern
// Actual implementation derives from semantic contract tests
export function migrateV1toV2(workflow) {
  // Rename fields, inject defaults, etc.
  workflow.schemaVersion = '2.0';
  workflow.layoutContract ??= generateDefaultLayout(workflow);
  return workflow;
}

```

## Layout Contract Resolution

After schema normalization, the renderer resolves the **layout contract** — a declarative specification defining how workflow nodes map to UI components. This contract operates independently from the logical workflow structure.

The contract validation follows rules established in `layout-rules.test.mjs`. Key contract properties include:

- `panels` — top-level container regions (header, main, sidebar)
- `columns` — width distributions within panels
- `widgets` — component placement mappings

When a layout contract is absent or incompatible, the renderer generates a default contract from the workflow's structural metadata.

```javascript
// Defining a custom layout contract
const customLayout = {
  panels: [{ id: 'header', position: 'top' }],
  columns: [{ id: 'main', width: '70%' }, { id: 'sidebar', width: '30%' }],
  widgets: [
    { id: 'taskList', panel: 'main' },
    { id: 'metadata', panel: 'sidebar' }
  ]
};

renderWorkflow(workflowJson, { layoutContract: customLayout });

```

## Version-Aware Rendering Pipeline

The complete rendering sequence follows five stages:

1. **Parse** — Deserialize workflow JSON and extract `schemaVersion`
2. **Migrate** — Apply version-specific transformations via semantic contract modules
3. **Validate** — Verify compliance against [`archify/schema/workflow.json`](https://github.com/tt-a1i/archify/blob/main/archify/schema/workflow.json)
4. **Apply Layout** — Resolve layout contract or generate fallback
5. **Render** — Produce the interactive UI view

```javascript
// Complete workflow loading and rendering
import { renderWorkflow } from '@archify/renderer';

async function loadAndRender(url) {
  const raw = await fetch(url).then(r => r.json());

  // Internal renderer behavior:
  // 1️⃣ Detect raw.schemaVersion
  // 2️⃣ Run migration steps if version < CURRENT_VERSION
  // 3️⃣ Validate upgraded object
  // 4️⃣ Resolve layoutContract (or fallback)
  // 5️⃣ Render UI
  const view = renderWorkflow(raw);
  document.body.append(view);
}

```

## Compatibility Guarantees in the Test Suite

The Archify renderer enforces backward compatibility through dedicated test files:

| Test File | Purpose |
|-----------|---------|
| `workflow-semantic-contract.test.mjs` | Defines semantic contracts governing schema migrations |
| `workflow-migration.test.mjs` | Validates end-to-end migration from older schema versions |
| `v1-compatibility.test.mjs` | Ensures legacy v1 workflows render correctly after migration |
| `layout-rules.test.mjs` | Validates layout contracts against renderer rule sets |
| `update-contract.test.mjs` | Confirms contract changes maintain backward compatibility |

These tests implement a **contract-first approach** where layout and schema evolutions must pass compatibility verification before release.

## Summary

- **Schema version detection** occurs at parse time, triggering migrations for legacy workflows
- **Semantic contracts** in the test suite (`workflow-semantic-contract.test.mjs`) define migration transformations
- **Layout contracts** separate visual structure from workflow logic, with fallback generation when absent
- **Compatibility tests** (`v1-compatibility.test.mjs`, `update-contract.test.mjs`) enforce stable evolution
- The rendering pipeline maintains five distinct stages from parsing to final UI output

## Frequently Asked Questions

### How does the renderer know which migration to apply?

The renderer reads the `schemaVersion` field and compares it against `CURRENT_VERSION`. Each intermediate version has a corresponding migration function in the semantic contract modules, applied sequentially until the workflow reaches the current schema.

### What happens if a workflow lacks a layout contract?

The renderer invokes `generateDefaultLayout()` to create a contract from the workflow's structural metadata. This ensures UI rendering succeeds even for minimal workflow definitions.

### Where are the layout contract validation rules defined?

Validation rules reside in `layout-rules.test.mjs` and are expressed as JSON-Schema constraints. These rules enforce valid panel configurations, widget placements, and responsive width distributions.

### Can custom layout contracts override the default behavior?

Yes. Pass a `layoutContract` option to `renderWorkflow()` as demonstrated in the code examples. Custom contracts undergo the same validation as generated defaults.