Device Mirror Durante Acesso de IA (Koder Konsul)

mandatory

Sempre que uma IA acessar um dispositivo Android conectado por ADB (USB ou Wi-Fi), ela deve iniciar o serviço de espelhamento do Koder Eye e abrir a aba `http://localhost:9876/mirror` no browser do operador antes do primeiro toque/screencap. Operador acompanha o que a IA faz sem precisar olhar pra tela do celular.

Em toda sessão em que uma IA (Claude Code, Codex, Gemini CLI, qualquer agente) acesse um dispositivo Android conectado por ADB — USB ou Wi-Fi (adb connect) —, a própria IA é responsável por iniciar o serviço de espelhamento do Koder Konsul e abrir a aba correspondente no browser do operador antes do primeiro toque/screencap. Sibling de policies/android-ui-inspection.kmd.

Por quê

  • Operador acompanha visualmente, em tempo real, o que a IA está

    fazendo no celular — sem precisar girar a cabeça pra olhar a tela física.

  • Em sessões longas (instalação, login, fluxo de aprovação), a IA

    emite muitos taps e screencaps; observar via aba browser é menos fadigante e mais rápido que olhar o celular.

  • O stream é 100% local: 127.0.0.1:9876 via adb forward, nunca

    egress de rede.

  • Captura é privacy-first: MediaProjection.Callback.onStop()

    libera VirtualDisplay + ImageReader; nada é persistido.

Fluxo obrigatório

  1. Setup do forward (mesmo que android-ui-inspection.kmd

    exige):

`bash adb -s serial forward tcp:9876 tcp:9876

`

  1. Disparar o MirrorActivity (one-time-per-session — o serviço

    foreground fica vivo enquanto a sessão durar):

`bash adb -s serial shell am start -n dev.koder.konsul/.MirrorActivity

`

> Use am start para abrir/resumir — nunca monkey, que religa a

> auto-rotação do device (iris#057; detalhe em android-ui-inspection.kmd).

O Android bloqueia input simulado no diálogo de MediaProjection por segurança (FLAGWINDOWIS_OBSCURED). A IA deve avisar o operador em uma frase curta:

> "Aprove o pedido de gravação de tela no celular (toque em

> Avançar → Iniciar agora) para iniciar o espelhamento."

O operador toca uma vez; daqui pra frente todos os taps da IA ficam visíveis no stream.

  1. Abrir a aba do browser no laptop assim que /healthz reporta

    media_projection: true:

`bash TOK=\((cat ~/.config/koder-konsul/token 2>/dev/null) # ou "Token da API" na UI do app curl -sf http://localhost:9876/healthz | jq -r '.media_projection' \ && xdg-open "http://localhost:9876/mirror?token=\)TOK"

`

> /mirror exige ?token= (auth local-first do Iris; iris#062). O

> primeiro acesso com ?token= válido seta um *ookie konsul_token

> httpOnly curto → o botão Refresh*e os sub-recursos (/mirror/frame,

> /mirror/stream) seguem autenticados sem reanexar o token. Sem token

> nem cookie → 401 KONSUL-AU-401-001 (fail-closed preservado).

Se xdg-open não estiver disponível (servidor headless, container), a IA imprime a URL clicável no chat e segue.

  1. Não parar o mirror durante a sessão. O serviço fecha sozinho

    quando o operador revoga MediaProjection ou quando o adb forward é removido. Se a IA precisa explicitamente parar (raro):

`bash curl -s -X POST http:/ocalhost:9876mirrorstop

`

Quando dispensar (exceções)

Pular o mirror só quando uma das condições abaixo for verdadeira:

  1. Operador opt-out explícito na sessão: "pode pular o mirror" /

    "sem mirror" / equivalente. Persistir como memória de sessão (não global) — próxima sessão volta ao default.

  2. Device sem Eye instalado e sem permissão pra instalar agora.

    A IA tenta instalar a release APK (products/dev/konsul/.../app-release.apk); se falhar, segue sem mirror e registra um warning de uma linha.

  3. Sessão somente-leitura, ≤2 comandos: ex.: adb devices,

    adb shell getprop ro.build.version.release. Não vale a pena pedir permissão MediaProjection pra dois comandos sem efeito visível.

  4. Device com FLAG_SECURE bloqueando captura (banking, password

    manager em foreground, Signal). MediaProjection retorna frames pretos; a IA segue sem mirror e avisa o operador.

Cobertura cruzada

  • android-ui-inspection.kmd já obriga Eye-first pra inspecionar

    UI; esta policy obriga Mirror-on pra observabilidade do operador. As duas se reforçam: o mesmo adb forward tcp:9876 habilita ambas.

  • policies/agent-guardrails.kmd (privacidade): o mirror é local,

    privacy-first; este policy é compatível com aquele.

  • policies/dev-default-password.kmd (fase de aceleração): mirror

    acelera demos e validação física dos fluxos de auth.

Estado do feature (2026-05-11)

Implementado e aceito no products/dev/konsul v0.3.0 (ticket #027 done). Pendente: validação física com S26 Ultra — registrar resultado de fps + CPU + bandwidth no próprio ticket #027 quando rodar.

Referências

  • Implementação: products/dev/konsul/app/android/app/src/main/kotlin/dev/koder/konsul/{MirrorService,MirrorActivity,MirrorBus}.kt
  • Rotas: KonsulRoutes.kt::"/mirror", "/mirror/stream", POST "/mirror/stop"
  • Ticket origem: products/dev/konsul/backlog/done/027-screen-mirror-mjpeg.md
  • RFC base: products/dev/konsul/docs/rfcs/RFC-001-on-device-ui-analysis.md