- Architecture
Stale tool results and business-state conflicts
Stale tool results need current intent, authority, deadlines, and atomic version checks. Run local SQLite race and retry fixtures.
- Author
Udit Goenka- Editorial date
- Reading time
- 27 min

TL;DR: A recent tool response can still be stale when an action executes. Bind approval to immutable intent, an authoritative state version, current authority, and a deadline; compare those inputs atomically with the write, and treat exact retries as historical evidence rather than renewed permission.
The agent reads an order, asks the caller to confirm a preference, and submits the update. Another process changed the order while the caller was answering. Repeating the original tool result more confidently cannot make it current.
The workflow-enforcement guide explains why conversational intent needs deterministic application boundaries. This guide focuses on the read-to-write interval. It provides a complete local SQLite reference with conditional mutation, an operation ledger, post-await checks, concurrency fixtures, rollback checks, and explicit remote-outcome limits.
The artifact changes only invented local rows inside temporary fixture databases. It does not call a CRM, reserve a real booking, or implement a distributed transaction. Its emitted report distinguishes a local commit, historical retry evidence, rejected stale work, and a remote outcome that remains unknown without an authoritative receipt.
Table of contents
- Keep stale results as evidence
- Distinguish age from business identity
- Make the comparison atomic
- Freeze the material proposal
- Check current authority as well as state
- Enforce deadlines after waiting for locks
- Run the complete local transaction reference
- Preserve exact retry semantics
- Read the concurrency and rollback fixtures
- Recheck after every asynchronous boundary
- Repair a conflict before asking again
- Keep remote outcomes explicitly unknown
- Choose a precise acceptance matrix
- Inspect the operation ledger
- Distinguish local failure and business conflict
- Preserve resource lifetime independently of transactions
- Design a focused integration replay
- Frequently asked questions
- Verify the write boundary first
Keep stale results as evidence
A tool result describes what the tool observed at a particular boundary. It can be correct at that moment and unsuitable for a later mutation. Preserve its version and provenance instead of treating a successful read as a standing invitation to write indefinitely.
A real protocol discussion about next-action hints raises concurrent mutation as a reason tool hints can become stale. That is practitioner context, not a benchmark of a specific implementation. The engineering consequence is to validate current authoritative state when the operation would take effect.
The retrieval-for-speech guide describes how retrieved facts become useful spoken answers. A next-action suggestion returned with those facts remains data. It cannot create permission, lock inventory, or approve a corrected request merely because the model finds it persuasive.
Keep the original read result available where authorized. A conflict should not erase the evidence that led to the proposal. The caller may need an explanation of what changed, and an engineer may need to distinguish a stale snapshot from a parser defect or an authorization failure.
The published reference models one delivery-preference update on a synthetic resource. Its business row has an authoritative integer version. A proposal carries the version it expects, while the write checks that version against the actual row under the same local transaction that performs the change.

Distinguish age from business identity
Age and version answer different questions. Age describes elapsed time under a declared clock. A business version identifies a particular state under the authoritative service's contract. A snapshot can be very recent and already superseded by another writer.
Do not replace the version comparison with a freshness window. A short time-to-live may be useful for admission or user experience, but it does not prevent a concurrent update inside that interval. Conversely, an old unchanged record might still have the expected version while requiring renewed approval under a separate deadline policy.
The cache-key guide explains why material context belongs in evidence identity. A cache hit must not collapse tenant, policy, resource, or current-intent distinctions. If a result lacks its required version, represent that metadata as missing rather than inventing a zero version.
The reference admits zero as a legitimate initial version. Its strict integer guard rejects booleans, negative values, and missing metadata. That distinction protects both correctness and diagnosis: an initial state is different from a producer that failed to supply the expected version at all.
Use the actual service's version semantics. A timestamp, sequence counter, ETag, and revision identifier are not interchangeable merely because they can be serialized as strings. Document which token the authoritative mutation checks and what a failed comparison means for the consuming workflow.
Make the comparison atomic
A separate read-before-write check leaves an interval in which another writer can change the resource. The authoritative mutation must enforce the precondition as part of the operation itself. A client observing a match cannot make that observation remain true through an unrelated later write.
RFC 9110 section 13.1.1 defines If-Match and strong entity-tag comparison for conditional requests. Section 15.5.13 describes the precondition-failed response. Use the actual resource server's documented conditional-update support rather than assuming that an ordinary GET followed by PUT provides equivalent protection.
The local example uses an SQL predicate on resource and expected version. It checks the affected-row count, advances the version only when the predicate matched, and records the operation result within the same transaction. No model-generated explanation can override a zero affected-row result.
PostgreSQL's transaction-isolation documentation describes concurrency behavior and serialization boundaries for that database. It is relevant design evidence, not a claim that this SQLite harness reproduces PostgreSQL's isolation implementation. Select and test the actual backend contract before porting the pattern.
The duplicate-booking guide addresses another race: business-intent deduplication across attempts. Version comparison protects against overwriting changed state, while an operation identity protects the retry semantics of one intended change. A deployment may need both.

