> ## Documentation Index
> Fetch the complete documentation index at: https://obversa.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Decisions Bound to Bytes

> Reuse a result or a decision only while every covered byte still matches.

Bind a review's verdict or a person's approval to the exact bytes it
judged, and get it back only while those bytes still match. Use it when a
result or a decision will be acted on later, or by another process, and a
changed input must void it. For the question itself, read
[Callback gates](/docs/reviewing/callback-gates); this page is what makes an
answer stick to its subject.

A proof artifact has one content digest. An accepted-result record binds a
review outcome to that proof and the bytes it covered. An approval record
binds a stored action decision to the same kind of exact subject. While
every covered byte still matches, you can reuse the result or act on the
approval. Change one of those bytes and you get `wait` instead.

## Accept a result

`writeProofArtifact` stores the stable JSON bytes of one proof packet, and
`createAcceptedResultRecord` binds a review outcome to it:

```ts examples/proof-bound-approval.ts (excerpt) {1-2,9-18} theme={null}
  const proofArtifact = await writeProofArtifact(
    storage.artifactStore,
    { namespace: storage.record.namespace, runId },
    {
      inputs: { proposal: digest('1') },
      result: { passed: true, tests: 21 },
    },
  );
  const acceptedBinding = {
    inputHashes,
    proofScope,
    proofArtifact,
    graph: {
      definitionDigest: plan.plan.graph.definitionDigest,
      typeVersion: plan.plan.graph.typeVersion,
    },
    workspaceAnchor,
  } as const;
  const firstReview = await createAcceptedResultRecord(
    storage,
    runId,
    architectureReview.position,
    {
      ...acceptedBinding,
      result: { verdict: 'pass' },
      reviewerIdentity: { provider: 'anthropic', model: 'reviewer-a' },
    },
  );
```

The proof reference carries the content digest, byte length, media type
and `proof-packet` purpose. Reordered object fields produce the same bytes
and digest; changed proof data produces another. You choose the packet
fields and the proof scope, and `writeProofArtifact` doesn't check how the
proof was produced.

An accepted result is stored only when the graph matches the stored run
plan and the run holds exactly one dispatch for that position, followed by
a completed event with the same node and result. Missing, failed or
conflicting completions are refused with `INVALID_STORED_VALUE`. The record
binds the result to input hashes, proof scope and artifact, graph
definition and type version, workspace anchor, and the reviewer identity
you supply; the reviewer fingerprint is the digest of that identity.
Writing the same complete record again at the same position does nothing.
A different binding for the same completed result there is refused with
`REVISION_CONFLICT`.

Accepted results need a `WorkspaceAnchor`: workspace root, repository
identity, HEAD revision, content fingerprint, capture scope and file
states, with `schemaVersion: 1`. The validators bind its bytes into the
record digest but don't validate its fields, compare it with the run's
workspace binding or verify the checkout. For a real workspace, use an
anchor your workspace provider captured, and verify it before you reuse a
result. The example's `/workspace` anchor is made-up data to show digest
matching.

## Bind an approval

`createApprovalCallbackGate` puts the subject digest into the callback
request before its identity is created, so the question is about these
exact bytes:

```ts examples/proof-bound-approval.ts (excerpt) {12,14,16-23} theme={null}
  const approvalDefinition: CallbackGateDefinition = {
    gateId: 'apply-reviewed-output',
    gateVersion: 1,
    decisionText: 'Apply these exact reviewed bytes?',
    responseSchema: {
      type: 'object',
      properties: { kind: { type: 'string' } },
      required: ['kind'],
    },
    input: { change: 'runtime-update' },
  };
  const request = createApprovalCallbackGate(approvalDefinition, approvalSubject);
  const callbacks = await createStoredCallbackClient(storage, runId);
  await callbacks.post(request, approvalSubject);
  const claim = await callbacks.claim(request.requestId, 'human-review');
  if (!claim.ok) throw new Error('The approval request was not claimed.');
  const submitted = await callbacks.submit(
    request.requestId,
    claim.claimToken,
    'human-review',
    request.digest,
    { kind: 'allow' },
    { id: 'release-owner', kind: 'human' },
  );
```

