How to Migrate Archify Workflow Schemas from v1 to v2: Complete Migration Guide

Archify workflow schema migration from v1 to v2 is performed by the migrateWorkflowDocument function in archify/migrations/workflow-v2.mjs, which validates the source document, probes legacy layout capacity, plans a readable-v2 layout, maps column ranks, adjusts the view box, and returns a validated v2 document with full diagnostic reporting.

Archify stores workflow definitions as JSON documents that evolve through schema versions. Version 1 (v1) uses the fixed-v1 contract, while version 2 (v2) adopts the readable-v2 contract, which introduces a richer layout model and a new schema_version field. This guide walks through the complete Archify workflow schema migration process with production-ready code examples from the tt-a1i/archify repository.

How the Migration Function Works

The migrateWorkflowDocument function in archify/migrations/workflow-v2.mjs executes a deterministic 10-step pipeline. Each step surfaces detailed diagnostics if issues occur.

Step 1: Validate the Source Document

The incoming JSON is checked against the v1 schema using validateSchema. Any schema-validation errors abort the migration early and populate preExistingDiagnostics.

// From archify/migrations/workflow-v2.mjs
import { schemaDiagnostics, validateSchema } from './schema-diagnostics.mjs';

const preflight = validateSchema(workflow, 'fixed-v1');
if (!preflight.valid) {
  return { ok: false, preExistingDiagnostics: preflight.diagnostics };
}

Step 2: Detect No-Op Migrations

If the document already carries schema_version: 2, the function recompiles it to ensure the view box remains valid, skipping transformation.

// Lines 39-58 of workflow-v2.mjs
if (workflow.schema_version === 2) {
  const receipt = compileWorkflow(workflow);
  return { ok: true, document: workflow, noOp: true };
}

Step 3: Reject Unsupported Schema Versions

Any source with a schema_version other than 1 or 2 triggers a diagnostic with code migration/source-schema-version.

Step 4: Compile the Legacy Layout

The original v1 workflow is compiled with the legacy compiler (compileWorkflow) to obtain a baseline receipt at line 73:

const legacy = compileWorkflow(workflow, { layoutEngine: 'fixed-v1' });

Step 5: Probe Legacy Capacity

Two specialized probes strip away author-defined viewBox constraints to reveal true spatial requirements:

  • legacyLayoutProbe (lines 40-63): Generates a capacity-only workflow ignoring viewBox
  • legacyRequirementProbe (lines 65-72): Determines minimum required dimensions

This separation ensures the readable-v2 compiler sees real spatial needs, not author-imposed constraints.

Step 6: Plan a Readable-v2 Layout

The migration generates a readable-v2 layout using createReadableLayout. If auto-generation fails, it falls back to planningWorkflow:

// Line 88
const readableLayout = createReadableLayout(legacyProbe);

// Line 93 - fallback
if (!readableLayout.valid) {
  readableLayout = planningWorkflow(legacyProbe);
}

Step 7: Build the Horizontal Rank Map

createMappedWorkflowCandidate aligns legacy column centers (LEGACY_COLUMN_CENTERS) with newly planned column centers (lines 104-125). This guarantees identical node ordering after migration.

Step 8: Adjust the View Box

If the migrated document's meta.viewBox is too small for required capacity, it expands to meet the workflow/viewbox-capacity diagnostic threshold (lines 30-41 of the second half of workflow-v2.mjs).

Step 9: Final Validation

The migrated document is re-compiled and re-validated against the v2 schema (lines 44-66). Remaining diagnostics populate newSchemaDiagnostics.

Step 10: Return Structured Result

The result builder (lines 90-113) returns:

{
  ok: boolean,
  document: WorkflowV2 | null,
  preExistingDiagnostics: Diagnostic[],
  migrationDiagnostics: Diagnostic[],
  newSchemaDiagnostics: Diagnostic[]
}

Running the Migration in Practice

Basic Node.js Usage

import { readFileSync, writeFileSync } from 'fs';
import { migrateWorkflowDocument, serializeMigratedWorkflow } from './archify/migrations/workflow-v2.mjs';

// Load v1 workflow
const v1Json = readFileSync('my-workflow-v1.json', 'utf8');
const workflow = JSON.parse(v1Json);

// Execute migration
const result = migrateWorkflowDocument(workflow);

if (result.ok) {
  writeFileSync(
    'my-workflow-v2.json',
    serializeMigratedWorkflow(result.document)
  );
  console.log(`✅ Migrated: ${result.document.meta.title || 'untitled'}`);
} else {
  console.error('❌ Migration failed');
  process.exit(1);
}

Processing Batch Migrations

import { readdirSync } from 'fs';
import { migrateWorkflowDocument, serializeMigratedWorkflow } from './archify/migrations/workflow-v2.mjs';

