Graph
Each stage uses an ordinary node with a stored attempt record. The apply node changes one target and reads it back. A separate verification node checks that result before the next action. The final node checks that all protected records remain in their destinations.Contract
A source record holds an ID, a declared kind, metadata, and a body string.
A destination record holds an ID, a revision, an active flag, content, and
the last action’s identity. The fixture stores these records as UTF-8 JSON
files with mode
0600.
The mapping must preserve each complete source record in an active
destination. A change that drops metadata or alters a protected body is
refused. The recipe does not extract semantic facts from prose or decide
which facts can be discarded.
Approval and writes
The proposal covers destination content, expected revisions, mappings, and source hashes. Approval binds its exact bytes and the proof packet through the stored callback APIs. The host posts and answers the callback only while the executor is stopped. Before each write, the file adapter checks stored approval, live source hashes, the target’s version and active status, and the verified backup. Models can propose or review data; the deterministic adapter applies it. The runnable fixture’sapprove() helper supplies a scripted answer. A real
host must collect its decision through the stored callback client.
The backup retains the original source and target file bytes, including all
record fields needed to restore them. Artifact hashes protect these bytes.
The recipe checks the backup before use. It provides no automatic restore.
Each file merge has one stable action identity taken from its original
stored node attempt. The target’s content, revision, and action witness are
saved together through one file replacement. The witness identifies the
write that produced the content.
The recipe appends intent and result events to each target’s own stream.
It keeps source event histories separate. It never imports a source’s event
history into a target stream or the executor’s run stream.
Failure, pause, and recovery
A readback that succeeds with different bytes records a mismatch and pauses the graph before the next write. A person must decide what happens next. Changing the file back and calling resume does not clear that mismatch. A readback that cannot run fails the graph. An action that fails before an uncertain outward result also fails it. If a write succeeds but its response is lost, the recipe reads the target before deciding whether it completed. After a process crash leaves an action’s outcome unknown, the executor pauses that attempt for reconciliation. On resume, the recipe checks the saved intent, exact target bytes, and action witness. A matching completed write returns its evidence without another application. Unknown or mismatched state stays paused. Resume alone never authorizes a repeated write. This adapter assumes one writer owns the synthetic record directory. An external service requires its own conditional-write and action-status contract. The file example makes no guarantee about an arbitrary remote API.Run the line
From an Obversa checkout, run:Source
Copy all three files fromexamples/safe-change/: recipe.ts drives the
stored graph, file-adapter.ts reads and changes records, and example.ts
runs the fixture below. Keep them in one directory. They import public
runtime exports.