Files
artemis_control/AGENTS.md

6.6 KiB

Artemis Control

Build spec for Paperclip. Follow the phases in section 11 in order. Do not skip a phase's Definition of Done. When something is unclear, ask Sam — do not guess.


1. Purpose and outcome

Artemis is the phone's hands. It drives the phone screen from .13 over Tailscale using ADB wireless, so the Hub can do things no deep link allows.

Outcome (the single success statement):

Sam says "Open Spotify, search Rolling Stones Honky Tonk, play it, make a song radio" and it happens on the phone, reliably.

Google Assistant cannot do this, because it cannot search inside an app. Artemis can, because it uses the app's own UI.

2. Scope

In scope

  • Hold an ADB session to the phone over Tailscale.
  • Read the screen (element text and positions).
  • Act: launch, tap, type, swipe, scroll, back, home.
  • Named recipes for common tasks (for example, play a song in Spotify).
  • A small action API for the Hub.

Out of scope

  • Understanding speech. The Hub does that.
  • Native phone actions (calls, contacts, SMS). Those belong to the Kotlin app.
  • The phone app itself. That is kotlin_phone_app_admin.
  • Voice and outbound conversations. That is voice_outbound.

3. Users and roles

  • No direct user. Artemis is driven by the Hub.
  • Sam may edit the recipes file by hand.

4. Functional requirements

ID Requirement
FR-1 Hold an ADB session to the phone over Tailscale. Reconnect after a drop.
FR-2 Read the screen with adb shell uiautomator dump — element text and bounds.
FR-3 Act with adb shell input: tap, type, swipe, scroll, back, home, key events.
FR-4 Find an element by text and tap its centre. Do not use fixed coordinates where text exists.
FR-5 Named recipes for known tasks (spotify_play, spotify_radio, maps_navigate).
FR-6 Action API: POST /act {"task": "...", "params": {...}} returns ok or failed with a reason.
FR-7 Wake the screen before acting.
FR-8 Fail cleanly: element not found, app not installed, app logged out, timeout. Never tap blindly.
FR-9 Health: report ADB connected and phone reachable.
FR-10 Log every action: task, steps, result, duration.
FR-11 Per-step timeout. A recipe never runs forever.

5. Screens and UX flow

No UI in v1. Artemis is headless. It exposes an API and reads a recipes file.

  • Recipes file — a plain file (YAML or JSON) that Sam can edit to add or change a task. This replaces a UI for now.
  • Optional later — a small desktop page to view recipes and recent runs. Build it only if the recipes file becomes painful.

Example flow

Hub: POST /act {"task":"spotify_play","params":{"query":"Rolling Stones Honky Tonk"}}
Artemis: wake screen → launch Spotify → tap "Search" → type query
         → wait → tap first result → tap Play
Artemis: {"status":"ok","duration_ms": 4200}

6. Look and feel

Not applicable in v1 (no UI). If a desktop page is added later, reuse the Family Home Lab design system: /home/sam/Docker/Containers/family-home-lab/portal/static/tokens.css.

7. Data model

Files and SQLite inside the service. Suggested:

Store Holds
recipes/ One file per task. Steps and selectors. Editable.
action_log (SQLite) task, params, steps, result, duration, created-at
session ADB connection state

8. Integrations

System Use
ADB The control channel. Wireless, over Tailscale.
Tailscale Reaches the phone from .13 when away from home.
Hub Calls /act. Nothing comes back to the Hub.
Kotlin app The partition: native actions go there, in-app navigation comes here.
OmniRoute Only if a future step needs a vision fallback. Not in v1.

9. Technology (locked)

Item Value
Language Go
Transport ADB wireless over Tailscale
Host .13, Docker (or a systemd service — decide in Phase 1)
Container This project's own.
Port Allocate one (suggest 8793) for the action API.
URL none (no UI). A status page is optional later.
Auth A bearer token for the Hub, from environment.d.

10. Rules and constraints

  1. No LLM in the action path. Recipes are deterministic.
  2. Find by text, not fixed coordinates, where text exists.
  3. Never tap blindly. If a step cannot find its target, fail.
  4. Screen must be awake. Wake it first.
  5. Secrets come from environment.d.
  6. Log every action.
  7. Own folder, own container, own port.
  8. Do not put the Hub in the loop for the phone call itself. Calls are the Kotlin app.

11. Build order

Phase 1 — Prove the ADB link Install ADB on .13. Pair the phone. Connect over Tailscale. Screenshot and dump the UI tree. DoD: the view tree of a real phone screen is fetched. This is the risk phase — prove it first.

Phase 2 — Act primitives Tap by text, type, scroll, back, home, launch an app. DoD: Artemis opens a named app and taps a named element on it.

Phase 3 — Spotify recipe Launch, search, play. DoD: spotify_play with a real query plays the right song.

Phase 4 — Song radio Open the menu and choose "song radio". DoD: spotify_radio starts a real radio.

Phase 5 — Maps recipe Open maps and search a place. DoD: maps_navigate opens a real search.

Phase 6 — Action API POST /act, bearer token, health, timeouts. DoD: the Hub calls /act and the phone responds.

Phase 7 — Resilience Wake the screen, reconnect after a drop, fail cleanly on a missing element. DoD: a dropped ADB session recovers without a restart.

Phase 8 — Documentation DoD: project-docs run; docs updated.

12. Acceptance criteria

  • spotify_play plays the correct song from a spoken query, end to end.
  • spotify_radio starts a radio.
  • A missing element produces a clean failure, not a wrong tap.
  • A dropped ADB session recovers automatically.
  • The Hub can call /act and get a result.
  • Every action is logged.

13. Decisions and remaining questions

Resolved:

  1. ADB over Tailscale is the mechanism.
  2. No UI in v1. A recipes file replaces a UI.
  3. Find by text from the UI dump, not screenshots or vision.
  4. Partition: native actions → Kotlin app; in-app navigation → Artemis.

Remaining:

  1. Which tasks after Spotify and maps? (WhatsApp message? Other music apps?)
  2. Locked screen: must Artemis unlock it, or does Sam leave it awake?
  3. Action API shape: one generic /act, or one endpoint per task?
  4. Docker or a systemd service on .13? ADB can be awkward in a container.
  5. Speed: what is an acceptable time for a 6-step recipe?