# Skill: operate a surface through `org.classprofiles.operator/core@1`

Self-contained operating instructions. `profile.json` is authoritative; this is the view an agent reads.

A surface is anything you can look at and act on: a browser tab, a desktop, a terminal. The floor is the same for all three. Which kind you are holding is a facet.

## The loop

**Address → read → act → settle → read again.** Four verbs, and the fourth is often unnecessary because acting already tells you whether things settled.

| Verb | What it does | What to know |
|---|---|---|
| `operator.list_surfaces` | Returns what you can work with, each with an identifier and a kind | Read-only. Call it first; everything else needs a `surface_id` |
| `operator.perceive` | Returns the targets you may act on, the words on the surface, and how settled it is | Read-only. Pass `query` to narrow instead of taking everything |
| `operator.act` | Performs one input on one target and reports the outcome | Writes. Effects are decided by the surface, not by this service |
| `operator.settle` | Waits until nothing more is changing | Read-only. Usually unnecessary — `act` already returns readiness |

## Worked calls

Find what you can work with.

```json
operator.list_surfaces
{}
```

```json
{ "surfaces": [ { "id": "sfc_2ab9", "kind": "browser", "label": "Reference document" } ] }
```

Read it. Narrow with `query` rather than pulling the whole surface.

```json
operator.perceive
{ "surface_id": "sfc_2ab9", "query": "Submit" }
```

```json
{
  "targets": [ { "ref": "e47", "role": "button", "name": "Submit" } ],
  "readiness": "settled"
}
```

Act on a target you were given. Never on one you composed yourself.

```json
operator.act
{ "surface_id": "sfc_2ab9", "target": "e47", "action": "press" }
```

```json
{ "changed": true, "readiness": "settled" }
```

That result is the whole point: you know the press landed **without a second call to find out**. When nothing happened, you are told plainly rather than left to assume:

```json
{ "changed": false, "readiness": "settled" }
```

Enter text with the same verb and a `value`:

```json
operator.act
{ "surface_id": "sfc_2ab9", "target": "e12", "action": "enter_text", "value": "design review" }
```

## Rules

1. **Targets are obtained, never constructed.** A `ref` comes from a `perceive`. Do not invent one, do not guess at it, and do not carry one across surfaces. An unknown target fails with JSON-RPC `-32602` rather than acting on whatever now sits nearby.
2. **Read the receipt before assuming.** `changed: false` means your input landed on something inert — change approach rather than repeating it.
3. **Re-issue is not safe.** `operator.act` declares `at_most_once_unenforced`: a press cannot be de-duplicated, because what it does is the surface's decision. If a call's outcome is uncertain, **look before retrying**.
4. **Confirm before acting where other people can see.** `operator.act` is flagged socially irreversible, because an input may post, send, or purchase. Confirm unless the user authorised that exact act.
5. **Prefer words to pixels.** `perceive` returns structure and text cheaply. A picture needs `operator/screenshot@1`, costs far more, and cannot be acted upon — targets come from the structured reading.
6. **Check the card before reaching for a facet.** Navigation is `operator/browser@1`; raising an application is `operator/desktop@1`. If the card does not declare it, say so rather than improvising.

## Facets

**`operator/browser@1`** — for agents that control a browser.

```json
operator.navigate
{ "surface_id": "sfc_2ab9", "url": "https://example.org/reference" }
```

Surfaces then carry `address`. Without this facet you can work with whatever is already open, but cannot send it anywhere.

**`operator/desktop@1`** — for agents that control a desktop.

```json
operator.focus_app
{ "surface_id": "sfc_7c10", "application": "Text Editor" }
```

Surfaces then carry `application`. This one is idempotent — raising an app twice leaves the same app in front. Without it you can work with whatever already has focus.

**`operator/screenshot@1`** — a picture with its measurements, for layout a structured reading cannot express.

## What this contract does not cover

Read this before relying on it.

- **A surface changing underneath you.** Targets can go stale mid-task. The floor says an unknown target must fail loudly; it does not say how to recover.
- **Blocking states.** `Receipt.blocked_by` exists so a modal can be reported rather than resembling an ordinary failure, but resolving one is not in the floor.
- **What an input will do.** Unbounded and decided by the surface. No annotation here can narrow it, which is why `operator.act` keeps every pessimistic default.
- **Which surface you should be on.** Choosing among several is a routing question and belongs to another layer.
