How Archify Ensures Deterministic Compilation of Diagrams
Archify guarantees deterministic compilation through a canonical JSON normalization pipeline, stable comparison utilities, and a deterministic ZIP archive writer that produces byte‑for‑byte identical outputs on every run.
Deterministic compilation means that feeding the same source files into Archify always yields exactly the same artifact—critical for reproducible builds, CI caching, and reliable diffing. This article breaks down the five mechanisms implemented in the tt-a1i/archify repository that make this guarantee possible.
Canonical JSON Representation
Before any layout or rendering work begins, Archify transforms the workflow description into a normalized JSON object with strict ordering rules.
In archify/renderers/workflow/workflow-compiler.mjs, the compiler repeatedly applies Object.keys(value).sort(stableCompare) to every map structure. Arrays containing nodes, edges, phases, and groups are sorted by stable criteria such as node ID and edge key. This eliminates nondeterministic ordering that JavaScript's object property enumeration could introduce.
The result: the internal representation of your diagram is identical every time, regardless of how the original source file was structured.
Stable Comparison Helpers
All sort operations rely on a single source of truth for ordering: the stableCompare utility.
Exported from archify/renderers/shared/utils.mjs, this function provides a deterministic total order for strings, numbers, and mixed values. It ensures that every comparison yields the same result across platforms and Node.js versions—no floating‑point or locale‑dependent surprises.
This utility is invoked throughout the pipeline, from canonical JSON construction to ZIP entry sorting.
Deterministic ZIP Packaging
After HTML, SVG, and auxiliary assets are generated, Archify does not rely on standard ZIP utilities that iterate directories in filesystem order.
Instead, scripts/write-deterministic-zip.mjs implements a controlled packaging process:
- Walks the output directory and collects every file entry
- Sorts entries by their binary name using
Buffer.compare - Writes entries to the ZIP archive in that exact order
The sortedEntries function in this script ensures that the resulting .zip file is byte‑for‑byte identical each time the same source is compiled.
Explicit Stable Identifiers
Every structural element in an Archify diagram carries a stable, author‑derived identifier.
In archify/delta/architecture-delta.mjs, functions like sortedObjects and sortedBy construct canonical structures where each id field comes from author‑provided IDs or deterministic fallbacks. The compiler never generates IDs from layout positions, which would change when the diagram is re‑rendered with different dimensions or scaling.
This design choice prevents geometry‑dependent drift between builds.
Consistent Hashing for Artifact Verification
The generated HTML includes a deterministic hash block that records the hash of the compiled artifact. Because both the source data and its ordering are canonical, this hash remains constant across builds.
You can see this in action in scripts/gallery-template.html—the receipt view displays deterministic hashes that confirm reproducibility and enable tamper detection downstream.
Complete Compilation Example
Here is a runnable workflow that produces a deterministic ZIP output:
// Compile a workflow and produce a deterministic ZIP
import { compileWorkflow } from './archify/renderers/workflow/workflow-compiler.mjs';
import { execFileSync } from 'child_process';
import path from 'path';
import fs from 'fs';
// 1. Load a workflow JSON (author‑authored, stable IDs)
const workflow = JSON.parse(fs.readFileSync('my-workflow.json', 'utf8'));
// 2. Run the compiler – returns a fully-rendered HTML directory
await compileWorkflow(workflow, {
outDir: 'build/out',
// all internal sorts are deterministic, no extra options needed
});
// 3. Package the output deterministically
execFileSync('node', [
path.join('scripts', 'write-deterministic-zip.mjs'),
'build/out', // <directory to zip>
'my-workflow.zip' // <output file>
]);
Running this script repeatedly on the same my-workflow.json will always produce my-workflow.zip with an identical byte stream.
Key Files in the Determinism Pipeline
| File | Role in Deterministic Compilation |
|---|---|
scripts/write-deterministic-zip.mjs |
Sorts ZIP entries and writes them in reproducible order |
archify/renderers/workflow/workflow-compiler.mjs |
Canonical JSON construction, stable sorting of nodes/edges/groups |
archify/delta/architecture-delta.mjs |
Provides sortedObjects, sortedBy helpers for deterministic structure |
archify/renderers/shared/utils.mjs |
Implements stableCompare for total order across all sorts |
scripts/gallery-template.html |
Displays deterministic hash blocks that verify reproducibility |
Summary
- Canonical JSON normalization eliminates object ordering variance before any rendering occurs
stableCompareutility provides platform‑independent total ordering for all sort operations- Deterministic ZIP writer produces byte‑for‑byte identical archives by sorting entries before writing
- Stable identifier generation prevents geometry‑dependent ID drift
- Consistent hashing enables reliable caching and tamper detection in CI pipelines
Together, these mechanisms make Archify suitable for environments where reproducible builds are mandatory.
Frequently Asked Questions
Why does deterministic compilation matter for CI pipelines?
Deterministic compilation enables reliable caching and meaningful diffs in version control. When the same source always produces identical bytes, build systems can safely skip redundant work and developers can audit exactly what changed between versions. Without determinism, unrelated metadata like timestamps or filesystem ordering would create false positives in diffs and cache invalidations.
Does Archify require special configuration to enable deterministic output?
No. Determinism is built into the default compilation pipeline. You do not need to pass flags or configure sorting behavior. The compileWorkflow() function and write-deterministic-zip.mjs script apply canonical ordering automatically. The example code in this article runs with default options only.
What prevents JavaScript's object key ordering from breaking determinism?
Archify explicitly sorts every map structure using Object.keys(...).sort(stableCompare) before serializing or processing data. This happens in workflow-compiler.mjs for structural elements like nodes and edges. By not relying on JavaScript's insertion‑order guarantees or enumeration behavior, the compiler ensures cross‑platform consistency.
Can I verify that my Archify build is truly deterministic?
Yes. Run the compilation pipeline multiple times on identical source and compare hashes. The deterministic hash block embedded in the generated HTML (visible in gallery-template.html) provides a quick verification. For deeper inspection, use sha256sum or similar tools on the output ZIP—the checksum should match across runs.
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 →