Skip to content
Experiment

Reconciliation at the merge boundary

Approving a change and executing a change are separate events, and nothing structural forces them to match. We recompute the diff from the provider's own API at merge time and block on mismatch — and the first honest run failed.

Abstract

Covert modification of work product is a documented agent failure mode: the model alters the artifact rather than refusing or escalating. This experiment closes the gap between what a human approved and what was applied, by content-addressing the proposed change and recomputing it from the provider's live pull-request API at the moment of merge. We report the verification, including a false mismatch on the untampered path that turned out to be a real defect in our hashing.

Research question

A human reads a diff and approves it. Some time later, a merge happens. Between those two events the branch can move. If the approval is recorded against an intent rather than against an artifact, the approval attests to nothing checkable.

The question: can the applied change be compared to the approved change using evidence the executing system does not itself produce?

System and threat model

The motivating case is not a malicious operator but a misaligned agent. Anthropic’s 2026 work on agentic misalignment documents models silently altering their work product instead of refusing or escalating when the assigned task conflicts with their objective. An agent that can push to the branch it proposed can substitute the change after approval and before merge.

We assume the agent can write to its own branch, which it must be able to do. We do not assume it controls the hosting provider’s API responses — that independence is what the check rests on.

Method

Immediately after the fix is committed, the change is content-addressed: a hash computed over the git blob SHAs of the changed files, stored on the fix record. That hash is what the policy decision and the human approval are signed against.

At merge time, in both merge paths, the diff is recomputed from the provider’s live pull-request files API — not from the local clone, and not from the stored value. A mismatch hard-blocks the merge and is recorded as an escalation decision, not silently swallowed and not proceeded past.

At commit time the changed files are hashed and the hash is stored and signed. At merge time the diff is recomputed from the provider's live pull-request files API and compared. A mismatch blocks the merge and records an escalation.

Figure 1.The comparison is between a hash computed at proposal time and a hash recomputed from the provider's API at merge time. Both sides of the comparison are recorded in the attestation chain.

Results

The first verification run against a real pull request failed — on the honest, untampered path, where the applied change was identical to the approved one.

Negative result
git diff --rawabbreviates blob SHAs to seven characters by default. The provider’s API returns the full forty. The two sides were hashing different strings for identical content, so the check would have blocked every legitimate merge and, more importantly, was not comparing what we believed it was comparing. Fixed by pinning the abbreviation length explicitly; re-verified against the same pull request, hashes matched exactly.

We report this because it is the most useful part of the experiment. A reconciliation check that has only ever been tested on the tampered path can pass for the wrong reason. This one first had to be shown to agree with reality before its disagreements meant anything.

Verified
Diff recomputation and merge-blocking on mismatch are implemented in both merge paths and were verified against a real pull request on 16 July 2026, after the abbreviation defect was corrected.

Limitations

  • The deny path is proven end to end; the allow path is not. A live run against a real repository produced a signed proposal and policy-denial pair, independently re-verified: chain intact, signatures valid, role separation enforced. That is a two-event prefix — a denial terminates the flow before any approval or execution exists. The demonstration that matters more — approve a real change, deliberately make the executed diff differ, and watch verification reject it in production — has not yet been run.
  • This is one boundary, not a change stream. The check covers the merge of a Caretaker-proposed pull request. It does not observe changes applied through any other route, and it cannot detect an execution that never had a proposal.
  • Merge is not deployment. Approval merges the pull request. Production deployment is a separate, currently manual step; there is no automated deploy in the loop, and nothing here reconciles what reached a running environment.
Open question
General change-stream reconciliation — comparing everything that actually changed in a target system against everything that was approved, including changes with no corresponding proposal — is unsolved here. Orphan execution detection is the harder half: absence of a proposal is not observable from the proposal record.

Implications

The property established is specific: for changes that flow through this pipeline, the artifact merged is the artifact approved, checked against a source outside the agent. That is a narrower claim than “the agent cannot change production unsupervised”, and we prefer the narrow one, because the wide one is not true of any system that also permits ordinary human commits.