The subject covers input artifact hashes, proof scope and artifact, the
proposed output bytes, the effective permissions, and a workspace anchor or
`null`. `post` stores that exact subject with the request, and `submit`
stores the answer and the approval record in one event batch. The record
also binds the stored run plan, graph, the actor you supply, the router
path and the action decision. Each effective permission must match one
permission admitted by the stored run plan, name and JSON scope exactly,
key order aside; the subject may use a subset.

## Resolve before you act

`resolveAcceptedResult` and `resolveApproval` return the stored value only
while the current subject matches the record:

```ts examples/proof-bound-approval.ts (excerpt) {1,7,17,22} theme={null}
  const unchangedAccepted = await resolveAcceptedResult(
    reopenedStorage,
    runId,
    architectureReview.position,
    { ...acceptedBinding, reviewerIdentity: { provider: 'anthropic', model: 'reviewer-a' } },
  );
  const changedAnchor = await resolveAcceptedResult(
    reopenedStorage,
    runId,
    architectureReview.position,
    {
      ...acceptedBinding,
      workspaceAnchor: { ...workspaceAnchor, fingerprint: 'c'.repeat(64) },
      reviewerIdentity: { provider: 'anthropic', model: 'reviewer-a' },
    },
  );
  const unchangedApproval = await resolveApproval(
    reopenedStorage,
    runId,
    { request, ...approvalSubject },
  );
  const changedApproval = await resolveApproval(
    reopenedStorage,
    runId,
    { request, ...changedSubject },
  );
```

Run the file with `npx tsx proof-bound-approval.ts`; it calls no model and
writes to a temporary directory it removes:

```json Output theme={null}
{"proof":{"digest":"sha256:db5b2a0eb5743b52617a78335dbc003a9a10619dc6cab05f6099f81c9b7fb329","byteLength":133,"recordsShareDigest":true},"callback":{"responseSurvivedReopen":true,"changedRequest":true},"acceptedResult":{"unchanged":"accepted","changedAnchor":"wait"},"approval":{"unchanged":"allow","changedOutput":"wait"}}
```

Two accepted-result records cite one proof digest. The callback answer
survived reopening the storage. The unchanged result resolves to
`accepted` and the unchanged approval to `allow`; a changed workspace
anchor and a changed proposed output each return `wait`. A `wait` needs
fresh proof or a decision by the host, and a changed binding needs a newly
completed proof position; it can't replace the acceptance stored for an
earlier completion. The host owns every effect after approval: these APIs
don't make a backup, apply output, read the effect back, reconcile an
uncertain effect or merge files.

## Share evidence

`createProofCache` serves bounded proof packets for one host process and
one stored run, so fresh workers get the same evidence without reading
unchanged sources again:

```ts examples/proof-cache.ts (excerpt) {5,7-9} theme={null}
  const cache = createProofCache({
    storage,
    runId,
    sources,
    maxPacketBytes: 16_000,
    proofJobs: [
      { id: 'review', mode: 'read-only', sourceIds: ['config', 'policy'], proofScope: { kind: 'config-review' } },
      { id: 'policy', mode: 'read-only', sourceIds: ['policy'], proofScope: { kind: 'policy-review' } },
      { id: 'apply', mode: 'effectful', sourceIds: ['config'], proofScope: { kind: 'write' } },
    ],
  });
  const [first, second, policyPacket] = await Promise.all([
    cache.packet('review'), cache.packet('review'), cache.packet('policy'),
  ]);
```

Declare each source by id with a `revision()` that returns an authoritative
content revision and a `read(expectedRevision, maxBytes)` that returns
complete JSON or text for that revision. The cache checks revisions before
and after capture and hashes the content; it refuses an oversized packet or
a capture that races a source change, and never truncates. Declare each
proof job's sources, scope and mode: only `read-only` jobs can request
packets or stored results, and the cache executes no job. Concurrent
requests share source reads, a changed source invalidates only the packets
that depend on it, and a host restart starts a cold cache while stored
artifacts and records stay in run storage.

