Repository navigation
fix(flow): halt a relabelled Save on the Save, not the scroll before it - #1337
Merged
Merged
Conversation
…it (#1331) A closed-loop scroll stops when the next step's anchor resolves. When the vendor relabels that control, the scroll used up its budget and the run halted on the scroll, so self-repair refused it ("not a click"). Now, when every readiness probe missed because no direct deterministic rung found the target, a non-consequential scroll hands the miss to the next click. That click accepts only direct rungs (structural, template, OCR; no model) and halts with the ordinary "Could not resolve target" error and no input. A target that resolved but was out of place or failed its identity check still halts on the scroll, as does a consequential scroll or one in a program graph. The RECONCILIATION_REQUIRED outcome on openIMIS is correct: the Tab key and the unlabelled picker click carry risk_review_required, so a write cannot be ruled out. Self-repair's refusal now names the unsettled steps and says a person can review them with `qualify set-risk`; once reviewed, the same halt is HALTED_BEFORE_EFFECT and repairable (tested). The reliability classifier files the handed-off halt as resolution_failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e-halt-1331 # Conflicts: # packages/flow/openadapt_flow/runtime/replayer.py
abrichr
added a commit
that referenced
this pull request
Oct 19, 2026
MockMed, all 22 drift modes, 3 trials, a real Claude repair agent and a scripted approver: 30 stops, 21 reached repair, 6 resumed and verified (relink and redesign 3 of 3 each), 0 wrong saves in 66 runs. Not repaired: a save moved into a closed menu, a new interstitial, a new required choice, and font/zoom false stops of a pixel postcondition. The worklist run (vendor change after the pre-flight): 10 stopped items, 2 repairs on the test record, 2 person decisions, 10 of 10 resumed and verified. Routed offline: the 8 recorded OpenEMR stops behind #1347 and the 3 openIMIS relabel stops of #1331 (before #1337) were all RECONCILIATION_REQUIRED, so none reached repair. Docs: SELF_REPAIR (repair is the default, Measured), REPAIR_LIFECYCLE, LIMITS, JIT (reuse binding), CAPABILITIES; llms-full.txt and the public artifact inventory regenerated with their scripts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
abrichr
added a commit
that referenced
this pull request
Oct 19, 2026
…enIMIS live The live openIMIS run of the relabelled Save (#1331, with #1337 merged locally and a scripted risk review) found two self-repair bugs: - a re-targeted save that carries a submit_binding got the DOM locator under the new point, and a step may not carry both, so the patched bundle failed to load even though the agent found the right control. The patch now keeps such a step visual and keeps its binding. - the halted session stays open while a probe opens another, and two Playwright drivers can't share a thread. Tests hid it behind their fixture's shared browser. run now shares one browser for every session of a repair. Measured: with the review, the stop reaches repair 3 of 3 (0 of 3 before); the agent found SAVE CLAIM 2 of 3; no fix passed the probe, because the replay sees the Save disabled where the template was cropped from the enabled button. Nothing was written. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e-halt-1331 # Conflicts: # CAPABILITIES.md # packages/flow/openadapt_flow/repair/self_repair.py # packages/flow/openadapt_flow/runtime/replayer.py
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.
Refs #1331. This PR fixes both causes in code. It does not re-run the openIMIS drift row live (see "Not done").
What was wrong
1. The halt lands on the scroll. The cause is locator resolution, not settle or step order. A closed-loop scroll stops when the next step's anchor resolves. After the relabel, the Save never resolves, so
step_014uses its 2.5x budget and the run halts there._repairablethen refuses it because a scroll is not a click.I replayed the readiness probe offline on the recorded frames of all three item-50 attempts (
~/.cache/openadapt-scoreboard/.../2026-10-19-a/item-050-{1,2,3}), against the launch-4 bundle. On every frame before and after the scroll, the Save resolves bygeometryonly. Scroll readiness rightly rejects that rung. On the healthy item 49 it resolves bytemplateat the recorded point.2. RECONCILIATION_REQUIRED is correct, so I didn't relax it.
step_002(Tab) andstep_012(unlabelled picker click) carryrisk_review_required. They acted, and nothing proves they wrote nothing. Calling thatHALTED_BEFORE_EFFECTwould be a false claim of no effect. I found no outcome that was labelled wrong. The existing reviewed-risk binding (openadapt-flow qualify set-risk) clears it. Once a person classifies both steps, the same halt isHALTED_BEFORE_EFFECTand_repairablereturns the Save. The test covers this.Changes
runtime/replayer.py: when every readiness probe of the next click missed because no direct rung found it, a non-consequential scroll in a linear run hands the miss to that click. The click then accepts only direct rungs (structural, template, OCR, no model). It halts with the usualCould not resolve target for step ...error,delivery_attempted=Falseand no input. These cases still halt on the scroll as before: a target that resolved but was out of position or failed its identity check, a consequential scroll, and a scroll in a program graph.repair/self_repair.py: thenot_repairablereason for a run that endedRECONCILIATION_REQUIREDnames the unsettled steps. When all of them are unreviewed-risk steps, it points toqualify set-risk.benchmark/reliability.py: the handed-off halt is classified asresolution_failed.SELF_REPAIR.md(halt rules),CAPABILITIES.mdrow, regeneratedllms-full.txt. No new commands.Tests
tests/test_relabelled_save_halt.py, a synthetic openIMIS-shaped fixture: Tab and picker (both unreviewed), a scroll up, and a relabelled icon-only Save. It checks three things: the halt is on the Save with no Save input; an unreviewed run staysRECONCILIATION_REQUIREDwith an explanatory refusal; a reviewed run isHALTED_BEFORE_EFFECTand repairable. Two of the three fail onmain(checked in a detached worktree). The fail-closed one passes on both, as intended.tests/test_replayer.py: two exhaustion tests now expect the halt on the click. A new test checks that an identity miss keeps the halt on the scroll.test_replayer.py,test_program_ir_phase1.py,test_transaction_outcome.py,test_relabelled_save_halt.py,test_capabilities_map.py(213 passed). CI runs the full suite.Not done
openadapt-demo) is stopped. Starting it plus the compose stack under a load average of about 190 would delay the timed measurements, so I left it.step_002andstep_012on the launch-4 bundle (qualify init, thenqualify set-risk ... --classification state_changing). In the scoreboard, a scripted reviewer would stand in for that person and should be disclosed inmeta.json(demo: CUA to program on openIMIS claims, plus the scoreboard (arms 1-3) #1303).step_015and go to self-repair. The Save's identity template has tokens, so frame campaigns apply rather thanneeds_fault_probes.🤖 Generated with Claude Code