Freeze the material proposal
Approval must cover stable material values. Keeping a caller's mutable dictionary inside an approved proposal allows later formatting or repair code to change the eventual request without creating a new approval. Copy supported values into an owned immutable shape before presenting or admitting the operation.
The example factory accepts a fixed set of scalar fields. It validates identity grammar, supported preference values, version, epoch, and deadline. The resulting frozen dataclass contains no nested mutable mapping. A source-dictionary mutation and direct field assignment are both exercised by the fixture.
Python's dataclass documentation makes clear that frozen assignment behavior is not recursive deep immutability or runtime annotation enforcement. The commit function therefore revalidates even a manually constructed proposal. A class name cannot replace actual field checks.
The literal identifier guide explains why resource identifiers must preserve their admitted characters. A normalization change can redirect the proposal to another record. Validate the supported literal before freezing it and keep display or spoken formatting separate from the authoritative payload.
The local intent digest covers the fixed action, subject, tenant, resource, and value. The authoritative approval record also binds the deadline and approved expected version. A caller cannot extend expiry or substitute a new expected version merely by creating another operation identity with the same visible preference.
Check current authority as well as state
A current business version does not establish permission. The subject's access may have been revoked, the session owner may have changed, or the caller may have repaired the current intent. Those conditions require separate current checks at the same protected boundary.
The caller-authentication guide separates verified identity, live session, and action-specific approval. This artifact assumes those external processes have populated a trusted local authority record. It does not verify credentials or let a model write the authority table.
OWASP's authorization guidance supports checking permissions on each request. The local transaction reads the current subject, tenant, authority epoch, revocation state, intent digest, approved version, and deadline before admitting a new mutation or historical retry response.
The authority epoch represents the current owner or policy generation in this bounded model. Production systems may require more fields, but they cannot omit the equivalent ownership check after asynchronous work. A late successful result from an old generation cannot authorize repaired intent in the new owner.
The spoken prompt-injection guide adds the trust boundary: transcript and tool-result content cannot create or broaden those fields. Keep the authority producer separate from untrusted suggestions about what the agent should do next.
Enforce deadlines after waiting for locks
A proposal can expire while waiting for a network response, an application queue, or a database lock. Checking the deadline before those waits does not establish that it remains valid when the operation actually reaches the write boundary.
The reference begins its immediate transaction and only then reads the trusted clock. That ordering matters because lock acquisition can block. The deadline comparison occurs inside the transaction that reads authority and mutates business state, rather than using a time captured before the database wait.
The audio-backpressure guide demonstrates a related final-admission principle for held media. Work can become stale while nothing else is queued. Here the object is a business proposal, and the deadline and authority must be checked at its actual protected submission point.
The fixture rejects at exact expiry, including a case that advances the clock while the coroutine is suspended. A newer operation identity does not renew the same expired approval. Renewing permission requires a fresh authoritative approval under the workflow's real confirmation contract.
Clock domains remain explicit. The example uses bounded nonnegative integer ticks supplied by a trusted test clock. It does not compare a monotonic deadline with a wall-clock timestamp or accept an untrusted request's idea of current time. A real adapter must define its own conversion and expiration policy.
Run the complete local transaction reference
Run the entire fence with Python's standard library and SQLite support. It creates temporary local databases, opens independent connections for the race fixture, executes conditional mutations, verifies rollback after an injected SQL failure, and closes owned connections on normal and exceptional exits.
The trusted authority record is synthetic setup. It represents a verified current approval supplied by an external controller, not a credential implementation. Every result emitted by the fence is actual local fixture output; no remote request, customer booking, or live concurrency benchmark is claimed.
import asyncio
from concurrent.futures import ThreadPoolExecutor
from contextlib import contextmanager
from dataclasses import dataclass, replace, FrozenInstanceError
from hashlib import sha256
import json
from pathlib import Path
import re
import sqlite3
from tempfile import TemporaryDirectory
from threading import Barrier
@dataclass(frozen=True)
class Proposal:
operation: str
subject: str
tenant: str
resource: str
value: str
version: int
epoch: int
deadline: int
def proposal(fields):
names = {'operation', 'subject', 'tenant', 'resource', 'value', 'version', 'epoch', 'deadline'}
if type(fields) is not dict or set(fields) != names:
raise ValueError('unsupported proposal shape')
for key in ('operation', 'subject', 'tenant', 'resource'):
if type(fields[key]) is not str or not re.fullmatch(r'[A-Za-z0-9_-]{1,48}', fields[key]):
raise ValueError('invalid identity')
if type(fields['value']) is not str or fields['value'] not in ('pickup', 'delivery'):
raise ValueError('unsupported value')
if any(type(fields[k]) is not int or not 0 <= fields[k] <= 1000000
for k in ('version', 'epoch', 'deadline')):
raise ValueError('invalid numeric evidence')
return Proposal(**fields)
def intent(p):
return sha256(json.dumps(['set_delivery', p.subject, p.tenant, p.resource, p.value],
separators=(',', ':')).encode()).hexdigest()
def payload(p):
return json.dumps([p.subject, p.tenant, p.resource, p.value, p.version, p.epoch, p.deadline],
separators=(',', ':'))
@contextmanager
def connection(path):
db = sqlite3.connect(path, isolation_level=None, timeout=5)
try:
yield db
finally:
db.close()
def initialize(path, p):
with connection(path) as db:
db.executescript('''
CREATE TABLE business(resource TEXT PRIMARY KEY, value TEXT, version INTEGER NOT NULL);
CREATE TABLE authority(resource TEXT PRIMARY KEY, subject TEXT, tenant TEXT,
epoch INTEGER, revoked INTEGER, intent TEXT,
deadline INTEGER, approved_version INTEGER);
CREATE TABLE operations(operation TEXT PRIMARY KEY, payload TEXT NOT NULL, version INTEGER NOT NULL);
''')
db.execute('INSERT INTO business VALUES (?, ?, ?)', (p.resource, 'unset', 0))
db.execute('INSERT INTO authority VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
(p.resource, p.subject, p.tenant, p.epoch, 0, intent(p), p.deadline, p.version))
def commit(path, p, clock):
if type(p) is not Proposal:
raise ValueError('proposal required')
proposal({name: getattr(p, name) for name in p.__dataclass_fields__})
with connection(path) as db:
with db:
db.execute('BEGIN IMMEDIATE')
now = clock() # Read after lock acquisition, not before waiting for it.
if type(now) is not int or not 0 <= now <= 1000000:
return {'status': 'invalid-clock'}
old = db.execute('SELECT payload, version FROM operations WHERE operation=?',
(p.operation,)).fetchone()
if old is not None and old[0] != payload(p):
return {'status': 'identity-conflict'}
a = db.execute('SELECT subject, tenant, epoch, revoked, intent, deadline, approved_version FROM authority WHERE resource=?',
(p.resource,)).fetchone()
if a is None or a[3] != 0:
return {'status': 'revoked-or-missing'}
if (a[0], a[1], a[2]) != (p.subject, p.tenant, p.epoch):
return {'status': 'authority-conflict'}
if (a[5], a[6]) != (p.deadline, p.version):
return {'status': 'approval-conflict'}
if now >= p.deadline:
return {'status': 'expired'}
if a[4] != intent(p):
return {'status': 'intent-conflict'}
if old is not None:
return {'status': 'historical-result', 'version': old[1], 'authorizes_new_work': False}
changed = db.execute('UPDATE business SET value=?, version=version+1 WHERE resource=? AND version=?',
(p.value, p.resource, p.version)).rowcount
if changed != 1:
return {'status': 'stale-version'}
new_version = p.version + 1
db.execute('INSERT INTO operations VALUES (?, ?, ?)', (p.operation, payload(p), new_version))
return {'status': 'committed', 'version': new_version}
async def after_wait(path, p, wait, clock):
await wait()
return commit(path, p, clock) # Final current evidence checked inside transaction.
def mutate(path, statement, parameters=()):
with connection(path) as db:
db.execute(statement, parameters)
def remote_without_receipt():
return {'status': 'unknown', 'next': 'authoritative-reconciliation-required'}
source = dict(operation='op-A', subject='subject-A', tenant='tenant-A', resource='order-A',
value='pickup', version=0, epoch=0, deadline=10)
p = proposal(source)
source['value'] = 'delivery'
assert p.value == 'pickup'
try:
p.value = 'delivery'
except FrozenInstanceError:
pass
else:
raise AssertionError('mutable proposal')
for key, bad in (('version', True), ('epoch', None), ('deadline', -1)):
try:
proposal({**source, key: bad})
except ValueError:
pass
else:
raise AssertionError('invalid metadata accepted')
reports = []
with TemporaryDirectory() as directory:
path = str(Path(directory) / 'local.sqlite')
initialize(path, p)
first = commit(path, p, lambda: 1)
assert first == {'status': 'committed', 'version': 1}
retry = commit(path, p, lambda: 1)
assert retry['status'] == 'historical-result' and not retry['authorizes_new_work']
assert commit(path, replace(p, value='delivery'), lambda: 1)['status'] == 'identity-conflict'
assert commit(path, replace(p, operation='op-B'), lambda: 1)['status'] == 'stale-version'
assert commit(path, replace(p, operation='op-C', deadline=20), lambda: 1)['status'] == 'approval-conflict'
assert commit(path, replace(p, operation='op-D', version=1), lambda: 1)['status'] == 'approval-conflict'
assert commit(path, replace(p, operation='op-E', epoch=1), lambda: 1)['status'] == 'authority-conflict'
assert commit(path, replace(p, operation='op-F'), lambda: True)['status'] == 'invalid-clock'
assert commit(path, p, lambda: 10)['status'] == 'expired'
mutate(path, 'UPDATE authority SET revoked=1')
assert commit(path, p, lambda: 1)['status'] == 'revoked-or-missing'
mutate(path, 'UPDATE authority SET revoked=NULL')
assert commit(path, p, lambda: 1)['status'] == 'revoked-or-missing'
reports.extend([first, retry])
with connection(path) as observed:
assert observed.execute('SELECT COUNT(*) FROM operations').fetchone()[0] == 1
try:
observed.execute('SELECT 1')
except sqlite3.ProgrammingError:
pass
else:
raise AssertionError('owned connection not closed')
try:
with connection(path) as failed_handle:
raise RuntimeError('synthetic owned-resource failure')
except RuntimeError:
pass
try:
failed_handle.execute('SELECT 1')
except sqlite3.ProgrammingError:
pass
else:
raise AssertionError('exception left owned connection open')
race = str(Path(directory) / 'race.sqlite')
initialize(race, p)
barrier = Barrier(2)
def contender(op):
barrier.wait()
return commit(race, replace(p, operation=op), lambda: 1)['status']
with ThreadPoolExecutor(max_workers=2) as workers:
raced = list(workers.map(contender, ('race-A', 'race-B')))
assert sorted(raced) == ['committed', 'stale-version']
rollback = str(Path(directory) / 'rollback.sqlite')
initialize(rollback, p)
mutate(rollback, "CREATE TRIGGER abort_record BEFORE INSERT ON operations BEGIN SELECT RAISE(ABORT, 'synthetic fault'); END")
try:
commit(rollback, p, lambda: 1)
except sqlite3.DatabaseError:
pass
else:
raise AssertionError('fault not raised')
with connection(rollback) as db:
assert db.execute('SELECT value, version FROM business').fetchone() == ('unset', 0)
assert db.execute('SELECT COUNT(*) FROM operations').fetchone()[0] == 0
async def suspended_case(name, change, expected):
target = str(Path(directory) / (name + '.sqlite'))
initialize(target, p)
entered, release = asyncio.Event(), asyncio.Event()
clock_value = [1]
async def wait():
entered.set()
await release.wait()
task = asyncio.create_task(after_wait(target, p, wait, lambda: clock_value[0]))
await entered.wait()
if change == 'expiry':
clock_value[0] = 10
elif change == 'revocation':
mutate(target, 'UPDATE authority SET revoked=1')
elif change == 'business':
mutate(target, 'UPDATE business SET version=version+1')
else:
mutate(target, 'UPDATE authority SET intent=?', (intent(replace(p, value='delivery')),))
release.set()
result = await task
assert result['status'] == expected
return {'fixture': name, 'actual': result['status']}
async def suspended_tests():
return [await suspended_case('expiry-after-await', 'expiry', 'expired'),
await suspended_case('revoked-after-await', 'revocation', 'revoked-or-missing'),
await suspended_case('repair-after-await', 'repair', 'intent-conflict'),
await suspended_case('state-after-await', 'business', 'stale-version')]
suspended = asyncio.run(suspended_tests())
unknown = remote_without_receipt()
assert unknown['status'] == 'unknown'
print(json.dumps({'fixture_class': 'Synthetic', 'local_results': reports,
'concurrent_statuses': sorted(raced), 'after_wait': suspended,
'rollback': 'verified', 'owned_connection': 'closed',
'remote_timeout_contract': unknown, 'remote_call': 'not-performed'}))
The JSON report includes a committed local version, a labeled historical retry result, concurrent dispositions, post-await failures, rollback evidence, resource-lifetime evidence, and an explicit unknown remote-timeout contract. It states that no remote call occurred. These fields make the reusable report inspectable without a fabricated provider success receipt.
Preserve exact retry semantics
An exact retry is the same logical operation with the same immutable payload. The operation ledger associates its identity with the canonical request fields and recorded result. Reusing that identity with changed values is an identity conflict, not an invitation to reinterpret the old request.
The AWS Builders' Library article on idempotent APIs discusses caller-provided request identity and differing intent. It supports separating retry identity from a convenient hash of similar-looking parameters. Your provider's actual idempotency contract still owns retention windows, conflict handling, and recovery behavior.
The reference stores the full canonical payload alongside the operation identity. The payload includes expected version, epoch, and deadline as well as subject, tenant, resource, and value. An exact retry can return its recorded version without executing another mutation, provided current authority and timing evidence still satisfy this local contract.
A historical result explicitly sets authorizes_new_work to false. A caller must not use that record to revive canceled or superseded work. The local function checks revocation before returning the history result, so an old success cannot restore current permission after the authority record is revoked.
The cache-spoken-answers guide explains why reusing a past answer is also a factual boundary. A historical commit record can describe what happened previously without being a fresh account-state read or a current action approval.
Read the concurrency and rollback fixtures
The concurrent fixture starts two contenders with independent connections and different operation identities against the same expected version. A barrier ensures both are ready before entering their commits. The asserted result is one local commit and one stale-version disposition, regardless of which contender acquires the write lock first.
That is a controlled synthetic race, not evidence about production throughput or every possible database schedule. SQLite serializes the relevant local writes under its own contract. PostgreSQL, a remote CRM, or a provider API needs its own focused integration fixture using its actual isolation and conditional-write behavior.
PostgreSQL's constraint documentation explains uniqueness and other schema constraints for that system. The local operations table uses a primary key as part of its ledger contract. A uniqueness check is useful only when coordinated with the protected mutation, rather than performed in an unrelated preflight that another writer can race.
The rollback fixture installs a trigger that aborts ledger insertion after the update would otherwise succeed. The test then verifies that both business value and version remain unchanged and no operation row was recorded. This protects the local all-or-nothing boundary between mutation and its replay evidence.
Python's sqlite3 documentation distinguishes transaction behavior from connection lifetime. The context manager closes the owned handle in finally. The fixture retains a handle after leaving that scope and verifies that it cannot execute a query, including after an exception.
Recheck after every asynchronous boundary
The after_wait helper awaits preparation and then enters the same commit path. Its fixtures change expiry, revocation, current intent, or business version while the coroutine is suspended. Each resumed operation must be rejected for the appropriate current condition before any local mutation occurs.
The interruption-safety guide explains why late completion is not renewed ownership. A prepared tool result can remain valid historical evidence while becoming unusable for the active task. The application should retain that distinction instead of deleting evidence or silently attaching it to a repaired request.
The self-correction guide describes how later speech changes the intended value. After a repair, the old tool result cannot authorize the new preference. The local authority intent digest changes, and the older proposal receives intent-conflict even if its original business version still matches.
An additional await requires another final check. Do not perform a correct local query, await an unrelated step, and then assume the earlier admission is still authoritative. For remote side effects, the downstream service must enforce equivalent current conditions at its own write boundary or expose a documented conditional operation.

