For AI agents: the complete documentation index is available at https://a3s-lab.github.io/Test/en/llms.txt, the full documentation bundle is available at https://a3s-lab.github.io/Test/en/llms-full.txt, and this page is available as Markdown at https://a3s-lab.github.io/Test/en/guide/testkit.md.

Add Web Test Kit

If the goal is to select an element, drag over a region, sketch the intended UI, or attach a page capture during development, install Test Kit and mount two components at the application root. After the three setup steps below, the page shows an A3S Review launcher. The default feedback path then has two decisions: choose an element or area, then describe the requested result.

What Test Kit adds

Test Kit connects a rendered page to its implementation without turning the page into an editor.

NeedImplementation
Let an agent read the page beyond a screenshotA headless Context Runtime derives bounded facts after DOM, accessibility, style, and layout are computed
Let a person point at the exact problemOne right-side Review Overlay keeps element and area visible, then reveals advanced marking, board, and capture tools on demand
Lead a selected node back to codeExplicit component boundaries, DOM ownership registration, and optional Source Map v3 produce ranked source spans
Prevent an old target from reaching a new pageExact revision deltas retain only unaffected context targets; every uncertain binding fails closed
Keep review separate from source mutationSaving stays local; only explicit submission enters the A3S Test repair ledger
browser finishes rendering
  -> Context Runtime publishes a bounded revision
  -> reviewer selects one target and describes the change
  -> Test Kit attaches current page, component, geometry, and source evidence
  -> explicit send crosses into the repair ledger
  -> the workspace-owning agent edits source
  -> A3S Test verifies a newer rendered revision

Three-step React setup

1. Install the development dependency

Run the version-pinned command in the frontend project:

npm install --save-dev @a3s-lab/testkit@0.6.2

The package is published on the official npm Registry with GitHub OIDC provenance. The pinned 0.6.2 package includes the simplified review panel, bounded SVG design board, in-page region capture, live CLI compatibility handshake, ranked rendered-node source mapping, and revision-scoped Page Context diffs without a browser extension, drawing SDK, screenshot plug-in, or screen-sharing permission.

Verify that the dependency belongs to the current project:

npm ls @a3s-lab/testkit

2. Mount at the application root

This is the smallest working React integration. Test Kit is enabled only during development, while the product application remains a normal child.

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { A3SReviewOverlay, A3STestKit } from '@a3s-lab/testkit/react';
import { App } from './App';

const testKitEnabled = import.meta.env.DEV;

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <A3STestKit enabled={testKitEnabled} page={{ id: 'app' }}>
      <App />
      <A3SReviewOverlay enabled={testKitEnabled} locale="en" />
    </A3STestKit>
  </StrictMode>,
);

enabled must explicitly be true before the browser bridge is installed. Do not rely on tree shaking to infer the environment, and do not enable the visible Review Overlay on a normal production page.

3. Open the page and verify

Start the existing development server and open the page. The integration is ready when an A3S Review button appears in the lower-right corner. Ctrl/Command+Shift+F opens the same side panel. If the launcher is absent, check these three conditions first.

  • A3STestKit and A3SReviewOverlay belong to the same React tree.
  • Both enabled props evaluate to true in the browser.
  • The integration mounts from a client entry rather than rendering only on the server.

Test Kit is a frontend SDK and does not add an a3s-testkit terminal command. Install the A3S Test CLI and Agent Skill only when tests must run from the terminal or an agent must receive repair work.

When the CLI is installed, verify the actual rendered integration instead of inferring compatibility from node_modules:

a3s-test init
a3s-test doctor
a3s-test dev --json

doctor checks the static package range. Before emitting ready, dev waits briefly for client hydration and validates a3s.test.testkit-handshake/1, the package identity, SDK range, Page Context protocol, required capabilities, and the live Review Overlay. Its ready event contains the admitted handshake. If a required boundary is missing or incompatible, A3S Test aborts only the browser session it opened and prints the exact install or mount repair.

After admission, dev --json also reports a3s.test.local-repair-bridge/1 under ready.repair_bridge. Send a finding from the ordinary Review Overlay and the same stdout stream emits a repair_batch only after the existing repair ledger and owned before evidence are durable. The event includes the generated session ID, so the coding agent can claim it without starting a separately coordinated repair-watch process. An optional page with no Test Kit reports repair_bridge: null and does not poll.

Most projects can stop here

