Archify Compare Command: Rollback Path and Atomic Commit Explained
The Archify CLI ensures safe architecture updates by validating artifacts before any file system changes, then committing atomically with automatic rollback on failure.
Archify is a CLI-driven visual-architecture engine that treats infrastructure diagrams as versioned artifacts. The compare command sits at the heart of its delivery workflow, enabling teams to diff architecture changes, validate receipt integrity, and commit updates—or fully reverse them—without leaving the system in a partial state. This article breaks down how the compare command's rollback path and atomic commit mechanism work together to prevent corrupted deployments.
How the Archify Compare Command Works
The compare command in archify/bin/archify.mjs takes two architecture artifacts—an HTML rendering and a receipt JSON—and produces a validated diff ready for commit. The CLI entry point delegates to compareComparePair, which orchestrates the entire workflow from parsing through potential rollback.
The command structure follows this pattern:
node bin/archify.mjs compare path/to/prev.html path/to/next.html
Under the hood, Archify extracts htmlCandidate and receiptCandidate from the provided paths, then subjects them to strict validation before any permanent changes occur.
Pre-Commit Validation: The Fail-Fast Gate
Before touching the file system, Archify validates the receipt JSON against multiple criteria:
completeness === 'complete'— ensures the architecture generation finishedchecksPassed === checkCount— confirms all quality gates passed
This validation lives early in archify/bin/archify.mjs (around line 677). If any check fails, the process aborts immediately with no side effects. This fail-fast design guarantees that invalid artifacts never reach the commit phase.
The validation step is critical for atomicity: by catching errors before the first write, Archify eliminates the need to undo partial work from malformed inputs.
Atomic Commit Implementation in commitComparePair
Once validation succeeds, control passes to commitComparePair, also defined in archify/bin/archify.mjs. This function implements true atomicity through a staged commit pattern:
async function commitComparePair({ htmlCandidate, receiptCandidate, outputPath, receiptPath }) {
const committed = [];
// Write the new HTML
await fs.promises.writeFile(outputPath, htmlCandidate);
committed.push({ label: 'HTML', path: outputPath });
// Write the new receipt
await fs.promises.writeFile(receiptPath, receiptCandidate);
committed.push({ label: 'Receipt', path: receiptPath });
}
The committed array serves as a transaction log. Every successful write is recorded with its label and path, enabling deterministic reversal if subsequent operations fail.
Staging and Finalization Strategy
While the simplified snippet above writes directly to target locations, the full implementation uses staging directories where possible, then performs atomic moves. This minimizes the window where files exist in an inconsistent state.
Automatic Rollback on Commit Failure
The rollback mechanism activates when any file operation throws. The catch block in commitComparePair implements reverse-order cleanup:
} catch (e) {
const rollbackErrors = [];
for (const item of [...committed].reverse()) {
try { await fs.promises.unlink(item.path); }
catch (err) {
rollbackErrors.push(`${item.label}: remove failed (${err.message})`);
}
}
// Surface error with rollback details
}
Key implementation details:
- Iteration in
reverse()order ensures dependency-sensitive cleanup (remove receipt before HTML if receipt depends on HTML location) - Each rollback attempt is wrapped in individual try/catch to continue past non-critical failures
- Accumulated
rollbackErrorsprovides complete visibility into what succeeded and what didn't
Error Taxonomy and Failure Modes
Archify distinguishes between two failure states with distinct error codes:
| Error Code | Meaning | When It Occurs |
|---|---|---|
delta/commit-failed |
Write operation failed, but rollback succeeded | Initial fs.writeFile or fs.rename throws, all committed items removed |
delta/commit-rollback-failed |
Write failed and rollback partially or fully failed | Cleanup of committed items encountered errors, system may be in inconsistent state |
This explicit taxonomy, defined in archify/bin/archify.mjs, enables operators to quickly assess severity and determine manual intervention needs.
Visualizing the Rollback Path: Exception Lanes in Architecture Diagrams
Archify's visual output reinforces the rollback concept through dedicated exception lanes in workflow diagrams. The workflow definition in archify/examples/deployment-release.lifecycle.json shows this structure:
- Node
"id":"rollback"with"lane":"exceptions" - Edge
"from":"ready" to "rollback"marked"variant":"security"
These visual elements serve two purposes:
- Engineering clarity — developers see recovery paths as first-class workflow components
- Auditability — reviewers can trace exactly where and how the system returns to known-good states
The UI layer (viewer.lens.compare and related scripts) highlights the rollback node, making the recovery path instantly identifiable in generated guides.
Practical Examples: Running Compare and Triggering Rollback
Successful Compare and Commit
# Compare an architecture to itself (demo mode)
node bin/archify.mjs compare \
examples/deployment-release.lifecycle.html \
examples/deployment-release.lifecycle.html
This executes the full validation and commit path when the receipt validates successfully.
Provoking Rollback for Testing
# Point to a non-existent receipt to trigger failure
node bin/archify.mjs compare \
examples/deployment-release.lifecycle.html \
missing/receipt.json
Expected output includes error code delta/commit-failed or delta/commit-rollback-failed with populated rollbackErrors array detailing cleanup results.
Integration with Smoke Testing
The scripts/package-smoke.mjs harness exercises the compare command in CI pipelines. It:
- Generates architecture artifacts
- Invokes
comparewith validation enabled - Asserts receipt integrity
- Verifies rollback behavior through intentional failure injection
This ensures the rollback path remains functional across releases.
Related Components and Test Coverage
| File | Responsibility | Rollback Relevance |
|---|---|---|
archify/test/guide.test.mjs |
Unit tests for generated guides | Verifies rollback nodes appear in visual output |
archify/recipes/scenarios.mjs |
High-level scenario definitions | Includes "rollback" as a recoverable signal type |
archify/examples/deployment-release.lifecycle.json |
Example workflow | Demonstrates exception lane structure |
Summary
- Fail-fast validation in
archify/bin/archify.mjsprevents invalid artifacts from reaching the file system - Atomic commit via
commitComparePairuses acommittedtransaction log for deterministic writes - Automatic rollback reverses successful operations in reverse order when failures occur
- Explicit error codes (
delta/commit-failedvsdelta/commit-rollback-failed) clarify recovery needs - Visual exception lanes in workflow diagrams make rollback paths auditable and reviewable
Frequently Asked Questions
How does Archify ensure no partial state during a failed compare?
Archify validates all inputs before the first file write, then records every successful operation in the committed array. If any subsequent write fails, the catch block iterates through committed in reverse order and removes each file. This guarantees either complete success or complete reversion—no intermediate states persist.
What is the difference between delta/commit-failed and delta/commit-rollback-failed?
delta/commit-failed means the initial commit operation failed but cleanup succeeded—the system returned to its original state. delta/commit-rollback-failed indicates a more serious condition where both the commit and the subsequent rollback encountered errors, potentially leaving the system in an inconsistent state requiring manual intervention.
Where is the rollback path visually defined in Archify workflows?
The rollback path appears as an exception lane in workflow JSON files like archify/examples/deployment-release.lifecycle.json. Look for nodes with "lane":"exceptions" and edges connecting failure states to the rollback node. The UI layer renders these in a distinct visual style to highlight recovery routes.
Can I test the rollback behavior without modifying source code?
Yes. Invoke node bin/archify.mjs compare with a non-existent receipt path or invalid JSON. This triggers validation or commit failure and exercises the full rollback mechanism. The scripts/package-smoke.mjs harness includes automated tests that verify this behavior in CI environments.
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 →