A bundle exported after retention cleanup pruned the run's details
(workflow.details_state "pruned", history_complete false, no events) was
reported ok. Match PHP Core (workflow#980, 05ffc579): report the
history.details_pruned error at workflow.details_state with the pruned
timestamp and history_complete in the context. Bundle simulation and both
CLIs now block such bundles. Retained bundles and older exports without
the marker are unchanged, and the extended dedupe key is accepted as
exported.
The regression fixture is the exact pruned export from #228, produced by
the workflow#980 head whose tree the merge kept.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Closes #228.
Change
durable_workflow.history_bundle_verifynow fails a retention-pruned bundle (workflow.details_state == "pruned") with thehistory.details_prunederror, matching PHP Core'sBundleIntegrityVerifier.checkRetainedDetailsfrom workflow#980 (merged05ffc5794f8d554c4fb10c29a62da60e1a9e946c):at <details_pruned_at>), pathworkflow.details_state, and context{details_pruned_at, history_complete}. A missing, empty or non-string timestamp becomesnull, as in PHP'sstringValue.details_state: "retained", and older exports without the field. Only the exact string"pruned"triggers the error.dedupe_key(…:details-pruned:<timestamp>) is accepted as exported. Python performs no dedupe-key check, so there's no new rule.failed,simulate_bundlesanddurable-workflow-replay-verify --simulate-bundlesblock the bundle (block_and_investigate), anddurable-workflow-history-bundle-verifyexits nonzero. Bundle simulation doesn't execute workflow code; this is the integrity layer.Regression fixture
tests/fixtures/history_bundles/retention_pruned/pruned-bundle.jsonholds the exact bytes from #228: a realTestGreetingWorkflowrun, completed, pruned and exported by the workflow#980 head2e562997. The merge05ffc579kept that head's files unchanged (the compare shows no file diff). File sha256 is57f12ffb…bbf; the canonical checksum8fa57d07…01acstill matches.PHP's corpus entry
tests/Fixtures/V2/ReplayRegression/retention-pruned-run-export.json(sha2567016af05…) is a scenario descriptor that generates pruned exports at test time and carries no bundle bytes.provenance.jsonrecords that, along with PHP's expected verification result. The test asserts that Python's findings equal PHP's expected findings exactly.Evidence (local, macOS, Python 3.12.4)
tests/test_history_bundle_pruned.pyhas 14 tests: fixture bytes untouched, exact PHP parity, dedupe key, a pruned marker without a timestamp, retained and absent unchanged, near-miss markers, and simulation plus both CLIs.main's verifier, the 7 detection tests fail and the 7 unchanged-behavior controls pass.Expected to conflict with #229 only in
CHANGELOG.md(both add under Unreleased).🤖 Generated with Claude Code