Choose additional configuration only when the workflow needs it.

  • Element marking, area selection, board, and capture: Use A3STestKit with A3SReviewOverlay.
  • Headless Page Context in CI: Keep A3STestKit and omit the visible A3SReviewOverlay.
  • Component ownership and source hints: Add A3STestBoundary.
  • Exact selected-node source ownership: Let a framework adapter call registerSource and, when needed, registerSourceMap.
  • Send findings to a custom service: Add a same-origin repairEndpoint or onSubmitted.
Test Kit is an enhancement, not a prerequisite

A3S Test can still use browser accessibility semantics for typed actions, assertions, and evidence without Test Kit. Add Test Kit when you need component ownership, bounded source hints, multi-space geometry, rendered UI evidence, or human marking.

Add component boundaries when needed

A3STestBoundary is not required to start the Review Overlay. Wrap a region only when A3S Test needs component ownership or a bounded source hint.

import { A3STestBoundary } from '@a3s-lab/testkit/react';

<A3STestBoundary
  id="checkout-form"
  name="Checkout form"
  source={{ file: 'src/Checkout.tsx' }}
>
  <Checkout />
</A3STestBoundary>;

Map a selected node to source

Most applications need only the source hint on A3STestBoundary. It gives every descendant a coarse owning-file candidate. Framework adapters can provide an exact DOM owner and optionally trace its generated location through an explicitly supplied encoded Source Map v3.

import { registerSource, registerSourceMap } from '@a3s-lab/testkit';

const unregisterMap = registerSourceMap({
  id: 'vite-app',
  generatedFile: 'http://127.0.0.1:3000/assets/app.js',
  mapUrl: 'http://127.0.0.1:3000/assets/app.js.map',
  map: encodedMap,
});

const unregisterOwner = registerSource({
  id: 'react:pay-button',
  framework: 'react',
  elements: () => [document.querySelector('[data-testid=pay]')!],
  includeDescendants: false,
  generated: {
    file: 'http://127.0.0.1:3000/assets/app.js',
    line: 1,
    column: 1,
  },
});

export function disposeSourceMapping() {
  unregisterOwner();
  unregisterMap();
}

The selected node then carries ranked sourceMapping.candidates with a confidence, an exact or ancestor relation, and an origin of framework_adapter, source_map, boundary_hint, or generated. The same record enters explicitly submitted repair context, so the coding agent can open the likely file without another browser discovery turn.

Registration is explicit by design. Test Kit never reads React Fiber, Vue instances, or other framework-private state, never discovers or downloads source maps, and drops sourcesContent before storing a registered map. A source candidate is navigation evidence; it does not grant file-read or edit authority.

Framework-neutral integration

A non-React page can install the runtime directly and register one or more component boundaries.

import { getPageContextBridge, installTestKit } from '@a3s-lab/testkit';

const checkout = document.querySelector('#checkout');
if (!checkout) throw new Error('Checkout root is missing');

const runtime = installTestKit({
  enabled: import.meta.env.DEV,
  page: { id: 'checkout' },
  ready: () => document.readyState !== 'loading',
  facts: () => ({ currency: 'CNY' }),
  redact: ['[data-payment-field]'],
});

const unregister = runtime.registerBoundary({
  id: 'checkout-form',
  name: 'Checkout form',
  elements: () => [checkout],
  source: { file: 'src/checkout.ts' },
});

export function disposeTestContext() {
  unregister();
  runtime.dispose();
}

console.log(getPageContextBridge()?.probe());

Keep one active runtime per page. Calling installTestKit again disposes the previous runtime first. Call dispose() when an SPA replaces its application root, a micro-frontend unmounts, or a test fixture ends, so observers and the bridge do not remain attached.

Next.js client boundary

A3STestKit uses browser effects and must mount from a Client Component. Server rendering can still produce the product page; Test Kit installs its bridge only after hydration.

'use client';

import { A3SReviewOverlay, A3STestKit } from '@a3s-lab/testkit/react';

export function TestContext({ children }: { children: React.ReactNode }) {
  const enabled = process.env.NODE_ENV !== 'production';

  return (
    <A3STestKit enabled={enabled} page={{ id: 'app' }}>
      {children}
      <A3SReviewOverlay enabled={enabled} locale="en" />
    </A3STestKit>
  );
}

If browser tests in CI require Page Context, keep A3STestKit enabled and omit A3SReviewOverlay. Do not rely on tree shaking to infer production state; set enabled from an explicit environment condition.

Verify the integration

Check the probe, then read the smallest snapshot.

import { getPageContextBridge } from '@a3s-lab/testkit';

