Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions docs/docs/command-line-references.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,10 @@ Starts the Valdi [hotreloader](./start-about.md#prototype-quickly-with-hot-reloa
- The `--target` option should be a valid Bazel target (ex: `//:hello_world_hotreload`).
- The `--module` option will query and run targets in the current workspace which match the module_name.<br></br>

`valdi debugger [--host host] [--port port] [--strict-port] [--json]`\
`valdi debugger [--host host] [--port port] [--strict-port] [--json] [--web-preview-url url] [--chromium-debugging-port port]`\
Starts a local browser-based Valdi debugger web interface. The debugger attaches
to running Valdi daemon targets and exposes live view hierarchy, preview,
inspector data, element snapshots, heap dumps, and runtime logs. CPU profiling
inspector data, element snapshots, heap dumps, input dispatch, and runtime logs. CPU profiling
uses a separate Hermes debugger connection.

- The default host is `127.0.0.1`; the debugger rejects non-loopback bind
Expand All @@ -164,7 +164,28 @@ uses a separate Hermes debugger connection.
available port so multiple local debugger sessions can run at once.
- Use `--strict-port` to fail instead of auto-selecting another port.
- Use `--json` to print one machine-readable startup object with the selected
`url`, `port`, `requestedPort`, and `portWasAutoSelected` fields.<br></br>
`url`, `port`, `requestedPort`, and `portWasAutoSelected` fields.
- Use `--web-preview-url` to attach the integrated Elements and Console panel
to one exact loopback web/Owl page. The command prints a temporary unpacked
extension directory, adds the explicit Valdi debugger query parameters to
the preview URL, and defaults Chromium CDP discovery to port `9222`.
- Use `--chromium-debugging-port` when Owl/Chromium was launched with a
different loopback `--remote-debugging-port`. The target page must provide
the opt-in `window.__VALDI_WEB_DEBUGGER__` snapshot/highlight contract.<br></br>

`valdi inspect input <capabilities|query|tap|focus|text|key|scroll> [contextId]`\
Queries or controls a running debug `valdi_application` through the default,
cross-platform debugger input contract.

- Target an element with `--element-id`, `--accessibility-id`, or `--selector`.
- Use `--client` to choose a connected target and `--port 13591` for a
standalone macOS app; the default port `13592` targets in-app mobile clients.
- Action-specific values include `--text`, `--key`, `--focused`/`--no-focused`,
`--selection-start`, `--selection-end`, `--x`, `--y`, `--delta-x`, and
`--delta-y`.
- Each successful command writes exactly one JSON object to standard output.
- Start with `capabilities`, then use `query` to discover stable
`accessibilityId` selectors and available actions.<br></br>

`valdi test [--module module_name] [--target target_name]`\
Executes the test(s) for the provided targets. Note that multiple modules OR targets can be provided to execute all tests simultaneously. If no modules or targets are provided, ALL tests within the current workspace will be ran.<br></br>
Expand Down
49 changes: 48 additions & 1 deletion docs/docs/performance-tracing.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,54 @@ To help you debug performance issues, Valdi provides a cross-platform tracing AP

### Recording traces

#### Using the Valdi Debugger

With a hot reloader connected to the application, run `valdi debugger`, attach
to a native target, and open **Performance**. The **UI Performance** card can
start and stop a renderer trace or capture a bounded interval of up to 15
seconds. Enable **Renderer events** to include component `onRender()` spans and
ViewModel-change triggers. Exported captures use Chrome Trace JSON and can be
opened in [Perfetto UI](https://ui.perfetto.dev/). Native trace recording is
process-wide; the selected context is recorded as the capture target used to
reach the runtime, not as the origin of each trace event.

To keep debugger responses bounded before serialization, the native recorder
retains at most 10,000 events, 2 KiB per trace name, and 1 MiB of aggregate
trace-name data per active recording window. Capture results report how many
events were dropped by those limits. Automatically stopped and recently
completed results remain available for retry for one minute before they are
discarded.

The debugger proxies these operations through `/api/performance/trace/status`,
`start`, `stop`, and `capture`; the application keeps ownership of the recorder,
so captures continue to work across the loopback debugger HTTP connection.

#### Web preview traces

When `valdi debugger` is attached to an exact loopback web preview, the
integrated DevTools **Performance** panel can sample navigation, resource, heap,
and main-thread metrics. It can also record one global Chromium trace at a
time. The timeline filters are **Valdi**, **Browser**, and **All**. Enabling
Valdi renderer events reloads the inspected page with the explicit tracing
query parameters; browser events remain available without that reload.

Web capture operations use the separate
`/api/devtools/performance/trace/status`, `start`, `stop`, `capture`, and
`enable` routes. They do not replace the daemon-backed `/api/performance/*`
routes described above. Every web request is bound to the exact inspected
`sessionId`, `inspectedUrl`, and per-tab `targetNonce`; a changed or incomplete
identity fails closed.

One-shot web captures run for their requested duration from 100 milliseconds
through 15 seconds. Manually started recordings automatically stop after a
15-second watchdog. Normalization happens as CDP events arrive, retaining at
most 10,000 events with trace names no larger than
2 KiB. The complete JSON response is limited to 4 MiB, and an automatically
completed result remains retrievable for one minute. Responses contain the
bounded normalized trace list and export metadata, not a second raw or
Perfetto event list. The panel constructs Chrome Trace JSON only when you
choose **Export trace**.

> [!NOTE]
> Please make sure to add `//src/valdi_modules/src/valdi/benchmarking` to the `deps` attribute of the `valdi_module()` call in your module's `BUILD.bazel`.

Expand Down Expand Up @@ -91,4 +139,3 @@ The Valdi runtime traces some default important events that happens during the l
- `Valdi.setUserDefinedViewport`: The framework is reacting to a scroll change.
- `Valdi.updateVisibility`: The framework is resolving the viewports for the nodes. It is finding out which nodes are visible and which nodes are not visible on the screen.
- `Valdi.calculateLayout`: The framework is calculating the frames (rectangles) for the nodes. This can happen because nodes have been inserted/removed, because a layout attribute has changed (like `padding`), or because the available space for the root component has changed (for instance if the window has been resized). This can be an expensive operation. Because of this, you should avoid triggering changes in the elements that will cause a layout pass to happen when scrolling. If you need to move elements or show/hide them when scrolling, prefer using the `translationX`/`translationY` attributes or `opacity` which are not layout attributes and don't trigger layout passes when they change.

22 changes: 21 additions & 1 deletion docs/docs/stdlib-persistence.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,27 @@ The `persistence` module provides a simple key-value store that persists data ac
- LRU cache behavior with maximum weight limits
- Batch writes for performance

### Web debugger inspection

The web binding exposes a read-only, bounded snapshot for attached developer
tools. It inspects the existing in-memory stores and the established
`valdi.PersistentStore.<name>` browser records without hydrating, rewriting, or
removing them. Store names, entry keys, values, serialized records, store and
entry counts, browser-key scans, and the aggregate UTF-16/UTF-8 payload are all
bounded. Truncation and corruption are reported as snapshot metadata so an
inspector cannot wedge application persistence or perform unbounded work.
When `PersistentStore` is loaded in a debug runtime, this snapshot is published
to the generic debugger Data panel as the read-only `persistent-store`
provider. The adapter applies a smaller 43 KiB transport projection and reports
the exact known store and entry omissions. Native bindings that do not expose
the snapshot callback advertise the provider as unavailable.

The snapshot is intentionally an inspector, not a secret scanner: entry keys
and values are returned unredacted and can contain credentials, personal data,
or other sensitive application state. Only consume it from an explicitly
debug-enabled runtime over an authenticated local debugger transport, and do
not publish or attach snapshots without reviewing their contents.

## Installation

Add the `persistence` module to your `BUILD.bazel` dependencies:
Expand Down Expand Up @@ -435,4 +456,3 @@ The `persistence` module works on:
- **Encryption has overhead** - only use for sensitive data
- **LRU caching helps** - use maxWeight to limit storage usage
- **TTL prevents bloat** - set reasonable expiration times

64 changes: 62 additions & 2 deletions docs/docs/workflow-inspector.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,68 @@ Valdi Inspector is a desktop application, written in Valdi itself, which can be
```
You should now be able see and interact with the component from the provided component path in a window on your desktop

### Automating a live target

Debug `valdi_application` targets register the debugger input contract automatically. The browser debugger uses
this contract for its interactive preview. The fastest scriptable path is the CLI, which prints exactly one JSON
result on standard output:

```sh
valdi inspect input capabilities --port 13591
valdi inspect input query --port 13591 --selector '#composer'
valdi inspect input text --port 13591 --accessibility-id composer --text 'Hello from automation'
valdi inspect input key --port 13591 --accessibility-id composer --key Enter
```

As with `valdi inspect tree` and `snapshot`, omit the context when only one is active, or pass it as the last
positional argument. The `capabilities` action is context-free and only needs a connected client. Use `--client`
when more than one target is connected. Port `13591` is the standalone macOS app port; the CLI's default `13592`
targets in-app mobile clients.

The same contract is also exposed by the browser debugger for tools already using its HTTP API. Start
`valdi debugger --json`, then use the returned loopback URL:

```sh
curl -X POST "$VALDI_DEBUGGER_URL/api/input?port=13591&clientId=CLIENT_ID&contextId=CONTEXT_ID" \
-H 'content-type: application/json' \
-d '{"type":"tap","accessibilityId":"send-button"}'
```

The response's `input.contractVersion` is `1`. Call `{"type":"capabilities"}` to discover the operations and
selector forms supported by the connected target. Contract version 1 provides:

* `query` — returns typed element descriptors. With no selector, it returns all rendered elements in the
context. Descriptors include the element and parent IDs, tag, local and absolute frame, accessibility
metadata, enabled/focused state, and supported actions.
* `tap` — semantically invokes the rendered element's nearest `onTap` callback. It does not perform native hit
testing; supplied coordinates become callback coordinates rather than a visibility or bounds gate.
* `focus` — sets the `focused` interactive attribute on a `textfield` or `textview`.
* `text` — sets the input value and selection, then invokes `onChange`.
* `key` — supports `Enter`/`Return`, `Escape`, grapheme-safe `Backspace`/`Delete`, and one printable grapheme.
Return inserts a newline in editable `textview` elements unless `ignoreNewlines` is set; return callbacks and
focus-closing behavior remain independent.
* `scroll` — changes the nearest scroll container's content offset by `deltaX` and `deltaY`.

An action can identify its element with a numeric `elementId`, an `accessibilityId`, or one of these stable
selector forms:

```json
{ "selector": "#composer" }
{ "selector": "[accessibilityId=\"composer\"]" }
{ "selector": { "accessibilityId": "composer", "tag": "textfield" } }
```

Prefer unique `accessibilityId` values. Ambiguous selectors fail and return the matching element descriptors
instead of choosing an arbitrary element. Numeric element IDs are scoped to one renderer context and may change
after a render or hot reload.

Debugger input intentionally follows Valdi's rendered callbacks and interactive attributes rather than
synthesizing operating-system events. This makes the same contract work across platforms, including
SnapDrawing-backed elements. A semantic tap can therefore address an off-screen or visually occluded rendered
element and does not prove that a user could physically reach it. Use platform UI automation when validating
visibility, occlusion, native hit testing, or any other behavior that depends on the operating system's event
dispatch.

## Brief implementation details

[the implementation]: #todo-implementation-link
Expand All @@ -68,5 +130,3 @@ The hot reloader establishes a TCP connection between the device/simulator and t
* Inaccurate attribute inspection from CSS documents on .vue components
* Of course, since the Component preview runs outside of iOS/android, any custom native view will not actually render anything



1 change: 1 addition & 0 deletions npm_modules/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ For complete documentation, see:
- Restricts the server to loopback addresses because debugger snapshots can contain application data
- Prefers port `8765` and automatically selects the next available port so multiple local sessions can run at once
- Supports `--json` for automation-friendly startup output
- Supports exact-page Owl/Chromium attachment with `--web-preview-url` and `--chromium-debugging-port`; this emits a temporary first-party DevTools extension directory and an explicitly opted-in preview URL

**`valdi skills`** - AI assistant skills
- Installs Valdi context files into Claude Code, Cursor, or GitHub Copilot so AI tools generate correct Valdi code instead of React patterns
Expand Down
Loading
Loading