Code Is A Projection
For decades we have behaved as though code is the software.
It is not.
Code is a projection of software.
That sounds abstract until you look at a rewrite. Replace a React application with SwiftUI. Replace a Node service with Rust. Replace a dashboard with a voice flow and an agent tool. Every file can change. Every function can change. The build system, package graph, runtime, and language can all change.
Yet if users can still authenticate, permissions are still enforced, the same state changes happen under the same authority, accessibility still works, latency remains inside the same promise, and every invariant still holds, then the software did not disappear.
The implementation changed.
The object survived.
The object was never the text. It was the set of identities, constraints, effects, proofs, and user-facing promises that the text happened to satisfy.
We have been versioning the shadow and calling it the object.
Login Flow
A durable object made from identity, state, policy, effects, interface obligations, and runtime proof.
components, hooks, routes
views, bindings, actions
prompts, flags, terminal output
capability, dry run, execution receipt
assertions and browser probes
human operating model
The Projection Mistake
Today's tools treat source code as the canonical representation.
Everything else is secondary.
Documentation is commentary. Tests are checks. Screenshots are artifacts. Accessibility trees are derived views. Agent plans are external instructions. Runtime telemetry is an after-the-fact observation. The running application is what the code produced this time.
That model is useful. It gives us editors, compilers, linters, diffs, packages, review, and deployment.
But it is too shallow for software that needs to move across languages, runtimes, interfaces, and agents.
Consider the login flow.
Where does it live?
Not in one file. Not in one function. Not even in one repository. It exists across routing, authentication, browser behavior, UI state, storage, analytics, accessibility semantics, operational policy, tests, docs, and user expectation.
The code is one place where that reality becomes visible.
It is not the reality.
- Identity
- login.start, login.complete, session.currentUserStable handles let different projections know they are talking about the same thing.
- Policy
- anonymous users may request auth; authenticated users may create a sessionAuthority is part of the software, not just a branch inside a handler.
- Effects
- issue token, update session, redirect, write audit eventThe outside world touched by the flow has to remain bounded.
- Interface
- input method, focus path, error recovery, accessible nameThe user-facing shape is a semantic obligation, not decoration.
- Proof
- type gate, auth gate, browser probe, accessibility snapshot, receiptA projection is trusted only when it can explain what survived.
The Shape Beneath The Code
Every representation reveals part of the same underlying object.
A compiler projects it as an executable program. A browser projects it as DOM, pixels, events, layout, focus, and network effects. A screen reader projects it as accessibility nodes and actions. A test suite projects it as executable claims. Git projects it as lines. An agent projects it as a plan with possible actions.
None of those views is the whole software.
They are lenses.
This is why the question "what changed?" is often badly formed. A line changed. A function changed. A layout changed. A dependency changed. But the more important question is which semantic claim changed.
Did identity change? Did authority change? Did observable behavior change? Did a proof go stale? Did the runtime promise narrow or widen? Did a projection lose something the old one could express?
That is the real diff.
A Projection Needs Receipts
If code is a projection, then a rewrite is not trusted just because it compiles.
It needs a receipt.
The receipt says what the projection claims to preserve, what it changed, which proof it produced, and where the target could not express the source without loss.
That is the difference between a translation and a semantic projection.
Translation produces new code.
Projection produces new code plus an account of the object that survived.
Why Merge Feels Blind
Traditional merge operates on text because text is treated as the object.
That gives us a useful baseline. Text has exact bytes, lines, spans, hashes, comments, and history. Those should not disappear.
But text is a low-resolution view of meaning.
When two people or agents edit the same feature, they rarely disagree about characters. They disagree about a semantic object from two angles.
One branch changes ownership. Another changes behavior. Another changes a public contract. Another moves layout. Another changes accessibility. Another changes performance. Text merge can notice overlap, but it cannot explain whether the same object still satisfies both branches.
Semantic merge starts from a different question:
is there a valid output projection
that satisfies base + branch A + branch B?That makes merge less like splicing files and more like admitting a new projection of the software object.
1export function LoginButton({ login, disabled }) {2 return (3 <button disabled={disabled} onClick={login}>4 Sign in5 </button>6 );7}Constraints Outlive Implementations
Implementations change constantly.
Constraints change slowly.
The user must be able to authenticate. Permissions must be enforced. Keyboard navigation must work. Sensitive data must not leak. Public contracts must not break silently. Payment authority must not widen because a UI was translated. A visual projection must not claim equivalence without runtime evidence.
Those are closer to the identity of the software than the implementation is.
Files are still useful. Text is still useful. Code review is still useful. The mistake is not using files. The mistake is letting the file be the deepest thing the system can name.
A serious semantic layer does not delete code. It puts code in its proper place.
Code becomes a renderer.
One renderer among several.
Code Is One Compilation Target
Once software is understood as a semantic object, code becomes one compilation target.
Not the only one.
The same object might project into React, SwiftUI, HTML, CSS, JavaScript, Rust, a CLI, a voice flow, a Playwright probe, a documentation page, an agent action, an audit timeline, or a temporary workbench for one incident.
That does not mean all projections are equally good. It means the system can ask a sharper question:
what form should this software take here,
and what proof does that form owe?That is the downstream change.
Software stops being a pile of files that occasionally produce behavior. It becomes a constraint-bearing object that can take different bodies under evidence.
This is why semantic merge, runtime proof, superset languages, plugin contracts, and shapeshifting interfaces are the same project at different scales.
They all require the same move:
stop treating the projection as the source of truth
start naming the object that projections must preserveFiles Still Matter
The lazy version of this argument says files go away.
They probably do not.
HTML did not disappear because the DOM exists. SQL did not disappear because query planners exist. Source code will not disappear because semantic graphs exist.
But source code can stop carrying the whole burden.
It can be a human-writable body. A lowering target. A review surface. A debugging surface. A portable serialization. A way to make the semantic object concrete enough to execute.
The deepest representation becomes the thing that survives translation, merge, refactor, runtime projection, agent delegation, and UI reshaping.
That is the object.
Code is how the object becomes executable in one world.
Software is what remains recognizable when that world changes.