Repair a conflict before asking again
A conflict is a reason to obtain current evidence, not merely to repeat the previous confirmation prompt. Read the new authoritative state, explain material changes, construct a new immutable proposal, and obtain the required approval for that exact current context.
The yes-but repair guide is relevant when the caller's acknowledgment changes part of the proposal. Treat the complete reply as a repair. An affirmative fragment cannot confirm old values while the rest of the response requests a different operation.
The partial-transcript guide addresses the recognition side. A provisional value can help prepare a read, but it should not cause an authoritative write before the current complete intent and required confirmation are established.
The new confirmation request needs a new identity. An exact retry of the old request preserves its original fields and timing evidence. Do not reuse the old operation identity with refreshed versions or deadlines and call the result an idempotent retry; the reference explicitly classifies that change as a conflict.
Keep unavailable and changed evidence separate. If the authoritative read fails, the application still lacks the information needed to repair the proposal. It should not fabricate a new current version or assume that no response means the business state stayed unchanged.
Keep remote outcomes explicitly unknown
A local SQL transaction cannot roll back a remote action already accepted by another service. A timeout after submission can mean several things: the request was never received, it was rejected, it completed, or it remains in progress. Missing response evidence does not identify which outcome occurred.
The reference's remote_without_receipt function is a small outcome contract, not a provider simulator. It returns unknown and requires authoritative reconciliation. The test asserts that local representation and explicitly reports that no remote call was performed.
The truthful tool-waiting guide explains how to speak while that evidence is pending. A caller should not hear that an action definitely failed or succeeded merely because the client stopped waiting. Preserve the actual operation identity for lookup or reconciliation under the provider's documented recovery route.
An outbox can coordinate a local intent record with later delivery, but it does not magically create a transaction across services. The recipient still needs an appropriate idempotent or conditional operation, and the sender needs durable outcome reconciliation. Those are integration responsibilities beyond this local fixture.
The CRM authorization-failure guide adds the permission side. Retrying after a timeout must not ignore a current revocation or transform a denied action into a broadly privileged refresh loop. Preserve provider-specific reasons without exposing raw secrets in the conversation.

