# Meatbag Desktop Agent Handoff Date: 2026-06-30 Project: Meatbag Ecosystem: WhetForge Repository: http://localhost:3000/bill/meatbag Branch: main ## Current State Meatbag is a Kotlin/Compose Multiplatform MVP scaffold for a "Human Latency Optimization Tool." The intended flow is: 1. CLI agent or script sends an SDUI request to the backend. 2. Ktor backend evaluates active devices and user attention rules. 3. Backend pushes a JSON UI payload over WebSocket to the best device. 4. Human taps a response. 5. Client posts the response back to the backend. 6. Backend completes the pending agent callback. The repository has three modules: - `common`: shared kotlinx.serialization models for SDUI primitives, attention tiers, device context, callbacks, and responses. - `backend`: stateful Ktor backend with in-memory device registry and routing engine. - `client`: Compose Multiplatform stateless renderer and desktop simulator, plus Android/Wear attention hook scaffolding. ## Important Commit Initial pushed commit: ```text 8b4cb8e Initialize Meatbag SDUI platform ``` This handoff should be committed after that initial push. ## Gitea Notes The actual Gitea is containerized in Colima/Docker: - URL: `http://localhost:3000` - Repo: `http://localhost:3000/bill/meatbag` - Container name: `gitea` - SSH exposed by container: host port `2222` to container port `22` If `localhost:3000` is down, check: ```sh colima status colima start docker ps ``` Do not use the old top-level `/Users/blindmouse/gitea_setup.sh` as the source of truth. That was an older non-container setup path. ## What Works Conceptually - `common/src/commonMain/kotlin/meatbag/common/UiPrimitive.kt` - Strict sealed serializable SDUI model hierarchy: - `ApprovalRequest` - `ActionList` - `TextInput` - `Message` - Attention schema: - `SILENT_HAPTIC` - `BACKGROUND_NOTIFICATION` - `OVERRIDE_SCREEN` - Payload/context types: - `WebSocketPayload` - `AttentionPolicy` - `DeviceContext` - `CallbackRequest` - `ApprovalResponse` - `backend/src/main/kotlin/meatbag/backend/RoutingEngine.kt` - In-memory pending request map. - Mock `UserRuleSet`. - Watch-first routing for silent haptics. - Override-screen fan-out to multiple active devices. - Enriched payload context per target device. - `backend/src/main/kotlin/meatbag/backend/Application.kt` - `GET /api/status` - `POST /api/request` - `POST /api/respond` - `WS /ws/connect?deviceType=WEAR_OS_WATCH|PHONE|DESKTOP` - `client/src/commonMain/kotlin/meatbag/client/ComponentRegistry.kt` - Stateless UDF renderer. - No reflection. - Typed `ComponentIntent` out, converted to `ApprovalResponse` at the client boundary. - `client/src/desktopMain/kotlin/meatbag/client/Main.kt` - Desktop simulator for local payload testing and WebSocket connection testing. ## Not Ready Yet The repo is not yet a ready-to-install Android/Wear app for an S23 Ultra or watch. Missing pieces: - Android app packaging: - `AndroidManifest.xml` - `MainActivity` - Compose app bootstrap for `MeatbagClient` - internet permission - cleartext HTTP allowance for local backend testing - Wear app packaging: - Wear entry point - manifest - real haptic implementation using Android vibrator APIs - watch-specific UI constraints - Build verification: - Previous environment did not have a Java runtime available, so Gradle tests/builds were not run successfully. ## Recommended Next Task Make the Android phone client installable first, then add Wear OS. Suggested sequence: 1. Install/confirm JDK 17 on the machine doing the build. 2. Run: ```sh ./gradlew :common:jvmTest :backend:test :client:compileKotlinDesktop ``` 3. Fix any compile issues from the recent scaffold. 4. Add Android app entry: - `client/src/androidMain/AndroidManifest.xml` - `client/src/androidMain/kotlin/meatbag/client/MainActivity.kt` - Compose root that uses `MeatbagClient` - host/IP configuration for the backend 5. Verify an S23 can connect to: ```text ws://:8080/ws/connect?deviceType=PHONE ``` 6. Add Wear OS entry after phone works: ```text ws://:8080/ws/connect?deviceType=WEAR_OS_WATCH ``` 7. Wire `WearAttentionFeedback` to real haptic APIs. ## Local Backend Smoke Test Shape Once backend runs on the computer: ```sh ./gradlew :backend:run ``` Connect a client WebSocket: ```text ws://localhost:8080/ws/connect?deviceType=WEAR_OS_WATCH&deviceId=watch_1 ``` Send an approval request: ```sh curl -X POST 'http://localhost:8080/api/request?urgent=true' \ -H 'Content-Type: application/json' \ -d '{ "type": "ApprovalRequest", "id": "req_1", "prompt": "Allow agent to continue?", "target": "desktop-agent" }' ``` Respond: ```sh curl -X POST 'http://localhost:8080/api/respond' \ -H 'Content-Type: application/json' \ -d '{ "requestId": "req_1", "approved": true }' ``` ## Caution There is a mistakenly downloaded standalone Gitea binary at: ```text /Users/blindmouse/bin/gitea ``` And old non-container setup files under: ```text /Users/blindmouse/gitea ``` Those are not the active Gitea. The active Gitea is the Docker container named `gitea`.