# Helixwright 1.0 Public API Reference

Target SDK: `helixwright==1.0.0` (local release candidate).

Runtime contract: Browser RPC protocol `6`, endpoint `/rpc/v6`, core contract `0075`,
semantic hash
`40DFB6DEDAA4CD9A1F56BCEBB019A08B1F57025A28069E79605945CA1FF60BE8`.

## Namespace inventory

The root namespace contains only day-to-day automation:

```text
ActionReceipt, AmbiguousStateError, Classification, ElementNotFoundError,
Frame, HelixwrightError, Input, Locator, MaxTransitionsError, MotionProfile,
OscillationError, OutcomeContract, OutcomeVerdict, Page, ReadinessContract,
ReadinessSignal, RunContext, RunResult, RuntimeActionEffect, Signature, State,
StateMachine, StateClassificationError, StateMachineCancelledError,
StateMachineDeadlineError, StateMachineError, Trace, Transition,
TransitionAssertionError, UnknownStateError, WaitTimeoutError,
admin, attach, errors, expert, launch, signals
```

Administrative and expert types are intentionally namespaced; do not import an
unlisted compatibility alias.

## Launch functions

### `hw.launch(...) -> Page`

```text
hw.launch(
    url=None,
    *,
    config=None,
    reuse_profile_id=None,
    name=None,
    group=None,
    tags=None,
    start_pages=None,
    proxy=None,
    client=None,
    base_url=None,
    headless=False,
    timeout_ms=30000,
    motion=None,
) -> hw.Page
```

- Without `reuse_profile_id`, Desktop creates a new server-owned profile.
- `proxy` accepts a URL string, mapping, `hw.admin.Proxy`, or `None`.
- `motion` accepts `MotionProfile`, preset string, mapping, or `None`.
- `config` must be `hw.admin.LaunchConfig` and cannot be combined with duplicate
  explicit configuration fields.
- The returned page owns the new automation session. Context exit proves Local API
  session removal and browser inactivity.

### `hw.attach(session_id, ..., take_ownership=False) -> Page`

```text
hw.attach(
    session_id,
    *,
    client=None,
    base_url=None,
    motion=None,
    take_ownership=False,
) -> hw.Page
```

Default attach is control-only. `take_ownership=True` explicitly transfers lifecycle
ownership to the returned page.

## `Page`

`Page` is returned by `launch()`/`attach()` and is a context manager.

### Identity and document

| Member | Return |
| --- | --- |
| `session_id` | automation session id or `None` |
| `profile_id` | profile id or `None` |
| `profile` | `hw.admin.Profile` or `None` |
| `rpc_endpoint_path` | admitted endpoint string |
| `rpc_info` | copy of the admitted hello object |
| `rpc_capabilities` | copy of capability versions |
| `url` | current URL from an atomic document snapshot |
| `title()` | document title |
| `content()` | document HTML |
| `info()` | page/profile/session/runtime diagnostic mapping |

### Navigation

```text
goto(url, *, wait="load", timeout_ms=None) -> Page
back(*, timeout_ms=30000) -> Page
forward(*, timeout_ms=30000) -> Page
reload(*, ignore_cache=False, timeout_ms=30000) -> Page
wait_for_url(url, *, timeout_ms=30000) -> str
close() -> None
```

`goto.wait` is `none`, `commit`, `domcontentloaded`, or `load`.

### Locators and frames

```text
locator(selector) -> Locator
get_by_role(role, *, name=None) -> Locator
get_by_text(text, *, exact=False) -> Locator
get_by_label(text) -> Locator
get_by_placeholder(text, *, exact=False) -> Locator
get_by_alt_text(text, *, exact=False) -> Locator
get_by_title(text, *, exact=False) -> Locator
get_by_test_id(test_id) -> Locator
frame(target) -> Frame
frames() -> list[dict]
targets() -> list[dict]
```

### Scrolling, screenshot, motion, statecharts, recording

```text
scroll(dy=0, dx=0, *, x=None, y=None, timeout_ms=30000) -> RuntimeActionEffect
scroll_until(selector, *, max_rounds=40, step=None, container=None,
             into_view=True, timeout_ms=30000) -> Locator
screenshot(path=None, *, timeout_ms=None) -> bytes
set_motion(motion) -> Page
motion -> MotionProfile
machine(states, **kwargs) -> StateMachine
record(path, *, full_html=True, **kwargs) -> hw.expert.TraceRecorder
last_action_effect -> RuntimeActionEffect | None
```

`last_action_effect` is diagnostic page state. The effect returned by the specific
action is the authority for concurrent-safe proof.

### Page-owned controllers

Instances are available as:

```text
page.input      Input
page.trace      hw.expert.TraceController
page.probe      hw.expert.ProbeController
page.tabs       hw.expert.TabController
page.network    hw.expert.NetworkController
page.downloads  hw.expert.DownloadController
page.dialogs    hw.expert.DialogController
page.cookies    hw.expert.CookieController
page.console    hw.expert.ConsoleController
```

## `Frame`

`page.frame(target)` creates an immutable frame-chain scope.

```text
scope -> hw.expert.ContextScope
depth -> int
page -> Page
url -> str
probe -> hw.expert.ProbeController
input -> Input
last_action_effect -> RuntimeActionEffect | None
locator(selector) -> Locator
get_by_role/get_by_text/get_by_label/get_by_placeholder/get_by_alt_text/
get_by_title/get_by_test_id(...) -> Locator
scroll_until(...) -> Locator
classify(states, *, min_confidence=0.5, ambiguity_margin=0.1) -> Classification
machine(states, **kwargs) -> StateMachine
frame(target) -> Frame
```

Entering/exiting a `Frame` context has no browser cursor side effect.

## `Locator`

### Composition and collection

```text
scope -> hw.expert.ContextScope
locator(selector) -> Locator
get_by_role/get_by_text/get_by_label/get_by_placeholder/get_by_alt_text/
get_by_title/get_by_test_id(...) -> Locator
nth(index) -> Locator
first -> Locator
last -> Locator
all() -> list[Locator]
count() -> int
```

### Atomic actions

```text
click(*, timeout_ms=None, ready=None) -> RuntimeActionEffect
double_click(*, timeout_ms=None, ready=None) -> RuntimeActionEffect
hover(*, timeout_ms=None, ready=None) -> RuntimeActionEffect
fill(text, *, timeout_ms=None, ready=None) -> RuntimeActionEffect
type(text, *, timeout_ms=None, ready=None) -> RuntimeActionEffect
press(key, *, timeout_ms=None, ready=None) -> RuntimeActionEffect
select(value=None, *, label=None, index=None, timeout_ms=None, ready=None)
    -> RuntimeActionEffect
drag_to(target, *, timeout_ms=None, ready=None, native=False)
    -> RuntimeActionEffect
upload(files, *, verify=True, timeout_ms=None, ready=None)
    -> RuntimeActionEffect
```

`ready` accepts `ReadinessContract`, `ReadinessSignal`, a sequence of signals, or
`None`. Mechanical actionability is always added by the SDK/core.

### Read and wait

```text
wait(state="visible", *, timeout_ms=None) -> Locator
scroll_into_view(*, timeout_ms=None) -> Locator
text() -> str
value() -> Any
input_value(*, timeout_ms=None) -> Any
attr(name) -> Any
visible() -> bool
enabled() -> bool
checked() -> bool
exists() -> bool
rect() -> Any
screenshot(path=None, *, timeout_ms=None) -> bytes
explain(*, timeout_ms=None) -> dict
resolve(*, timeout_ms=None) -> dict
```

Supported wait states: `attached`, `detached`, `visible`, `hidden`, `enabled`,
`editable`.

## `Input`

Low-level coordinate/keyboard actions:

```text
move(x, y, *, timeout_ms=30000) -> RuntimeActionEffect
click(x, y, *, button="left", timeout_ms=30000) -> RuntimeActionEffect
double_click(x, y, *, button="left", timeout_ms=30000) -> RuntimeActionEffect
wheel(dy=0, dx=0, *, x=None, y=None, timeout_ms=30000)
    -> RuntimeActionEffect
drag(x1, y1, x2, y2, *, duration_ms=None, profile=None, hold_ms=None,
     overshoot=None, tremor=None, timeout_ms=30000) -> RuntimeActionEffect
key(key, *, timeout_ms=30000) -> RuntimeActionEffect
type(text, *, timeout_ms=30000) -> RuntimeActionEffect
paste(text, *, timeout_ms=30000) -> RuntimeActionEffect
pointer_path(points, *, timeout_ms=30000) -> RuntimeActionEffect
gesture(*, timeout_ms=30000) -> hw.expert.Gesture
```

Held down/up control exists only inside one balanced `Gesture` transaction.

## Readiness

### `ReadinessSignal`

```text
hw.ReadinessSignal(kind, params={}, description=None)
hw.ReadinessSignal.element_state(selector, state, *, value=True, description=None)
hw.ReadinessSignal.attribute(selector, name, *, equals=None, absent=False,
                             description=None)
hw.ReadinessSignal.network_response(url, *, method=None, status=None,
                                    after_action=False, description=None)
```

`as_rpc()` returns the serializable signal mapping.

### `ReadinessContract`

```text
hw.ReadinessContract(
    all_of=(),
    any_of=(),
    stable_frames=2,
    quiet_ms=0,
    lease_ms=250,
    description=None,
)
```

Methods/properties:

```text
require(*signals) -> ReadinessContract
accept_any(*signals) -> ReadinessContract
as_rpc(*, action) -> dict
has_business_conditions -> bool
```

The object is immutable. `stable_frames >= 2`; `quiet_ms >= 0`; `lease_ms` is
1..5000 ms.

## Action effects and outcomes

### `ActionReceipt`

```text
action_id -> str | None
confirmed -> bool
as_dict() -> dict
```

### `RuntimeActionEffect`

Important fields include action id/kind/selector, exact receipt, dispatch phase,
before/after summaries, URL/focus/value/scroll/DOM/AX changes, correlated network,
console, dialog, download and error records, and appeared/disappeared/changed evidence.

```text
as_dict() -> dict
from_action(*, kind, selector, started_at, ended_at=None, ok=True,
            error=None, return_value=None, receipt=None, before=None,
            after=None, metadata=None, **changes) -> RuntimeActionEffect
duration_ms -> float
failed -> bool
has_any_change -> bool
has_progress -> bool
no_effect -> bool
receipt_confirmed -> bool
reconcile_required -> bool
unknown_outcome -> bool
```

### `OutcomeContract`

```text
hw.OutcomeContract(
    success_states=[],
    branch_states=[],
    branch=[],
    progress=[],
    success=[],
    failure=[],
    no_effect="report",
    same_state_with_progress="wait_and_reclassify",
    timeout_ms=None,
    require_receipt=True,
)
```

`judge(effect, scope, *, machine=None, state_before=None) -> OutcomeVerdict` and
`as_dict() -> dict`.

`OutcomeVerdict.as_dict()` returns the typed status, matched/missing signals,
before/after states, action effect, retry/report flags, reason, signal results, dispatch
phase, and reconcile requirement.

## `MotionProfile`

```text
hw.MotionProfile(
    name="balanced", seed=None, tempo=1.0, precision=1.0,
    drag_profile="flick", drag_duration_ms=None, drag_hold_ms=0.0,
    overshoot=1.0, tremor=1.0, dwell=1.0, pointer_interval_ms=16.0,
    min_move_duration_ms=120, max_move_duration_ms=1800,
    min_drag_duration_ms=260, max_drag_duration_ms=2400,
)
```

Factories/methods: `fast`, `balanced`, `careful`, `slider`, `preset`, `from_seed`,
`from_profile_data`, `as_dict`, `as_rpc_policy`, `move_duration`, `drag_duration`, and
`drag_kwargs`.

## Statechart types

### `Signature`

```text
hw.Signature(
    name="",
    url_substr=None,
    title_substrs=[],
    absent_title_substrs=[],
    require_selectors=[],
    absent_selectors=[],
    texts=[],
    form_fields=[],
    weight_url=1.0,
    weight_title=1.0,
    weight_selector=1.0,
    weight_absent=1.0,
    weight_text=0.5,
    weight_field=0.75,
)
```

`to_dict()` and `from_dict(mapping)` are the serialization surface.

### `State`

```text
hw.State(
    name,
    match,
    handler=None,
    expect=None,
    ready=None,
    children=None,
    regions=(),
    frame=None,
    passive=False,
    terminal=False,
    min_confidence=None,
    per_state_timeout_ms=None,
)
```

`State` is frozen. An ordinary non-terminal state requires a handler and an exact
outcome contract. A passive state has no handler or readiness contract and requires
`OutcomeContract(require_receipt=False)` for a browser-observed transition. Terminal
states cannot own actions, readiness, outcomes, children, or regions.

### `StateMachine`

```text
hw.StateMachine(
    states,
    *,
    name="machine",
    min_confidence=0.5,
    ambiguity_margin=0.1,
    logger=None,
)
```

```text
run(scope, *, until=None, max_transitions=25, per_state_timeout_ms=15000,
    deadline_ms=120000, cancel_event=None, oscillation_repeats=3,
    data=None, scope_label="page", parent=None, failure_dir=None) -> RunResult
```

`RunResult` exposes `final_state`, `transitions`, `reached_until`, `last_effect`,
`last_verdict`, `last_readiness`, `states_visited`, and `as_dict()`.

`RunContext` exposes `machine`, `scope`, mutable run `data`, current classification/state,
`ready`, exact last effect/verdict/readiness, `url`, `classify()`, and `log()`.

### Classification, transitions, and offline Trace

- `Classification(...).as_dict()` preserves the selected state, ranked candidates,
  confidence, ambiguity/unknown/error flags, and before/after epoch evidence.
- `Transition(...)` is the structured run-history record for state, scope, action,
  readiness, outcome, receipt, region, target, and trigger evidence.
- `Trace(events, source=None)` and `Trace.load(path)` expose `actions`, `timeline`,
  `digest`, `effect_of`, `segment`, and `replay_text` for bounded offline evidence
  inspection. They do not dispatch browser actions.

## `hw.admin`

Exact exports:

```text
AutomationRpc, AutomationSession, Client, LaunchConfig, Profile, Proxy,
discover_base_url
```

### `hw.admin.Client`

```text
hw.admin.Client(
    base_url=None,
    timeout=120.0,
    capability=None,
    max_response_bytes=67108864,
)
```

Methods:

```text
health() -> dict
session() -> dict
require_ready() -> None
request(method, path, body=None, query=None, timeout=None) -> Any
request_job(method, path, body=None, query=None, timeout=None,
            poll_timeout=None, poll_interval=0.4, cancel_on_timeout=True) -> Any
```

Manager instances:

```text
client.profiles.list(**filters) -> list[Profile]
client.profiles.get(profile_id) -> Profile
client.profiles.create(*, name=None, group=None, tags=None, proxy=None) -> Profile
client.profiles.update(profile_id, **fields) -> Profile
client.profiles.delete(profile_id) -> Any
client.profiles.clone(profile_id, *, count=None, name_suffix=None,
                      keep_proxy=None, **fields) -> Any

client.proxy.check(proxy=None, **fields) -> Any
client.cores.list() -> Any
client.cores.ensure(family="chromium", version="149.0.7827.156") -> Any
client.browser.active(*, timeout=None) -> Any
client.browser.start(profile_id) -> Any
client.browser.stop(profile_id) -> Any
client.browser.stop_all() -> Any
client.automation.list(*, include_rpc=True) -> Any
client.automation.get(session_id, *, include_rpc=True) -> Any
client.automation.launch(...) -> tuple[Profile, AutomationSession]
client.automation.stop(session_id) -> Any
client.automation.stop_post(session_id) -> Any
```

### Administrative models

- `LaunchConfig(...).as_kwargs() -> dict` mirrors `hw.launch` configuration.
- `Proxy(scheme, host, port, username=None, password=None).as_payload() -> dict`.
- `Profile` exposes `id`, `account_id`, `name`, `code`, `get`, `refresh`, `update`,
  `launch`, and `clone`.
- `AutomationRpc(host, port, token)` and
  `AutomationSession(session_id, profile_id, pid, rpc, raw)` represent Local API
  session data.

## `hw.expert`

Exact exports:

```text
ConsoleController, ContextId, ContextScope, CookieController, DialogController,
DownloadController, Effect, FlowActionIR, FlowIR, FlowStateIR,
FlowTransitionIR, Gesture, Mark, NetworkController, ProbeController,
SnapshotQuery, SnapshotResult, StateSnapshot, TabController, Trace,
TraceController, TraceRecorder, classify_states, digest,
discriminate_signatures, effect_of, extract_signature, load_trace, segment,
stability, timeline, trace_diff
```

### Context and snapshots

```text
ContextScope(target_id=None, _frame_chain=())
  .child(selector_mapping) -> ContextScope
  .on_target(target_id) -> ContextScope
  .as_rpc() -> dict
  .depth -> int
  .frame_chain -> tuple

ContextId(target_id, frame_id, document_epoch).as_rpc() -> dict
SnapshotQuery(id, selector, fields=(...)).as_rpc() -> dict
StateSnapshot.from_rpc(value, expected_ids) -> StateSnapshot
StateSnapshot.get(query_id) -> SnapshotResult
```

`SnapshotResult(id, status, count, element, error)` is one query result from the same
atomic snapshot. `Mark` is an integer-compatible Trace checkpoint carrying `id`, `seq`,
and `label`. `Effect.as_dict()` returns an action digest and `Effect.raw(...)` returns a
bounded view over the same recorded bytes.

### `Gesture`

Builder methods: `move`, `down`, `up`, `wheel`, `key_down`, `key_up`, `text`, `paste`,
`pause`, then `commit()`. Properties: `events`, `committed`, `result`.

### Controllers

```text
TabController: list, new, switch, close, expect
NetworkController: listen, events, wait_for_response, expect_response, route,
                   block, clear_routes, body, bytes, headers, headers_raw, json
DownloadController: listen, list, expect
DialogController: set, accept, dismiss, off
CookieController: list, set, clear, storage_state
ConsoleController: listen, messages
TraceController: start_session, start, stop, clear, mark, segment, snapshot,
                 events, action, export
TraceRecorder: start, close, drain, action, mark, snapshot, probe,
               record_channel, capture_visual, begin_target_navigation,
               end_target_navigation, report, in_action
```

`NetworkController.headers_raw()` is the lossless ordered/duplicate-preserving header
surface. `headers()` is a convenience mapping.

### `ProbeController`

```text
scope, page, probe, url
scoped(scope) -> ProbeController
snapshot(*, full=False, max_nodes=None, max_text=None, context=None) -> dict
evaluate(expression, *, label=None, timeout_ms=None, context=None) -> Any
locator(selector, *, context=None) -> LocatorProbe
forms(*, limit=0, context=None) -> list[dict]
interactables(*, limit=200, context=None) -> list[dict]
cookies(*, context=None) -> list[dict]
storage(*, context=None) -> dict
listener_hints(selector=None, *, limit=200, context=None) -> list[dict]
selector_candidates(selector, *, limit=20, context=None) -> dict
classify(states, *, min_confidence=0.5, ambiguity_margin=0.1) -> Classification
signature(scope=None, *, name="", max_selectors=4, max_texts=3,
          max_fields=6) -> Signature
signatures(named_scopes) -> dict
state(predicates) -> str
effect_of(action_id=None, *, max_lines=40) -> Any
digest(*, scope=None, max=40) -> list[dict]
timeline(...) -> list[dict]
diff(a, b) -> list[dict]
```

Probe form/cookie/storage/network evidence is always full-fidelity under the private
owner-only evidence boundary.

### Flow IR

- `FlowStateIR(name, signature, context={}, ready=None, terminal=False, region=None)`.
- `FlowActionIR(action_id, state, kind, selector, readiness, dispatch_phase, receipt,
  outcome, command_id=None, trace_window=None)`.
- `FlowTransitionIR(source, target, trigger, action_id=None, outcome=None)`.
- `FlowIR(..., schema=1)` exposes `as_dict`, `validate`, `require_valid`, `write`, and
  `load`.

### Offline Trace helpers

`load_trace`, `timeline`, `digest`, `effect_of`, `segment`, `stability`, `trace_diff`,
`classify_states`, `extract_signature`, and `discriminate_signatures` operate on
structured evidence/signatures; they do not dispatch browser actions.

## `hw.signals`

Exact exports:

```text
Appeared, AxAlert, ConsoleMessage, DialogOpened, Disappeared, DomChanged,
DownloadStarted, ElementState, Network, Predicate, Signal, SignalResult,
SignalStatus, StateReached, UrlContains, UrlMatches, ValueChanged
```

Constructors:

```text
Appeared(selector)
Disappeared(selector)
DomChanged(selector=None)
ElementState(selector, disabled=None, enabled=None, visible=None, checked=None)
ValueChanged(selector=None)
Network(url_contains=None, method=None, status=None)
ConsoleMessage(level=None, text_contains=None)
AxAlert(name_contains=None)
DialogOpened(text_contains=None)
DownloadStarted()
StateReached(name)
UrlContains(text)
UrlMatches(pattern)
Predicate(fn, name=None)
```

Signals expose `as_dict`, `describe`, `evaluate`, and `matches`. `SignalResult` exposes
`status`, `signal`, `reason`, `error`, `evidence`, `matched`, and `as_dict()`.

Production `StateMachine` outcomes accept only exact built-in serializable signal
types; `Predicate` is not a production statechart signal.

## `hw.errors`

Exact exports:

```text
AmbiguousStateError, AutomationEndpointUnavailable,
AutomationSessionNotFound, BrowserLifecycleError, DesktopNotLoggedIn,
ElementNotFoundError, HelixApplicationError, HelixBusinessError,
HelixwrightError, LaunchRollbackError, LocalApiError, LocalApiUnavailable,
LoginRejected, MaxTransitionsError, OscillationError, ProfileNotFound,
ReachabilityError, RpcError, RpcMutationOutcomeUnknown,
RpcTransportProtocolError, RpcTransportTimeout, StateClassificationError,
StateMachineCancelledError, StateMachineDeadlineError, StateMachineError,
TransitionAssertionError, TransportError, UnknownStateError, WaitTimeoutError
```

See `errors.md` for failure-specific handling. In particular, reconcile unknown
mutation outcomes instead of replaying them.

## Private evidence invariant

Trace/Authoring evidence retains raw private values, including passwords, proxy
credentials, cookies, authorization, forms, storage, action arguments, request/response
headers and bodies. It uses an owner-only access boundary, `local_only=true`,
`upload=false`, and no automatic upload.
