Repository navigation
fix(pixel): every non-passing preview inspection returns a ready, validated next call or a measured diagnosis - #6748
Open
Lightheartdevs wants to merge 4 commits into
Open
Lightheartdevs wants to merge 4 commits into
Lightheartdevs wants to merge 4 commits into
Conversation
…ll or a measured diagnosis OpenClaw 2026.6.33 drops finalize revisions after a plugin tool call, so the inspection result is the only place a fix can reach the model. On main d4a61f3 (fleet round 107) the website journey failed on laptop, strixy and mac-mini while all three towers passed, and each failure ran out of the four-consecutive-failure budget on the inspector itself: - invalid_request named no step, key or args and told the model to "call tool_describe ... then retry through tool_call"; strixy obeyed it as tool_call {id:"tool_describe"} twice after flattened steps, laptop omitted exact:true and later sent {}. - no_match / invalid_selector gave generic locator advice; mac round 106 hit the fuse on a working page where the requirement-derived plan passes. - visibility_mismatch gave one generic sentence; laptop and mac read the receipt's "before" as a pre-script snapshot and called a real click-handler bug a timing issue. Now: - invalid_request names the failing step and key. A lossless repair (flattened selector or role/name moved into locator; exact:true on a role/name locator) is validated and offered as exactly-these-args with the request's own identifiers. Otherwise, on a valid snapshot binding, the guard-bound owner requirement supplies the #6740 plan over the valid steps; else one placeholder shape example. The tool_describe/tool_call sentence is gone; the unsupported-role error lists the roles. - A failed receipt whose failing step is a locator failure consults the bound requirement and appends a ready plan that never reuses the failing locator and never equals the failing plan (chooseTransitionTarget gains an avoid option). A role/name locator that matched nothing for assert-visible or click may be a hidden element and keeps its existing feedback. [class="..."] selectors get the whole-string explanation. - visibility_mismatch, click_failed and unstable get the step's measured display, visibility, opacity and rectCount, the earlier clicks, fixed inspector facts (scripts run, real click, "before" is that step's measurement) and one repair-and-republish step; no args. Details stay the capsule receipt (or the invalid_request shape) and isError stays true; the INCOMPLETE path, page-error precedence, Evidence JSON and palette line are unchanged. One assertion in inspection_transition_coverage.test.mjs that required a tower2 round 102 locator failure to stay byte-identical now checks the recorded text is kept with one ready call added. Tests: unit tests for the argument repair and rejection text; replays of strixy r107, laptop r107 (through createToolLoopGuard), mac r106 and mac r107 from recorded bytes and receipts; opt-in real-Chromium replays in ods/tests/test_preview_inspection.py. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nd the measured target Review of PR #6748 found that the new failure texts could steer a model the wrong way. Replays of rounds 105 to 107 through the real guard and real Chromium showed where: - The text before any click treated requestedVisibilityTransition's hidden-first default as the owner's words. It told hide-on-click owners to hide the element as the page loads, and said "the owner asked for it hidden initially" for plain toggles. - After a click, any failing step got "repair the source". On tower2 round 107 (a passing session) that included the model's own extra check of the renamed "Hide sold out" button, after steps 4, 6 and 7 had already measured the card hidden, then clicked, then visible. - "Inspect the new snapshot with the same steps" kept state-qualified locators that the suggested repair removes; laptop round 107 call 40 failed that way. - Laptop round 107 was not rescued. Its first ready args kept a step that could not pass. A visible button styled text-transform: uppercase was called hidden. A role/name heading target turned a broken toggle into a no_match dead end. - A ready call was offered on the failure that exhausts the progress budget, where the next call is always refused. Changes: - statedVisibilityDirection (preview-interaction-assurance.mjs) returns 'hidden' for an initially-hidden phrase or a click that only reveals, and 'visible' for a click that only hides. A toggle, both or neither gives undefined. requestedVisibilityTransition is unchanged. - The guard keeps the stated direction with the intent, and a preserve turn inherits it. The new previewInspectionGuidance(toolCallId, params) returns it for exactly the pending call, together with finalFailure from the read-only budget.failureEnds(lane). index.js passes it to the tool. Guidance is wording only: proof, the budget and the requirement are unchanged. - Before any click: - Stated and the page is wrong: repair. - Stated and the plan is reversed: the owner-order plan on the same snapshot. - Not stated: both orders, and the owner is not named. - After a click: - Passing earlier steps already measured one locator hidden, then clicked, then visible, and the failing step is another element: those steps are offered. - The failing step is another element: the target plan is offered. - The element changed where the plan expected no change: the corrected step is offered. - The target did not change: repair. - Steps after a repair are the target plan (an id, or an item CSS locator that avoids the class the repair may change), never "the same steps". - A lossless argument repair that tests no change gives way to the owner's requirement plan. - A role/name click that matched no rendered control: - The text names text-transform and earlier renames as causes. - The control's published CSS locator is offered, from control names now recorded in the outline. - Failure paths prefer a CSS item target over a role/name heading. The target is bounded below any element that holds another heading or the control. A heading matched hidden and then unrendered after the click is offered only a CSS target. - On the failure that ends tool use, every next step is replaced by: do not call any tool, answer now. - The coaching no longer says "call tool_describe"; tool_call takes the tool's id directly (OpenClaw 2026.6.33 tool-search findEntry). Tests: - Guard-level guidance tests: stated direction, preserve-turn inheritance, toggle, finalFailure, outline control names. - Replays: laptop round 107 calls 4, 5, 13, 24 and 26, strixy round 107 at the limit, tower2 round 107 calls 20 and 21, and mac round 107 with and without the requirement. - Reviewer probes P4, P5 and P9. - failureEnds unit test. - Opt-in Chromium BrowserTests: the uppercase control, the CSS item target on site-c54d9d87, the call-24 id click, and the mac round 107 repair steps. inspection_transition_coverage.test.mjs is not modified further. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…call PR #6741 added load-time control names to the capsule receipt and locator feedback built from them (presentName, nameDiagnosis). It conflicted with this branch in three files. - workspace-preview-inspect.mjs: - locatorFeedback keeps #6741's texts, split into diagnosis and next step so a final failure can replace the next step. - When the load-time names show the requested name on a rendered control, the same steps are offered with that control's published CSS locator. #6741 already names that locator as the fix. - A name that differs keeps #6741's repair-or-rename text with no ready call. - Only an unexplained role/name click miss adds the rename causes (text-transform, an earlier click). The generic text #6741's tests pin is kept. - The evidence copy omits controls, as in #6741. - tool-loop-guard.mjs: both import additions. - test_preview_inspection.py: both BrowserTests blocks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Sep 26, 2026
Open
…the owner's target measuredFeedback offered an earlier passing transition of any locator as the ready call when a later step failed. On a page whose click reveals an unrelated element but leaves the owner's requested card hidden, that call passed, bound the visibility proof and verified the run (reviewer probe P1/P1c of #6748). The guard's own instruction says not to substitute an unrelated passing interaction. With a target named from the published source, the passing prefix is offered only when it changed that target, and never when the failing step is on the target itself, which is then its measured defect. Tower2 round 107 call 20 (the prefix changed the target) keeps its ready call. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Problem
OpenClaw 2026.6.33 drops
before_agent_finalizerevisions after a plugin tool call, so an inspection fix can reach the model only in the tool result. On main d4a61f3 (fleet round 107),website_create_artifact_preview_interactionfailed on laptop, strixy and mac-mini, and the failure cascaded intowebsite_followup_editandconversation_reload_continuity. All three towers passed.Every failing host used up the progress budget (4 consecutive or 12 total failures) on the inspector itself:
tool_call {id:"tool_describe"}twice and was stopped.exact:true.beforeas a pre-script snapshot, and later sent{}.Evidence is in tower2
ods-main-qualification-20260924-r049, round-10{5,6,7}.Change
Every non-passing inspection result now names exactly one of these:
isErrorstays true.detailsstays the capsule receipt, or theinvalid_requestshape. The Evidence JSON, the palette line, page-error precedence and the INCOMPLETE (#6740) path are unchanged. Proof binding is unchanged.Rejected arguments (
invalid_request)selectoror role/name intolocator, and addsexact:trueto a role/name locator..event-card.sold-outhidden, clicks, then asserts it visible.tool_describesentence is gone. The guard's coaching now saystool_calltakes the tool's id directly, which is how OpenClaw 2026.6.33 tool-searchfindEntryworks.Locator failures (
no_match,selector_not_unique,invalid_selector)no_matchdead end (laptop call 13, site-c54d9d87).text-transform: uppercasebutton.Measured failures (
visibility_mismatch,click_failed,unstable)statedVisibilityDirection: an initially-hidden phrase or a click that only reveals means hidden first, and a click that only hides means visible first. A toggle, both or neither leaves it unstated.Final failure
previewInspectionGuidance(toolCallId, params)is bound to exactly the pending call, likepreviewInspectionTransition. It carries the stated direction andfinalFailurefrom the read-onlybudget.failureEnds(lane).Review fixes (round 1, d775fbd)
finalFailurereplaces the next stepReplays of rounds 105 to 107 through the real guard and real Chromium:
#showSoldOutBtnplan → passes on the repaired page. Three failures, with a reset in between..reveal-btn) pass once the handler toggles the class.Review fixes (round 2, f67b0ab)
#notebut leaves the requested#midnight-cardhidden, the plan#notehidden, click,#notevisible,#midnight-cardvisible failed at step 4 and was offered steps 1 to 3. Sending them passed, bound the visibility proof and set the run's verification to passed (reviewer probes P1 and P1c, direct andtool_call). The guard's own instruction says not to substitute an unrelated passing interaction.inspection_recovery_replay.test.mjs: "another element's passing change is never offered in place of the owner's target". It fails on 447fd80 and passes here.Composition notes (for whichever of these lands second)
failureEndsdoes not know about Defer a host-guided inspection failure that would stop the run for exactly one corrected attempt, with every hard bound kept #6749's waiting charge. Composed as merged, a correctable failure at the fuse is told "do not call any tool" even though the budget admits its corrected call. The strixy test "the failure that ends tool use names no further call" fails on main + fix(pixel): every non-passing preview inspection returns a ready, validated next call or a measured diagnosis #6748 + Defer a host-guided inspection failure that would stop the run for exactly one corrected attempt, with every hard bound kept #6749. A reviewer sweep of 300 plans found 83 results worded as final whose next call the guard admitted. The integration needsfailureEnds(lane, {correctable})to follow Defer a host-guided inspection failure that would stop the run for exactly one corrected attempt, with every hard bound kept #6749's failure path, plus acorrectableWaitshint. With that, the same sweep finds 0 mismatches and the full suite passes.Merge with main (#6741)
Main moved: #6741 added load-time control names. This branch merges 6cba572. The three conflicts are resolved as described in the merge commit:
controls.The branch merges cleanly with current main 321f82a (#6746, playground paths only).
Not changed, and why
boundVisibilityInspection). This behavior predates this PR. Gating proof on direction would rest on the wording heuristic, and "Clicking shows it; clicking again hides it" already derives visible-first, so correct toggles would fail. This PR only removes the steering: it never offers a plan reversed against a stated direction.Deliberate test edits (owner sign-off)
inspection_transition_coverage.test.mjs: one assertion (from round 1). The tower2 r102 create-turnno_matchtext is kept byte for byte, with one ready call inserted. This is the same pattern as laptop call 5. Nothing else in that file changed.preview_interaction_assurance.test.mjs: the finalize coaching assertion/tool_describe/is inverted, and the newtool_callsentence is asserted.Tests
Full Linux suite (
remote-js-test.sh, tower2):tower2 Linux:
node --test ods/tests/test-preview-inspection.mjs: 30/30.python3 -m unittest tests/test_preview_inspection.py: OK (89 tests, 46 opt-in skipped).Opt-in real Chromium (
ODS_PREVIEW_BROWSER_TESTS=1): all 39 BrowserTests pass, including fix(pixel): verify owner-requested exact control names after the page scripts run #6741's. They ran locally on Windows, with the Playwright headless shell and a scratch shim foros.killpg. tower2 has no Python Playwright. The new tests cover:New or updated JS tests:
inspection_guidance.test.mjs: stated direction for exactly the pending call, inheritance on a preserve turn, toggle,finalFailure, and outline control names.inspection_recovery_replay.test.mjs: laptop calls 4, 5, 13, 24 and 26; strixy at the limit; tower2 r107 calls 20 and 21; mac r107 with and without the requirement; P4, P5 and P9; and load-time names with the published control.run_progress_budget.test.mjs:failureEnds.ods/tests/test-preview-inspection.mjs: direction-aware texts, and the final failure across every failing path.inspection-recovery-tower2-round107.json, byte for byte fromJ/round-107/tower2/serving-logs/openclaw-pixel-a674292a-….jsonl.gz.🤖 Generated with Claude Code