From page exploration to stable regression
For an unfamiliar page, the coding agent starts from a fresh observation and chooses one action at a time. Once the path works and local evidence can prove its success condition, preserve the explicit actions, waits, and assertions as ACL for local development or CI. Both workflows use the same actions, drivers, evidence, and cleanup rules.
Agent sessions
The calling agent retains planning authority. Every turn follows the same sequence:
- Obtain a fresh observation and
observation_idfrom A3S Test. - Choose one action from visible state.
- Let A3S Test validate the action schema, capability, provenance, and policy.
- Execute through the driver and invalidate stale refs after state changes.
- Observe again until local evidence proves success or failure.
Semantic refs are not durable locators. @e1 or a Test Kit @c7 must bind to the latest observation that produced it. A model cannot claim state that the driver or Test Kit did not record.
Common commands:
agent act --action-json exposes the complete action schema. In v1.0.0, action protocol revision 15 includes the revision-7 selection-scoped insert_text action, revision-8 live control-state expectations, revision-9 target-bound rendered-output expectations, revision-10 ordered rendered-text collections, revision-11 two-target rendered-layout relations, revision-12 visual-viewport and pointer-hit expectations, revision-13 exact or component-scoped focus ownership, revision-14 disclosure, toggle, read-only, required, and validity state, and revision-15 bounded visual-viewport coverage. insert_text still acts only inside an editing context established by an earlier action and carries no target or locator authority of its own.
ACL suites
Express a stable path in ACL:
Run static admission before opening a surface:
Unknown blocks or attributes, duplicate identifiers, ambiguous conditions, invalid locators, and unsafe artifact paths fail before launch. Assertion failures, timeouts, and ambiguously dispatched actions are never replayed automatically.
Prove live control state
Presence and text are insufficient evidence for forms. A button can be visible but disabled, a checkbox can exist but be unchecked, and a multi-select can contain the right labels while holding the wrong selection. Revision 8 observes those states directly:
The complete paired conditions are enabled/disabled, checked/unchecked, and selected/unselected. value and selected_values use a separate target. Expected selected values must be unique and compare as a canonical exact set: order does not matter, but an extra or missing value fails. selected_values = [] is valid only when one real target exposes an empty selection.
Target resolution and state comparison are separate proof steps.
Web semantic targets traverse open Shadow DOM and recognize native multi-select listbox and option roles. A direct browser ref can read value, enabled, native checkbox/radio checked state, and admitted ARIA state, but the standalone ref protocol cannot expose native option selection or multi-select arrays. Use a stable semantic or CSS target for those forms. A Page Context ref remains valid when A3S Test resolves it to such a target before dispatch.
The checked-in evidence covers 400/400 deterministic Web classifications, 100/100 stable state windows, 100/100 transient-state rejections, and a standalone Chromium flow with 15/15 positive checks plus 4/4 negative error classifications and no private runtime leak.
Prove copy, repeated-item count, and exact rendered order
Page-wide text can pass because the same words appear in the wrong region. A one-element visibility assertion can pass while a list silently drops, duplicates, or reorders rows. Revisions 9 and 10 observe those facts directly.
These assertions deliberately use different identity rules.
Text normalization trims both ends and collapses whitespace runs, so nested markup and formatting line breaks do not create accidental mismatches. rendered_texts applies that rule independently to every item without sorting or deduplication. Empty locators produce []; ["Shipping", "Shipping"] remains distinct from ["Shipping"]. ACL and Web cap vectors at 256 items. visible_count = 0 and rendered_texts = [] are positive evidence from an evaluated locator, not missing-reference shortcuts. ACL accepts semantic or CSS locators but rejects observation refs and visual points for both collection forms.
CSS counting follows rendered pixels: aria-hidden by itself still counts, while hidden, display-none, visibility-hidden, fully transparent, and zero-geometry elements do not. Semantic counting follows the accessible interaction plane, excludes accessibility-hidden ancestry, and traverses open Shadow DOM. Neither form claims screenshot-level occlusion or viewport intersection.
The revision-9 datasets classify 600/600 scalar-text/count cases. Revision 10 adds 600/600 ordered-vector cases covering matches, reorders, duplicate/content mismatches, empty matches, empty-versus-expected mismatches, and invalid selectors. Combined stability datasets accept 300/300 consistent scalar-text/vector/count windows and reject 300/300 transients. The standalone Chromium CLI regression proves 12 passing observations, 12 error classes, three accepted and three rejected 100 ms windows, and exact runtime cleanup.
Prove spatial relationships from rendered geometry
Page Context can describe geometry, but a regression still needs an explicit product claim. Revision 11 compares two freshly resolved rectangles in one surface observation:
The closed vocabulary covers direction (above, below, left_of, right_of), containment (contains, inside), intersection (overlaps, not_overlapping), six edge/center alignments, and width/height/size equality. Tolerance is a bounded integer from 0 through 1,024 CSS pixels. It allows limited edge intrusion for direction and containment, requires overlap greater than the tolerance on both axes, and uses absolute difference for alignment and size.
Both targets must be repeatable semantic or CSS locators. Browser refs and visual points fail ACL admission because their geometry belongs to one observation. Current Page Context refs remain usable only after both resolve to stable locators. Web then resolves and reads both rectangles in one page evaluation, preventing a dynamic page from combining geometry sampled at different moments.
CSS follows visual rendered visibility, so an otherwise visible aria-hidden target remains measurable. Semantic locators follow the accessible interaction plane, exclude accessibility-hidden ancestry, and traverse open Shadow DOM. Missing, ambiguous, invalid, hidden-semantic, and malformed geometry stay driver errors. Only two valid rectangles that violate the requested relation become test.assert.layout.
A passing result records both targets, both rectangles, relation, tolerance, and matched = true. Stability retains that complete payload under assertion.first and assertion.last; a later relation mismatch becomes test.assert.unstable. GUI requires both frames in one fresh CUA snapshot, while TUI fails closed instead of treating terminal cells as browser geometry.
The checked-in evidence classifies 3,400/3,400 deterministic relation cases, accepts 100/100 sustained windows, rejects 100/100 transients, and verifies all 17 relations, 25 positive assertions, and 15 negative or driver-error cases in standalone Chromium with exact fixture and runtime cleanup.
Prove viewport presence and pointer reachability
Rendered visibility establishes a box, not where it is, how much of it is present, or what receives a pointer hit. Revisions 12 and 15 expose those facts separately.
Use in_viewport when any positive area is enough. Use viewport_coverage_at_least when a minimum material share must be present, and viewport_coverage_at_most when most or all of a target should remain outside. Coverage is intersection area divided by complete target area. at_least accepts integer percentages from 1 through 100; at_most accepts 0 through 99, excluding the two unconditionally true endpoints. Use pointer_reachable when browser hit testing must reach the target or a composed-tree descendant at one of nine deterministic points over the visible intersection. Coverage proves geometry, not occlusion. None of these forms proves enabled state, keyboard access, event handling, or business clickability.
Web resolves the stable locator, captures both rectangles, and performs optional deep hit testing in one page evaluation. Semantic locators and hit testing cross open Shadow DOM. Native paint and pointer-events rules decide occlusion, so a transparent pointer-receiving cover blocks while pointer-events: none passes through. Rust then recomputes the ratio and every 1/6, 1/2, 5/6 sample coordinate before accepting the evidence.
Browser refs and visual points fail ACL admission because they cannot be re-resolved through a stability window. A current Page Context ref may resolve to a stable semantic or CSS locator first. Missing, ambiguous, invalid, and malformed evidence stays driver-owned. Valid offscreen geometry becomes test.assert.in_viewport; valid threshold mismatches become test.assert.viewport_coverage_at_least or .viewport_coverage_at_most; nine valid misses become test.assert.pointer_reachable. GUI and TUI fail closed.
The checked-in evidence covers 1,000/1,000 base Core geometry cases plus 2,000/2,000 threshold cases, 4,000/4,000 Web protocol classifications, 300/300 sustained and 300/300 transient windows, and a standalone Chromium matrix with 37 passing assertions and 25 negative or driver-error classifications plus exact cleanup.
Prove where keyboard focus landed
Sending Tab, Shift+Tab, or a focus action proves only that input was dispatched. Revision 13 observes the resulting focus owner directly.
Use focused when one exact element must own focus. Use focus_within when any control inside a component, dialog, or composite scope is valid. The scoped form follows the rendered flat tree through assigned slots, DOM parents, and open-shadow hosts. The two negative forms still require a real resolved target; absence cannot masquerade as correct focus behavior.
Web resolves the stable locator and reads the deepest active element through nested open shadow roots in one page evaluation. Semantic locators cross open Shadow DOM and exclude accessibility-hidden composed ancestry. CSS retains current-document query semantics. Browser refs and visual points fail ACL admission, while a current Page Context ref may first resolve to a stable locator. GUI and TUI fail closed without equivalent evidence.
Keep these assertions separate from visible focus styling, pointer reachability, enabled state, and business activation. A correct focus owner does not prove any of those facts. Checked-in coverage classifies 600/600 deterministic Web cases, accepts 200/200 sustained windows, rejects 200/200 transients, and verifies 17 positive assertions plus 11 negative or driver-error classifications in standalone Chromium. The browser flow includes forward and reverse Tab, open Shadow DOM, assigned slots, hidden slot ancestry, timed focus movement, and exact cleanup.
Prove live semantic state
Revision 14 observes five state dimensions directly from the rendered control.
The inverse forms are collapsed, pressed, writable, optional, and valid. Web gives applicable native state priority: <details>.open, native read-only or required properties, and Constraint Validation when willValidate is true. Other elements may expose valid ARIA state. Boolean ARIA accepts only true and false; aria-invalid also accepts grammar and spelling. Mixed pressed state, unknown tokens, and absent evidence fail closed as unsupported.
The dimensions remain independent. writable proves only that the applicable read-only state is false, so combine it with enabled when the requirement is actual editability. Negative forms still require a resolved target and an observed boolean. Missing elements cannot masquerade as collapsed, unpressed, writable, optional, or valid.
ACL accepts repeatable semantic and CSS locators and rejects browser refs or visual points as test.spec.semantic_state_target_unstable. A current Page Context ref may resolve to a stable locator before dispatch. Missing, ambiguous, invalid, and unsupported evidence stays driver-owned; only an observed mismatch receives the condition-specific test.assert.* code. GUI and TUI fail closed, and all ten forms accept bounded assertion stability.
Checked-in coverage classifies 1,000/1,000 deterministic Web cases, accepts 100/100 sustained windows, rejects 100/100 transient windows, and verifies 27 positive assertions plus 17 negative or driver-error classifications in standalone Chromium. The fixture covers native state, valid and invalid ARIA, open Shadow DOM, precedence, transient expansion, and exact cleanup.
Prove that UI has no visible match
Use hidden when closing, dismissing, removing, or visually hiding a target is the product requirement. The assertion passes when the stable locator has no matching element or when every match has no rendered visible box.
hidden is runner policy around the existing positive visibility assertion. It does not add an action variant; the current protocol is revision 15 because of the typed expectations above. The runner sends a positive probe to the surface driver and classifies its result deterministically.
Use role, label, test ID, placeholder, text, CSS, or another stable locator supported by the selected surface. ACL admission rejects ref() and visual_point() as test.spec.hidden_target_unstable: both belong to an observation, so an unresolved value may be stale rather than hidden. A programmatic suite that bypasses admission fails before dispatch as test.run.assertion_mode_invalid.
expect hidden observes immediately. To prove the target remains hidden through hydration or rollback, combine it with bounded sampling:
If the initial hidden probe passes and a later probe finds a visible target, the result is test.assert.unstable. The stability payload retains visible = false in assertion.first and the visible counterexample in assertion.last.
Wait until a target disappears
Use wait hidden when disappearance is the readiness condition. It completes immediately for an already hidden or absent target, without guessing an animation duration.
The ACL compiler keeps Action::Wait(WaitCondition::Visible(target)) and adds runner-owned WaitMode::Hidden. This still reuses the earlier visible-action variant under current action protocol revision 15. Runner executes an immediate positive visibility assertion, then repeats it every 50 ms while the target remains visible.
The static ceiling is 1,201 probes. A longer programmatic deadline cannot exceed it and fails with test.run.hidden_wait_probe_limit. Scenario timeout and cancellation keep their normal statuses and exit codes, close the exact owned session, and retain last_visible counter-evidence. output.data.wait reports outcome, poll_interval_ms, max_probes, probes, and observed_ms. Agent-run deterministic verification uses the same runner path, so the ACL has identical semantics there.
Prove that transient UI has settled
A one-shot expectation answers “is this true at this observation?” That is sufficient for static content, but it can accept one frame of a loading flash, hydration replacement, optimistic update, or animation. When the product requirement is “this remains true while the interface settles,” declare that time requirement on the expectation:
These three synchronization tools answer different questions.
After the initial expectation passes, the runner starts the 300 ms window, repeats the same read-only assertion every 25 ms, and always takes a final sample at the boundary. If sample 2 or later is false, the step fails with test.assert.unstable. A passing step retains machine-readable evidence:
The first false sample keeps its original test.assert.* code because the stability window never started. A later false sample becomes test.assert.unstable. A driver or infrastructure error retains its own code and makes the window inconclusive. Scenario cancellation and deadline can interrupt both interval waits and driver calls; owned cleanup still runs.
Sampling is finite evidence. It detects a change only when that change overlaps an observation point, so it cannot prove absolute continuity between samples. A shorter interval raises temporal resolution and browser work. Reserve it for product-relevant flicker, and budget timeout_ms for all preceding steps, the full stability window, command latency, and any admitted infrastructure retry.
Local verification still decides the result
A deployment may inject a schema-constrained HTTP LLM provider through a3s-test agent run, but the provider can only propose one typed action or request completion. It cannot decide the verdict, fabricate observation, or authorize repair. Success still requires at least one local expect and clean closure of the exact owned surface.
Continue with Test Kit for rendered page context and human repair review.
