Skip to main content
Approve the exact bytes a change will write, and let nothing else through. Use it when a step edits files whose contents are facts you can’t lose: a migration of records, a merge of protected sources into a destination. When a person’s yes is enough on its own, use a person decides; this pattern binds that yes to the proposed output, so a changed byte makes the old approval void.

Shape

The run

The proposal covers the destination content, the expected revisions, the mappings and the source hashes. Approval binds those exact bytes and the proof packet through the stored callback APIs. The host posts and answers the callback only while the executor is stopped:
examples/safe-change.ts (excerpt)
The run pauses at the approval. approve() supplies a scripted answer here; a real host collects its decision through the stored callback client. Before each write, the file adapter checks the stored approval, the 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 backup keeps the original source and target bytes, with every record field needed to restore them, and artifact hashes protect it. Each write saves the target’s content, revision and action witness together through one file replacement, and appends intent and result events to the target’s own stream. A readback that succeeds with different bytes records a mismatch and pauses the graph before the next write; changing the file back and calling resume doesn’t clear it. After a crash leaves a write’s outcome unknown, resume checks the saved intent, the exact target bytes and the witness. A matching completed write returns its evidence without another application. Resume alone never authorises a repeated write.

What the run did

Four synthetic source kinds, document, current record, discussion comment and historical entry, are merged into two destinations. The example writes only to a temporary directory and removes it when done, and calls no model. Run it with npx tsx safe-change.ts, with safe-change-recipe.ts and safe-change-file-adapter.ts beside it:
Output
Every protected fact reached its destination, none was lost, both targets carry a result, and the backup matched the original bytes. 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 adapter assumes one writer owns the record directory. An external service needs its own conditional-write and action-status contract.
examples/safe-change.ts
The other two files, examples/safe-change-recipe.ts (the stored graph) and examples/safe-change-file-adapter.ts (reading and changing records), sit beside it and import only public runtime exports.

Next steps

  • Proof-bound acceptance and approval: how an approval is bound to the bytes, proof and workspace state it judged.
  • Safe node attempts: the attempt record each stage here keeps, and how a crash mid-write is reconciled.
  • Runtime: the executor, the stored callback client and the artifact store the recipe uses.