diff --git a/.github/workflows/companion.yml b/.github/workflows/companion.yml
new file mode 100644
index 0000000..3870d5a
--- /dev/null
+++ b/.github/workflows/companion.yml
@@ -0,0 +1,39 @@
+name: companion
+
+# Guards the shared P2P contract: the companion is the only app with a headless
+# test suite, so it runs on every push/PR that touches it. The watch apps have no
+# CI-runnable build (DevEco/JerryScript, device-only) — see their AGENTS.md.
+on:
+ push:
+ paths:
+ - 'apps/phone-android/**'
+ - 'docs/p2p-protocol.md'
+ - '.github/workflows/companion.yml'
+ pull_request:
+ paths:
+ - 'apps/phone-android/**'
+ - 'docs/p2p-protocol.md'
+ - '.github/workflows/companion.yml'
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: apps/phone-android
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: '17'
+
+ - name: Set up Gradle
+ uses: gradle/actions/setup-gradle@v4
+
+ - name: Unit tests
+ run: ./gradlew test --no-daemon
+
+ - name: Assemble debug APK
+ run: ./gradlew assembleDebug --no-daemon
diff --git a/AGENTS.md b/AGENTS.md
index 2f96120..1fd46c8 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -21,7 +21,7 @@ incompatible developer platforms, so there are two watch apps sharing one design
contract ([docs/platform-constraints.md](docs/platform-constraints.md)).
Maturity: real-HA-integration in progress ([docs/specs/01-real-ha-integration.md](docs/specs/01-real-ha-integration.md)).
-Domains: `light`, `switch`, `lock`. Localization: EN + RU.
+Domains: `light`, `switch`, `lock`, `cover`, `scene`, `sensor` (sensor read-only). Localization: EN + RU.
## The three apps — read the right rules
diff --git a/CLAUDE.md b/CLAUDE.md
index a881435..97c6a3d 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -32,8 +32,9 @@ Claude-specific guidance.
Mock run + Code Linter; watch-lite = builds/installs on a real GT; companion = `./gradlew test`.
State the evidence; if you couldn't run a check, say so instead of asserting it passed.
- **Scope discipline.** Touch only what the task needs, and don't carry one app's conventions into
- another. Don't remove deliberate placeholders (`setRemoteApp`, `PEER_FINGERPRINT`, `module.json5`
- metadata) — see the per-app gotchas.
+ another. `setRemoteApp` / `PEER_FINGERPRINT` are now filled with the real companion bundle +
+ debug-cert fingerprint; the remaining deliberate placeholder is `module.json5`'s `client_id`
+ (`PUT_YOUR_CLIENT_ID_HERE`) — don't remove it. See the per-app gotchas.
- **Surface assumptions and ask** when requirements are ambiguous — the repo author prefers an
extra question over a wrong inference.
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index baedf3d..f0bd93c 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -42,8 +42,9 @@ The human owns decisions; agents own execution. Stop and get a human decision be
- Reversing or adding an **ADR** (architecture, transport, protocol).
- A **breaking P2P protocol change** (`v` bump) — it commits the future companion repo to a contract.
-- Filling in real secrets/identity: `setRemoteApp(...)` / `PEER_FINGERPRINT` / `client_id` /
- `supportLists` / `agconnect-services.json` (today intentional placeholders).
+- Filling in real secrets/identity: `setRemoteApp(...)` / `PEER_FINGERPRINT` / `supportLists` are
+ filled (real companion bundle + debug-cert fingerprint); still placeholders: `module.json5`'s
+ `client_id` and `agconnect-services.json` (git-ignored, local-only).
- Adding a **production dependency** to a watch app (they are intentionally dependency-free).
- Anything where the spec is ambiguous — the author prefers an extra question over a wrong inference.
diff --git a/README.md b/README.md
index f50f640..1186815 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ sharing one design and one wire contract — see [docs/platform-constraints.md](
|------|------|--------|-------|
| [`apps/watch-arkts/`](apps/watch-arkts/) | Full-wearable watch app | **Watch 4/5/Ultimate** | ArkTS + ArkUI (Stage), `ArcList` |
| [`apps/watch-lite/`](apps/watch-lite/) | Lite-wearable watch app | **Watch GT 4/5/6** | JS (FA), HML/CSS, JerryScript (ES5.1) |
-| [`apps/phone-android/`](apps/phone-android/) | Phone companion (P2P ↔ HA REST) | Android | Kotlin + Compose — *not written yet* |
+| [`apps/phone-android/`](apps/phone-android/) | Phone companion (P2P ↔ HA REST) | Android | Kotlin + Compose |
The two watch apps are **mirror architectures in different runtimes** — they share the
[P2P protocol](docs/p2p-protocol.md), the domain model, and the layering, but **no code**
diff --git a/apps/phone-android/AGENTS.md b/apps/phone-android/AGENTS.md
index 8a1063c..c3fc0b2 100644
--- a/apps/phone-android/AGENTS.md
+++ b/apps/phone-android/AGENTS.md
@@ -9,7 +9,7 @@ Different stack from the watches (Kotlin, not ArkTS/JS). Open `apps/phone-androi
| | |
|---|---|
| Language / UI | Kotlin, Jetpack Compose (Material3) |
-| Build | Gradle (version catalog `gradle/libs.versions.toml`), AGP 8.7, JDK 17 |
+| Build | Gradle (version catalog `gradle/libs.versions.toml`), AGP 8.13.2, JDK 17 |
| SDK | compileSdk 35, minSdk 26, targetSdk 35 |
| App id | `ru.gentslava.homeassistant.companion` (companion). The watch peer is `ru.gentslava.homeassistant` |
| HA | OkHttp + kotlinx-serialization (`Bearer` token) |
diff --git a/apps/phone-android/app/src/main/AndroidManifest.xml b/apps/phone-android/app/src/main/AndroidManifest.xml
index 53e9280..eb7a5d7 100644
--- a/apps/phone-android/app/src/main/AndroidManifest.xml
+++ b/apps/phone-android/app/src/main/AndroidManifest.xml
@@ -9,6 +9,13 @@
+
+
+
+
+