`resolveAccepted(jobId, position, current)` derives the hashes, scope and
artifact from the current packet and checks the stored acceptance again
with the graph, verified anchor and reviewer identity you pass. Reviewers
share evidence and keep separate answers: a different reviewer identity
doesn't inherit another's result. Run `npx tsx proof-cache.ts`:

```json Output theme={null}
{"sourceReads":{"config":2,"policy":1},"proofRuns":1,"sharedPacket":true,"reused":"accepted","changedSource":"wait","unaffectedPacket":true,"changedReviewer":"wait","effectfulRefused":true}
```

Two packet requests shared one artifact. The stored review was reused,
refused for a different reviewer, and refused again after the configuration
changed, while the independent policy packet was kept. The effectful job
was refused a packet.

## Failure

* **`INVALID_STORED_VALUE`**: the run has no single completed dispatch for
  the position an accepted result names.
* **`REVISION_CONFLICT`**: a different binding for a result already
  accepted at that position.
* **`SUBJECT_MISMATCH`**: `post` throws `ApprovalSubjectError` for a
  permission outside the stored plan; `submit` returns `invalid` and
  `resolveApproval` returns `wait` in the same case.
* **`KNOWN_SECRET`**: the local event store rejects a write whose reviewer
  identity or actor contains a configured secret, nested values and keys
  included. A rejected approval write stores neither the answer nor the
  record.

## Limits

* **Identities are stored whole.** The supplied `reviewerIdentity` and
  `actor` objects are kept beside their fingerprints, unauthenticated.
  Supply only non-secret identifiers; the store can't catch a credential
  that isn't on its `knownSecrets` list.
* **The proof cache trusts its adapters.** Source declarations and revision
  behaviour are the host's trusted code. A node's `retrySafe` governs crash
  recovery; it doesn't make a job read-only.