const bridge = getPageContextBridge();
if (!bridge) throw new Error('Test Kit bridge is unavailable');

const probe = bridge.probe();
const snapshot = bridge.snapshot({
  detail: 'summary',
  scope: { kind: 'page' },
  limits: { nodes: 100, uiNodes: 50 },
});

console.log({
  protocol: probe.protocol,
  revision: snapshot.revision,
  ready: snapshot.page.ready,
  components: snapshot.components.map((component) => component.id),
  truncated: snapshot.truncated,
});

A healthy integration meets at least these conditions.

  • probe.protocol equals a3s.test.page-context/1.
  • Test Kit 0.6.0 reports revision_diff in probe.capabilities.
  • snapshot.page.id matches the integration config.
  • snapshot.page.ready becomes true after the current render completes.
  • Declared boundaries appear in components.
  • The target has semantic locators or geometry, and redacted regions expose no original sensitive text.
  • When truncated is true, the caller narrows scope or follows nextCursor.

If the bridge is absent, ready stays false, or the UI record is omitted, use Troubleshooting instead of adding arbitrary polling to the product page.

Choose context or review mode

GoalComponents to mount
Local or CI automationA3STestKit, plus A3STestBoundary where useful; no visible interface is required
Human marking and batch repairAdd A3SReviewOverlay to the Context Runtime and configure an explicit submission handler or repair endpoint

Opening the Review Overlay, viewing advice, or saving a local draft never grants source-editing authority. Only a finding the reviewer explicitly sends enters the session-owned repair flow.

Sketch or attach the intended UI

After selecting an element or rectangular area, open Design reference from the finding editor. The board replaces the review panel and slides in from the right with one lightweight transition, without a page-blocking scrim or a second stacked pop-up. Drawing, image, history, and style actions share one localized icon toolbar.

The built-in SVG board supports freehand strokes, rectangles, text, selection, movement, resizing, styling, undo, and redo on a bounded 960 × 600 surface. A reviewer may also choose Select screenshot area, drag over one part of the visible browser page, and release to add that crop to the board. Escape cancels the temporary selection layer. This DOM capture excludes the Test Kit overlay and does not request screen-sharing permission. Upload, paste, and drop remain available for PNG or JPEG screenshots.

The board runs inside the Test Kit Shadow DOM and does not load a drawing SDK, license key, watermark, remote font, or CDN asset. It admits no more than 250 objects. Source images are limited to 8 MiB; inline references are limited to 384 KiB, 1,600 × 1,200, and 1,920,000 pixels. When a Web session receives the finding, the driver validates the image header and dimensions, writes repairs/<finding-id>/design-reference.png|jpg under the session artifact root, calculates its SHA-256 digest, and replaces the inline bytes with typed artifact metadata.

The overlay shares the A3S UI visual contract without adding a runtime UI dependency to the application. During the package build, Test Kit reads the pinned A3S UI foundation, task-pane, toolbar, and status-badge CSS exports, scopes root and dark-theme selectors to the overlay, and generates TypeScript constants for the Shadow DOM stylesheet. Host-page CSS cannot leak into that surface, and consumers do not need to import another stylesheet.

A design reference is reviewer evidence, not an instruction boundary or a verification result. It neither grants workspace authority nor replaces the before-and-after evidence owned by A3S Test.

Provider configuration reference

PropDefault or requirementPurpose
enabledExplicitly requiredInstalls the browser bridge only when strictly true
page.idRequiredIdentifies the current page context
readydocument.readyStateReports whether the page has completed its observable render
facts{}Returns project facts under JSON and byte bounds
redact[]Hides text and form content under matching selectors
maxNodes500Page Context node ceiling, with a 5,000 hard limit
maxStringBytes4 KiBPer-string ceiling, with a 16 KiB hard limit
maxEncodedBytes1 MiBEncoded Page Context ceiling, with an 8 MiB hard limit
uiUnderstandingtrueEnables the optional UI-understanding record
maxUiNodes200UI sampled-node ceiling, with a 1,000 hard limit
maxUiStateSamples200State-candidate ceiling, with a 1,000 hard limit
maxUiDurationMs32Per-capture UI time, with a 100 ms hard limit
maxUiEncodedBytes256 KiBEncoded UI ceiling, with a 1 MiB hard limit
repairStoragesessionSelect memory, current-tab session, or local
repairEndpointUnsetOptional same-origin repair adapter
maxQualityReports5Deterministic quality reports retained, clamped from 1 to 20
maxDesignAuditReports5Advisory design reports retained, clamped from 1 to 20

Installation options set ceilings. An individual snapshot() may lower node, string, encoding, UI-node, state, duration, and UI-encoding budgets but cannot raise them.

Public bridge API

Most React applications only need the components. Framework integrations, fixtures, and custom review surfaces can call getPageContextBridge() to use the same public bridge. Capture and mutation methods remain bound by the active runtime, current page revision, and installation budgets; read methods return cloned store state.

MethodPurpose and resultState and authority boundary
probe()Returns protocol, SDK version, and capability namesSynchronous capability discovery only; it does not capture a snapshot
snapshot(request?)Reads summary, scoped, diff, or forensic detail for page, node, component, or region scopeResults may truncate; cursor, scope, and revision must stay aligned
resolve(nodeId)Resolves a private current node ID to a still-connected DOM ElementPage-local integration only; unknown, removed, or stale nodes return null
waitForChange(revision, timeoutMs)Waits for a higher revision, returning it immediately when available or null on timeoutTimeout must be an integer from 0 through 300,000 ms
waitForDiff({ sinceRevision, timeoutMs, ...request })Waits for one higher revision and returns its exact bounded diff, or null on timeoutInvalid baselines and timeouts reject; no value is rounded or clamped
subscribe(listener)Subscribes to context, quality, design-audit, and repair events and returns an unsubscribe functionA listener observes events but receives no action or workspace authority
submitRepair({ findings, batchId? })Validates findings, captures current context, and returns queued recordsA repeated finding ID is idempotent; this call is the explicit send step
peekRepairBatch(limit?), takeRepairBatch(limit?)Reads or page-locally reserves up to 100 queued findingstake prevents duplicate pickup on one bridge; it does not replace an agent lease claim
listRepairs(), listRepairBatches()Reads submission-ordered records and aggregate batch stateReturns structured clones; mutating them cannot change store state
exportRepairs(findings), exportRepairsMarkdown(findings)Exports up to 100 findings as protocol JSON or MarkdownExport does not submit, claim, or authorize repair
applyRepairEvent(event)Applies a strict state event returned by an agent or serverRequires increasing sequence, a valid transition, and idempotent request ID
submitRepairAction(action), takeRepairActions(limit?)Queues and picks up human reply, accept, dismiss, or reopen actionsSession-side acknowledgement is still required
addRepairReply(reply), listRepairReplies(findingId)Appends and reads a bounded discussion threadThe finding must exist; request ID and message length are bounded
reportQuality(report), listQualityReports(), dismissQualityFinding(reportId, findingId), dismissQualityReport(reportId)Admits, reads, or closes deterministic Surface Contract quality reportsProtocol, size, finding IDs, and scope are strict; report verdict is unchanged
reportDesignAudit(report), listDesignAuditReports(), dismissDesignAuditFinding(reportId, findingId), dismissDesignAuditReport(reportId)Admits, reads, or closes advisory design-audit reportsRequires current revision, valid provenance, and live nodes; dismissal has no repair side effect
setAnimationsPaused(paused), animationsPaused()Pauses or resumes current Web Animations and playing media, and reads pause stateReview-only visual stabilization; dispose resumes content paused by Test Kit
dispose()Disconnects observers, waiters, listeners, boundaries, reports, and the global bridgeIdempotent; active-runtime operations reject afterward, while cloned repair history remains readable

TestKitRuntime also exposes registerBoundary(). The top-level function of the same name first looks up an installed bridge and throws when none exists. installTestKit({ enabled: false }) returns a disabled runtime: probe() and snapshot() reject explicitly, while repair and report methods return empty results instead of silently enabling collection.

Observe only what changed

Capture one normal baseline, then wait for the next meaningful difference:

let baseline = bridge.snapshot({ detail: 'summary', ui: false });
const diff = await bridge.waitForDiff({
  sinceRevision: baseline.revision,
  timeoutMs: 5_000,
  ui: false,
});

if (diff?.delta?.status === 'reset_required') {
  baseline = bridge.snapshot({ detail: 'summary', ui: false });
}

complete names every changed or removed node and changed component, plus independent page, facts, and UI invalidation. reset_required means the exact baseline is outside bounded history or its complete invalidation set cannot fit the byte ceiling; discard the old evidence instead of treating it as “no change.” Cursors bind the complete request and revision, so diff pagination cannot silently drift to another baseline.

Review Overlay props and callbacks

A3SReviewOverlay can use only its built-in interface or notify the host application about draft and submission events. Callbacks observe completed UI events. Synchronous exceptions and rejected promises are isolated so they cannot corrupt review state.

Prop or callbackDefault or triggerPurpose
enabledfalseMounts the Shadow DOM overlay only when strictly true and a compatible bridge exists
defaultOpenfalseSets initial panel expansion; it is not a controlled prop afterward
autoSendfalseSets whether the first save submits directly; reviewers can still toggle it
localeautoSelects English or Simplified Chinese and may follow <html lang>
messagesUnsetOverrides known presentation keys; blanks and values over 2,048 characters are ignored
copyToClipboardnavigator.clipboard.writeTextInjects copying for restricted iframes, Electron, or custom permission environments
onCopiedAfter successful JSON or Markdown copyReceives format, final text, and copied drafts
onDraftAdded, onDraftUpdated, onDraftDeletedAfter the corresponding local draft operationSynchronizes host draft counts or telemetry; no finding has been sent yet
onDraftsClearedAfter clearing drafts or copy-and-clear preferenceReceives clones of the drafts actually removed
onSubmittedAfter submitRepair() returnsReceives the SubmittedRepair[] that actually entered the Repair Ledger

Review language and project copy

A3SReviewOverlay supports locale="auto" | "en" | "zh-CN". The default, auto, observes <html lang> while mounted: every zh-* tag selects Simplified Chinese and other languages use English. Pass an explicit locale when the review surface must not follow the host page.

Projects can override a bounded subset of interface copy:

<A3SReviewOverlay
  enabled={import.meta.env.DEV}
  locale="en"
  messages={{
    reviewTitle: 'Page review',
  }}
/>

messages accepts only known message keys. Blank values and strings longer than 2,048 characters are ignored. Overrides affect presentation only; they never enter page context, repair instructions, or hidden agent input.

What A3S Test can observe

Each snapshot carries a monotonic revision and binds these facts together:

  • Roles, accessible names, state, and DOM hierarchy.
  • Test Kit boundaries, component identity, and bounded source hints.
  • Preferred semantic locators with an explicit fallback order.
  • Element geometry in viewport, document, and normalized coordinate spaces.
  • Layout viewport, device pixel ratio, and optional visual-viewport offset and scale.
  • Bounded computed style, page facts, and redacted form state.
  • Observed design tokens, overflow/clipping-aware layout relationships, repeated structures, real interaction-state differences, and timeline-aware motion facts.

MutationObserver, ResizeObserver, scrolling, viewport, and navigation signals advance the revision. An unchanged page is not polled. Browser refs, coordinates, screenshots, and UI evidence expire on drift. A Page Context @cN may retain only its stable locator when a complete Rust-validated delta proves that its private node identity did not change; missing or reset metadata clears every old context binding.

Distinguish actionable refs from read-only evidence

RefMeaningAuthority
@eNAccessible semantic node in the browser observationActionable only in the observation that produced it
@cNUniquely actionable node in current Page ContextActionable in that observation; only an unaffected stable locator may cross revision drift
@uNEvidence node in UI understandingRead-only and only connects style, layout, state, and motion facts

Public observations never expose Test Kit's private node IDs, and persistent session metadata stores only domain-separated SHA-256 node fingerprints. A uniquely actionable UI node reuses @cN; other evidence nodes project to @uN. Any @uN action is rejected during ACL admission or before driver dispatch. If projection cannot preserve both graph integrity and the encoded byte budget, A3S Test omits the optional UI evidence.

Rendered UI understanding

Every snapshot includes an optional nested a3s.test.ui-understanding/1 record by default. It complements the browser accessibility tree instead of creating a competing tree or inferring product intent.

EvidenceBrowser-derived facts
Style profileColors, typography, spacing, radii, shadows, z-index values, safe root design properties, and responsive conditions.
Layout graphFlex, Grid, normal flow, exact client/scroll extents, signed offsets, per-axis overflow and active clipping, resolved physical margin/border/padding edges, box sizing, writing mode, text direction, containing, offset-parent, scroll-container, and stacking-context relationships.
Repeated structuresDeterministic fingerprints from tag, role, semantic state, bounded subtree shape, and computed style. Class names alone never define a component.
State differencesDifferences from a previously observed default state to a real hover, focus, focus-visible, checked, expanded, selected, or disabled state. Test Kit does not synthesize interactions to collect them.
Motion profileTransitions, CSS and Web Animations, document/scroll/view/named timelines, animation ranges, keyframe names, sticky and scrolling nodes, canvas and media surfaces, and reduced-motion preference.

The record has its own observationId because focus, hover, or a running animation can change computed state without changing the semantic page revision. Its pageRevision, viewport, and scope must still match the containing Page Context snapshot. Physical box edges stay separate from writing mode and text direction, so Test Kit does not invent a logical layout intent. Named CSS timelines remain named unless the browser exposes their resolved Web Animations timeline; Test Kit never guesses whether they are scroll- or view-driven. The Web driver rejects stale bindings, unknown fields, invalid geometry, malformed box-model evidence, inconsistent overflow/clipping or timeline evidence, inconsistent truncation, or budget violations. It also rejects duplicate layout nodes or edges, missing parents or edge endpoints, containment that conflicts with parentNodeId, incomplete or cyclic containment, duplicate evidence references, component representatives outside their member set, and layout data above the declared sampled-node count.

Default limits are 200 sampled nodes, 200 state candidates, 32 ms, and 256 KiB. Installation options maxUiNodes, maxUiStateSamples, maxUiDurationMs, and maxUiEncodedBytes can lower those ceilings, and each snapshot() request may lower them again. Use snapshot({ ui: false }) for one request or uiUnderstanding={false} for an installation that does not need this projection.

Verification screenshots remain A3S Test evidence. A screenshot deliberately attached as a design reference is part of the finding instead. When a reviewer explicitly sends a finding, the same bounded UI record accompanies its untrusted: true repair context so the workspace-owning agent can correlate a selected node with the page's visual system.

Human marking and batch repair

Test Kit 0.6.2 keeps review work in one fixed side panel. The default path has two decisions: choose an element or area, then describe the requested result. Text, Multi, Draw, and Layout stay under More tools until needed. Selecting a target replaces the tools with the editor in the same panel; saving or sending is the final action. New feedback and Findings are the only top-level views, while preferences live in the header. There is no target-attached editor, secondary floating tray, or nested modal.

The design board temporarily replaces the review panel and returns to the same editor when closed. Preferences and findings scroll inside short desktop viewports. On mobile, the panel becomes a single full-width surface, primary controls provide at least 44-CSS-pixel touch targets, and form text remains 16 pixels to prevent browser zoom. At every viewport size, starting a marking mode slides the panel aside and leaves only a compact finish/cancel bar, so content previously covered by the panel remains directly selectable. Page markers stay below the panel when it returns.

Visible node and text markers, including the active candidate, are recomputed from live DOM rectangles after page or nested-container scrolling. The transient hover rectangle is cleared as soon as selection completes, so it cannot remain at an old viewport coordinate. Region markers retain their captured scroll origin. Closing Test Kit removes every rendered page marker until the panel is opened again.

The overlay supports element, text, click or drag multi-selection, rectangular findings, and freehand findings. A reviewer can:

  1. Select one target or assemble an ordered batch.
  2. Add repair instructions, replies, conflict relationships, and review decisions.
  3. Save a local draft or explicitly send it to the owning A3S Test session.
  4. Wait for the coding agent to edit source and run fresh-browser verification.
  5. Accept, reject, or reopen the result.

With the overlay open, E, M, T, A, and D start element, multi, text, area, and draw marking. L, P, and H toggle Layout Mode, page motion, and marker visibility. Letter shortcuts never intercept input while focus is inside a text field or editor.

The overlay lives in an open Shadow DOM. Localized labels, statuses, hints, live announcements, and ARIA names share one message catalog, while focus returns to a durable control after closing an editor, cancelling marking, or hiding the UI. Localization does not alter page-context or repair protocols.

Layout Mode emits only typed placement or rearrange intent with viewport CSS-pixel targets. It never moves, reorders, or styles the host DOM.

Its 90 built-in component types display and search in both English and Simplified Chinese. A known catalog selection follows a live locale change, while a project-specific free-form component value remains unchanged.

Security boundary

Test Kit receives no workspace, shell, MCP, or source-editing credentials. DOM context is explicitly marked as untrusted evidence. The Quality Store, Design Audit Store, and Repair Ledger remain separate. Viewing advice or opening an editor does not grant repair authority.

Deterministic Surface Contract differences may block a suite, but their overlay projection remains a review candidate. Design-audit output is always advisory. A candidate reaches the existing single or batch repair flow only after a person saves or sends it.

Production builds normally disable Test Kit. CI may keep A3STestKit enabled while omitting A3SReviewOverlay. In Next.js, mount both from a client component and gate them explicitly with process.env.NODE_ENV !== "production".

Continue in depth