CelinQ Insights · No. 50

Proof-Carrying Merges: How Automatic EA Conflict Resolution Can Explain Itself

An automatic merge you can't inspect is a decision you're asked to trust blindly. CelinQ writes down exactly why each one was safe, every time.

A NILUS perspective on collaborative modelling for Sparx Enterprise Architect

There is a particular kind of unease that comes from opening a shared document, a shared codebase, or a shared model and discovering that something changed while you were away — and that a piece of software, not a colleague, made the decision about what should happen. It does not matter how good the software's judgement usually is. The moment you cannot see why it decided what it decided, you are left with two unappealing options: audit the change by hand, which defeats the purpose of automation in the first place, or trust it and hope, which is a bad habit to build in any system that governs something as consequential as a shared architecture model. Enterprise architects, more than most professionals, are trained to be suspicious of exactly this kind of unexplained authority, because their entire discipline is built on being able to justify why a model looks the way it does. A merge engine that cannot answer "why did you decide that" is not a tool this audience should be expected to trust, no matter how good its track record is.

Why black-box merging is risky

The risk is not hypothetical. Automatic reconciliation of a shared model is exactly the kind of decision that, if wrong even occasionally, corrupts the thing everyone depends on being able to trust. A tool that silently decides "these two changes are compatible, I merged them" and turns out to be wrong even one time in a hundred has not saved its users a hundred small manual reviews — it has replaced them with the much worse job of discovering, weeks later, that some past merge quietly produced a model that does not actually reflect what either person intended, with no record of what happened or why. That failure mode is worse than the problem automation was meant to solve, because it is invisible until it isn't, and by the time it surfaces, the evidence needed to fix it may already be gone. Earlier articles in this series, including the piece on model-aware merge rules, describe a whole family of situations — a rename alongside a move, disjoint property writes, distinct tagged-value keys — where CelinQ merges automatically with real confidence. That confidence is only worth anything if it can be checked, not merely asserted.

A proof instead of a guess

CelinQ's answer is what the Fusion engine calls a proof-carrying merge. The term is precise rather than decorative: every time an automatic merge fires — every F0 proven merge and every F1 policy merge — the specific rule that proved the two changes compatible is written into the revision alongside the merged result itself. Nothing is recorded as simply "merged automatically." Each decision names the exact rule that justified it, and that rule is not a vague category; it corresponds to a specific, testable claim about which atoms each side actually touched. This record lives permanently in the workspace's decision history and is visible afterwards in the Control Plane's Fusion view, which lists open decisions awaiting a human alongside the recent auto-merges that never needed one — the same interface, the same level of visibility, whether the decision was made by a rule or by a person. There is no separate, quieter channel where automatic changes happen invisibly. Nothing about this pipeline touches an external AI service or leaves the server at any point; Fusion is a deterministic function that runs entirely inside the transaction that applies a change, which means an organisation can run CelinQ fully air-gapped and every one of these guarantees still holds exactly as described here.

DISJOINT_PROPERTY_WRITES, read plainly

Take the most common rule in practice as a concrete example of what a proof actually says. Two architects, working from the same base, each change a different scalar field of the same element — one corrects the Name, the other updates the Status as part of a lifecycle review. The rule that fires is DISJOINT_PROPERTY_WRITES, and what it asserts, precisely, is that the set of fields written by one side and the set of fields written by the other share no members. That is not a heuristic guess about how likely the two changes are to be compatible; it is a direct, checkable fact about which fields each ChangeSet actually touched, verifiable by looking at the two ChangeSets themselves. Anyone reviewing this decision later does not have to take the system's word that the merge was safe — they can see the rule name, know exactly what claim it makes, and confirm it against the recorded evidence if they choose to.

MAP_DISTINCT_KEYS, and where its boundary sits

Tagged values work as a map rather than a flat set of scalars, and the rule MAP_DISTINCT_KEYS makes the equivalent claim at that level: two architects added or changed different keys within the same element's tagged-value collection, and because the keys are distinct, both additions are retained. What makes this rule trustworthy is exactly where it refuses to apply. The moment two people write different values to the same key, the claim MAP_DISTINCT_KEYS makes is simply false, and the rule does not fire — the engine raises a MapKeyConflict capsule instead, because that is a genuine disagreement no proof can paper over. A rule that only ever fires when its claim is precisely and verifiably true, and stands aside the instant that claim would be false, is the difference between a proof and a convenient assumption.

CelinQ Control Plane Fusion view showing a proof-carrying auto-merge log entry, an F0-proven merge annotated with the rule codes DISJOINT_PROPERTY_WRITES and MAP_DISTINCT_KEYS.
The Control Plane's Fusion log, showing an F0-proven auto-merge with its rule codes attached. This is a demonstration workspace with fictional content, used to illustrate the interface.

This is what that record looks like in practice: not a bare "merged" entry, but a line that names the entity, the revision, the fusion level, and the specific rule or rules that made the automatic decision defensible. An administrator scanning this log after the fact is not being asked to trust a summary. They are looking at the same evidence the engine itself used to decide.