<Accordion title="Full file: proof-bound-approval.ts">
  ```ts examples/proof-bound-approval.ts theme={null}
  import { mkdtemp, realpath, rm } from 'node:fs/promises';
  import { tmpdir } from 'node:os';
  import { join } from 'node:path';

  import {
    compileGraph,
    createAcceptedResultRecord,
    createApprovalCallbackGate,
    createStoredCallbackClient,
    createGraphExecutor,
    dagGraphType,
    persistRunDefinition,
    resolveAcceptedResult,
    resolveApproval,
    resolveGraphPlan,
    writeProofArtifact,
    type ApprovalSubjectInput,
    type CallbackGateDefinition,
    type Sha256Digest,
    type WorkspaceAnchor,
  } from '@obversa/runtime';
  import { createLocalRunStorage } from '@obversa/runtime/storage/local';

  const digest = (digit: string): Sha256Digest => (
    `sha256:${digit.repeat(64)}` as Sha256Digest
  );

  const storagePolicy = {
    schemaVersion: 1,
    maxEventPayloadBytes: 64_000,
    maxAppendBatchBytes: 128_000,
    maxArtifactBytes: 1_000_000,
    maxTotalArtifactBytesPerRun: 4_000_000,
    retention: 'until-run-delete',
    sensitiveContent: {
      marked: 'reject',
      exact: 'reject',
      freeText: 'redact-before-hash',
    },
  } as const;

  const graph = compileGraph(dagGraphType, {
    id: 'proof-bound-approval',
    definitionVersion: 1,
    data: {
      globalConcurrency: 2,
      keyedConcurrency: {},
      stopOnError: true,
      retryCapPerNode: 0,
    },
    nodes: [
      { id: 'architecture', data: { kind: 'required', key: null } },
      { id: 'correctness', data: { kind: 'required', key: null } },
    ],
    edges: [],
  });
  const packageIdentity = {
    source: 'npm:@example/proof-bound-approval',
    version: '1.0.0',
    digest: digest('7'),
  } as const;
  const plan = resolveGraphPlan(graph.describe(), {
    package: packageIdentity,
    admission: {
      package: packageIdentity,
      permissions: [{ name: 'workspace.write', scope: { paths: ['packages/runtime'] } }],
    },
    executionLanes: [],
  });
  const workspaceAnchor: WorkspaceAnchor = {
    schemaVersion: 1,
    root: '/workspace',
    repositoryId: '/workspace/.git',
    head: 'a'.repeat(40),
    fingerprint: 'b'.repeat(64),
    scope: null,
    files: [],
  };
  const proofScope = { kind: 'change', paths: ['packages/runtime'] } as const;
  const inputHashes = { proposal: digest('1') };
  const runId = 'proof-bound-approval-run';

  const directory = await realpath(await mkdtemp(join(tmpdir(), 'obversa-proof-approval-')));
  try {
    const openStorage = () => createLocalRunStorage({
      directory: join(directory, 'storage'),
      namespace: 'proof-approval-example',
      policy: storagePolicy,
    });
    const storage = openStorage();
    await persistRunDefinition(storage, {
      runId,
      eventId: 'proof-bound-approval-started',
      timestamp: '2026-01-01T00:00:00.000Z',
      graphDefinition: graph.definition,
      resolvedPlan: plan,
      resolvedInputs: {},
      workspaceBinding: null,
      hostBinding: null,
    });
    const initialCommands = graph.decide(graph.initialState());
    const architectureReview = initialCommands.find((command) => (
      command.kind === 'dispatch' && command.nodeId === 'architecture'
    ));
    const correctnessReview = initialCommands.find((command) => (
      command.kind === 'dispatch' && command.nodeId === 'correctness'
    ));
    if (architectureReview?.kind !== 'dispatch' || correctnessReview?.kind !== 'dispatch') {
      throw new Error('The review graph did not dispatch both review nodes.');
    }
    const reviewNode = {
      prompt: null,
      scratchDirectory: directory,
      workspace: { mode: 'none', directory: null, allowedPaths: [] },
      trustedCaller: {},
      permissions: [],
      policy: {
        inputBytes: 100_000,
        outputBytes: 100_000,
        timeoutMs: 5_000,
        teardownGraceMs: 100,
        memoryBytes: 100_000_000,
        filesChanged: 0,
        linesChanged: 0,
        callTokens: null,
      },
      resultContract: null,
      runData: async () => ({ verdict: 'pass' }),
      parseResult: null,
      tokenBudget: null,
      decideAction: async () => ({ kind: 'allow' } as const),
    } as const;
    const executor = await createGraphExecutor({
      runId,
      graph,
      storage,
      nodes: { architecture: reviewNode, correctness: reviewNode },
      engines: [],
    });
    const completed = await executor.run(new AbortController().signal);
    if (completed.kind !== 'complete') throw new Error('The review nodes did not complete.');

    const proofArtifact = await writeProofArtifact(
      storage.artifactStore,
      { namespace: storage.record.namespace, runId },
      {
        inputs: { proposal: digest('1') },
        result: { passed: true, tests: 21 },
      },
    );
    const acceptedBinding = {
      inputHashes,
      proofScope,
      proofArtifact,
      graph: {
        definitionDigest: plan.plan.graph.definitionDigest,
        typeVersion: plan.plan.graph.typeVersion,
      },
      workspaceAnchor,
    } as const;
    const firstReview = await createAcceptedResultRecord(
      storage,
      runId,
      architectureReview.position,
      {
        ...acceptedBinding,
        result: { verdict: 'pass' },
        reviewerIdentity: { provider: 'anthropic', model: 'reviewer-a' },
      },
    );
    const secondReview = await createAcceptedResultRecord(
      storage,
      runId,
      correctnessReview.position,
      {
        ...acceptedBinding,
        result: { verdict: 'pass' },
        reviewerIdentity: { provider: 'openai', model: 'reviewer-b' },
      },
    );

    const proposedOutput = new TextEncoder().encode('approved output');
    const approvalSubject: ApprovalSubjectInput = {
      workspaceAnchor,
      inputArtifactHashes: inputHashes,
      proofScope,
      proofArtifact,
      proposedOutput,
      effectivePermissions: [{
        name: 'workspace.write',
        scope: { paths: ['packages/runtime'] },
      }],
    };
    const approvalDefinition: CallbackGateDefinition = {
      gateId: 'apply-reviewed-output',
      gateVersion: 1,
      decisionText: 'Apply these exact reviewed bytes?',
      responseSchema: {
        type: 'object',
        properties: { kind: { type: 'string' } },
        required: ['kind'],
      },
      input: { change: 'runtime-update' },
    };
    const request = createApprovalCallbackGate(approvalDefinition, approvalSubject);
    const callbacks = await createStoredCallbackClient(storage, runId);
    await callbacks.post(request, approvalSubject);
    const claim = await callbacks.claim(request.requestId, 'human-review');
    if (!claim.ok) throw new Error('The approval request was not claimed.');
    const submitted = await callbacks.submit(
      request.requestId,
      claim.claimToken,
      'human-review',
      request.digest,
      { kind: 'allow' },
      { id: 'release-owner', kind: 'human' },
    );
    if (!submitted.ok) throw new Error(`The approval was refused: ${submitted.reason}`);

    const reopenedStorage = openStorage();
    const reopenedCallbacks = await createStoredCallbackClient(reopenedStorage, runId);
    const changedSubject: ApprovalSubjectInput = {
      ...approvalSubject,
      proposedOutput: new TextEncoder().encode('changed output'),
    };
    const changedRequest = createApprovalCallbackGate(approvalDefinition, changedSubject);
    await reopenedCallbacks.post(changedRequest, changedSubject);
    const unchangedAccepted = await resolveAcceptedResult(
      reopenedStorage,
      runId,
      architectureReview.position,
      { ...acceptedBinding, reviewerIdentity: { provider: 'anthropic', model: 'reviewer-a' } },
    );
    const changedAnchor = await resolveAcceptedResult(
      reopenedStorage,
      runId,
      architectureReview.position,
      {
        ...acceptedBinding,
        workspaceAnchor: { ...workspaceAnchor, fingerprint: 'c'.repeat(64) },
        reviewerIdentity: { provider: 'anthropic', model: 'reviewer-a' },
      },
    );
    const unchangedApproval = await resolveApproval(
      reopenedStorage,
      runId,
      { request, ...approvalSubject },
    );
    const changedApproval = await resolveApproval(
      reopenedStorage,
      runId,
      { request, ...changedSubject },
    );

    console.log(JSON.stringify({
      proof: {
        digest: proofArtifact.digest,
        byteLength: proofArtifact.byteLength,
        recordsShareDigest: firstReview.binding.proofArtifact.digest
          === secondReview.binding.proofArtifact.digest,
      },
      callback: {
        responseSurvivedReopen: (await reopenedCallbacks.history(request.requestId)).some((event) => (
          event.kind === 'callback-submitted'
        )),
        changedRequest: (await reopenedCallbacks.listPending()).some((pending) => (
          pending.requestId === changedRequest.requestId
        )),
      },
      acceptedResult: {
        unchanged: unchangedAccepted.kind,
        changedAnchor: changedAnchor.kind,
      },
      approval: {
        unchanged: unchangedApproval.kind,
        changedOutput: changedApproval.kind,
      },
    }));
  } finally {
    await rm(directory, { recursive: true, force: true });
  }
  ```
</Accordion>

<Accordion title="Full file: proof-cache.ts">
  ```ts examples/proof-cache.ts theme={null}
  import assert from 'node:assert/strict';
  import { execFile } from 'node:child_process';
  import { mkdir, mkdtemp, realpath, rm, writeFile } from 'node:fs/promises';
  import { tmpdir } from 'node:os';
  import { join } from 'node:path';
  import { promisify } from 'node:util';

  import {
    compileGraph,
    createAcceptedResultRecord,
    createGitWorktreeProvider,
    createGraphExecutor,
    createProofCache,
    dagGraphType,
    persistRunDefinition,
    resolveGraphPlan,
    type GraphNodeBinding,
    type ProofSource,
    type Sha256Digest,
  } from '@obversa/runtime';
  import { createLocalRunStorage } from '@obversa/runtime/storage/local';

  const git = promisify(execFile);
  const directory = await realpath(await mkdtemp(join(tmpdir(), 'obversa-proof-cache-')));

  try {
    const repository = join(directory, 'repository');
    await mkdir(repository);
    await git('git', ['init', '-q', '-b', 'main'], { cwd: repository });
    await writeFile(join(repository, 'README.md'), '# Proof cache example\n');
    await git('git', ['add', 'README.md'], { cwd: repository });
    await git('git', [
      '-c', 'user.name=Example', '-c', 'user.email=example@example.com',
      'commit', '-qm', 'initial',
    ], { cwd: repository });
    const workspace = createGitWorktreeProvider({ repositoryPath: repository });
    const workspaceAnchor = await workspace.capture();
    assert.equal((await workspace.verify(workspaceAnchor)).ok, true);

    const graph = compileGraph(dagGraphType, {
      id: 'cached-proof',
      definitionVersion: 1,
      data: {
        globalConcurrency: 1,
        keyedConcurrency: {},
        stopOnError: true,
        retryCapPerNode: 0,
      },
      nodes: [{ id: 'review', data: { kind: 'required', key: null } }],
      edges: [],
    });
    const packageIdentity = {
      source: 'npm:@example/cached-proof',
      version: '1.0.0',
      digest: `sha256:${'7'.repeat(64)}` as Sha256Digest,
    };
    const plan = resolveGraphPlan(graph.describe(), {
      package: packageIdentity,
      admission: { package: packageIdentity, permissions: [] },
      executionLanes: [],
    });
    const runId = 'cached-proof-run';
    const storage = createLocalRunStorage({
      directory: join(directory, 'storage'),
      namespace: 'proof-cache-example',
      policy: {
        schemaVersion: 1,
        maxEventPayloadBytes: 64_000,
        maxAppendBatchBytes: 128_000,
        maxArtifactBytes: 1_000_000,
        maxTotalArtifactBytesPerRun: 4_000_000,
        retention: 'until-run-delete',
        sensitiveContent: { marked: 'reject', exact: 'reject', freeText: 'redact-before-hash' },
      },
    });
    await persistRunDefinition(storage, {
      runId,
      eventId: 'cached-proof-started',
      timestamp: '2026-01-01T00:00:00.000Z',
      graphDefinition: graph.definition,
      resolvedPlan: plan,
      resolvedInputs: {},
      workspaceBinding: null,
      hostBinding: null,
    });

    // These in-memory sources own their revisions; every payload edit advances it.
    const config = { revision: '1', content: 'timeoutMs: 1000' };
    const policy = { revision: '1', content: 'A timeout must be positive.' };
    const sourceReads = { config: 0, policy: 0 };
    const sources: ProofSource[] = Object.entries({ config, policy }).map(([id, source]) => ({
      id,
      revision: async () => source.revision,
      read: async (expectedRevision, maxBytes) => {
        assert.equal(source.revision, expectedRevision);
        assert.ok(Buffer.byteLength(JSON.stringify(source.content)) <= maxBytes);
        sourceReads[id as keyof typeof sourceReads] += 1;
        return source.content;
      },
    }));
    const cache = createProofCache({
      storage,
      runId,
      sources,
      maxPacketBytes: 16_000,
      proofJobs: [
        { id: 'review', mode: 'read-only', sourceIds: ['config', 'policy'], proofScope: { kind: 'config-review' } },
        { id: 'policy', mode: 'read-only', sourceIds: ['policy'], proofScope: { kind: 'policy-review' } },
        { id: 'apply', mode: 'effectful', sourceIds: ['config'], proofScope: { kind: 'write' } },
      ],
    });
    const [first, second, policyPacket] = await Promise.all([
      cache.packet('review'), cache.packet('review'), cache.packet('policy'),
    ]);
    let proofRuns = 0;
    const result = { verdict: 'pass', proof: first.proofArtifact.digest };
    const node: GraphNodeBinding = {
      prompt: null,
      scratchDirectory: directory,
      workspace: { mode: 'none', directory: null, allowedPaths: [] },
      trustedCaller: {},
      permissions: [],
      policy: {
        inputBytes: 100_000, outputBytes: 100_000, timeoutMs: 5_000,
        teardownGraceMs: 100, memoryBytes: 100_000_000,
        filesChanged: 0, linesChanged: 0, callTokens: null,
      },
      resultContract: null,
      runData: async () => {
        proofRuns += 1;
        const captured = first.packet.sources.find((source) => source.id === 'config');
        const timeout = typeof captured?.content === 'string'
          ? /^timeoutMs: ([0-9]+)$/.exec(captured.content)
          : null;
        assert.ok(timeout && Number(timeout[1]) > 0, 'The captured config needs a positive timeout.');
        return result;
      },
      parseResult: null,
      tokenBudget: null,
      decideAction: async () => ({ kind: 'allow' }),
    };
    const executor = await createGraphExecutor({ runId, graph, storage, nodes: { review: node }, engines: [] });
    assert.equal((await executor.run(new AbortController().signal)).kind, 'complete');
    const dispatch = graph.decide(graph.initialState()).find((command) => command.kind === 'dispatch');
    assert.ok(dispatch?.kind === 'dispatch');
    const current = {
      graph: { definitionDigest: plan.plan.graph.definitionDigest, typeVersion: plan.plan.graph.typeVersion },
      workspaceAnchor,
      reviewerIdentity: { id: 'scripted-timeout-review', version: 1 },
    };
    await createAcceptedResultRecord(storage, runId, dispatch.position, {
      ...current,
      inputHashes: first.inputHashes,
      proofArtifact: first.proofArtifact,
      proofScope: first.proofScope,
      result,
    });
    assert.equal((await workspace.verify(workspaceAnchor)).ok, true);
    const reused = await cache.resolveAccepted('review', dispatch.position, current);
    assert.equal(reused.kind, 'accepted');
    if (reused.kind === 'accepted') assert.deepEqual(reused.record.result, result);
    const changedReviewer = await cache.resolveAccepted('review', dispatch.position, {
      ...current, reviewerIdentity: { id: 'different-reviewer', version: 1 },
    });
    config.content = 'timeoutMs: 2000';
    config.revision = '2';
    const changedSource = await cache.resolveAccepted('review', dispatch.position, current);
    const unchangedPolicy = await cache.packet('policy');
    await assert.rejects(async () => cache.packet('apply'));

    console.log(JSON.stringify({
      sourceReads,
      proofRuns,
      sharedPacket: first.proofArtifact.digest === second.proofArtifact.digest,
      reused: reused.kind,
      changedSource: changedSource.kind,
      unaffectedPacket: policyPacket.proofArtifact.digest === unchangedPolicy.proofArtifact.digest,
      changedReviewer: changedReviewer.kind,
      effectfulRefused: true,
    }));
  } finally {
    await rm(directory, { recursive: true, force: true });
  }
  ```
</Accordion>

## Next steps

* [A file change approved byte for byte](/docs/patterns/safe-change): an
  approval bound to exact output bytes, with a backup and a readback.
* [Callback gates](/docs/reviewing/callback-gates): the stored client and the
  request identity an approval rides on.
* [Workspace](/docs/concepts/workspace): capturing and verifying the anchor a
  result is bound to.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.