Choose a precise acceptance matrix
In this table, ✓ means the boundary explicitly checks the stated condition. ✗ means it does not provide that guarantee. These are contract descriptions, not comparative performance measurements or a claim of distributed exactly-once execution.
| Condition | Timestamp-only read | Published local transaction | Remote integration requirement |
|---|---|---|---|
| Concurrent state changed | ✗ Age cannot detect every write | ✓ Conditional version predicate | Authoritative conditional mutation |
| Proposal alias changed | ✗ No ownership guarantee | ✓ Immutable supported fields | Preserve actual submitted snapshot |
| Approval expired while waiting | ✗ Earlier check can age out | ✓ Clock read after lock acquisition | Final service-side timing contract |
| Current intent repaired | ✗ Old hint remains old | ✓ Current intent comparison | New exact approval and operation |
| Same identity, changed payload | ✗ Similarity is insufficient | ✓ Identity conflict | Provider-specific deduplication contract |
| Historical success after revocation | ✗ Cache can mislead | ✓ Current revocation checked first | No revival of canceled work |
| Remote timeout outcome | ✗ No receipt | ✗ Remote call not performed | Reconcile authoritative outcome |
The observability guide can help structure the evidence for each row. Keep proposal version, current authority identity, operation identity, disposition, and downstream outcome distinct. Do not replace them with one successful-tool-call counter that hides stale, denied, unknown, or historical responses.
The telemetry-redaction guide explains how to retain those diagnostics without copying raw tool payloads into every span. A reason code and version can be useful, while the associated identifiers still require access and retention policy because they may remain linkable.
Inspect the operation ledger
The ledger is evidence about an operation identity and its exact original payload. It is not a list of values that the application is free to reinterpret later. An exact retry uses the same canonical fields; a material correction changes those fields and therefore cannot claim the old operation's recorded result as its own.
Notice that the payload retains expected version, authority epoch, and deadline. Those fields affect the meaning of the operation even when the visible delivery preference is unchanged. Renewing approval or refreshing the expected business version creates a different proposal. The local identity-conflict result makes that distinction explicit instead of silently overwriting the ledger entry.
The approved version and deadline also live in the trusted authority record. This prevents a proposal producer from extending its own approval by changing only a deadline or choosing the latest business version after a conflict. The fixture attempts both changes under new operation identities and expects approval-conflict rather than a fresh commit.
The operation identity itself is scoped by this small teaching database. A production service must define its real namespace, tenant boundary, retention window, and collision handling. Do not assume that a key unique in one local file remains unique across every account, provider, region, or business workflow. The appropriate identity follows the actual intended operation and service contract.