const results = readdirSync('./workflows/v1')
  .filter(f => f.endsWith('.json'))
  .map(file => {
    const workflow = JSON.parse(readFileSync(`./workflows/v1/${file}`, 'utf8'));
    return { file, result: migrateWorkflowDocument(workflow) };
  });

const failures = results.filter(r => !r.result.ok);
const successes = results.filter(r => r.result.ok);

console.log(`Batch complete: ${successes.length} succeeded, ${failures.length} failed`);

Handling Migration Diagnostics

When result.ok is false, inspect three diagnostic arrays for actionable details:

Array When Populated Typical Codes
preExistingDiagnostics Invalid v1 source document schema/invalid-type, schema/required-field
migrationDiagnostics Failure during transformation migration/source-schema-version, layout/planning-failed
newSchemaDiagnostics Invalid v2 output workflow/viewbox-capacity, schema/unknown-field

Diagnostic Processing Example

function reportDiagnostics(result) {
  const all = [
    ...(result.preExistingDiagnostics || []),
    ...(result.migrationDiagnostics || []),
    ...(result.newSchemaDiagnostics || [])
  ];

  for (const d of all) {
    console.error(`[${d.severity.toUpperCase()}] ${d.code}: ${d.message}`);
    
    if (d.location) {
      console.error(`  at: ${d.location.path.join('.')}`);
    }
    
    if (d.supportedFixes?.length) {
      console.error(`  fixes: ${d.supportedFixes.join(', ')}`);
    }
  }
}

Key Source Files for Archify Workflow Schema Migration

Understanding these files helps debug complex migrations:

  • archify/migrations/workflow-v2.mjs — Core migration driver with migrateWorkflowDocument and serializeMigratedWorkflow
  • archify/renderers/workflow/workflow-compiler.mjs — Shared compiler for both v1 (fixed-v1) and v2 (readable-v2) layouts
  • archify/renderers/workflow/workflow-migration-geometry.mjs — Geometry utilities including createMappedWorkflowCandidate, intrinsicWorkflow, and planningWorkflow
  • archify/test/workflow-migration.test.mjs — End-to-end test suite demonstrating valid migration patterns
  • archify/renderers/shared/validator.mjs — Schema validation engine used for both input and output verification

Testing Your Migrations

The repository includes a test harness at archify/test/workflow-migration.test.mjs:

import { test } from 'node:test';
import { strict as assert } from 'node:assert';
import { migrateWorkflowDocument } from '../../migrations/workflow-v2.mjs';

test('v1 to v2 migration preserves node ranks', async () => {
  const v1 = {
    schema_version: 1,
    meta: { title: 'Test', viewBox: { x: 0, y: 0, width: 800, height: 600 }},
    nodes: [
      { id: 'a', column: 0, row: 0 },
      { id: 'b', column: 1, row: 0 }
    ],
    edges: []
  };

  const result = migrateWorkflowDocument(v1);
  
  assert.ok(result.ok, 'Migration should succeed');
  assert.equal(result.document.schema_version, 2);
  
  // Rank order preserved despite layout engine change
  const ranks = result.document.layout.nodes.map(n => n.rank);
  assert.deepStrictEqual(ranks, [0, 1]);
});

Run with: node --test archify/test/workflow-migration.test.mjs

Summary

  • migrateWorkflowDocument in archify/migrations/workflow-v2.mjs is the sole entry point for Archify workflow schema migration
  • The 10-step pipeline validates, probes legacy capacity, plans readable layouts, maps column ranks, and adjusts view boxes
  • Capacity-driven probes (legacyLayoutProbe, legacyRequirementProbe) ensure accurate spatial planning independent of original viewBox constraints
  • Horizontal rank mapping preserves node ordering across layout engine changes
  • Three diagnostic arrays provide granular failure analysis for CI/CD integration

Frequently Asked Questions

What happens if my v1 workflow has an invalid schema?

The migration aborts immediately with preExistingDiagnostics populated. Fix the source document and retry—no partial migration occurs.

Can I migrate directly from versions older than v1?

No. The migration rejects any schema_version other than 1 or 2 with diagnostic code migration/source-schema-version. Upgrade to v1 first using earlier migration tools if needed.

Why does my migrated workflow have a larger view box than the original?

The readable-v2 layout engine may require more space. The migration expands meta.viewBox to meet capacity requirements rather than cropping content, preserving intentional author padding where possible. Check diagnostic workflow/viewbox-capacity for details.

How can I verify a migration succeeded without manual inspection?

Assert result.ok === true, verify result.document.schema_version === 2, and confirm result.newSchemaDiagnostics is empty. The test suite in archify/test/workflow-migration.test.mjs provides reference assertions for automated validation.

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 →