TREE_MOVE_PLUS_RENAME

The rule covered in most depth in the earlier piece on merge rules deserves a second look here specifically as a proof rather than as a mechanism. When one architect renames an element and another moves it, from the same base, TREE_MOVE_PLUS_RENAME asserts that the Name atom and the tree-parent atom are structurally independent — that combining a change to one with a change to the other cannot produce a result different from applying them in either order, because neither operation reads or depends on the value the other one writes. That is a claim about commutativity, and it is exactly the kind of claim that is easy to get wrong if you assume it rather than verify it for the specific pair of atoms involved. The reason CelinQ can state it with confidence is that the claim is checked in the engine's own test suite, one case per rule family, against the real merge logic rather than a simplified model of it — the same pure, deterministic function that runs in production, exercised directly rather than approximated.

DIAGRAM_DISTINCT_OBJECT_GEOMETRY

Diagrams extend the same logic to visual layout. When two architects reposition two different shapes on the same diagram — one moving a component box, another adjusting the placement of an interface lollipop elsewhere on the same canvas — the rule DIAGRAM_DISTINCT_OBJECT_GEOMETRY asserts that the geometry atoms belong to different diagram objects entirely, and merges both placements without asking anyone to choose. This matters because diagrams are exactly the kind of artefact where a cruder tool tends to overreact: a whole-diagram comparison sees two people who both "changed the diagram" and has no way to tell that from the inside, they changed two unrelated shapes. The rule's proof is, again, narrow and specific — it names the two distinct objects and confirms neither side's geometry write touched the other's — and it stops applying the instant both sides touch the same object's position, which is handled by a separate, more careful rule that decomposes the transform into a translation and a resize before deciding whether the two edits actually commute.

A proof that only ever claims exactly what it can verify, and says nothing at all the moment it cannot, is worth more than a heuristic that is right more often but cannot tell you which time it might be wrong.

Reproducible by construction, not just by claim

A proof is only as good as the thing that produced it, and it is worth being specific about what stands behind these particular proofs rather than treating "deterministic" as a marketing adjective. The Fusion engine that evaluates every one of these rules is written as a pure function of exactly three inputs — the recorded base state, the two divergent states, and the workspace's policy configuration — with no clock, no random number generator, and no network call anywhere inside it. Give it the same three inputs on any machine, at any time, and it produces the identical output every time, which is precisely what allows the rule matrix described throughout this series to be exhaustively unit-tested rather than merely trusted on the strength of a demo. Each rule family — disjoint writes, distinct map keys, move-plus-rename, geometry composition, and the rest — is exercised directly against this real engine in the test suite, not against a simplified stand-in, and the same classification logic that decides sequential-versus-concurrent runs identically whether the underlying store is SQLite or PostgreSQL. This is also what makes the earlier claim about air-gapped operation more than a compliance talking point: because nothing in this pipeline depends on an external service, a determinism guarantee tested once holds everywhere the engine runs, disconnected network or not.

This same discipline extends to how the whole pipeline is validated under load, not just rule by rule in isolation. CelinQ's Fusion benchmark drives a hundred thousand operations through the real store and the real merge pipeline from five concurrent simulated clients, with every source of randomness seeded so the run is fully reproducible — the same command, run again, produces the same numbers. The invariants that matter are asserted rather than merely reported: any silent loss of a client's work, any unwanted resurrection of a deleted entity, or any client failing to converge to the same final state as everyone else causes the run itself to fail outright. A proof-carrying merge that could only be trusted in isolated, hand-picked examples would not be worth much. One that has been exercised a hundred thousand times over, with the failure conditions defined precisely enough to catch it automatically if anything ever goes wrong, is a different kind of claim entirely — and it is the standard this article is arguing every vendor's automatic-merge claims, CelinQ's own included, should be expected to meet before anyone accepts them.

Invariant validation as the last line of defence

A rule proving two changes compatible is not the end of the pipeline. Before any merged state is committed, CelinQ runs a shadow validation pass against the model's structural invariants: that every referenced parent still exists, that every relationship and diagram-node endpoint still resolves to a real entity, that no containment cycle has been introduced, and that identity remains unique throughout. This is deliberately independent of the merge rules themselves — it is not asking "was this merge proven safe," it is asking "does the resulting model actually make sense as a model," which is a different question and one worth checking separately even after a rule has already fired. A proposed state that would violate one of these invariants is not applied; it becomes a ValidationRejected capsule instead, a second safety net that catches the class of error no per-rule proof was ever designed to catch. Proof-carrying merges are trustworthy partly because they are proven correct at the level of individual atoms, and partly because even a proven merge is still checked against the shape of the model as a whole before it is allowed to land.

Policy decisions carry their own label, not a borrowed one

Not every automatic merge is a proof in the strict F0 sense. Some situations — two conflicting moves of the same diagram object, or concurrent edits to the same free-text notes field — have no universally safe resolution, but a workspace administrator may decide that a specific convenience trade-off, such as letting the most recent geometry edit win or appending both notes edits together, is acceptable for their team. These are recorded as F1 policy merges, under rule names such as POLICY_LAST_WRITER_GEOMETRY or POLICY_NOTES_APPEND, and the naming is deliberate: a policy decision is never mislabelled as a proof. An auditor reading the revision history later can tell, at a glance, the difference between "this was merged because it was mathematically impossible for it to be wrong" and "this was merged because an administrator opted into a specific, named convenience trade-off for this workspace." The pattern that a policy-driven decision should always be traceable to the specific policy that authorised it, and should remain distinguishable from a proven merge even as workspace settings change over time, is central to why this record is trustworthy for governance purposes rather than merely convenient for debugging.

What "automatic conflict resolution" usually means, and what it means here

It is worth being direct about how this compares to the way "automatic conflict resolution" is often marketed elsewhere, because the phrase gets used for very different things. In a great deal of tooling, an automatic merge means the software applied a general heuristic — often, quietly, some variant of last-write-wins, or a similarity score that decided two changes were "probably fine" to combine — and the honest answer to "why did it do that" is that the heuristic said so, which is not really an answer at all. The broader case for treating conflict resolution as a genuine semantic problem, rather than a text-diffing exercise dressed up with a friendlier interface, is covered from first principles in the earlier piece on Enterprise Architect conflict resolution. What this article adds to that argument is narrower and more specific: it is not enough for a merge engine to be usually right. For a shared architecture model that a whole organisation depends on being accurate, it has to be able to show, for every automatic decision, exactly which specific, checkable claim justified it — and to say nothing at all, and ask a person instead, the moment that claim would not hold. That is a materially higher bar than "usually right," and it is the bar this entire series has been describing rule by rule.

Revision audit and why this matters at enterprise scale

None of this would matter much for a two-person team working from the same desk. It matters a great deal for the organisations this series is written for — public-sector and enterprise architecture practices where a model is a governed artefact, not a personal sketchpad, and where "why does this connector exist" or "who approved this element being renamed" needs a real answer months or years later, not a shrug. Every proof-carrying decision, automatic or manual, becomes part of the same ordered revision history that records everything else CelinQ tracks: who made a change, when, against what base, and — for every automatic merge — exactly which rule made it defensible to apply without asking a person first. This is what turns "the tool merged it" from an assertion the team has to take on faith into a claim an auditor can independently verify, entity by entity, rule by rule, against the actual recorded evidence. It is also what makes the harder cascading scenarios described in the earlier piece on root-cause conflict grouping auditable at all: when a single deletion produces a handful of related capsules, the fact that each one carries its own proof or its own evidence is precisely what lets a reviewer, or an auditor working after the fact, see that they share a root cause in the first place, rather than facing an anonymous pile of "conflicts" with no way to tell which belong together.

Proof-carrying does not mean the merge is guaranteed to match what an architect would have chosen by hand in every philosophical sense. It means the merge is guaranteed to be exactly what the named rule says it is — and that claim is checked, not assumed, every single time.

The honest limits

It would undercut everything argued above to pretend this approach automates away the need for human judgement, and it does not try to. The rule matrix behind proof-carrying merges is deliberately narrow: it proves a small, well-defined set of situations safe and stops decisively the moment a situation falls outside that set, handing it to a person as a capsule rather than stretching a rule to cover a case it was never designed for. That means the majority of genuinely interesting architectural disagreements — two people who both moved the same element to different destinations, two people who wrote different values to the same tagged-value key, a delete colliding with a concurrent edit — are, correctly, never proven automatically at all, and this series has spent its earlier articles arguing that this is exactly as it should be. An optional, server-administered AI layer can sit above this pipeline to offer a recommendation on those harder, F2-level cases — covered in a later article on AI-assisted conflict resolution — but it is worth being explicit here that this recommendation layer is separate from, and never a substitute for, the deterministic proofs described in this article. It is off by default, it never auto-commits an ambiguous change, and every one of the guarantees described above — the rule-based F0 and F1 decisions, the shadow validation, the complete audit trail — holds identically whether that optional layer is switched on, switched off, or unavailable because a workspace runs in sovereign, fully air-gapped mode. A merge engine that needed an external service to be trustworthy would not actually be trustworthy at all; proof-carrying merges are proof-carrying precisely because the proof lives entirely inside the deterministic engine, checkable by anyone, with or without anything else running alongside it.

That is, in the end, the point this five-article arc has been building towards. A rename and a move can merge themselves because the claim that they are independent can be proven, not merely assumed. A deletion colliding with an edit cannot merge itself, because no proof of safety is available, and the honest answer is a tombstone capsule with full evidence attached rather than a confident guess in either direction. A cascade of dozens of touched rows collapses to a handful of genuine decisions because the classification underneath is precise enough to tell noise from disagreement — and every one of those decisions, automatic or human, is written down clearly enough that nobody has to take the workspace's word for what happened. Trust, in a system like this, is not something you extend once and then stop checking. It is something the system re-earns on every single merge, by showing its work.