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 viewBoxlegacyRequirementProbe(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 withmigrateWorkflowDocumentandserializeMigratedWorkflowarchify/renderers/workflow/workflow-compiler.mjs— Shared compiler for both v1 (fixed-v1) and v2 (readable-v2) layoutsarchify/renderers/workflow/workflow-migration-geometry.mjs— Geometry utilities includingcreateMappedWorkflowCandidate,intrinsicWorkflow, andplanningWorkflowarchify/test/workflow-migration.test.mjs— End-to-end test suite demonstrating valid migration patternsarchify/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
migrateWorkflowDocumentinarchify/migrations/workflow-v2.mjsis 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 originalviewBoxconstraints - 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →