HW-01: stable effect identity and durable receipt contract#139
Conversation
|
Repair3 pushed at e7f25e2. SQLiteEffectStore.complete() and fail() now canonicalize the original Mapping instead of collapsing it through dict(...). Added adversarial receipt/error regressions proving duplicate item streams are rejected while durable state remains claimed and no receipt/error persists. Local evidence: focused 20 passed; adversarial 3 passed; full 497 passed, 1 skipped; all four crash windows converged with one external effect and one durable receipt; exact allowlist/ancestry and git diff --check passed. Fresh independent SR then QR remain mandatory; do not merge. |
|
Repair4 at 4e65e72 binds EffectClaim.operation_id to the durable record before adapter lookup/performance. TDD evidence: the forged replace(valid_claim, operation_id=other_id) regression failed at e7f25e2 (DID NOT RAISE), then passed after the fix. Focused HW-01 suite: 21 passed. Four crash windows: each converged completed with one external effect and one durable receipt. Full suite: 498 passed, 1 skipped. git diff --check passed; exact repair diff is limited to src/hermes_workflows/effects.py and tests/test_effect_idempotency.py; e7f25e2 is an ancestor. Awaiting fresh independent SR/QR; do not merge. |
|
HW-01 repair5 pushed at Blocker repaired: TDD evidence:
Do not merge; fresh independent specification and quality/security review remain required. |
|
Repair6 pushed at 1f91be755925b59f93e068a81f5e8c2d53dd83a2 (from 79d0e56).
No merge performed. |
|
Repair8 pushed at 145803a: SQLiteEffectStore.complete() now rechecks durable unsafe authorization inside the completion transaction while preserving active-claim/token/expiry fencing. Added a real temporary-SQLite regression proving unauthorized public completion leaves the intent claimed and writes no receipt. Verification: focused 28 passed; all four crash windows passed; full suite 505 passed, 1 skipped; git diff --check clean; exact cumulative six-path allowlist and required ancestry verified. |
Summary
effects.adapters, contract v1)Delivery semantics
This contract is at least once, not exactly once. Supported idempotent adapters must deduplicate by the stable operation ID and provide receipt lookup. The durable receipt proves what the adapter reported; it does not claim universal exactly-once delivery.
Base and scope
583459d3ee36dae63f89dbd87d175f91b53ec39d79d0e5677b09859be70632c6003c96fcddbb671fStable identity receipt
Contract fixture vector:
op_779cfb267aaf4485e131af3c56d0366053f28814563e018beefab5b9627eaf950443d565a2434c98e2d2034c8bdc5621cc77e23864d75088f7b6e29e3d8ed9284808144715e0dfd168768fbe8ee17dac1a57f91bfe673af6065ac2a43cd91bf9The first TDD command failed with
ModuleNotFoundError: hermes_workflows.effects, then passed after implementation.Crash transcripts
Probe operation ID for all four windows:
op_d00b6c1fa97f79cb17494d6de67bea401b866b896bbcdb324fa62837d8c41c1cProbe input hash:
2c4c3d67557b89e6376283cf6017041fb69327f0e6a006715ec56471485a90e7Fencing rows below are
[state, claim_attempts, SHA-256(claim_token)]; raw opaque tokens are not exposed.[completed, 2, 3a614ac684eaf54235de04917066bddcceff57cf980876e5c5c919ba7e9e19ee][completed, 2, ce3b765b4b770d7d9a70276fb1252bd6d5e53ef3b6641b95dec24489d5014654][completed, 2, 274fe711d387d86e31e75ef37637a3924e33bd92002647515196f632ba54ace7][completed, 1, de1567ec2c7575e47d22887c51e519d069915408266a5c3fb1a45fdd79573edd]Contract evidence
access_tokenVerification
uv run pytest -q tests/test_effect_idempotency.py tests/contracts/test_effect_adapter_contract.py tests/test_runtime_services_contract.py→54 passedpython tests/probes/kill_after_effect.py→ all four windows converged to one external effect and one completed receiptuv run pytest -q→488 passed, 2 skippedgit diff --check→ cleanNon-goals
No central runtime activation, generic retry, lease cancellation, callbacks, live service/profile/registry/DB mutation, exactly-once claim, inferred purity, or UI redesign.
Do not merge until independent HW-01 specification and quality reviews pass.
Repair 1 evidence (782786b)
Closed the two fresh operation-identity integrity blockers at exact head
782786b2f2b8120bdf40fdde5be02caed0a59079:Mappinginput was silently collapsed and forged hash-shapedoperation_idwas persisted.SQLiteEffectStore.ensure_intentrecomputes complete identity from workflow/effect/adapter/canonical input before insertion and rejects mismatch.14 passed.16 passedacross compatibility + effect/adapter tests.491 passed, 1 skipped.2/2/2/1.git diff --check: clean. Exact six-path allowlist and base ancestry from583459d3ee36dae63f89dbd87d175f91b53ec39d: verified.Fresh independent SR, then fresh independent QR, remain mandatory before merge.
Repair 2 evidence (fc00967)
Closed the fresh receipt operation-identity blocker at exact head
fc0096772f95dd57fdd2bd75e81302288d5924a5:operation_idvalues were accepted and durably completed under the requested operation.18 passed.495 passed, 1 skipped.2/2/2/1.git diff --check: clean. Exact six-path allowlist and base ancestry from583459d3ee36dae63f89dbd87d175f91b53ec39d: verified.Fresh independent SR, then fresh independent QR, remain mandatory before merge.
Repair 5 evidence (79d0e56)
Closed the forged/stale/expired claim pre-adapter blocker at exact head
79d0e5677b09859be70632c6003c96fcddbb671f:adapter.callshad 2 entries instead of 0).24 passed.501 passed, 1 skipped.2/2/2/1.git diff --check: clean. Exact six-path allowlist verified; onlysrc/hermes_workflows/effects.pyandtests/test_effect_idempotency.pychanged.Fresh independent SR, then fresh independent QR, remain mandatory before merge.
Repair 7 evidence (a62fbd8)
Closed SR8's unsafe-policy bypass at exact head
a62fbd8c80a4d3bfc09933a3fcaa7eecb57292e7:ensure_intent(UNSAFE)+ claim +execute_claimedregression performed and durably completed the external effect without authorization; the authorized-path regression also proved no durable authorization column existed.prepare(..., allow_unsafe=True)persists it, andexecute_claimedrechecks the durable evidence before adapter lookup orperform. Unauthorized direct-store intents remain inventoriable/once-claimable but cannot call the adapter or write a receipt.27 passed.504 passed, 1 skipped.2/2/2/1.git diff --check: clean. Exact six-path allowlist and ancestry from repair base1f91be7c3742a539cd16aac810018e7783c7161c: verified; five allowed paths changed.9f3276542ccd570bfb90d4ecce2d27936df4da6caee45a05a387f68b7d59e52e.Fresh independent SR, then fresh independent QR, remain mandatory before merge.
Repair 9 evidence (78d9255)
Closed QR12s stale-claim generation bypass at exact head
78d925502120b2cf628a544596e4f4f5f598877d:145803a: a real temporary-SQLite expiry/reclaim regression forced the token generator to repeat the prior ownership token; the reclaimed attempt reused it, so stale and current claims were indistinguishable.SQLiteEffectStore.claim()no longer accepts caller-chosen tokens. The store generates ownership internally and refuses to reuse the active generations token, retrying generation before any durable claim transition.29 passed.506 passed, 1 skipped.2/2/2/1.git diff --check: clean. Cumulative diff is exactly within the six-path allowlist; base583459d3ee36dae63f89dbd87d175f91b53ec39dremains an ancestor.Fresh independent SR, then fresh independent QR, remain mandatory before merge.