SHAPE

SHIFT

Back to homepage

Identity Is The Merge Primitive

Semantic merge is often described as understanding code.

That is too vague.

The practical primitive is identity. The system needs to know whether two edits are touching the same thing, different things, or a thing whose name moved while its meaning stayed connected.

Across JavaScript, TypeScript, JSX, HTML, and CSS, the useful question keeps repeating:

what is this thing?
what points at it?
did the identity survive the edit?
Semantic merge starts by turning text into named regions that can be compared across branches.

Names Are Not Enough

A name can be stable while meaning changes.

A meaning can stay stable while the name changes.

That is why identity needs more than text:

export name
local binding
module specifier
type declaration
React key
HTML id
data key
selector target
CSS Module class map
token-list member

Each one gives the merge system a way to say whether a change is independent or overlapping.

Identity By Surface

Identity looks different on different surfaces.

Identity MatrixStable Meaning By Surface
SurfaceClaimRequired proofCurrent evidenceRoute
ProvedJS importBindings commuteLocal name plus module sourceImport set identityAdmit disjoint additions
RequiredTypeScript APIPublic shape is stableDeclaration identityExport, field, modifier, generic shapeGate public contract
RequiredJSX listChildren keep identityStatic React keysKey values and duplicate-key checkAdmit or block list proof
RequiredHTMLElement target is stableElement identityid, data key, ARIA relationship, token listsAdmit structural merge
MissingCSSRule reaches same targetSelector target graphSelector, cascade scope, CSS Module mapProve target or route runtime
Identity is not one field. It is the surface-specific handle the system can safely compare.

When the handle is stable, parallel edits can often commute.

When the handle is missing, the system should stop before pretending it knows the merge is safe.

Identity Enables Rebase

A text merge sees positions.

A semantic merge sees carried identity.

export interface User {  id: string;  fullName: string;  nickname?: string;} export function displayName(user: User) {  return user.nickname ?? user.fullName;} export function Profile({ user }) {  return <h2 data-user-id={user.id}>{displayName(user)}</h2>;}
RegionAgent AAgent BRelationshipRoute
Userpublic typeAdds nicknameRenames display fieldSame public contractTyped rebase
fullNamefield identityReads display valueOwns field renameDependency overlapRebase read through field identity
displayNamefunction identityIntroduces helperChanges field contractCompatible if helper adaptsGate output
data-user-idHTML identityPreserves element targetPreserves user identityStable rendered targetRuntime proof if behavior changes

Identity lets the system distinguish a true overlap from a text collision that can be carried forward.

The rebase is not magic.

It is the system saying: this worker edit was made against an old name, but the identity can be followed through the current head.

Identity Can Fail

Some identity evidence is strong.

Some is weak.

Some is absent.

Examples:

two JSX children share the same key
CSS selector reaches a different element set
HTML id is duplicated
CSS Module export map is missing
type alias preserves name but changes assignability
import specifier resolves to a different module

Those are not edge cases.

They are identity failures.

The right response is not to guess. The right response is to route: require a proof, split the task, ask a question, or block the merge.

The Mental Model

Semantic merge works when the system can keep hold of identity while the text moves.

Text tells us where bytes changed.

Identity tells us what changed.

Proof tells us whether the changed thing is still allowed to join the output.