How Changes Are Classified in Archify's Architecture Delta: Semantic, Topology, and Geometry Detection
Archify's Architecture Delta turns two validated architecture snapshots into a deterministic proof by classifying every entity change into semantic, evidence, geometry, topology, or scope categories based on specific field differences.
Archify is an open-source tool that generates architectural diagrams and delta proofs between versions. Understanding how the Archify Architecture Delta classifies changes is essential for interpreting diff reports and automating architectural governance. The classification engine, implemented in archify/delta/architecture-delta.mjs, examines components, connections, and boundaries to categorize modifications at the field level.
The Five Classification Dimensions
The delta engine groups entity fields into five distinct classifications. Each entity type—Component, Connection, and Boundary—maps its internal fields to these classifications as defined in lines L151-L162 of the core delta module.
Component Classification Mapping
Components track identity through semantic and evidence fields, plus spatial positioning:
| Classification | Fields |
|---|---|
| semantic | type, label, sublabel, tag |
| evidence | sources |
| geometry | row, col, pos, size |
Connection Classification Mapping
Connections emphasize topology (endpoints) alongside semantic and routing geometry:
| Classification | Fields |
|---|---|
| topology | from, to |
| semantic | label, variant |
| geometry | fromSide, toSide, route, via, labelAt, labelDx, labelDy, labelSegment, width |
Boundary Classification Mapping
Boundaries track scope containment and padding adjustments:
| Classification | Fields |
|---|---|
| scope | wraps |
| geometry | pad |
Detecting Field-Level Changes with fieldChanges
The fieldChanges function (lines L141-L148) iterates over these classification groups to detect modifications. It compares normalized field values between before and after snapshots, returning both the classifications touched and the specific fields altered:
function fieldChanges(before, after, groups) {
const classifications = [];
const changedFields = [];
for (const [classification, fields] of Object.entries(groups)) {
const changed = fields.filter(
(field) => !equal(normalizedField(before, field), normalizedField(after, field))
);
if (changed.length) classifications.push(classification);
changedFields.push(...changed.map((field) => `/${field}`));
}
return { classifications: sorted(classifications), changedFields: sorted(changedFields) };
}
A classification is recorded if and only if at least one field in that group differs between snapshots. Changed fields are prefixed with / to indicate JSON Pointer paths.
Mapping Classifications to Human-Readable Statuses
Once classifications are identified, the statusFor function (lines L163-L168) derives the high-level change status. This mapping determines the final symbol displayed in delta reports:
function statusFor(classifications, kind) {
if (classifications.some(v => ['topology','semantic','scope'].includes(v))) return 'changed';
if (classifications.includes('evidence')) return 'evidence-changed';
if (classifications.includes('geometry'))
return kind === 'connection' ? 'rerouted' :
kind === 'component' ? 'moved' : 'geometry-changed';
return 'same';
}
This logic yields the following delta symbols:
+(added): New entity detected-(removed): Entity no longer present~(changed): Semantic, topology, or scope modificationevidence-changed: Onlysourceslist updated↔(moved/rerouted/geometry-changed): Pure geometry adjustment (components move, connections reroute, boundaries resize)
Orchestrating the Comparison with compareEntities
The compareEntities function (lines L170-L184) orchestrates the complete diff. It walks the union of entity IDs from both snapshots, invokes fieldChanges for matches, and assigns statuses:
function compareEntities(baseIndex, headIndex, kind, groups, describe) {
const changes = [];
const identityClassification = kind === 'connection' ? 'topology'
: kind === 'boundary' ? 'scope'
: 'semantic';
for (const id of sorted(new Set([...baseIndex.keys(), ...headIndex.keys()]))) {
const base = baseIndex.get(id);
const head = headIndex.get(id);
if (!base) changes.push({ ...describe(id, undefined, head), status: 'added', classifications: [identityClassification], changedFields: [] });
else if (!head) changes.push({ ...describe(id, base, undefined), status: 'removed', classifications: [identityClassification], changedFields: [] });
else {
const fields = fieldChanges(base, head, groups);
const status = statusFor(fields.classifications, kind);
if (status !== 'same') changes.push({ ...describe(id, base, head), status, ...fields });
}
}
return changes;
}
Entities existing in only one snapshot receive an identity classification (topology for connections, scope for boundaries, semantic for components) to mark them as added or removed.
Practical Usage Examples
Generating Delta Reports via CLI
Use the CLI entry point at archify/bin/archify.mjs to generate HTML delta proofs:
# Compare two architecture JSON files and emit an HTML delta
archify compare architecture \
snapshots/base.json snapshots/head.json \
--output examples/checkout-platform-delta.html
The generated HTML contains a Changes list displaying:
- Entity kind (Component / Relationship / Boundary)
- Status symbol (
+,-,~, or↔) - Classification list (e.g.,
semantic, geometry) - Exact changed fields (e.g.,
/label, /row)
Programmatic Access to Classifications
Import compareArchitecture directly to inspect classifications programmatically:
import { compareArchitecture } from './archify/delta/architecture-delta.mjs';
import base from './snapshots/base.json';
import head from './snapshots/head.json';
const receipt = compareArchitecture(base, head);
console.log(receipt.summary); // { added: 2, removed: 1, changed: 4, ... }
console.log(receipt.changes[0]); // { id:'c-42', status:'changed', classifications:['semantic','geometry'], changedFields:['/label','/row'] }
The receipt.changes array contains the complete classification payload for automation or custom reporting.
Summary
- Archify Architecture Delta uses five classifications (semantic, evidence, geometry, topology, scope) to categorize every architectural change.
- Field mappings are defined per entity type in
archify/delta/architecture-delta.mjs, lines 151-162. - The
fieldChangesfunction detects modified fields by classification group, whilestatusFormaps these to human-readable statuses likemoved,rerouted, orchanged. - Pure geometry changes emit distinct symbols (
↔) compared to semantic or topology changes (~), allowing precise communication of refactoring versus restructuring. - The deterministic comparison algorithm ensures consistent, reproducible delta proofs across CLI and programmatic interfaces.
Frequently Asked Questions
What is the difference between topology and semantic classifications?
Topology classifications track structural relationships—specifically the from and to endpoints of connections. Semantic classifications track meaning and identity, including labels, types, tags, and variants. A connection changing its endpoint receives a topology classification (status: changed), while a connection keeping the same endpoints but changing its label receives only a semantic classification.
How does Archify distinguish between a component moving versus a connection rerouting?
Both changes trigger the geometry classification, but the statusFor function (lines 163-168) checks the entity kind parameter. For components, geometry changes return moved; for connections, they return rerouted; for boundaries, they return geometry-changed. This distinction provides appropriate semantics for each entity type without requiring separate classification categories.
Can I customize which fields trigger specific classifications?
Currently, the field-to-classification mappings are hardcoded in the groups objects within compareEntities invocations (around lines 151-162). To customize classifications, you would need to modify the source in archify/delta/architecture-delta.mjs, specifically the groups parameter passed to fieldChanges for each entity type.
What happens if only the evidence/sources field changes?
If only the sources field differs, the entity receives an evidence-changed status rather than changed. This distinction allows reviewers to ignore updates that merely reflect new source code references (such as updated line numbers) while flagging actual architectural modifications for review.
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 →