Repository navigation
flow: run the API step in durable runs without ever resending a save - #1358
Merged
Merged
Conversation
A durable or resumed run used to fall back to the GUI steps. Now the API step runs there too, under the same no-double-write rule. - The span's steps are checkpointed together once the save was sent (api_folded, then api). A save that wasn't sent checkpoints nothing in the span, so a resume runs the whole API step again. - A resume that would start inside a span whose steps were folded stops at the save: that save may have landed, so it is never sent again and never redone through the GUI on an empty form. This holds even when the approval authorizes one uncertain retry. A run that fell back to the GUI and stopped at the GUI save resumes it as before. - The attended reconcile action reads the record back and finishes the run when the record is there, without sending. - The linear loop now records each span result at its own index (it used the span's first index for all of them). - action_evidence accepts api_folded as a skipped, undelivered step. RECONCILIATION_REQUIRED is unchanged. Reconcile can't prove a record check that needs a before-snapshot (exact_new_set, count_new_only, collateral loss); that limit is the same for GUI saves and is documented. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The referral measurement found it: the save checks the right record on screen, the API step sent the save without any identity check, and the durable checkpoint then refused the result for lacking identity evidence, after the save had landed. The API step now runs for an identity-checked save only when its binding names a right-record contract; otherwise the GUI steps run and the report says why. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #1355 (approval binding). Merge that first; this PR then retargets to
main.Second of the small PRs that put the API step, pipelined read-back and self-repair in one production profile. This one handles durable runs.
Why
The API step (#1269) fell back to the GUI steps in every durable or resumed run. Standard and Regulated runs are durable, so production never used it.
What changes
api_folded, the save asapi. If the save wasn't sent (for example the record check's pre-state couldn't be read, or an approval stopped the item), nothing in the span is checkpointed, so a resume runs the whole API step again.reconcileaction reads the record back and finishes the run when the record is there, without sending anything.RECONCILIATION_REQUIREDis unchanged.action_evidenceacceptsapi_foldedas a skipped step with nothing delivered.Known limit (documented in API_TIER.md)
Reconcile reads the record as it is now, so it can't prove a record check that compares with the state before the save (
exact_new_set,count_new_only, a collateral-loss guard). The pause then stays for a person to check the record. The same limit already applies to GUI saves. Lifting it would need a protected pre-send baseline, which is not in this PR.Tests
tests/test_api_step_durable.py(new, 6 tests): a clean durable run checkpointsapi_foldedandapi. After a lost response, an ordinary resume is refused and a resume that authorizes one retry still stops without sending. Reconcile finishes without sending. A save the record check refutes isn't redone. An unsent save resumes the whole API step and saves once. A GUI fallback that halted at the save resumes on the GUI.Locally: 512 passed across the API tier, approval, durable, attended, resume, uncertain-delivery and multi-surface suites.
ruffand strict mypy pass. One unrelated e2e test (tests/e2e/test_chaos.py::TestLayoutSwapMidRun::test_swapped_type_buttons_still_select_the_right_type) fails the same way onorigin/main.Synthetic data only.
🤖 Generated with Claude Code