Phase 3 of AGENTS.md section 11.
Recipes file (FR-5)
- recipes/ holds one hand-editable file per task; recipes/spotify_play.recipe
is the first one.
- internal/recipe parses directives, guards, parameters and steps, and runs
them with a per-step and a whole-run timeout (FR-11).
- Steps name text ("tap the element whose text is Search"), never coordinates.
- guards name screens Artemis must never tap on, so a signed-out or
first-run Spotify fails with its own reason (FR-8).
- Every run appends task, params, steps, result and duration to
logs/runs.jsonl (FR-10).
spotify_play
- launch, search, play, then wait for the transport button to say "Pause".
- internal/ui/rows.go adds tap_row: a result row is a clickable container with
a title and a subtitle, so a one-line search suggestion is not a result, and
the tap lands on the row's centre rather than on its "More options" button.
This fixes a real wrong tap: a plain text tap hit a 126x12 pixel
"More options for song Honky Tonk Women - Live" button.
Locked screen (AGENTS.md section 13 Q2, decided)
- Artemis fails loudly on a secure keyguard and never types a PIN. No secret is
stored. A non-secure keyguard is still dismissed.
- internal/ui/keyguard.go reads the KeyguardServiceDelegate block plus
cmd lock_settings is-user-secure.
- Every acting command wakes the screen before it checks the keyguard: a dozing
phone reports showing=false, because the lock screen is not drawn yet.
- AGENTS.md records the decision and that storing a PIN for auto-unlock is
rejected for now.
Verified live: the phone locked itself mid-session, and keyguard, tap and
run spotify_play all refused with "phone is locked; unlock it and retry".
The live end-to-end playback run still needs an unlocked phone.
94 lines
3.7 KiB
Markdown
94 lines
3.7 KiB
Markdown
# Artemis Control
|
|
|
|
Artemis is the phone's **hands**. It drives the Pixel 8a screen from `.13` over
|
|
Tailscale using **ADB wireless**, so the Hub can do things no deep link allows.
|
|
|
|
The build spec is [`AGENTS.md`](AGENTS.md). Follow the phases in section 11 in
|
|
order.
|
|
|
|
## Status
|
|
|
|
| Phase | State |
|
|
|---|---|
|
|
| 1 — Prove the ADB link | ✅ proven — see [`docs/phase-1-adb-link.md`](docs/phase-1-adb-link.md) |
|
|
| 2 — Act primitives | ✅ done — tap by text, type, scroll, back, home, launch |
|
|
| 3 — Spotify recipe | 🟡 built — recipes file, guards, `spotify_play`; the live end-to-end run is still to do, see [`docs/phase-3-spotify-recipe.md`](docs/phase-3-spotify-recipe.md) |
|
|
| 4 — Song radio | not started |
|
|
| 5 — Maps recipe | not started |
|
|
| 6 — Action API | not started |
|
|
| 7 — Resilience | not started |
|
|
| 8 — Documentation | not started |
|
|
|
|
## Layout
|
|
|
|
```
|
|
cmd/artemis/ command line entry point
|
|
internal/adb/ timeout-bounded wrapper around the adb binary
|
|
internal/ui/ read the screen (uiautomator dump) and act on it (input)
|
|
internal/recipe/ the recipes file format and its runner
|
|
recipes/ one hand-editable file per task
|
|
logs/ run log (JSON lines, not committed)
|
|
docs/ phase evidence and notes
|
|
```
|
|
|
|
## Build and test
|
|
|
|
Go is not installed system-wide on `.13`; use a one-off nix shell. Nothing is
|
|
added to `nixos-rebuild` and no system module changes.
|
|
|
|
```sh
|
|
nix shell nixpkgs#go -c go build -o bin/artemis ./cmd/artemis
|
|
nix shell nixpkgs#go -c go vet ./...
|
|
nix shell nixpkgs#go -c go test ./...
|
|
```
|
|
|
|
## Use
|
|
|
|
The phone address defaults to `100.101.49.17`. Override with `ARTEMIS_PHONE`,
|
|
pin a serial with `ARTEMIS_ADB_SERIAL`, point at a different adb with
|
|
`ARTEMIS_ADB`, point at another recipes directory with `ARTEMIS_RECIPES`, and
|
|
move the run log with `ARTEMIS_LOG`.
|
|
|
|
```sh
|
|
./bin/artemis connect # scan for the wireless-debugging port, then connect
|
|
./bin/artemis devices
|
|
./bin/artemis dump # text nodes and bounds
|
|
./bin/artemis keyguard # lock-screen state; exits 1 when locked
|
|
./bin/artemis launch com.spotify.music
|
|
./bin/artemis tap "Search" # find by text, tap its centre (FR-4)
|
|
./bin/artemis type "Rolling Stones Honky Tonk"
|
|
./bin/artemis scroll down
|
|
./bin/artemis back
|
|
./bin/artemis home
|
|
./bin/artemis demo # Phase 2 DoD: launch an app, tap a named element
|
|
```
|
|
|
|
## Recipes
|
|
|
|
A recipe is a plain-text file in `recipes/` that Sam edits by hand. Steps name
|
|
what to find on screen; there are no coordinates anywhere.
|
|
|
|
```sh
|
|
./bin/artemis recipes # list them
|
|
./bin/artemis run spotify_play query="Rolling Stones Honky Tonk"
|
|
```
|
|
|
|
Read [`docs/phase-3-spotify-recipe.md`](docs/phase-3-spotify-recipe.md) for the
|
|
file format, the verbs, and why list rows need their own step.
|
|
|
|
## Rules that the code enforces
|
|
|
|
- **Find by text, never fixed coordinates.** `tap` resolves a text match to
|
|
bounds and taps the centre; `tap_row` scores result rows against the query
|
|
and taps the winning row's centre.
|
|
- **Never tap blindly.** A missing or disabled element is a loud failure, not a
|
|
guessed coordinate. A named bad screen (`guard`) fails with its own reason.
|
|
- **Never touch a locked phone.** A secure keyguard stops Artemis with
|
|
`phone is locked; unlock it and retry`. No PIN is stored, read or typed
|
|
(AGENTS.md section 13 Q2).
|
|
- **Wake first.** Every acting command wakes the screen before it acts (FR-7),
|
|
and it checks the keyguard only after the screen is on.
|
|
- **Bound every command.** No adb call runs without a timeout, and a recipe has
|
|
a per-step and a whole-run timeout (FR-11).
|
|
- **Log every run.** Each run appends a JSON line to `logs/runs.jsonl` (FR-10).
|