Distinguish local failure and business conflict
A stale-version response is a normal conditional-operation outcome. An unavailable database or an SQL exception is an execution failure. A current authority mismatch is a permission or ownership problem. Preserving these distinctions helps the controller select a useful next step rather than retrying every case with the same old proposal.
The rollback fixture is intentionally an execution failure. It aborts ledger insertion after the transaction has attempted its business update. The subsequent assertions inspect the actual database and verify that the value, version, and ledger remain at their original state. That proves the specific local transaction path did not leave an unrecorded mutation behind.
The normal stale-version fixture follows a different path. Its conditional update affects no row because the expected version is obsolete. The function returns a bounded disposition and records no new committed operation. The caller can then fetch current facts and decide whether a repaired proposal is still appropriate.
Do not hide a database error inside a stale result. If the application cannot determine the authoritative state, it lacks the evidence needed to call the proposal outdated or current. A failure route should preserve that uncertainty and use the actual storage recovery contract. The reference lets SQL exceptions propagate to its fixture rather than fabricating a successful mutation receipt.
Preserve resource lifetime independently of transactions
A transaction context and a connection lifetime solve different problems. Committing or rolling back a transaction does not necessarily close the database handle. An example that creates connections repeatedly can leak resources even while every state assertion passes, especially when exceptions leave the normal return path early.
The connection helper therefore uses a finally block to close the handle it creates. Commit enters that owned-resource scope and then uses the database transaction context within it. A return from a policy branch still exits both scopes, so the transaction completes appropriately and the owned handle closes.
The fixture verifies the actual handle after leaving a normal connection scope and after an explicit exception inside that scope. Both handles must reject a later query as closed. This is a resource-lifetime observation, not a claim that a context manager magically makes every external client or pooled connection safe.
A production pool has a different ownership contract: an operation may return a borrowed connection rather than close the underlying socket. Test that real contract directly. Do not transplant a close-on-every-call example into a pool while claiming identical lifecycle behavior, and do not assume a successful rollback proves the connection was released to the right owner.
Design a focused integration replay
Start by recording an authoritative read and the exact proposed mutation it produced. Preserve the original version and approval reference. Then introduce one controlled change before final submission: another writer advances the business state, the authority epoch changes, the caller repairs the value, or the deadline passes while work is suspended.
Those scenarios should produce distinguishable outcomes at the actual adapter boundary. A state conflict should not be reported as a credential failure. A repaired intent should not inherit old approval. An expired proposal should not receive a new lease merely because the transport retried it. Keep the expected outcome with the observed result so a reviewer can see which contract the replay actually exercised.
The local after_wait fixture makes suspension deterministic with events. It does not rely on a guessed sleep duration to create a race. The state mutation happens after the waiting coroutine announces it has entered the boundary and before it is released. That ordering makes the negative assertion useful even on a fast or heavily loaded development machine.
For a real remote service, add the provider's actual conditional request, permission response, operation lookup, and timeout-recovery behavior. That is proposed integration work, not something this fence already performed. A local SQLite pass must remain labeled local so it cannot be mistaken for proof of a CRM's atomicity or a carrier's delivery behavior.
Finally, keep the current intent and the historical result visible at the same time. An old success can help explain what happened before a repair, while the active controller refuses to use it for new work. Deleting history would lose diagnosis; reviving it would lose safety. The local contract preserves the history label and checks current authority before returning it.
The network-resume guide adds another practical boundary. A reconnected transport can deliver an old response after the conversation has moved on. Preserve the operation and proposal identity so the controller can classify that response as historical, obsolete, or current. Transport recovery must not silently renew approval or advance a business version on the caller's behalf.
The regression-testing guide explains how to preserve these cases across changes. Keep the complete published fence as the source of truth for this artifact. A helper copied into another test file can drift from the article and accidentally pass while the delivered code still has a defect. Execute the exact functions and inspect their emitted report after every material correction.
Use a failure ledger that retains all attempted operation identities in a real replay. A contender rejected for stale state is still an attempted operation; it should not disappear from evaluation simply because it did not mutate a row. An unknown remote result likewise remains unknown until reconciliation, rather than being excluded from a completion denominator to make the integration look more reliable.
The synthetic report demonstrates dispositions without reporting a performance rate. Its concurrent fixture has a deterministic expected relationship between contenders, not a workload intended to estimate latency, throughput, or production conflict prevalence. Those measurements would require an actual workload description, units, observed timings, backend configuration, and a declared population beyond this local correctness exercise.
That distinction keeps the first implementation step useful. An engineer can verify the transaction, retry, expiry, and repair boundaries immediately, then design a separate integration or load experiment around the real service. Correctness evidence and performance evidence can support each other without being presented as the same result.
Frequently asked questions
What makes a tool result stale?
It no longer provides the current evidence needed for the intended operation. A result can be accurate when read and superseded before execution. Preserve its version and compare against the authoritative mutation boundary rather than assuming a recent successful response remains usable.
Why is a timestamp weaker than a business version?
Age describes elapsed time, while a version identifies a state under the service contract. Another writer can change the resource immediately after a read. A freshness window therefore cannot replace an atomic expected-version comparison.
How does If-Match prevent a lost update?
When supported and enforced by the resource server, it makes a request conditional on the selected representation's entity tag under HTTP semantics. The server must evaluate the condition at the operation boundary. A client-only comparison does not provide equivalent protection.
What does a 412 response mean?
HTTP defines it as a precondition failure under the relevant request conditions. Interpret the actual provider's documented response and obtain current state where appropriate. Do not simply resend an unchanged proposal while pretending the failed precondition was advisory.
Where must version checking occur?
At the authoritative state mutation, coordinated with the write. The local example uses a conditional SQL update inside the same transaction as authority checks and ledger recording. A production API needs equivalent documented conditional behavior or another suitable concurrency contract.
Can a read check and write be separate calls?
They can be separate for application flow, but the earlier check cannot guarantee the later state stayed unchanged. The write itself still needs its authoritative precondition. Otherwise another writer can intervene between the two calls.
How should a stale booking proposal be repaired?
Read current authoritative facts, construct a new immutable proposal, and reconfirm material changes. Keep the original read and review evidence where authorized. A refreshed version or deadline under the old operation identity is a changed request, not an exact retry.
Does fresh data imply fresh authorization?
No. Permission, session ownership, current intent, and business state are separate evidence. The reference checks current authority and approval as well as the state version. A recent read cannot override revocation or authorize another subject's action.
Why must approved values be copied and frozen?
A mutable alias can change the eventual payload after approval. The reference copies supported scalars and tests both source mutation and direct rebinding. Frozen annotations alone would not recursively protect arbitrary nested objects, so the accepted shape remains explicit.
How should identical retries behave?
Follow the operation's documented contract. This reference returns labeled historical evidence without another mutation, subject to current authority and expiry checks. Its result explicitly says it does not authorize new work or restore a canceled operation.
What if one idempotency key carries new values?
The local ledger returns identity-conflict. Exact retries retain the original immutable payload, including version and timing fields. Material changes need a new logical request and appropriate approval rather than reuse of the old operation's identity.
Can a local database transaction protect a remote API?
It cannot roll back an independently completed remote side effect. Use the provider's actual conditional or idempotent contract and an appropriate durable delivery and reconciliation design. The published fence performs no remote request and claims only local transaction behavior.
When is an outbox useful?
It can durably coordinate a local intent record with later delivery. It does not automatically provide a distributed transaction or eliminate recipient-side duplication concerns. The real consumer and reconciliation routes still need explicit contracts and integration tests.
How should pending provider outcomes be represented?
Preserve pending or unknown until authoritative evidence resolves them. A timeout does not prove failure or success. The reference emits an unknown-with-reconciliation contract and explicitly reports that it did not contact a provider.
Can a successful historical retry restore canceled work?
It must not become current authority. The local function checks current revocation before returning history, and its historical response disallows new work. The controller must preserve terminal ownership and avoid replaying speech or side effects from old success evidence.
What should be reconfirmed after a conflict?
Every material fact that changed the proposed operation or its context. That can include resource, value, version-dependent facts, or permission scope. A fresh model explanation is insufficient; the trusted current approval must cover the repaired immutable proposal.
How should zero and missing versions differ?
Zero is an admitted initial integer version in this teaching model. Missing evidence is invalid metadata. Use strict type checks so booleans, empty strings, and absent fields do not silently collapse into a legitimate version value.
How should schema revisions be recorded?
Keep the serialization or policy identity needed to interpret historical payloads and evidence. Do not change an old operation's material payload in place. The bounded artifact uses one fixed schema; expanding it requires a declared compatibility and replay policy.
What concurrency fixtures prove the local contract?
The fence uses independent SQLite connections, two contenders for one expected version, and an asserted single local commit. It also verifies rollback after ledger failure and state changes after an await. These are synthetic local checks, not production throughput measurements.
What remains for the production adapter to guarantee?
Trusted authority provenance, current ownership, real conditional mutation, durable operation identity, and remote outcome reconciliation remain integration obligations. Recheck after waits and protect actual submitted fields. A passing local fixture cannot certify a remote provider's behavior.
Verify the write boundary first
For 60db Agent integrations, identify the authoritative version and action service before adding retry logic. Run the complete local fixture, inspect the emitted statuses, and compare its transaction boundary with the real adapter's conditional-update and idempotency contract.
Then test conflicts, repairs, expiry, revocation, and unknown remote outcomes through that actual integration. Preserve old evidence as history while ensuring only the current exact intent can authorize a new mutation.
