Skip to content

Make the sandbox loss-injection demo compatible with recovery reconstruction #56

Description

@rmcdaniel

Status Summary

At sample-app:main commit 45f68b9e876a5094c61f2f1f393e8923820e7262, the documented php artisan app:sandbox --snapshot-every=2 --inject-loss-after=2 path inserts a successful evict tool call immediately after the latest snapshot. durable-workflow/ai correctly journals every completed post-snapshot call and replays it when rebuilding a lost sandbox.

When the next call discovers the loss, reconstruction therefore replays evict against the restored sandbox. The replay deletes that replacement and its result names a different sandbox ID than the recorded result, so outcome validation fails. Even without that result mismatch, reconstruction would return a sandbox that the replay just removed. The README, sandbox walkthrough, and conformance surface currently claim this command demonstrates a successful recovery.

How to fix

Provide a development/test loss-injection boundary that is not represented as a successfully completed tool effect requiring reconstruction. Keep the trigger deterministic across workflow replay and activity retries, consume it only for the intended loss event, and do not weaken reconstruction of genuine completed post-snapshot effects. Update the Sample App command/configuration and documentation to use that boundary.

Add package-level coverage for the injection semantics and a Sample App end-to-end check proving the documented command completes with one recovery, preserves the snapshotted workspace state, and continues the remaining calls.

Delete when

The exact documented loss-injection command completes on Sample App main against a published durable-workflow/ai artifact, reports the expected recovery, and cross-repository CI prevents a successfully journaled destructive injection from being replayed against the replacement sandbox.

Required source targets

durable-workflow/ai@main
durable-workflow/sample-app@main

Metadata

Metadata

Assignees

No one assigned

    Labels

    authority:githubGitHub is the authoritative lifecycle record for this workbeta:compatibleMay be completed without changing the frozen beta contractkind:cross-repositoryWork spans more than one public repositorypriority:P2Normal-priority product workrepo:sample-appOwned by the sample application repositorystatus:readyReady for implementation

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions