Skip to content

Decouple preview/audit transition evaluation from mutating engine execution #220

Description

@rlippmann

Problem

preview() currently evaluates transitions by executing the normal mutating engine path and then restoring the previous state.

Current flow:

  1. Capture current state through a persistence-oriented state serialization path.
  2. Call engine.step(...).
  3. Capture resulting state.
  4. Restore the original state.

This preserves behavior, but couples audit functionality to the mutation/rollback model.

Desired direction

Introduce a private internal transition-evaluation path that computes the result of a transition without committing it.

Conceptually:

current state
    |
    v
compute next state
    |
    +--> preview/audit result
    |
    +--> commit for step()

step() remains the operation that commits authoritative state.

Benefits

  • Preview no longer needs temporary mutation and restore.
  • Audit can derive before/after state directly.
  • Preview and committed execution share the same transition logic.
  • Reduces coupling between runtime auditing and persistence APIs.
  • Creates a cleaner path toward future immutable state replacement.

Non-goals

  • Do not make transition evaluation a public API.
  • Do not remove state snapshots or persistence APIs.
  • Do not change external engine semantics.
  • Do not redesign the public audit contract.

Considerations

Any implementation should preserve:

  • preview results matching committed execution;
  • no mutation of the original engine during preview;
  • Python/TypeScript behavioral parity.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions