The Lockfile Is A Causal Graph
Lockfiles look like generated text, so teams often treat them as annoying merge debris.
That is the wrong model.
A lockfile is dependency evidence. It records the result of a resolver running under a set of constraints: manifests, version ranges, peer sets, platform filters, registry metadata, integrity hashes, package-manager rules, and sometimes install scripts. The text is just the serialization.
If two branches edit dependency state at the same time, a line conflict is often the least interesting part of the problem.
The Lockfile Has Parents
A source file usually has one obvious parent: the previous source file.
A lockfile has many.
package.json
workspace manifests
version ranges
peer dependency constraints
engine and platform fields
registry metadata
package manager version
resolution policyThose parents matter because the same visible version can mean different things under different causes. A package can resolve because a direct dependency changed, because a peer set changed, because a transitive package was deduped differently, or because the package manager changed its resolver.
Semantic merge should not ask only whether the lockfile text can be combined.
It should ask what resolution changed and why.
Concurrent Dependency Edits Are Not All The Same
Two dependency changes can commute.
One branch adds a dev-only linter. Another branch adds a runtime package in a separate workspace. If the resulting graph has no shared peer set, no shared transitive path, and no install-policy conflict, the merge can probably be admitted after a re-resolution and install proof.
Other edits do not commute.
One branch upgrades React. Another branch adds a package with a narrow React peer range. A text merge might succeed, but the resulting graph can be invalid, duplicated, or subtly different from either branch's tested environment.
Re-Resolve, Then Compare
The safest semantic dependency merge is usually not:
merge lockfile text
hope install worksThe safer shape is:
merge manifest intent
run the resolver from the merged head
compare the graph delta
run install and package gates
record the receiptThat is closer to how humans already fix lockfile conflicts. They do not carefully reason through every line by hand. They re-run the package manager, inspect the surprising changes, and run the project.
The missing piece is making that process explicit enough for a coordinator to admit or reject.
- Intent
- Add @acme/charts and upgrade viteThe manifest changes are the human-readable dependency intent.
- Parents
- base lock, worker lock, current head lockThe candidate has to say which dependency graph it was derived from.
- Graph delta
- 12 added, 4 replaced, 1 peer set changedThe review surface is compacted into semantic dependency changes.
- Proof
- install, audit policy, typecheck, focused package testsThe output is admissible only after the resolved graph has been exercised.
Package Managers Could Help More
Package managers already know most of this structure.
They know which manifests participated. They know why a package was selected. They know which peer dependencies were satisfied. They know whether a package is optional, platform-specific, linked, hoisted, or isolated. They know which package-manager version produced the file.
Semantic merge gets easier if package managers expose those facts as merge evidence instead of leaving every tool to reverse-engineer generated text.
The lockfile does not need to stop being text.
It needs a better receipt beside the text.
The Mental Model
A lockfile is a causal graph rendered as text.
The merge should preserve the rendered text, but it should review the graph.
That is the difference between "the conflict went away" and "the dependency world is still the one we meant to create."