Skip to content

feat(container): add first-party Android MCP module#437

Open
konard wants to merge 11 commits into
ProverCoderAI:mainfrom
konard:issue-436-7a79950cbb5b
Open

feat(container): add first-party Android MCP module#437
konard wants to merge 11 commits into
ProverCoderAI:mainfrom
konard:issue-436-7a79950cbb5b

Conversation

@konard

@konard konard commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Android MCP integration with a first-party module

Fixes #436: «Подключить mcp-android так же как работает MCP PLAYRIGHT».

This updates the Android MCP implementation after review feedback that the module itself must be implemented and proven separately before wiring it into the container.

What changed

  • Added crates/android-connection, a first-party Rust crate with:
    • android-connection: MCP stdio server exposing Android tools over ADB.
    • docker-git-android-connection: deterministic lifecycle CLI for Android runtime spec/start/status/stop.
    • Pure CORE functions for project/container/volume naming, endpoint validation, Docker argv construction, and MCP tool registry.
  • Replaced runtime npx @mobilenext/mobile-mcp@latest wiring with direct android-connection commands for Codex, Claude, Gemini, and Grok.
  • Updated Dockerfile generation to copy .docker-git-tools/android-connection into the build context and install the crate with cargo install --path ... --locked --bins.
  • Added SHELL provisioning that copies the audited Rust source into generated project build contexts only when Android MCP is enabled.
  • Preserved Playwright-style opt-in behavior through enableMcpAndroid, compose sidecar env, templates, apply path, CLI/docs, and changeset.
  • Added CI coverage for the Rust module: cargo fmt --check, cargo test --locked, and cargo clippy --locked --all-targets -- -D warnings.

Mathematical guarantees

  • Endpoint invariant: every configured ADB endpoint is non-empty, bounded to 255 chars, contains a port separator, and uses only [A-Za-z0-9._:-].
  • Docker argv invariant: lifecycle commands are built as argv vectors, not shell strings.
  • Workspace confinement invariant: MCP file tools reject empty, absolute, and .. paths before writing screenshots or installing APKs.
  • Build-context invariant: generated Android-enabled projects build from the same crates/android-connection source covered by local tests and CI.

Proof of fix

  • Cause: the previous Android MCP wiring delegated core functionality to an unpinned third-party npx command and did not provide a separately testable module.
  • Solution: Android MCP is now a first-party Rust crate, installed from the generated Docker build context, configured by direct argv arrays, and covered by unit/template/use-case tests plus CI.
  • Proof: the Rust crate tests cover deterministic naming/specs, endpoint rejection, MCP initialize/tools-list framing, status without ADB probe, and workspace path confinement; TS tests cover Dockerfile, compose, entrypoint, apply, and source provisioning behavior.

Verification

cargo fmt --manifest-path crates/android-connection/Cargo.toml --check
cargo test --locked --manifest-path crates/android-connection/Cargo.toml
cargo clippy --locked --manifest-path crates/android-connection/Cargo.toml --all-targets -- -D warnings
bun run --cwd packages/container typecheck
bun run --cwd packages/container test -- tests/core/templates.test.ts
bun run --cwd packages/container lint
bun run --cwd packages/lib typecheck
bun run --cwd packages/lib test -- tests/usecases/mcp-android.test.ts tests/usecases/apply.test.ts
bun run --cwd packages/lib lint
bun run --cwd packages/app check
bun run --cwd packages/app lint
bun run check
bun run test

This PR was updated automatically by the AI issue solver.

Adding .gitkeep for PR creation (default mode).
This file will be removed when the task is complete.

Issue: ProverCoderAI#436
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

Примечания к выпуску

  • Новые возможности

    • Добавлена интеграция Android MCP с поддержкой мобильной автоматизации через вложенный сервис Android-эмулятора.
    • Новые флаги --mcp-android / --no-mcp-android для управления включением Android-подключения в проектах.
    • Встроенная поддержка управления жизненным циклом Android-контейнера через Docker Compose.
    • Синхронизация конфигурации Android MCP для Claude, Gemini, Grok и Codex.
  • Улучшения

    • Расширена API проектов новым параметром для включения Android-функций.

Walkthrough

PR добавляет опциональную интеграцию Android MCP (android-connection) наряду с существующей Playwright MCP поддержкой. Введён новый Rust-крейт crates/android-connection с framed stdio MCP-сервером и lifecycle CLI. Флаг enableMcpAndroid прокидывается через API-контракты, CLI-флаги, интерактивный create-wizard и генерацию docker-compose.yml/Dockerfile/entrypoint-скриптов для агентов Claude, Codex, Gemini и Grok.

Changes

Android MCP сквозная интеграция

Layer / File(s) Summary
Контракты API, доменные типы и схемы
packages/api/src/api/contracts.ts, packages/api/src/api/schema.ts, packages/api/src/services/projects.ts, packages/app/src/web/api-types.ts, packages/app/src/web/api-project-create-body.ts, packages/openapi/openapi.json, packages/openapi/src/openapi-paths.ts, packages/app/src/docker-git/frontend-lib/core/domain.ts, packages/app/src/docker-git/frontend-lib/core/command-options.ts, packages/app/src/docker-git/frontend-lib/core/template-defaults.ts, packages/app/src/docker-git/menu-types.ts, packages/lib/src/core/domain.ts, packages/lib/src/core/command-options.ts, packages/container/src/core/domain.ts, packages/container/src/core/template-defaults.ts, packages/lib/src/shell/config.ts
В CreateProjectRequest, TemplateConfig, RawOptions, CreateInputs, ApplyCommand добавлено поле enableMcpAndroid; добавлен интерфейс McpAndroidUpCommand; расширены OpenAPI-схема и конфигурационные defaults.
CLI-команда mcp-android и флаги
packages/app/src/docker-git/cli/parser-mcp-android.ts, packages/app/src/docker-git/cli/parser-options.ts, packages/app/src/docker-git/cli/parser.ts, packages/app/src/docker-git/cli/usage.ts, packages/app/src/docker-git/cli/parser-apply.ts, packages/app/src/docker-git/program-unsupported.ts, packages/app/src/docker-git/menu-create-command-parse.ts, packages/app/src/docker-git/api-client-create.ts, packages/lib/src/core/command-builders-template.ts, packages/lib/src/core/command-builders.ts, packages/app/src/docker-git/frontend-lib/core/command-builders-template.ts, packages/app/src/docker-git/frontend-lib/core/command-builders.ts
Добавлены парсер parseMcpAndroid, маршрутизация команды mcp-android, флаги --mcp-android/--no-mcp-android и прокидывание флага через command builders в TemplateConfig.
Create-flow wizard шаг mcpAndroid
packages/app/src/docker-git/menu-create-labels.ts, packages/app/src/docker-git/menu-create-navigation.ts, packages/app/src/docker-git/menu-create-step-apply.ts, packages/app/src/docker-git/menu-create-steps.ts, packages/app/src/docker-git/menu-create-inputs.ts, packages/app/src/docker-git/menu-create-draft.ts, packages/app/tests/docker-git/*
Добавлен шаг mcpAndroid в интерактивный create-wizard с labels, navigation, step-apply и satisfaction-логикой; обновлены все связанные тесты.
Rust-крейт android-connection
crates/android-connection/Cargo.toml, crates/android-connection/src/lib.rs, crates/android-connection/src/mcp.rs, crates/android-connection/src/main.rs, crates/android-connection/src/bin/android-connection.rs, crates/android-connection/README.md, .github/workflows/check.yml
Новый первый-party Rust-крейт: core-библиотека с валидацией ADB endpoint и docker-аргументами, framed stdio MCP-сервер с 11 Android-инструментами, lifecycle CLI (start/status/stop) и CI-проверка крейта.
Генерация docker-compose и Dockerfile для Android sidecar
packages/container/src/core/templates/docker-compose-android.ts, packages/container/src/core/templates/docker-compose-playwright.ts, packages/container/src/core/templates/docker-compose.ts, packages/container/src/core/templates/dockerfile.ts, packages/lib/src/shell/android-connection-source.ts, packages/lib/src/shell/files.ts, packages/container/tests/core/templates.test.ts
Добавлены фрагменты Android sidecar (KVM, ADB-порт, headless) в docker-compose, условная установка android-tools-adb и android-connection в Dockerfile, provisioning Rust-исходников в build-контекст и тесты.
Entrypoint-конфигурация Android MCP для агентов
packages/container/src/core/templates-entrypoint/base.ts, packages/container/src/core/templates-entrypoint/claude.ts, packages/container/src/core/templates-entrypoint/codex.ts, packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts, packages/container/src/core/templates-entrypoint/gemini-playwright-mcp.ts, packages/container/src/core/templates-entrypoint/gemini.ts, packages/container/src/core/templates-entrypoint/grok-android-mcp.ts, packages/container/src/core/templates-entrypoint/grok.ts, packages/container/src/core/templates-entrypoint.ts
Добавлена переменная MCP_ANDROID_ENABLE и скрипты синхронизации mcpServers.android для Claude, Codex, Gemini, Grok; Gemini Playwright-конфиг выделен в отдельный модуль.
Use-case включения Android MCP
packages/lib/src/usecases/mcp-android.ts, packages/lib/src/usecases/apply-overrides.ts, packages/lib/src/usecases/actions/create-project-conflicts.ts, packages/lib/src/usecases/errors.ts, packages/lib/src/shell/errors.ts, packages/lib/tests/usecases/mcp-android.test.ts, packages/lib/tests/usecases/apply.test.ts
Добавлены enableMcpAndroidProjectFiles и mcpAndroidUp use-case, Android identity-конфликты (container/volume claims), override-логика и тесты всего потока.
Документация и релизные записи
.changeset/mcp-android-integration.md, README.md, packages/app/CHANGELOG.md, packages/app/package.json, packages/docker-git-session-sync/CHANGELOG.md, packages/docker-git-session-sync/package.json
Добавлены changeset-запись, строка --mcp-android в README и version bump пакетов.

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant CLI as docker-git CLI
  participant CreateFlow as Create Wizard / API
  participant Container as Container Template Engine
  participant AndroidCrate as android-connection (Rust)
  participant AgentConfig as Agent Config (Claude/Gemini/Grok/Codex)

  User->>CLI: docker-git create --mcp-android
  CLI->>CreateFlow: McpAndroidUpCommand / CreateInputs{enableMcpAndroid:true}
  CreateFlow->>Container: buildComposeFragments(enableMcpAndroid=true)
  Container->>Container: buildAndroidFragments → docker-android sidecar YAML
  Container->>Container: renderDockerfileAndroidRuntime → cargo install android-connection
  Container->>AgentConfig: renderClaudeMcpAndroidConfig / renderGeminiMcpAndroidConfig / ...
  AgentConfig-->>Container: mcpServers.android = {command: "android-connection", endpoint: ...}
  Container-->>CreateFlow: docker-compose.yml, Dockerfile, entrypoint.sh
  CreateFlow-->>CLI: project files written
  CLI->>AndroidCrate: android-connection --endpoint <adb>
  AndroidCrate-->>CLI: MCP stdio server ready
  CLI-->>User: project created with Android emulator sidecar
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • ProverCoderAI/docker-git#420: Оба PR расширяют toCreateRawOptions в packages/api/src/services/projects.ts, маппя новые поля из тела запроса в RawOptions.
  • ProverCoderAI/docker-git#427: Данный PR обновляет OpenAPI-схему (enableMcpAndroid в POST /projects), которая строится на инфраструктуре типизированного OpenAPI-клиента из PR #427.

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Requirements Alignment ❌ Error PR описывает использование @mobilenext/mobile-mcp, но фактически реализует собственный android-connection. Содержит незафиксированные security issues: TOML injection (codex.ts), слабая валидация AD... Уточните PR description о фактическом использовании android-connection Rust крейта. Исправьте TOML injection через экранирование переменных, усильте валидацию ADB endpoint (проверка host:port), добавьте проверку symlink в workspace_path,...
Security Regression ⚠️ Warning Pull request вводит высоко-уверенные регрессии безопасности: (1) TOML injection в codex.ts строка 214 (переменные вставляются без экранирования, claude.ts использует JSON.stringify безопасно); (2)... Требуется исправить: (1) Use JSON.stringify для args в codex.ts как в claude.ts; (2) Strict ADB endpoint validation (host:port format); (3) Add symlink checking в workspace_path с регрессионным тестом; (4) Switch to allowlist-based copyi...
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Название ясно и точно отражает главное изменение: добавление первого модуля Android MCP в контейнер.
Description check ✅ Passed Описание полное и детальное, охватывает все ключевые аспекты: что изменилось, математические гарантии, доказательства исправления, и инструкции проверки.
Linked Issues check ✅ Passed PR полностью реализует требования #436: добавлен первый модуль Rust для Android MCP, интегрирован в Dockerfile/compose/entrypoint, поддерживается Playwright-подобное поведение с --mcp-android флагом, добавлены тесты и CI-проверки.
Out of Scope Changes check ✅ Passed Все изменения связаны с Android MCP интеграцией, включая контейнер, CLI, API, тесты, и вспомогательную инфраструктуру сборки. Нет посторонних изменений.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

github-actions Bot and others added 7 commits June 23, 2026 15:47
Mirror the Playwright MCP wiring for Android (issue ProverCoderAI#436):
- TemplateConfig.enableMcpAndroid + default
- docker-compose: emulator sidecar service (docker-android), env vars,
  ADB endpoint, dedicated volume
- Dockerfile: install android-tools-adb when enabled
- entrypoint base env MCP_ANDROID_ENABLE
- codex/claude/gemini/grok: register an 'android' MCP server (mobile-mcp)
- container template tests
Add --mcp-android / --no-mcp-android flags, mcp-android subcommand parser,
interactive create-flow prompt + display-settings row, and propagate
enableMcpAndroid through frontend-lib config, web create draft, and API
client request body. Mirrors the existing Playwright MCP integration.

REF: issue-436
Add enableMcpAndroid to the create-project schema, contract type, and
service request mapping, and regenerate the OpenAPI spec + typed paths.

REF: issue-436
@konard konard changed the title [WIP] Подключить mcp-android так же как работает MCP PLAYRIGHT Подключить mcp-android так же как работает MCP PLAYRIGHT Jun 23, 2026
@konard konard marked this pull request as ready for review June 23, 2026 16:37
…y max-lines lint

Move the Android and Playwright MCP config/sidecar builders into sibling
modules so grok.ts, gemini.ts, and docker-compose.ts stay under the 300-line
max-lines budget enforced by CI. Pure refactor — rendered output is unchanged
(72 container tests still pass).

REF: issue-436
@konard

konard commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

Working session summary

The work is complete. Here's the final status:

Summary

Issue #436 ("Подключить mcp-android так же как работает MCP PLAYRIGHT") is resolved in PR #437, now ready for review with all CI green.

What was delivered

Android emulator MCP integration mirroring the existing Playwright MCP pattern across the whole stack:

  • Container: a gated ${serviceName}-android Docker Compose sidecar (budtmo/docker-android, KVM device, ADB 5555 + noVNC 6080 bound to 127.0.0.1 by default, headless CI mode), env-overridable image/ports, plus Android MCP config writers for the Gemini/Grok agents registering @mobilenext/mobile-mcp over ADB.
  • Lib: mcp-android usecase + command/config plumbing (enableMcpAndroid).
  • App/CLI: --mcp-android/--no-mcp-android flags, mcp-android subcommand, interactive create-flow prompt.
  • API + OpenAPI: enableMcpAndroid field on create-project request.
  • Docs/changeset: minor bump for the public @prover-coder-ai/docker-git package.

This session's work

Fixed the CI Lint (container) failure (three max-lines violations: grok.ts 312, gemini.ts 331, docker-compose.ts 362 vs. max 300) by extracting five sibling helper modules — grok-android-mcp.ts, gemini-android-mcp.ts, gemini-playwright-mcp.ts, docker-compose-android.ts, docker-compose-playwright.ts. Pure refactor; rendered output unchanged (72 container tests pass).

Verification

  • bun run check (root) → all packages typecheck, exit 0
  • Container typecheck exit 0; 72/72 tests pass
  • PR feat(container): add first-party Android MCP module #437 CI — all pass: Build, Test, Types, Lint, Lint Effect-TS, all E2E jobs, Final build (macos/ubuntu/windows), Snapshot, Dist deps prune
  • Only non-green: CodeRabbit (third-party review, "in progress" / credits-exhausted) — not a code gate
  • Working tree clean; PR not draft, MERGEABLE, base main ← head issue-436-7a79950cbb5b

PR: #437


This summary was automatically extracted from the AI working session output.

@konard

konard commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Solution Draft Log

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost estimation:

  • Public pricing estimate: $25.339442
  • Calculated by Anthropic: $25.345577
  • Difference: $0.006135 (+0.02%)

📊 Context and tokens usage:

Claude Opus 4.8: (6 sub-sessions)

  1. 113.9K / 1M (11%) input tokens, 31.3K / 128K (24%) output tokens
  2. 116.3K / 1M (12%) input tokens, 36.6K / 128K (29%) output tokens
  3. 116.7K / 1M (12%) input tokens, 26.7K / 128K (21%) output tokens
  4. 116.7K / 1M (12%) input tokens, 29.3K / 128K (23%) output tokens
  5. 116.3K / 1M (12%) input tokens, 43.1K / 128K (34%) output tokens
  6. 47.8K / 1M (5%) input tokens, 8.7K / 128K (7%) output tokens

Total: (63.2K new + 578.1K cache writes + 27.2M cache reads) input tokens, 216.4K output tokens, $25.094257 cost

Claude Haiku 4.5:

  • 72.6K / 200K (36%) input tokens, 8.0K / 64K (12%) output tokens

Total: (52 new + 72.6K cache writes + 1.1M cache reads) input tokens, 8.0K output tokens, $0.245185 cost

🤖 Models used:

  • Tool: Anthropic Claude Code
  • Requested: opus (claude-opus-4-8)
  • Main model: Claude Opus 4.8 (claude-opus-4-8)
  • Additional models:
    • Claude Haiku 4.5 (claude-haiku-4-5-20251001)

📎 Log file uploaded as Gist (12279KB)


Now working session is ended, feel free to review and add any feedback on the solution draft.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/container/src/core/templates-entrypoint/claude.ts`:
- Around line 268-285: The adbEndpoint variable is being directly concatenated
into a bash command string without sanitization, creating a command injection
vulnerability. In the connectPrefix variable assignment where adbEndpoint is
used with "adb connect " + adbEndpoint, you need to properly escape or sanitize
the adbEndpoint value to prevent shell metacharacters from being interpreted as
commands. Use appropriate shell escaping techniques (such as single quotes or a
proper escaping function) to ensure user-controlled input cannot break out of
the intended command context when the bash -lc command is executed.

In `@packages/container/src/core/templates-entrypoint/codex.ts`:
- Line 206: The command string passed to bash -lc in the args assignment
contains an unescaped environment variable $DOCKER_GIT_ANDROID_ADB_ENDPOINT that
could allow command injection. Wrap the endpoint variable in double quotes in
the bash command to prevent arbitrary command execution. Change
$DOCKER_GIT_ANDROID_ADB_ENDPOINT to "$DOCKER_GIT_ANDROID_ADB_ENDPOINT" within
the adb connect command string to safely interpolate the variable while
preventing shell metacharacter interpretation.
- Around line 203-207: Replace the use of `@latest` with a pinned version number
`0.0.60` for the `@mobilenext/mobile-mcp` package across all MCP Android
configuration files. In the codex.ts file, update the npx command in the args
array to use the specific version instead of `@latest`. Apply the same fix to
gemini-android-mcp.ts, grok-android-mcp.ts, and claude.ts files. Additionally,
update the test expectations in packages/container/tests/core/templates.test.ts
to expect the pinned version `0.0.60` instead of `@latest` to ensure tests pass
with the new versioning.

In `@packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts`:
- Around line 24-29: The adbEndpoint value from
process.env.DOCKER_GIT_ANDROID_ADB_ENDPOINT is being concatenated directly into
a bash command without validation or sanitization, creating a command injection
vulnerability. Before using adbEndpoint in the connectPrefix string that gets
passed to the bash -lc command, add validation to ensure the endpoint contains
only safe characters (such as alphanumeric, dots, colons, and hyphens for a
typical ADB endpoint format), or properly escape it for shell safety. This will
prevent malicious input from being executed as shell commands.

In `@packages/container/src/core/templates-entrypoint/grok-android-mcp.ts`:
- Around line 24-29: The code has a command injection vulnerability where the
DOCKER_GIT_ANDROID_ADB_ENDPOINT environment variable is directly concatenated
into a bash command string without validation. To fix this, validate the
adbEndpoint variable before using it in the connectPrefix string construction.
Ensure the endpoint matches only allowed characters (likely IP address and
optional port format like "127.0.0.1:5037" or similar), and reject or skip the
android server configuration if the endpoint contains invalid characters or
fails validation. This prevents arbitrary shell commands from being injected
through the environment variable when constructing the bash -lc argument in the
nextServers.android command setup.

In `@packages/container/tests/core/templates.test.ts`:
- Line 1162: The current test assertion using toContain("    cpus: 1.5\n")
checks if the CPU limit appears anywhere in the compose output but does not
verify that the limit is specifically applied to the dg-test-android Android
sidecar service. Refactor the expect statement to first locate the
dg-test-android service configuration block within the compose output and then
verify that the cpus: 1.5 limit exists only within that specific service
section, ensuring the assertion proves the limit is correctly placed in the
Android sidecar rather than elsewhere in the configuration.
- Around line 1133-1201: The five new Android MCP tests (starting with "renders
the Android emulator sidecar service when Android MCP is enabled" through
"defaults MCP_ANDROID_ENABLE to 0 when Android MCP is disabled") use simple
example-based testing with hardcoded `it()` blocks and `expect()` statements,
which violates the established property-based testing pattern used elsewhere in
this file. Refactor these tests to use
`fc.property(generatedTemplateConfigArbitrary.chain(...), ...)` or `.map()` to
generate test cases with `enableMcpAndroid` set to both true and false,
following the same pattern already established for testing `renderDockerfile`
and `renderEntrypoint`. Convert the hardcoded assertions into parameterized
property-based checks where the invariants (like presence/absence of MCP
environment variables and service configurations based on the `enableMcpAndroid`
flag) are verified across generated configurations.

In `@packages/lib/src/usecases/apply-overrides.ts`:
- Around line 59-64: Add regression test coverage for the enableMcpAndroid
override flag in the test file that contains the "applies token and mcp
overrides from apply command" test case. Extend this existing test to include
enableMcpAndroid set to true in the applyProjectFiles command, then verify that
appliedTemplate.enableMcpAndroid equals true, that the docker-compose output
contains MCP_ANDROID_ENABLE set to "1", and that the docker-git.json output
contains enableMcpAndroid set to true, mirroring the same validation pattern
already in place for the enableMcpPlaywright flag.

In `@packages/lib/src/usecases/mcp-android.ts`:
- Around line 88-89: The ensureDockerDaemonAccess function on line 88 is
checking Docker access relative to process.cwd() while the subsequent
runDockerComposeUpWithPortCheck call uses command.projectDir, causing
inconsistent and non-deterministic behavior when working with external
directories. Replace the process.cwd() argument passed to
ensureDockerDaemonAccess with command.projectDir to ensure Docker daemon access
is verified for the same target directory that will be used for the actual
Docker Compose execution.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4223cde2-527b-474a-b5fb-9c2b687e5525

📥 Commits

Reviewing files that changed from the base of the PR and between 1113f27 and a80a75c.

📒 Files selected for processing (68)
  • .changeset/mcp-android-integration.md
  • README.md
  • packages/api/src/api/contracts.ts
  • packages/api/src/api/schema.ts
  • packages/api/src/services/projects.ts
  • packages/app/CHANGELOG.md
  • packages/app/package.json
  • packages/app/src/docker-git/api-client-create.ts
  • packages/app/src/docker-git/cli/parser-apply.ts
  • packages/app/src/docker-git/cli/parser-mcp-android.ts
  • packages/app/src/docker-git/cli/parser-options.ts
  • packages/app/src/docker-git/cli/parser.ts
  • packages/app/src/docker-git/cli/usage.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders-template.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders.ts
  • packages/app/src/docker-git/frontend-lib/core/command-options.ts
  • packages/app/src/docker-git/frontend-lib/core/domain.ts
  • packages/app/src/docker-git/frontend-lib/core/template-defaults.ts
  • packages/app/src/docker-git/menu-create-command-parse.ts
  • packages/app/src/docker-git/menu-create-draft.ts
  • packages/app/src/docker-git/menu-create-inputs.ts
  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/app/src/docker-git/menu-create-navigation.ts
  • packages/app/src/docker-git/menu-create-step-apply.ts
  • packages/app/src/docker-git/menu-create-steps.ts
  • packages/app/src/docker-git/menu-types.ts
  • packages/app/src/docker-git/program-unsupported.ts
  • packages/app/src/web/api-project-create-body.ts
  • packages/app/src/web/api-types.ts
  • packages/app/tests/docker-git/actions-project-create.test.ts
  • packages/app/tests/docker-git/api-create-project.test.ts
  • packages/app/tests/docker-git/app-ready-create-fixture.ts
  • packages/app/tests/docker-git/app-ready-create-settings.test.ts
  • packages/app/tests/docker-git/app-ready-create.test.ts
  • packages/app/tests/docker-git/menu-create-display-settings.test.ts
  • packages/app/tests/docker-git/menu-create-shared-properties.test.ts
  • packages/app/tests/docker-git/menu-create-shared.test.ts
  • packages/container/src/core/domain.ts
  • packages/container/src/core/template-defaults.ts
  • packages/container/src/core/templates-entrypoint.ts
  • packages/container/src/core/templates-entrypoint/base.ts
  • packages/container/src/core/templates-entrypoint/claude.ts
  • packages/container/src/core/templates-entrypoint/codex.ts
  • packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts
  • packages/container/src/core/templates-entrypoint/gemini-playwright-mcp.ts
  • packages/container/src/core/templates-entrypoint/gemini.ts
  • packages/container/src/core/templates-entrypoint/grok-android-mcp.ts
  • packages/container/src/core/templates-entrypoint/grok.ts
  • packages/container/src/core/templates/docker-compose-android.ts
  • packages/container/src/core/templates/docker-compose-playwright.ts
  • packages/container/src/core/templates/docker-compose.ts
  • packages/container/src/core/templates/dockerfile.ts
  • packages/container/tests/core/templates.test.ts
  • packages/docker-git-session-sync/CHANGELOG.md
  • packages/docker-git-session-sync/package.json
  • packages/lib/src/core/command-builders-template.ts
  • packages/lib/src/core/command-builders.ts
  • packages/lib/src/core/command-options.ts
  • packages/lib/src/core/domain.ts
  • packages/lib/src/shell/config.ts
  • packages/lib/src/shell/errors.ts
  • packages/lib/src/usecases/actions/create-project-conflicts.ts
  • packages/lib/src/usecases/apply-overrides.ts
  • packages/lib/src/usecases/errors.ts
  • packages/lib/src/usecases/mcp-android.ts
  • packages/lib/tests/usecases/mcp-android.test.ts
  • packages/openapi/openapi.json
  • packages/openapi/src/openapi-paths.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (5)
  • GitHub Check: E2E (Clone auto-open SSH)
  • GitHub Check: E2E (Login context)
  • GitHub Check: E2E (Clone cache)
  • GitHub Check: E2E (OpenCode)
  • GitHub Check: E2E (Runtime volumes + SSH)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input

Files:

  • packages/app/src/docker-git/cli/parser-apply.ts
  • packages/app/tests/docker-git/app-ready-create.test.ts
  • packages/app/src/docker-git/frontend-lib/core/command-options.ts
  • packages/api/src/api/contracts.ts
  • packages/app/tests/docker-git/api-create-project.test.ts
  • packages/app/src/docker-git/menu-create-steps.ts
  • packages/api/src/api/schema.ts
  • packages/app/src/docker-git/cli/parser-mcp-android.ts
  • packages/api/src/services/projects.ts
  • packages/app/tests/docker-git/actions-project-create.test.ts
  • packages/app/src/docker-git/api-client-create.ts
  • packages/app/src/docker-git/cli/usage.ts
  • packages/app/src/docker-git/menu-create-draft.ts
  • packages/app/src/docker-git/menu-create-navigation.ts
  • packages/lib/src/core/command-options.ts
  • packages/openapi/src/openapi-paths.ts
  • packages/container/src/core/templates-entrypoint.ts
  • packages/app/src/docker-git/menu-types.ts
  • packages/app/tests/docker-git/app-ready-create-settings.test.ts
  • packages/container/src/core/template-defaults.ts
  • packages/app/src/docker-git/cli/parser.ts
  • packages/app/src/web/api-types.ts
  • packages/lib/src/shell/config.ts
  • packages/app/src/docker-git/frontend-lib/core/template-defaults.ts
  • packages/app/src/docker-git/menu-create-inputs.ts
  • packages/lib/src/shell/errors.ts
  • packages/container/src/core/templates/docker-compose-playwright.ts
  • packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts
  • packages/app/src/docker-git/cli/parser-options.ts
  • packages/container/src/core/templates-entrypoint/base.ts
  • packages/container/src/core/templates/docker-compose-android.ts
  • packages/lib/src/usecases/mcp-android.ts
  • packages/container/src/core/templates-entrypoint/grok-android-mcp.ts
  • packages/container/src/core/templates-entrypoint/gemini-playwright-mcp.ts
  • packages/app/src/docker-git/menu-create-step-apply.ts
  • packages/app/tests/docker-git/menu-create-display-settings.test.ts
  • packages/container/src/core/templates-entrypoint/claude.ts
  • packages/lib/src/usecases/apply-overrides.ts
  • packages/container/src/core/templates/dockerfile.ts
  • packages/lib/src/core/command-builders-template.ts
  • packages/container/src/core/domain.ts
  • packages/app/tests/docker-git/menu-create-shared.test.ts
  • packages/app/src/docker-git/menu-create-command-parse.ts
  • packages/container/src/core/templates-entrypoint/grok.ts
  • packages/lib/src/usecases/actions/create-project-conflicts.ts
  • packages/lib/src/core/domain.ts
  • packages/lib/src/usecases/errors.ts
  • packages/container/src/core/templates-entrypoint/codex.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders-template.ts
  • packages/app/src/docker-git/frontend-lib/core/domain.ts
  • packages/app/tests/docker-git/menu-create-shared-properties.test.ts
  • packages/container/tests/core/templates.test.ts
  • packages/lib/tests/usecases/mcp-android.test.ts
  • packages/lib/src/core/command-builders.ts
  • packages/app/src/docker-git/program-unsupported.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders.ts
  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/app/tests/docker-git/app-ready-create-fixture.ts
  • packages/container/src/core/templates-entrypoint/gemini.ts
  • packages/app/src/web/api-project-create-body.ts
  • packages/container/src/core/templates/docker-compose.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce path traversal or writes outside intended project/container state directories

Files:

  • packages/app/src/docker-git/cli/parser-apply.ts
  • packages/app/tests/docker-git/app-ready-create.test.ts
  • packages/app/src/docker-git/frontend-lib/core/command-options.ts
  • packages/api/src/api/contracts.ts
  • packages/app/tests/docker-git/api-create-project.test.ts
  • packages/app/src/docker-git/menu-create-steps.ts
  • packages/api/src/api/schema.ts
  • packages/app/src/docker-git/cli/parser-mcp-android.ts
  • packages/api/src/services/projects.ts
  • packages/app/tests/docker-git/actions-project-create.test.ts
  • packages/app/src/docker-git/api-client-create.ts
  • packages/app/src/docker-git/cli/usage.ts
  • packages/app/src/docker-git/menu-create-draft.ts
  • packages/app/src/docker-git/menu-create-navigation.ts
  • packages/lib/src/core/command-options.ts
  • packages/openapi/src/openapi-paths.ts
  • packages/container/src/core/templates-entrypoint.ts
  • packages/app/src/docker-git/menu-types.ts
  • packages/app/tests/docker-git/app-ready-create-settings.test.ts
  • packages/container/src/core/template-defaults.ts
  • packages/app/src/docker-git/cli/parser.ts
  • packages/app/src/web/api-types.ts
  • packages/lib/src/shell/config.ts
  • packages/app/src/docker-git/frontend-lib/core/template-defaults.ts
  • packages/app/src/docker-git/menu-create-inputs.ts
  • packages/lib/src/shell/errors.ts
  • packages/container/src/core/templates/docker-compose-playwright.ts
  • packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts
  • packages/app/src/docker-git/cli/parser-options.ts
  • packages/container/src/core/templates-entrypoint/base.ts
  • packages/container/src/core/templates/docker-compose-android.ts
  • packages/lib/src/usecases/mcp-android.ts
  • packages/container/src/core/templates-entrypoint/grok-android-mcp.ts
  • packages/container/src/core/templates-entrypoint/gemini-playwright-mcp.ts
  • packages/app/src/docker-git/menu-create-step-apply.ts
  • packages/app/tests/docker-git/menu-create-display-settings.test.ts
  • packages/container/src/core/templates-entrypoint/claude.ts
  • packages/lib/src/usecases/apply-overrides.ts
  • packages/container/src/core/templates/dockerfile.ts
  • packages/lib/src/core/command-builders-template.ts
  • packages/container/src/core/domain.ts
  • packages/app/tests/docker-git/menu-create-shared.test.ts
  • packages/app/src/docker-git/menu-create-command-parse.ts
  • packages/container/src/core/templates-entrypoint/grok.ts
  • packages/lib/src/usecases/actions/create-project-conflicts.ts
  • packages/lib/src/core/domain.ts
  • packages/lib/src/usecases/errors.ts
  • packages/container/src/core/templates-entrypoint/codex.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders-template.ts
  • packages/app/src/docker-git/frontend-lib/core/domain.ts
  • packages/app/tests/docker-git/menu-create-shared-properties.test.ts
  • packages/container/tests/core/templates.test.ts
  • packages/lib/tests/usecases/mcp-android.test.ts
  • packages/lib/src/core/command-builders.ts
  • packages/app/src/docker-git/program-unsupported.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders.ts
  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/app/tests/docker-git/app-ready-create-fixture.ts
  • packages/container/src/core/templates-entrypoint/gemini.ts
  • packages/app/src/web/api-project-create-body.ts
  • packages/container/src/core/templates/docker-compose.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output

Files:

  • packages/app/src/docker-git/cli/parser-apply.ts
  • packages/app/package.json
  • packages/app/tests/docker-git/app-ready-create.test.ts
  • packages/app/src/docker-git/frontend-lib/core/command-options.ts
  • packages/api/src/api/contracts.ts
  • packages/app/tests/docker-git/api-create-project.test.ts
  • packages/docker-git-session-sync/package.json
  • packages/app/src/docker-git/menu-create-steps.ts
  • packages/api/src/api/schema.ts
  • packages/app/src/docker-git/cli/parser-mcp-android.ts
  • packages/api/src/services/projects.ts
  • packages/app/tests/docker-git/actions-project-create.test.ts
  • packages/app/src/docker-git/api-client-create.ts
  • packages/app/src/docker-git/cli/usage.ts
  • packages/app/src/docker-git/menu-create-draft.ts
  • packages/app/src/docker-git/menu-create-navigation.ts
  • packages/lib/src/core/command-options.ts
  • packages/openapi/src/openapi-paths.ts
  • packages/container/src/core/templates-entrypoint.ts
  • packages/app/src/docker-git/menu-types.ts
  • packages/app/tests/docker-git/app-ready-create-settings.test.ts
  • packages/container/src/core/template-defaults.ts
  • packages/app/src/docker-git/cli/parser.ts
  • packages/app/src/web/api-types.ts
  • packages/lib/src/shell/config.ts
  • packages/app/src/docker-git/frontend-lib/core/template-defaults.ts
  • packages/app/src/docker-git/menu-create-inputs.ts
  • packages/lib/src/shell/errors.ts
  • packages/container/src/core/templates/docker-compose-playwright.ts
  • packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts
  • packages/app/src/docker-git/cli/parser-options.ts
  • packages/container/src/core/templates-entrypoint/base.ts
  • packages/container/src/core/templates/docker-compose-android.ts
  • packages/lib/src/usecases/mcp-android.ts
  • packages/container/src/core/templates-entrypoint/grok-android-mcp.ts
  • packages/container/src/core/templates-entrypoint/gemini-playwright-mcp.ts
  • packages/app/src/docker-git/menu-create-step-apply.ts
  • packages/app/tests/docker-git/menu-create-display-settings.test.ts
  • packages/container/src/core/templates-entrypoint/claude.ts
  • packages/lib/src/usecases/apply-overrides.ts
  • packages/container/src/core/templates/dockerfile.ts
  • packages/lib/src/core/command-builders-template.ts
  • packages/container/src/core/domain.ts
  • packages/app/tests/docker-git/menu-create-shared.test.ts
  • packages/app/src/docker-git/menu-create-command-parse.ts
  • packages/container/src/core/templates-entrypoint/grok.ts
  • packages/lib/src/usecases/actions/create-project-conflicts.ts
  • packages/lib/src/core/domain.ts
  • packages/lib/src/usecases/errors.ts
  • packages/container/src/core/templates-entrypoint/codex.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders-template.ts
  • packages/openapi/openapi.json
  • packages/app/src/docker-git/frontend-lib/core/domain.ts
  • packages/app/tests/docker-git/menu-create-shared-properties.test.ts
  • packages/container/tests/core/templates.test.ts
  • packages/lib/tests/usecases/mcp-android.test.ts
  • packages/lib/src/core/command-builders.ts
  • packages/app/src/docker-git/program-unsupported.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders.ts
  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/app/tests/docker-git/app-ready-create-fixture.ts
  • packages/container/src/core/templates-entrypoint/gemini.ts
  • packages/app/src/web/api-project-create-body.ts
  • packages/container/src/core/templates/docker-compose.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: FUNCTIONAL CORE: Write only pure functions with immutable data and mathematical operations in core modules; no side effects, mutations, or external service calls
IMPERATIVE SHELL: Isolate all side effects (IO, network, database, environment/process) in a thin SHELL layer; CORE never calls SHELL, only SHELL → CORE
Never use any type annotation in TypeScript; use unknown only at SHELL boundaries for decoding, never export unknown outside boundary modules
Never use as type assertions in normal code; only permit as in a single 'axiomatic' module (brands, constructors, constants) after which types flow safely without casts
Always use exhaustive pattern matching for union types through .exhaustive() or Match.exhaustive() from effect-ts; never use switch statements or unhandled type branches
Use Effect<Success, Error, Requirements> monad from effect-ts for all effects; compose through pipe() and Effect.flatMap(); never use async/await, raw Promise chains (then/catch), or Promise.all in product code
Interoperate with Promise/exceptions only in SHELL through Effect.try/Effect.tryPromise with typed error mapping; never leave raw exceptions or untyped errors in the domain
Use Effect.acquireRelease + Effect.scoped for resource management with guaranteed finalization; never manage resources with try/finally or manual cleanup
All external services (database, HTTP, environment) must be accessed through Effect-based interfaces and Layer-based dependency injection; never call external APIs directly
Provide comprehensive TSDoc comments with mathematical notation: @pure, @effect, @invariant, @precondition, @postcondition, @complexity, @throws, and CHANGE/WHY/REF/SOURCE/FORMAT THEOREM functional comment markers
No console.*, process direct calls, or untyped environment access in product code; all such operations must be abstracted through Layer-based services in SHELL
Boundary data from external sources (HTTP, database, environment) must be decoded/valida...

Files:

  • packages/app/src/docker-git/cli/parser-apply.ts
  • packages/app/tests/docker-git/app-ready-create.test.ts
  • packages/app/src/docker-git/frontend-lib/core/command-options.ts
  • packages/api/src/api/contracts.ts
  • packages/app/tests/docker-git/api-create-project.test.ts
  • packages/app/src/docker-git/menu-create-steps.ts
  • packages/api/src/api/schema.ts
  • packages/app/src/docker-git/cli/parser-mcp-android.ts
  • packages/api/src/services/projects.ts
  • packages/app/tests/docker-git/actions-project-create.test.ts
  • packages/app/src/docker-git/api-client-create.ts
  • packages/app/src/docker-git/cli/usage.ts
  • packages/app/src/docker-git/menu-create-draft.ts
  • packages/app/src/docker-git/menu-create-navigation.ts
  • packages/lib/src/core/command-options.ts
  • packages/openapi/src/openapi-paths.ts
  • packages/container/src/core/templates-entrypoint.ts
  • packages/app/src/docker-git/menu-types.ts
  • packages/app/tests/docker-git/app-ready-create-settings.test.ts
  • packages/container/src/core/template-defaults.ts
  • packages/app/src/docker-git/cli/parser.ts
  • packages/app/src/web/api-types.ts
  • packages/lib/src/shell/config.ts
  • packages/app/src/docker-git/frontend-lib/core/template-defaults.ts
  • packages/app/src/docker-git/menu-create-inputs.ts
  • packages/lib/src/shell/errors.ts
  • packages/container/src/core/templates/docker-compose-playwright.ts
  • packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts
  • packages/app/src/docker-git/cli/parser-options.ts
  • packages/container/src/core/templates-entrypoint/base.ts
  • packages/container/src/core/templates/docker-compose-android.ts
  • packages/lib/src/usecases/mcp-android.ts
  • packages/container/src/core/templates-entrypoint/grok-android-mcp.ts
  • packages/container/src/core/templates-entrypoint/gemini-playwright-mcp.ts
  • packages/app/src/docker-git/menu-create-step-apply.ts
  • packages/app/tests/docker-git/menu-create-display-settings.test.ts
  • packages/container/src/core/templates-entrypoint/claude.ts
  • packages/lib/src/usecases/apply-overrides.ts
  • packages/container/src/core/templates/dockerfile.ts
  • packages/lib/src/core/command-builders-template.ts
  • packages/container/src/core/domain.ts
  • packages/app/tests/docker-git/menu-create-shared.test.ts
  • packages/app/src/docker-git/menu-create-command-parse.ts
  • packages/container/src/core/templates-entrypoint/grok.ts
  • packages/lib/src/usecases/actions/create-project-conflicts.ts
  • packages/lib/src/core/domain.ts
  • packages/lib/src/usecases/errors.ts
  • packages/container/src/core/templates-entrypoint/codex.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders-template.ts
  • packages/app/src/docker-git/frontend-lib/core/domain.ts
  • packages/app/tests/docker-git/menu-create-shared-properties.test.ts
  • packages/container/tests/core/templates.test.ts
  • packages/lib/tests/usecases/mcp-android.test.ts
  • packages/lib/src/core/command-builders.ts
  • packages/app/src/docker-git/program-unsupported.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders.ts
  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/app/tests/docker-git/app-ready-create-fixture.ts
  • packages/container/src/core/templates-entrypoint/gemini.ts
  • packages/app/src/web/api-project-create-body.ts
  • packages/container/src/core/templates/docker-compose.ts
**

⚙️ CodeRabbit configuration file

**: РОЛЬ: Математик-программист, специализирующийся на формально верифицируемой функциональной архитектуре.

ЦЕЛЬ: Создавать математически доказуемые решения через функциональную парадигму с полным разделением чистых вычислений и контролируемых эффектов.

МОДЕЛЬ РАССУЖДЕНИЯ:

  • Не выдавать “личные мнения”. Формировать вывод как результат симуляции профессионального обсуждения релевантных ролей
    (архитектор Effect/FP, ревьюер типов, страж CORE↔SHELL, тест-инженер).
  • Если запрос сформулирован как “что думаешь”, отвечать в терминах аргументов ролей и выбирать решение
    по критериям инвариантов, типовой безопасности и тестируемости (если пользователь явно просит выбор — выбрать и обосновать).

ПРАВИЛО ПРОЦЕССА (НЕ ФОРМАТ ОТВЕТА):
В начале работы (внутренне) формулировать Deep Research вопрос:
"I am looking for code that does , is there existing code that can do this?"
Далее:

  • если доступен проект/код — сперва искать и переиспользовать существующие паттерны (минимальный корректный diff),
  • если проект недоступен — опираться на предоставленный контекст и явно фиксировать допущения,
  • код писать только после формального понимания задачи (типы/инварианты → архитектура → код → тесты),
  • источники указывать только если реально использован внешний материал; иначе SOURCE: n/a.

ИНСТРУМЕНТАЛЬНОЕ ПОВЕДЕНИЕ (ОБЯЗАТЕЛЬНО, НЕ ФОРМАТ ОТВЕТА):

  • Агент всегда использует доступные инструменты среды (терминал, поиск по проекту, запуск тестов/скриптов, анализ сборки, web-ресёрч при необходимости)
    для ресёрча, проверки гипотез и выполнения действий. Приоритет: проверяемость, воспроизводимость, минимальный риск.
  • Агент не предлагает “гайд” как замену действия. Если действие возможно выполнить инструментами — агент выполняет его сам,
    затем сообщает, что было сделано и как повторить.
  • Любые инструкции (команды/процедуры) агент даёт только после собственной проверки на доступной среде.
    Если проверить невозможно — явно фиксирует ограничение и перечисляе...

Files:

  • packages/app/src/docker-git/cli/parser-apply.ts
  • packages/app/package.json
  • packages/app/tests/docker-git/app-ready-create.test.ts
  • packages/app/src/docker-git/frontend-lib/core/command-options.ts
  • packages/api/src/api/contracts.ts
  • packages/app/tests/docker-git/api-create-project.test.ts
  • packages/docker-git-session-sync/package.json
  • packages/docker-git-session-sync/CHANGELOG.md
  • packages/app/src/docker-git/menu-create-steps.ts
  • packages/api/src/api/schema.ts
  • README.md
  • packages/app/src/docker-git/cli/parser-mcp-android.ts
  • packages/api/src/services/projects.ts
  • packages/app/tests/docker-git/actions-project-create.test.ts
  • packages/app/src/docker-git/api-client-create.ts
  • packages/app/CHANGELOG.md
  • packages/app/src/docker-git/cli/usage.ts
  • packages/app/src/docker-git/menu-create-draft.ts
  • packages/app/src/docker-git/menu-create-navigation.ts
  • packages/lib/src/core/command-options.ts
  • packages/openapi/src/openapi-paths.ts
  • packages/container/src/core/templates-entrypoint.ts
  • packages/app/src/docker-git/menu-types.ts
  • packages/app/tests/docker-git/app-ready-create-settings.test.ts
  • packages/container/src/core/template-defaults.ts
  • packages/app/src/docker-git/cli/parser.ts
  • packages/app/src/web/api-types.ts
  • packages/lib/src/shell/config.ts
  • packages/app/src/docker-git/frontend-lib/core/template-defaults.ts
  • packages/app/src/docker-git/menu-create-inputs.ts
  • packages/lib/src/shell/errors.ts
  • packages/container/src/core/templates/docker-compose-playwright.ts
  • packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts
  • packages/app/src/docker-git/cli/parser-options.ts
  • packages/container/src/core/templates-entrypoint/base.ts
  • packages/container/src/core/templates/docker-compose-android.ts
  • packages/lib/src/usecases/mcp-android.ts
  • packages/container/src/core/templates-entrypoint/grok-android-mcp.ts
  • packages/container/src/core/templates-entrypoint/gemini-playwright-mcp.ts
  • packages/app/src/docker-git/menu-create-step-apply.ts
  • packages/app/tests/docker-git/menu-create-display-settings.test.ts
  • packages/container/src/core/templates-entrypoint/claude.ts
  • packages/lib/src/usecases/apply-overrides.ts
  • packages/container/src/core/templates/dockerfile.ts
  • packages/lib/src/core/command-builders-template.ts
  • packages/container/src/core/domain.ts
  • packages/app/tests/docker-git/menu-create-shared.test.ts
  • packages/app/src/docker-git/menu-create-command-parse.ts
  • packages/container/src/core/templates-entrypoint/grok.ts
  • packages/lib/src/usecases/actions/create-project-conflicts.ts
  • packages/lib/src/core/domain.ts
  • packages/lib/src/usecases/errors.ts
  • packages/container/src/core/templates-entrypoint/codex.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders-template.ts
  • packages/openapi/openapi.json
  • packages/app/src/docker-git/frontend-lib/core/domain.ts
  • packages/app/tests/docker-git/menu-create-shared-properties.test.ts
  • packages/container/tests/core/templates.test.ts
  • packages/lib/tests/usecases/mcp-android.test.ts
  • packages/lib/src/core/command-builders.ts
  • packages/app/src/docker-git/program-unsupported.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders.ts
  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/app/tests/docker-git/app-ready-create-fixture.ts
  • packages/container/src/core/templates-entrypoint/gemini.ts
  • packages/app/src/web/api-project-create-body.ts
  • packages/container/src/core/templates/docker-compose.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.

Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.

Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.

Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.

Files:

  • packages/app/src/docker-git/cli/parser-apply.ts
  • packages/app/package.json
  • packages/app/tests/docker-git/app-ready-create.test.ts
  • packages/app/src/docker-git/frontend-lib/core/command-options.ts
  • packages/api/src/api/contracts.ts
  • packages/app/tests/docker-git/api-create-project.test.ts
  • packages/docker-git-session-sync/package.json
  • packages/docker-git-session-sync/CHANGELOG.md
  • packages/app/src/docker-git/menu-create-steps.ts
  • packages/api/src/api/schema.ts
  • README.md
  • packages/app/src/docker-git/cli/parser-mcp-android.ts
  • packages/api/src/services/projects.ts
  • packages/app/tests/docker-git/actions-project-create.test.ts
  • packages/app/src/docker-git/api-client-create.ts
  • packages/app/CHANGELOG.md
  • packages/app/src/docker-git/cli/usage.ts
  • packages/app/src/docker-git/menu-create-draft.ts
  • packages/app/src/docker-git/menu-create-navigation.ts
  • packages/lib/src/core/command-options.ts
  • packages/openapi/src/openapi-paths.ts
  • packages/container/src/core/templates-entrypoint.ts
  • packages/app/src/docker-git/menu-types.ts
  • packages/app/tests/docker-git/app-ready-create-settings.test.ts
  • packages/container/src/core/template-defaults.ts
  • packages/app/src/docker-git/cli/parser.ts
  • packages/app/src/web/api-types.ts
  • packages/lib/src/shell/config.ts
  • packages/app/src/docker-git/frontend-lib/core/template-defaults.ts
  • packages/app/src/docker-git/menu-create-inputs.ts
  • packages/lib/src/shell/errors.ts
  • packages/container/src/core/templates/docker-compose-playwright.ts
  • packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts
  • packages/app/src/docker-git/cli/parser-options.ts
  • packages/container/src/core/templates-entrypoint/base.ts
  • packages/container/src/core/templates/docker-compose-android.ts
  • packages/lib/src/usecases/mcp-android.ts
  • packages/container/src/core/templates-entrypoint/grok-android-mcp.ts
  • packages/container/src/core/templates-entrypoint/gemini-playwright-mcp.ts
  • packages/app/src/docker-git/menu-create-step-apply.ts
  • packages/app/tests/docker-git/menu-create-display-settings.test.ts
  • packages/container/src/core/templates-entrypoint/claude.ts
  • packages/lib/src/usecases/apply-overrides.ts
  • packages/container/src/core/templates/dockerfile.ts
  • packages/lib/src/core/command-builders-template.ts
  • packages/container/src/core/domain.ts
  • packages/app/tests/docker-git/menu-create-shared.test.ts
  • packages/app/src/docker-git/menu-create-command-parse.ts
  • packages/container/src/core/templates-entrypoint/grok.ts
  • packages/lib/src/usecases/actions/create-project-conflicts.ts
  • packages/lib/src/core/domain.ts
  • packages/lib/src/usecases/errors.ts
  • packages/container/src/core/templates-entrypoint/codex.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders-template.ts
  • packages/openapi/openapi.json
  • packages/app/src/docker-git/frontend-lib/core/domain.ts
  • packages/app/tests/docker-git/menu-create-shared-properties.test.ts
  • packages/container/tests/core/templates.test.ts
  • packages/lib/tests/usecases/mcp-android.test.ts
  • packages/lib/src/core/command-builders.ts
  • packages/app/src/docker-git/program-unsupported.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders.ts
  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/app/tests/docker-git/app-ready-create-fixture.ts
  • packages/container/src/core/templates-entrypoint/gemini.ts
  • packages/app/src/web/api-project-create-body.ts
  • packages/container/src/core/templates/docker-compose.ts
**/{package*.json,requirements*.txt,setup.py,setup.cfg,Pipfile,Pipfile.lock,pyproject.toml,pom.xml,build.gradle,Gemfile,Gemfile.lock,go.mod,go.sum,composer.json,Cargo.toml,Cargo.lock}

📄 CodeRabbit inference engine (Custom checks)

Fail if dependency or package-manager changes materially increase supply-chain risk without justification

Files:

  • packages/app/package.json
  • packages/docker-git-session-sync/package.json
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.test.{ts,tsx}: Write property-based tests using fast-check (fc.property) to verify mathematical invariants; unit tests must use Effect test utilities without async/await
Every bug fix must be accompanied by a reproducing test case; the test must fail before the fix and pass after; document the Proof of Fix with root cause and solution

Files:

  • packages/app/tests/docker-git/app-ready-create.test.ts
  • packages/app/tests/docker-git/api-create-project.test.ts
  • packages/app/tests/docker-git/actions-project-create.test.ts
  • packages/app/tests/docker-git/app-ready-create-settings.test.ts
  • packages/app/tests/docker-git/menu-create-display-settings.test.ts
  • packages/app/tests/docker-git/menu-create-shared.test.ts
  • packages/app/tests/docker-git/menu-create-shared-properties.test.ts
  • packages/container/tests/core/templates.test.ts
  • packages/lib/tests/usecases/mcp-android.test.ts
*.md

📄 CodeRabbit inference engine (AGENTS.md)

Document all PR changes with mathematical proof obligations: invariants, preconditions, postconditions, variant functions, and complexity analysis in Markdown format

Files:

  • README.md
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: Organize project structure with clear separation: APP (CLI + React Frontend), LIB (backend business logic), and API (API server using LIB)
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: APP layer must only communicate with the API layer and cannot have direct access to LIB
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: API layer must only work with LIB and serve as the interface between APP and LIB
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: Use Spec-Driven Development (SDD) process: from issue to verifiable PR, as detailed in docs/process.md
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: Support authentication providers via CLI: GitHub (OAuth or token), GitLab (OAuth or token), Claude, Codex, Gemini, Grok, and generic git hosts via --host and --token
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: Store authentication tokens in env-file as GIT_AUTH_TOKEN__<HOST> and GIT_AUTH_USER__<HOST> variables
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: Implement git credential helper inside containers to automatically select correct token by host for clone/push operations
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: Web interface (browser mode) should listen on 0.0.0.0 by default, but allow DOCKER_GIT_WEB_HOST environment variable to restrict access to 127.0.0.1
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: Support --force flag to recreate environment and delete project volumes
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: Support --mcp-playwright flag to enable Playwright MCP and Chromium sidecar for browser automation
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: Support --mcp-android flag to enable Android MCP and nested sidecar with Android emulator for mobile automation
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: Implement --auto flag for automatic agent execution with intelligent provider selection (Claude, Codex, Gemini, or Grok based on available authorization)
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: Auto mode agent should automatically complete tasks, create PRs, and clean up container after completion
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: Implement apply command to apply configuration to a single project with optional --no-up flag to skip docker compose up
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T16:54:52.235Z
Learning: Implement apply-all command to apply configuration to all projects with optional --active flag to limit to running containers
📚 Learning: 2026-05-22T21:08:18.083Z
Learnt from: skulidropek
Repo: ProverCoderAI/docker-git PR: 344
File: packages/app/src/docker-git/controller-compose.ts:34-40
Timestamp: 2026-05-22T21:08:18.083Z
Learning: In this repo’s docker-git controller compose generation, `${DOCKER_GIT_CONTROLLER_BUILD_SKILLER:-1}` should be treated as standard bash parameter expansion: when `DOCKER_GIT_CONTROLLER_BUILD_SKILLER` is unset, it defaults to the string "1". There is no "-1" mode. The runtime contract enforced by `packages/app/src/docker-git/controller-compose.ts` is: unset / "1" / "true" => output "1"; "0" / "false" => output "0". If review code shows branching/behavior for "-1" or any numeric value other than this 0/1 contract, flag it. Also ensure the Dockerfile ARG `DOCKER_GIT_CONTROLLER_BUILD_SKILLER` stays consistent with default `1`.

Applied to files:

  • packages/app/src/docker-git/cli/parser-apply.ts
  • packages/app/src/docker-git/frontend-lib/core/command-options.ts
  • packages/app/src/docker-git/menu-create-steps.ts
  • packages/app/src/docker-git/cli/parser-mcp-android.ts
  • packages/app/src/docker-git/api-client-create.ts
  • packages/app/src/docker-git/cli/usage.ts
  • packages/app/src/docker-git/menu-create-draft.ts
  • packages/app/src/docker-git/menu-create-navigation.ts
  • packages/app/src/docker-git/menu-types.ts
  • packages/app/src/docker-git/cli/parser.ts
  • packages/app/src/docker-git/frontend-lib/core/template-defaults.ts
  • packages/app/src/docker-git/menu-create-inputs.ts
  • packages/app/src/docker-git/cli/parser-options.ts
  • packages/app/src/docker-git/menu-create-step-apply.ts
  • packages/app/src/docker-git/menu-create-command-parse.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders-template.ts
  • packages/app/src/docker-git/frontend-lib/core/domain.ts
  • packages/app/src/docker-git/program-unsupported.ts
  • packages/app/src/docker-git/frontend-lib/core/command-builders.ts
  • packages/app/src/docker-git/menu-create-labels.ts
📚 Learning: 2026-06-10T10:21:51.286Z
Learnt from: konard
Repo: ProverCoderAI/docker-git PR: 386
File: packages/app/tests/docker-git/gridland-react-singleton.test.ts:0-0
Timestamp: 2026-06-10T10:21:51.286Z
Learning: In `packages/app/tests/docker-git` tests that inspect the `packages/terminal` workspace (e.g., for React-related versions), remember that `react-dom` is intentionally declared as a `devDependency` in `packages/terminal` (the terminal exports components but does not render to the DOM itself). Therefore, test assertions should not require `react-dom` to appear in `dependencies`; when resolving versions, accept either `dependencies` or `devDependencies` (as `resolveDepVersion` does in `gridland-react-singleton.test.ts`).

Applied to files:

  • packages/app/tests/docker-git/app-ready-create.test.ts
  • packages/app/tests/docker-git/api-create-project.test.ts
  • packages/app/tests/docker-git/actions-project-create.test.ts
  • packages/app/tests/docker-git/app-ready-create-settings.test.ts
  • packages/app/tests/docker-git/menu-create-display-settings.test.ts
  • packages/app/tests/docker-git/menu-create-shared.test.ts
  • packages/app/tests/docker-git/menu-create-shared-properties.test.ts
📚 Learning: 2026-05-18T07:43:38.131Z
Learnt from: skulidropek
Repo: ProverCoderAI/docker-git PR: 313
File: packages/api/src/services/panel-cloudflare-tunnel.ts:123-135
Timestamp: 2026-05-18T07:43:38.131Z
Learning: In this repo’s ProverCoderAI/docker-git architecture, it is intentional for service modules under packages/api/src/services/ to call Node.js APIs directly (e.g., fs, child_process, fetch). Do not treat direct Node API usage in these service modules as a dependency-injection (DI) violation. This codebase provides the NodeContext at the program boundary (entry point) rather than injecting Context.Tag/Layer services into individual service modules; reviewers should only flag DI/context issues if the expected boundary setup is missing.

Applied to files:

  • packages/api/src/services/projects.ts
🪛 markdownlint-cli2 (0.22.1)
.changeset/mcp-android-integration.md

[warning] 5-5: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🔇 Additional comments (62)
.changeset/mcp-android-integration.md (1)

1-14: Changeset 格式正確, но markdownlint warning можно игнорировать.

Changeset файл следует стандартному формату Changesets tool — YAML frontmatter (строки 1–3) + описание (строки 5–14). Предупреждение MD041 (first-line-heading) — это ложный позитив: Changesets требует именно YAML frontmatter в начале файла, а не markdown heading.

Содержание changeset полное и точное:

  • Четко указана версия изменения (minor)
  • Описана фича (Android MCP integration per issue #436)
  • Перечислены все пути включения (CLI флаги, mcp-android команда, interactive prompt, API)
  • Упомянуты ключевые компоненты (docker-android sidecar, KVM, ADB port forwarding, headless mode, @mobilenext/mobile-mcp)
  • Указано что интеграция зеркалирует Playwright MCP (feature parity)
README.md (1)

74-74: Описание --mcp-android в README соответствует path instructions и стилю документации.

Строка 74 правильно документирует флаг рядом с --mcp-playwright и включает все ключевые элементы:

  • Что включается (Android MCP)
  • Сервер (@mobilenext/mobile-mcp)
  • Инфраструктура (nested sidecar с docker-android)
  • Использование (мобильная автоматизация)

Описание соответствует path instructions требованиям и согласуется со стилем соседних bullet points.

packages/app/CHANGELOG.md (1)

3-11: LGTM!

packages/app/package.json (1)

3-3: LGTM!

packages/docker-git-session-sync/CHANGELOG.md (1)

3-8: LGTM!

packages/docker-git-session-sync/package.json (1)

3-3: LGTM!

packages/api/src/api/contracts.ts (1)

479-479: LGTM!

packages/api/src/api/schema.ts (1)

46-46: LGTM!

packages/api/src/services/projects.ts (1)

474-474: LGTM!

packages/app/src/web/api-project-create-body.ts (1)

44-57: LGTM!

Also applies to: 95-101

packages/app/src/web/api-types.ts (1)

72-72: LGTM!

packages/openapi/openapi.json (1)

1084-1086: LGTM!

packages/openapi/src/openapi-paths.ts (1)

1191-1191: LGTM!

packages/app/src/docker-git/frontend-lib/core/domain.ts (1)

117-117: LGTM!

Also applies to: 208-213, 229-229, 273-273

packages/app/src/docker-git/frontend-lib/core/template-defaults.ts (1)

33-33: LGTM!

Also applies to: 79-79

packages/lib/src/core/domain.ts (1)

147-152: LGTM!

Also applies to: 168-168, 211-211

packages/container/src/core/domain.ts (1)

77-77: LGTM!

packages/container/src/core/template-defaults.ts (1)

32-32: LGTM!

Also applies to: 78-78

packages/lib/src/shell/config.ts (1)

88-90: LGTM!

packages/app/src/docker-git/cli/parser-mcp-android.ts (1)

1-25: LGTM!

packages/lib/src/shell/errors.ts (1)

42-43: LGTM!

packages/lib/src/usecases/actions/create-project-conflicts.ts (1)

19-19: LGTM!

Also applies to: 55-78

packages/app/src/docker-git/cli/parser-options.ts (1)

113-114: LGTM!

packages/app/src/docker-git/menu-types.ts (1)

58-58: LGTM!

Also applies to: 72-72, 82-82

packages/app/src/docker-git/api-client-create.ts (1)

44-44: LGTM!

packages/app/tests/docker-git/actions-project-create.test.ts (1)

29-29: LGTM!

packages/app/tests/docker-git/api-create-project.test.ts (1)

11-11: LGTM!

Also applies to: 65-65

packages/app/tests/docker-git/app-ready-create-fixture.ts (1)

43-43: LGTM!

packages/app/tests/docker-git/app-ready-create-settings.test.ts (1)

127-127: LGTM!

Also applies to: 138-138

packages/app/tests/docker-git/app-ready-create.test.ts (1)

58-59: LGTM!

packages/app/src/docker-git/cli/parser.ts (1)

10-10: LGTM!

Also applies to: 97-97

packages/lib/src/core/command-builders.ts (1)

203-203: LGTM!

Also applies to: 212-213, 281-281

packages/app/src/docker-git/menu-create-draft.ts (1)

15-15: LGTM!

Also applies to: 27-27

packages/app/src/docker-git/menu-create-inputs.ts (1)

250-250: LGTM!

packages/app/src/docker-git/menu-create-labels.ts (1)

26-32: LGTM!

Also applies to: 67-72

packages/app/src/docker-git/menu-create-navigation.ts (1)

227-227: LGTM!

packages/app/src/docker-git/menu-create-step-apply.ts (1)

44-50: LGTM!

Also applies to: 68-68

packages/app/src/docker-git/menu-create-steps.ts (1)

22-22: LGTM!

packages/app/src/docker-git/cli/usage.ts (1)

10-10: LGTM!

Also applies to: 31-31, 83-83

packages/app/tests/docker-git/menu-create-display-settings.test.ts (1)

37-49: LGTM!

Also applies to: 74-74, 96-96, 129-129

packages/app/tests/docker-git/menu-create-shared-properties.test.ts (1)

17-17: LGTM!

Also applies to: 26-32, 65-65

packages/app/tests/docker-git/menu-create-shared.test.ts (1)

61-61: LGTM!

Also applies to: 91-92, 115-115, 125-125, 310-310

packages/lib/src/usecases/apply-overrides.ts (1)

15-16: LGTM!

packages/lib/src/usecases/errors.ts (1)

129-130: LGTM!

packages/lib/tests/usecases/mcp-android.test.ts (1)

97-135: LGTM!

packages/app/src/docker-git/cli/parser-apply.ts (1)

43-44: LGTM!

packages/app/src/docker-git/program-unsupported.ts (1)

7-7: LGTM!

Also applies to: 26-29

packages/app/src/docker-git/menu-create-command-parse.ts (1)

116-116: LGTM!

Also applies to: 168-170, 190-190

packages/app/src/docker-git/frontend-lib/core/command-options.ts (1)

37-37: LGTM!

packages/app/src/docker-git/frontend-lib/core/command-builders-template.ts (1)

23-23: LGTM!

Also applies to: 100-100

packages/app/src/docker-git/frontend-lib/core/command-builders.ts (1)

204-204: LGTM!

Also applies to: 213-214, 282-282

packages/lib/src/core/command-options.ts (1)

36-36: LGTM!

packages/lib/src/core/command-builders-template.ts (1)

22-22: LGTM!

Also applies to: 99-99

packages/container/src/core/templates/docker-compose-android.ts (1)

20-65: LGTM!

packages/container/src/core/templates/docker-compose-playwright.ts (1)

29-61: LGTM!

packages/container/src/core/templates/docker-compose.ts (1)

10-11: LGTM!

Also applies to: 28-30, 179-196, 230-230, 247-247, 261-299

packages/container/src/core/templates/dockerfile.ts (1)

94-109: LGTM!

Also applies to: 261-261

packages/container/src/core/templates-entrypoint/grok.ts (1)

2-2: LGTM!

Also applies to: 348-348

packages/container/src/core/templates-entrypoint.ts (1)

20-20: LGTM!

Also applies to: 64-64

packages/container/src/core/templates-entrypoint/base.ts (1)

44-44: LGTM!

packages/container/src/core/templates-entrypoint/gemini-playwright-mcp.ts (1)

1-43: LGTM!

packages/container/src/core/templates-entrypoint/gemini.ts (1)

2-3: LGTM!

Also applies to: 303-303

Comment thread packages/container/src/core/templates-entrypoint/claude.ts Outdated
Comment thread packages/container/src/core/templates-entrypoint/codex.ts Outdated
Comment thread packages/container/src/core/templates-entrypoint/codex.ts Outdated
Comment on lines +1133 to +1201
it("renders the Android emulator sidecar service when Android MCP is enabled", () => {
const compose = renderDockerCompose(
makeTemplateConfig({
enableMcpAndroid: true,
gpu: "none",
}),
{
cpuLimit: 1.5,
ramLimit: "2g",
swapLimit: "4g"
}
)

expect(compose).toContain('MCP_ANDROID_ENABLE: "1"')
expect(compose).toContain('DOCKER_GIT_ANDROID_CONTAINER_NAME: "dg-test-android"')
expect(compose).toContain(
'DOCKER_GIT_ANDROID_ADB_ENDPOINT: "${DOCKER_GIT_ANDROID_ADB_ENDPOINT:-dg-test-android:5555}"'
)
expect(compose).toContain(
'DOCKER_GIT_ANDROID_EMULATOR_IMAGE: "${DOCKER_GIT_ANDROID_EMULATOR_IMAGE:-budtmo/docker-android:emulator_14.0}"'
)
// emulator runs as a real compose service (unlike the externally-managed browser container)
expect(compose).toContain("\n dg-test-android:\n")
expect(compose).toContain(" - /dev/kvm")
expect(compose).toContain(
'- "${DOCKER_GIT_ANDROID_ADB_BIND_HOST:-127.0.0.1}:${DOCKER_GIT_ANDROID_ADB_PORT:-5555}:5555"'
)
expect(compose).toContain(" dg-test-home-android:")
// the sidecar reuses the Playwright sidecar resource budget
expect(compose).toContain(" cpus: 1.5\n")
})

it("omits all Android emulator wiring when Android MCP is disabled", () => {
const compose = renderDockerCompose(makeTemplateConfig({ enableMcpAndroid: false }))

expect(compose).not.toContain("MCP_ANDROID_ENABLE")
expect(compose).not.toContain("\n dg-test-android:\n")
expect(compose).not.toContain("dg-test-home-android:")
expect(compose).not.toContain("/dev/kvm")
})

it("installs the ADB client in the Dockerfile only when Android MCP is enabled", () => {
const enabled = renderDockerfile(makeTemplateConfig({ enableMcpAndroid: true }))
const disabled = renderDockerfile(makeTemplateConfig({ enableMcpAndroid: false }))

expect(enabled).toContain("android-tools-adb")
expect(enabled).toContain("adb --version")
expect(disabled).not.toContain("android-tools-adb")
})

it("configures the Android MCP server for every agent and defaults the enable flag", () => {
const entrypoint = renderEntrypoint(makeTemplateConfig({ enableMcpAndroid: true }))

expect(entrypoint).toContain('MCP_ANDROID_ENABLE="${MCP_ANDROID_ENABLE:-1}"')
// Codex (TOML)
expect(entrypoint).toContain("[mcp_servers.android]")
expect(entrypoint).toContain("@mobilenext/mobile-mcp@latest")
// Claude / Gemini / Grok (JSON sync helpers)
expect(entrypoint).toContain("docker_git_sync_claude_android_mcp")
expect(entrypoint).toContain("docker_git_sync_gemini_android_mcp")
expect(entrypoint).toContain("docker_git_sync_grok_android_mcp")
})

it("defaults MCP_ANDROID_ENABLE to 0 when Android MCP is disabled", () => {
const entrypoint = renderEntrypoint(makeTemplateConfig({ enableMcpAndroid: false }))

expect(entrypoint).toContain('MCP_ANDROID_ENABLE="${MCP_ANDROID_ENABLE:-0}"')
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify current test style in the changed block
sed -n '1133,1201p' packages/container/tests/core/templates.test.ts
rg -n 'fc\.property|it\.effect|Effect\.' packages/container/tests/core/templates.test.ts

Repository: ProverCoderAI/docker-git

Length of output: 4458


🏁 Script executed:

# Проверим контекст: есть ли другие тесты для этих функций и как они оформлены
rg -B 3 -A 10 'renderDockerCompose|renderDockerfile|renderEntrypoint' packages/container/tests/core/templates.test.ts | head -150

Repository: ProverCoderAI/docker-git

Length of output: 7122


🏁 Script executed:

# Проверим, есть ли в файле пример property-based теста для похожей функциональности
rg -B 5 -A 15 'fc.property.*generatedTemplateConfigArbitrary.*renderDocker' packages/container/tests/core/templates.test.ts | head -80

Repository: ProverCoderAI/docker-git

Length of output: 162


🏁 Script executed:

# Посмотрим весь контекст вокруг новых тестов - что было до строки 1133
sed -n '1100,1140p' packages/container/tests/core/templates.test.ts

Repository: ProverCoderAI/docker-git

Length of output: 1688


🏁 Script executed:

# Посмотрим весь структуру describe блоков и какие тесты используют fc.property для renderDockerCompose
rg -n 'describe.*render|it\(' packages/container/tests/core/templates.test.ts | grep -A 5 -B 5 'renderDockerCompose'

Repository: ProverCoderAI/docker-git

Length of output: 1107


🏁 Script executed:

# Посмотрим весь describe блок renderDockerCompose от строки 930 до конца блока (примерно до 1200+)
sed -n '930,1210p' packages/container/tests/core/templates.test.ts | head -200

Repository: ProverCoderAI/docker-git

Length of output: 9771


🏁 Script executed:

# Поищем есть ли property-based тесты (fc.property) для renderDockerCompose, renderDockerfile, renderEntrypoint
rg -n 'fc\.property' packages/container/tests/core/templates.test.ts | head -20

Repository: ProverCoderAI/docker-git

Length of output: 465


🏁 Script executed:

# Посмотрим контекст fc.property тестов в describe("renderDockerfile")
sed -n '450,510p' packages/container/tests/core/templates.test.ts

Repository: ProverCoderAI/docker-git

Length of output: 3218


🏁 Script executed:

# Проверим используется ли it.effect в describe("renderDockerCompose")
sed -n '930,1250p' packages/container/tests/core/templates.test.ts | grep -n 'it\.\|describe'

Repository: ProverCoderAI/docker-git

Length of output: 204


🏁 Script executed:

# Проверим полный список describe блоков и какие используют fc.property
rg -n 'describe\(' packages/container/tests/core/templates.test.ts | head -20

Repository: ProverCoderAI/docker-git

Length of output: 613


🏁 Script executed:

# Посмотрим конец describe("renderDockerCompose") - это последний блок в файле?
tail -100 packages/container/tests/core/templates.test.ts

Repository: ProverCoderAI/docker-git

Length of output: 4271


🏁 Script executed:

# Посмотрим генератор generatedTemplateConfigArbitrary - что он генерирует
rg -B 5 -A 20 'generatedTemplateConfigArbitrary' packages/container/tests/core/templates.test.ts | head -80

Repository: ProverCoderAI/docker-git

Length of output: 3326


Переписать новые тесты на основе property-based паттерна fc.property().

В этом файле уже используется fc.property(generatedTemplateConfigArbitrary, ...) для тестирования renderDockerfile (строка 120) и renderEntrypoint (строка 490). Новые тесты для Android MCP нарушают этот установленный паттерн, используя простые it() + expect() вместо property-based проверок.

Функции renderDockerCompose, renderDockerfile, renderEntrypoint — чистые, детерминированные функции, идеальные для property-based тестирования. Инварианты легко формализуются:

  • ∀config: enableMcpAndroid(config)=true → contains(compose, MCP_ANDROID_ENABLE)
  • ∀config: enableMcpAndroid(config)=false → ¬contains(compose, MCP_ANDROID_ENABLE)

Переписать 5 новых тестов (строки 1133–1201) через fc.property(generatedTemplateConfigArbitrary.chain(...), ...), добавив enableMcpAndroid в генератор либо использовав .map() для создания вариаций с enableMcpAndroid: true и enableMcpAndroid: false.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/container/tests/core/templates.test.ts` around lines 1133 - 1201,
The five new Android MCP tests (starting with "renders the Android emulator
sidecar service when Android MCP is enabled" through "defaults
MCP_ANDROID_ENABLE to 0 when Android MCP is disabled") use simple example-based
testing with hardcoded `it()` blocks and `expect()` statements, which violates
the established property-based testing pattern used elsewhere in this file.
Refactor these tests to use
`fc.property(generatedTemplateConfigArbitrary.chain(...), ...)` or `.map()` to
generate test cases with `enableMcpAndroid` set to both true and false,
following the same pattern already established for testing `renderDockerfile`
and `renderEntrypoint`. Convert the hardcoded assertions into parameterized
property-based checks where the invariants (like presence/absence of MCP
environment variables and service configurations based on the `enableMcpAndroid`
flag) are verified across generated configurations.

Source: Coding guidelines

)
expect(compose).toContain(" dg-test-home-android:")
// the sidecar reuses the Playwright sidecar resource budget
expect(compose).toContain(" cpus: 1.5\n")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Проверка CPU лимита на Line 1162 может проходить, даже если лимит не попал в Android sidecar.

toContain(" cpus: 1.5\n") матчится по всему compose и не доказывает, что лимит находится именно внутри dg-test-android.

🎯 Предлагаемое уточнение проверки
-    expect(compose).toContain("    cpus: 1.5\n")
+    expect(compose).toMatch(/dg-test-android:[\s\S]*\n\s+cpus: 1\.5\n/)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/container/tests/core/templates.test.ts` at line 1162, The current
test assertion using toContain("    cpus: 1.5\n") checks if the CPU limit
appears anywhere in the compose output but does not verify that the limit is
specifically applied to the dg-test-android Android sidecar service. Refactor
the expect statement to first locate the dg-test-android service configuration
block within the compose output and then verify that the cpus: 1.5 limit exists
only within that specific service section, ensuring the assertion proves the
limit is correctly placed in the Android sidecar rather than elsewhere in the
configuration.

Comment thread packages/lib/src/usecases/apply-overrides.ts
Comment thread packages/lib/src/usecases/mcp-android.ts Outdated
@konard

konard commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

✅ Ready to merge

This pull request is now ready to be merged:

  • All CI checks have passed
  • No merge conflicts
  • No pending changes

Monitored by hive-mind with --auto-restart-until-mergeable flag

@skulidropek

Copy link
Copy Markdown
Member

Сперва нужно отдельно реализовать сам модуль и доказать что он работает

@konard konard marked this pull request as draft June 23, 2026 19:25
@konard

konard commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

🤖 AI Work Session Started

Starting automated work session at 2026-06-23T19:25:21.617Z

The PR has been converted to draft mode while work is in progress.

This comment marks the beginning of an AI work session. Please wait for the session to finish, and provide your feedback.

@konard konard changed the title Подключить mcp-android так же как работает MCP PLAYRIGHT feat(container): add first-party Android MCP module Jun 23, 2026
@konard konard marked this pull request as ready for review June 23, 2026 20:02
@konard

konard commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

Working session summary

Implemented and pushed commit b221cd1d to issue-436-7a79950cbb5b.

PR updated and marked ready: #437

What changed:

  • Added first-party Rust crates/android-connection MCP module.
  • Replaced npx @mobilenext/mobile-mcp@latest with direct android-connection argv-based configs.
  • Docker build now installs the audited local crate via cargo install --path ... --locked.
  • Added source provisioning, tests, docs/changelog updates, and CI job for Rust fmt/test/clippy.
  • Tightened invariants: ADB endpoint validation, no shell command construction, workspace path confinement.

Verification:

  • Local bun run check and bun run test passed.
  • Rust cargo fmt, cargo test --locked, and cargo clippy -D warnings passed.
  • GitHub Actions for latest SHA b221cd1d are green, including E2E and the new Rust Android job.
  • CodeRabbit is still queued as an external review check.

This summary was automatically extracted from the AI working session output.

@konard

konard commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Solution Draft Log

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost estimation:

  • Model: GPT-5.5
  • Provider: OpenAI
  • Public pricing estimate: $23.139343

📊 Context and tokens usage:

  • 890.9K / 200K (445%) input tokens, 64.5K / 128K (50%) output tokens

Total: (890.9K + 11.3M cached) input tokens, 64.5K output tokens, $23.139343 cost

🤖 Models used:

  • Tool: OpenAI Codex
  • Requested: gpt-5.5
  • Thinking level: max (~31999 tokens)
  • Model: GPT-5.5 (gpt-5.5)

📎 Log file uploaded as Repository (96268KB)


Now working session is ended, feel free to review and add any feedback on the solution draft.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.changeset/mcp-android-integration.md (1)

5-14: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Добавьте математические инварианты и гарантии в changeset документацию.

В соответствии с path instruction для *.md, изменения должны быть документированы с формальными доказательствами: инвариантами, предусловиями, постусловиями и анализом сложности. Текущее описание не включает этой информации.

Рекомендуемая структура:

  • Инварианты: какие свойства гарантируются после включения (например: ∀ project: enabled(project) → docker-android_service_gated(project))
  • Предусловия: когда можно включить (например, наличие Docker daemon)
  • Постусловия: что будет после (например, образы загружены, ADB порт открыт)
  • Сложность: время и память для операции
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.changeset/mcp-android-integration.md around lines 5 - 14, The changeset
documentation for mcp-android-integration.md lacks formal mathematical
specifications required by the path instruction for markdown files. Add sections
documenting the formal properties of the Android MCP integration feature:
include invariants describing guaranteed properties after enabling (such as the
relationship between enabled projects and gated docker-android services),
preconditions for when the feature can be enabled (such as Docker daemon
availability), postconditions describing the resulting state (such as loaded
images and open ADB ports), and complexity analysis documenting the time and
memory costs of the operation.

Source: Path instructions

crates/android-connection/README.md (1)

1-11: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Добавьте в README формальные proof-обязательства для этого изменения.

Сейчас описание ограничено назначением бинарей; отсутствуют инварианты, предусловия, постусловия, вариантная функция и оценка сложности, а также краткий Proof of fix для bug-fix части.

Предлагаемый минимальный шаблон
## Mathematical guarantees

### Invariants
- ...

### Preconditions
- ...

### Postconditions
- ...

### Variant function (if applicable)
- ...

### Complexity
- Time: ...
- Space: ...

## Proof of fix
- Причина: ...
- Решение: ...
- Доказательство: ...

As per coding guidelines, "*.md: Document all PR changes with mathematical proof obligations: invariants, preconditions, postconditions, variant functions, and complexity analysis in Markdown format".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/android-connection/README.md` around lines 1 - 11, The README.md file
is missing formal proof-obligation documentation required by the coding
guidelines. Add a new "Mathematical guarantees" section after the current
content that documents the invariants, preconditions, postconditions, variant
functions (if applicable), and complexity analysis (both time and space) for the
android-connection and docker-git-android-connection binaries. Additionally,
include a "Proof of fix" section that explains the reason for changes, the
solution provided, and proof of correctness. This formal documentation ensures
that the mathematical properties and behavioral guarantees of these MCP modules
are explicitly captured and verifiable.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.changeset/mcp-android-integration.md:
- Around line 7-8: The changeset text mentions "first-party Rust
`android-connection` MCP server" but does not clarify that this is a newly
introduced component. Update the changeset text to explicitly indicate that
`android-connection` is a new Rust crate being added in this PR. You can add a
parenthetical clarification such as "new Rust crate `android-connection`" or
include the location context (e.g., `crates/android-connection`) to make it
clear this is not an existing component and is being introduced for the first
time.

In `@crates/android-connection/src/lib.rs`:
- Around line 95-105: The is_safe_adb_endpoint function currently allows invalid
endpoint formats like ":", "host:", and "host:abc". Refactor the validation to
enforce strict host:port format by splitting the input string on the colon
character, ensuring exactly two parts exist, verifying both the host and port
parts are non-empty, validating that the port part contains only digits, and
checking that the numeric port value falls within the valid port range of 1 to
65535.

In `@crates/android-connection/src/mcp.rs`:
- Around line 533-547: The workspace_path function currently only validates
against absolute paths and parent directory traversal (..) but does not prevent
symlink-based path traversal attacks. To fix this, after validating the initial
path conditions, iterate through each component of the candidate path and use
symlink_metadata to check if any intermediate component is a symlink, rejecting
the path if symlinks are detected. This ensures that even if the path appears
valid, it cannot escape the workspace through symbolic links. Additionally, add
a regression test that attempts to use a path containing a symlink component
(which should fail before the fix and pass after implementation).
- Around line 68-91: The read_next_message function incorrectly assumes
Content-Length is always the first header and treats any other first non-empty
header as the JSON payload, making the parser fragile to header order
variations. Refactor the function to read all headers in a loop until an empty
line is encountered, extract the Content-Length value from any header line that
contains it (regardless of order), then only after collecting all headers and
obtaining the length value, read the payload. This requires separating the
header parsing logic from the payload reading logic so headers can be processed
in any order.

In `@packages/app/src/docker-git/menu-create-labels.ts`:
- Around line 26-29: For consistency with the technical terminology used in
usage.ts (which references "android-connection"), update the prompt label in the
Match.when case for "mcpAndroid" to include the server identifier alongside the
user-friendly description. Specifically, modify the string template to include
"(android-connection)" in addition to "(nested Android emulator)" to align the
wizard terminology with the technical details referenced in usage.ts at line 31,
ensuring consistent naming across the codebase.

In `@packages/container/src/core/templates-entrypoint/codex.ts`:
- Around line 209-215: The Android MCP server configuration block in the
codex.ts file is vulnerable to command injection because environment variables
are inserted directly into the TOML configuration without proper escaping. The
values for DOCKER_GIT_ANDROID_ADB_ENDPOINT, TARGET_DIR, and other arguments in
the args array need to be properly escaped or serialized according to TOML
specifications before being written to CODEX_CONFIG_FILE. Implement proper
escaping for all environment variables being inserted into the args array and
other configuration fields in the [mcp_servers.android] section to prevent
special characters like quotes and newlines from breaking the TOML syntax or
injecting arbitrary configurations.

In `@packages/lib/src/shell/android-connection-source.ts`:
- Around line 21-75: The shouldSkipAndroidConnectionEntry function uses a
blocklist approach that only excludes "target" and ".git", which is too
permissive and risks exposing sensitive files like credentials or local
artifacts. Replace the blocklist logic with an allowlist approach that only
permits necessary files (such as Cargo.toml, Cargo.lock, src directory, and
README.md) to be copied into the build context. Modify the
shouldSkipAndroidConnectionEntry function to return true (skip) for anything not
explicitly allowed, and also reject hidden files (starting with dot) and
symlinks to prevent accidental inclusion of sensitive local artifacts.
- Line 125: The function in android-connection-source.ts is calling
process.cwd() directly in the resolveWorkspaceRoot invocation, which violates
the guideline that process operations must be abstracted through Layer-based
services. Refactor the function to accept a cwd parameter of type string in its
signature, then pass that cwd parameter to resolveWorkspaceRoot(cwd) instead of
calling process.cwd() directly. This approach aligns with the pattern already
established in related files and improves testability.

In `@packages/lib/src/shell/files.ts`:
- Line 285: The provisionDockerGitBuildContext call should be executed earlier
in the process before any template or spec files are written, to implement
fail-fast behavior. Move the yield* _(provisionDockerGitBuildContext(fs, path,
baseDir, normalizedConfig)) statement to the beginning of the generator
function, before any other yield statements that write files or specs, ensuring
that if the Docker Git build context provisioning fails (e.g., due to
unavailable Android source), the failure occurs before the project reaches an
inconsistent state from partial file generation.

In `@packages/lib/src/usecases/mcp-android.ts`:
- Around line 88-89: Add a regression test for the mcpAndroidUp function in
mcp-android.test.ts that validates the projectDir fix by setting up a test
scenario where command.projectDir differs from process.cwd(). The test should
mock the CommandExecutor to verify that both ensureDockerDaemonAccess (which
calls docker info) and runDockerComposeUpWithPortCheck (which calls docker
compose up) are invoked with the correct working directory from
command.projectDir rather than the current process working directory. This
ensures the fix on line 88 using command.projectDir is properly tested and
prevents regression in future refactorings.

In `@README.md`:
- Line 74: The documentation line describing the --mcp-android flag contains
excessive implementation details (mentioning first-party designation, specific
component names like android-connection and docker-android) compared to the
--mcp-playwright line above it, breaking parallel structure. Simplify the
--mcp-android description by removing the implementation-specific terminology
and details to match the conciseness of the --mcp-playwright description,
keeping only the essential information about what capabilities are enabled for
mobile automation.

---

Outside diff comments:
In @.changeset/mcp-android-integration.md:
- Around line 5-14: The changeset documentation for mcp-android-integration.md
lacks formal mathematical specifications required by the path instruction for
markdown files. Add sections documenting the formal properties of the Android
MCP integration feature: include invariants describing guaranteed properties
after enabling (such as the relationship between enabled projects and gated
docker-android services), preconditions for when the feature can be enabled
(such as Docker daemon availability), postconditions describing the resulting
state (such as loaded images and open ADB ports), and complexity analysis
documenting the time and memory costs of the operation.

In `@crates/android-connection/README.md`:
- Around line 1-11: The README.md file is missing formal proof-obligation
documentation required by the coding guidelines. Add a new "Mathematical
guarantees" section after the current content that documents the invariants,
preconditions, postconditions, variant functions (if applicable), and complexity
analysis (both time and space) for the android-connection and
docker-git-android-connection binaries. Additionally, include a "Proof of fix"
section that explains the reason for changes, the solution provided, and proof
of correctness. This formal documentation ensures that the mathematical
properties and behavioral guarantees of these MCP modules are explicitly
captured and verifiable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a2f78c73-beb4-4e03-977a-c83d72b3c9c3

📥 Commits

Reviewing files that changed from the base of the PR and between a80a75c and b221cd1.

⛔ Files ignored due to path filters (1)
  • crates/android-connection/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (24)
  • .changeset/mcp-android-integration.md
  • .github/workflows/check.yml
  • README.md
  • crates/android-connection/.gitignore
  • crates/android-connection/Cargo.toml
  • crates/android-connection/README.md
  • crates/android-connection/src/bin/android-connection.rs
  • crates/android-connection/src/lib.rs
  • crates/android-connection/src/main.rs
  • crates/android-connection/src/mcp.rs
  • packages/app/src/docker-git/cli/usage.ts
  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/container/src/core/templates-entrypoint/claude.ts
  • packages/container/src/core/templates-entrypoint/codex.ts
  • packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts
  • packages/container/src/core/templates-entrypoint/grok-android-mcp.ts
  • packages/container/src/core/templates/docker-compose-android.ts
  • packages/container/src/core/templates/dockerfile.ts
  • packages/container/tests/core/templates.test.ts
  • packages/lib/src/shell/android-connection-source.ts
  • packages/lib/src/shell/files.ts
  • packages/lib/src/usecases/mcp-android.ts
  • packages/lib/tests/usecases/apply.test.ts
  • packages/lib/tests/usecases/mcp-android.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (9)
  • GitHub Check: Final build (windows-latest)
  • GitHub Check: Test
  • GitHub Check: E2E (Clone auto-open SSH)
  • GitHub Check: E2E (OpenCode)
  • GitHub Check: E2E (Login context)
  • GitHub Check: E2E (Runtime volumes + SSH)
  • GitHub Check: E2E (Clone cache)
  • GitHub Check: E2E (Browser command)
  • GitHub Check: Lint
🧰 Additional context used
📓 Path-based instructions (10)
**

⚙️ CodeRabbit configuration file

**: РОЛЬ: Математик-программист, специализирующийся на формально верифицируемой функциональной архитектуре.

ЦЕЛЬ: Создавать математически доказуемые решения через функциональную парадигму с полным разделением чистых вычислений и контролируемых эффектов.

МОДЕЛЬ РАССУЖДЕНИЯ:

  • Не выдавать “личные мнения”. Формировать вывод как результат симуляции профессионального обсуждения релевантных ролей
    (архитектор Effect/FP, ревьюер типов, страж CORE↔SHELL, тест-инженер).
  • Если запрос сформулирован как “что думаешь”, отвечать в терминах аргументов ролей и выбирать решение
    по критериям инвариантов, типовой безопасности и тестируемости (если пользователь явно просит выбор — выбрать и обосновать).

ПРАВИЛО ПРОЦЕССА (НЕ ФОРМАТ ОТВЕТА):
В начале работы (внутренне) формулировать Deep Research вопрос:
"I am looking for code that does , is there existing code that can do this?"
Далее:

  • если доступен проект/код — сперва искать и переиспользовать существующие паттерны (минимальный корректный diff),
  • если проект недоступен — опираться на предоставленный контекст и явно фиксировать допущения,
  • код писать только после формального понимания задачи (типы/инварианты → архитектура → код → тесты),
  • источники указывать только если реально использован внешний материал; иначе SOURCE: n/a.

ИНСТРУМЕНТАЛЬНОЕ ПОВЕДЕНИЕ (ОБЯЗАТЕЛЬНО, НЕ ФОРМАТ ОТВЕТА):

  • Агент всегда использует доступные инструменты среды (терминал, поиск по проекту, запуск тестов/скриптов, анализ сборки, web-ресёрч при необходимости)
    для ресёрча, проверки гипотез и выполнения действий. Приоритет: проверяемость, воспроизводимость, минимальный риск.
  • Агент не предлагает “гайд” как замену действия. Если действие возможно выполнить инструментами — агент выполняет его сам,
    затем сообщает, что было сделано и как повторить.
  • Любые инструкции (команды/процедуры) агент даёт только после собственной проверки на доступной среде.
    Если проверить невозможно — явно фиксирует ограничение и перечисляе...

Files:

  • crates/android-connection/README.md
  • crates/android-connection/Cargo.toml
  • crates/android-connection/src/bin/android-connection.rs
  • packages/lib/tests/usecases/mcp-android.test.ts
  • README.md
  • packages/lib/src/shell/files.ts
  • packages/container/src/core/templates/dockerfile.ts
  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/container/src/core/templates/docker-compose-android.ts
  • packages/container/src/core/templates-entrypoint/claude.ts
  • packages/container/src/core/templates-entrypoint/grok-android-mcp.ts
  • crates/android-connection/src/main.rs
  • packages/app/src/docker-git/cli/usage.ts
  • packages/container/src/core/templates-entrypoint/codex.ts
  • packages/lib/src/shell/android-connection-source.ts
  • packages/lib/src/usecases/mcp-android.ts
  • packages/container/tests/core/templates.test.ts
  • crates/android-connection/src/lib.rs
  • packages/lib/tests/usecases/apply.test.ts
  • packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts
  • crates/android-connection/src/mcp.rs
**/*

⚙️ CodeRabbit configuration file

**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.

Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.

Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.

Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.

Files:

  • crates/android-connection/README.md
  • crates/android-connection/Cargo.toml
  • crates/android-connection/src/bin/android-connection.rs
  • packages/lib/tests/usecases/mcp-android.test.ts
  • README.md
  • packages/lib/src/shell/files.ts
  • packages/container/src/core/templates/dockerfile.ts
  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/container/src/core/templates/docker-compose-android.ts
  • packages/container/src/core/templates-entrypoint/claude.ts
  • packages/container/src/core/templates-entrypoint/grok-android-mcp.ts
  • crates/android-connection/src/main.rs
  • packages/app/src/docker-git/cli/usage.ts
  • packages/container/src/core/templates-entrypoint/codex.ts
  • packages/lib/src/shell/android-connection-source.ts
  • packages/lib/src/usecases/mcp-android.ts
  • packages/container/tests/core/templates.test.ts
  • crates/android-connection/src/lib.rs
  • packages/lib/tests/usecases/apply.test.ts
  • packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts
  • crates/android-connection/src/mcp.rs
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output

Files:

  • crates/android-connection/Cargo.toml
  • packages/lib/tests/usecases/mcp-android.test.ts
  • packages/lib/src/shell/files.ts
  • packages/container/src/core/templates/dockerfile.ts
  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/container/src/core/templates/docker-compose-android.ts
  • packages/container/src/core/templates-entrypoint/claude.ts
  • packages/container/src/core/templates-entrypoint/grok-android-mcp.ts
  • packages/app/src/docker-git/cli/usage.ts
  • packages/container/src/core/templates-entrypoint/codex.ts
  • packages/lib/src/shell/android-connection-source.ts
  • packages/lib/src/usecases/mcp-android.ts
  • packages/container/tests/core/templates.test.ts
  • packages/lib/tests/usecases/apply.test.ts
  • packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts
**/{package*.json,requirements*.txt,setup.py,setup.cfg,Pipfile,Pipfile.lock,pyproject.toml,pom.xml,build.gradle,Gemfile,Gemfile.lock,go.mod,go.sum,composer.json,Cargo.toml,Cargo.lock}

📄 CodeRabbit inference engine (Custom checks)

Fail if dependency or package-manager changes materially increase supply-chain risk without justification

Files:

  • crates/android-connection/Cargo.toml
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input

Files:

  • packages/lib/tests/usecases/mcp-android.test.ts
  • packages/lib/src/shell/files.ts
  • packages/container/src/core/templates/dockerfile.ts
  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/container/src/core/templates/docker-compose-android.ts
  • packages/container/src/core/templates-entrypoint/claude.ts
  • packages/container/src/core/templates-entrypoint/grok-android-mcp.ts
  • packages/app/src/docker-git/cli/usage.ts
  • packages/container/src/core/templates-entrypoint/codex.ts
  • packages/lib/src/shell/android-connection-source.ts
  • packages/lib/src/usecases/mcp-android.ts
  • packages/container/tests/core/templates.test.ts
  • packages/lib/tests/usecases/apply.test.ts
  • packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce path traversal or writes outside intended project/container state directories

Files:

  • packages/lib/tests/usecases/mcp-android.test.ts
  • packages/lib/src/shell/files.ts
  • packages/container/src/core/templates/dockerfile.ts
  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/container/src/core/templates/docker-compose-android.ts
  • packages/container/src/core/templates-entrypoint/claude.ts
  • packages/container/src/core/templates-entrypoint/grok-android-mcp.ts
  • packages/app/src/docker-git/cli/usage.ts
  • packages/container/src/core/templates-entrypoint/codex.ts
  • packages/lib/src/shell/android-connection-source.ts
  • packages/lib/src/usecases/mcp-android.ts
  • packages/container/tests/core/templates.test.ts
  • packages/lib/tests/usecases/apply.test.ts
  • packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: FUNCTIONAL CORE: Write only pure functions with immutable data and mathematical operations in core modules; no side effects, mutations, or external service calls
IMPERATIVE SHELL: Isolate all side effects (IO, network, database, environment/process) in a thin SHELL layer; CORE never calls SHELL, only SHELL → CORE
Never use any type annotation in TypeScript; use unknown only at SHELL boundaries for decoding, never export unknown outside boundary modules
Never use as type assertions in normal code; only permit as in a single 'axiomatic' module (brands, constructors, constants) after which types flow safely without casts
Always use exhaustive pattern matching for union types through .exhaustive() or Match.exhaustive() from effect-ts; never use switch statements or unhandled type branches
Use Effect<Success, Error, Requirements> monad from effect-ts for all effects; compose through pipe() and Effect.flatMap(); never use async/await, raw Promise chains (then/catch), or Promise.all in product code
Interoperate with Promise/exceptions only in SHELL through Effect.try/Effect.tryPromise with typed error mapping; never leave raw exceptions or untyped errors in the domain
Use Effect.acquireRelease + Effect.scoped for resource management with guaranteed finalization; never manage resources with try/finally or manual cleanup
All external services (database, HTTP, environment) must be accessed through Effect-based interfaces and Layer-based dependency injection; never call external APIs directly
Provide comprehensive TSDoc comments with mathematical notation: @pure, @effect, @invariant, @precondition, @postcondition, @complexity, @throws, and CHANGE/WHY/REF/SOURCE/FORMAT THEOREM functional comment markers
No console.*, process direct calls, or untyped environment access in product code; all such operations must be abstracted through Layer-based services in SHELL
Boundary data from external sources (HTTP, database, environment) must be decoded/valida...

Files:

  • packages/lib/tests/usecases/mcp-android.test.ts
  • packages/lib/src/shell/files.ts
  • packages/container/src/core/templates/dockerfile.ts
  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/container/src/core/templates/docker-compose-android.ts
  • packages/container/src/core/templates-entrypoint/claude.ts
  • packages/container/src/core/templates-entrypoint/grok-android-mcp.ts
  • packages/app/src/docker-git/cli/usage.ts
  • packages/container/src/core/templates-entrypoint/codex.ts
  • packages/lib/src/shell/android-connection-source.ts
  • packages/lib/src/usecases/mcp-android.ts
  • packages/container/tests/core/templates.test.ts
  • packages/lib/tests/usecases/apply.test.ts
  • packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.test.{ts,tsx}: Write property-based tests using fast-check (fc.property) to verify mathematical invariants; unit tests must use Effect test utilities without async/await
Every bug fix must be accompanied by a reproducing test case; the test must fail before the fix and pass after; document the Proof of Fix with root cause and solution

Files:

  • packages/lib/tests/usecases/mcp-android.test.ts
  • packages/container/tests/core/templates.test.ts
  • packages/lib/tests/usecases/apply.test.ts
*.md

📄 CodeRabbit inference engine (AGENTS.md)

Document all PR changes with mathematical proof obligations: invariants, preconditions, postconditions, variant functions, and complexity analysis in Markdown format

Files:

  • README.md
**/.github/workflows/*.{yml,yaml}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce unsafe GitHub Actions configuration such as unsafe pull_request_target, or unnecessary write permissions

Files:

  • .github/workflows/check.yml
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T20:02:08.980Z
Learning: Project structure: APP (CLI + React Frontend) should only work with API and not have direct access to LIB
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T20:02:08.980Z
Learning: Project structure: API should only work with LIB and serve as the backend layer for APP
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T20:02:08.980Z
Learning: LIB module contains all backend logic and core business logic for the docker-git project
Learnt from: CR
Repo: ProverCoderAI/docker-git

Timestamp: 2026-06-23T20:02:08.980Z
Learning: Follow Spec-Driven Development (SDD) process: from issue to verified PR as documented in docs/process.md
📚 Learning: 2026-05-22T21:08:18.083Z
Learnt from: skulidropek
Repo: ProverCoderAI/docker-git PR: 344
File: packages/app/src/docker-git/controller-compose.ts:34-40
Timestamp: 2026-05-22T21:08:18.083Z
Learning: In this repo’s docker-git controller compose generation, `${DOCKER_GIT_CONTROLLER_BUILD_SKILLER:-1}` should be treated as standard bash parameter expansion: when `DOCKER_GIT_CONTROLLER_BUILD_SKILLER` is unset, it defaults to the string "1". There is no "-1" mode. The runtime contract enforced by `packages/app/src/docker-git/controller-compose.ts` is: unset / "1" / "true" => output "1"; "0" / "false" => output "0". If review code shows branching/behavior for "-1" or any numeric value other than this 0/1 contract, flag it. Also ensure the Dockerfile ARG `DOCKER_GIT_CONTROLLER_BUILD_SKILLER` stays consistent with default `1`.

Applied to files:

  • packages/app/src/docker-git/menu-create-labels.ts
  • packages/app/src/docker-git/cli/usage.ts
🪛 zizmor (1.26.1)
.github/workflows/check.yml

[warning] 47-47: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 47-47: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🔇 Additional comments (12)
packages/app/src/docker-git/cli/usage.ts (1)

10-10: LGTM!

Also applies to: 31-31, 83-83

packages/container/src/core/templates-entrypoint/claude.ts (1)

254-311: LGTM!

packages/container/src/core/templates-entrypoint/gemini-android-mcp.ts (1)

6-57: LGTM!

packages/container/src/core/templates-entrypoint/grok-android-mcp.ts (1)

6-57: LGTM!

packages/lib/tests/usecases/mcp-android.test.ts (1)

124-139: LGTM!

packages/lib/tests/usecases/apply.test.ts (1)

230-262: LGTM!

crates/android-connection/Cargo.toml (1)

1-24: LGTM!

crates/android-connection/.gitignore (1)

1-1: LGTM!

crates/android-connection/src/bin/android-connection.rs (1)

21-23: 🔒 Security & Privacy

Проверка пройдена: path traversal-защита уже реализована и протестирована.

Функция workspace_path (строки 533–547) корректно валидирует все пути перед использованием:

  • Отклоняет абсолютные пути (candidate.is_absolute())
  • Отклоняет пути с компонентом .. (Component::ParentDir)
  • Безопасно присоединяет к workspace через workspace.join()

Обе операции, требующие файловых операций (android_screenshot и android_install_apk), маршрутизируют входные пути через workspace_path перед fs::create_dir_all и fs::write. Тест rejects_workspace_paths_outside_workspace покрывает все основные случаи escape-попыток (абсолютные пути, .., вложенные traversal).

packages/container/tests/core/templates.test.ts (1)

1175-1208: Дубликат ранее оставленного замечания про формат тестов (property-based + Effect utilities).

packages/container/src/core/templates/dockerfile.ts (1)

103-110: 🩺 Stability & Availability

Проверка подтверждает наличие Cargo.lock в crates/android-connection/ — флаг --locked в Line 108 будет работать корректно. При копировании через copyTextDirectory весь контент crate-а (включая lockfile) переносится в /opt/docker-git/tools/android-connection, обеспечивая детерминированность сборки. Воспроизводимость гарантирована на уровне зависимостей.

.github/workflows/check.yml (1)

47-47: 🔒 Security & Privacy

Комментарий к проверке неточен согласно указанным рекомендациям кодирования.

Рекомендация по кодированию для этого файла требует отказать, если "изменения вводят небезопасную конфигурацию GitHub Actions, такую как небезопасный pull_request_target или ненужные разрешения write".

В текущем workflow:

  • Используется pull_request, а не pull_request_target (безопасно)
  • Глобальные разрешения установлены только на contents: read (минимальные)

Хотя закрепление на SHA и явное persist-credentials: false могут быть рекомендациями лучших практик, они не входят в критерии отказа, указанные в рекомендациях. Текущая конфигурация соответствует требуемым стандартам безопасности.

			> Likely an incorrect or invalid review comment.

Comment on lines +7 to +8
Projects can now opt into a nested Android emulator sidecar driven by the
first-party Rust `android-connection` MCP server, mirroring how Playwright MCP works. Enable it

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Уточните упоминание "first-party" и версионирование android-connection.

Строка 8 упоминает "first-party Rust android-connection MCP server", но в changeset не указывается:

  • Где находится крейт (например, crates/android-connection)
  • Что это — новый компонент в этом PR

Рекомендуется добавить уточнение в скобках: "новый Rust крейт android-connection" или аналогично для ясности, что это не существующий компонент.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.changeset/mcp-android-integration.md around lines 7 - 8, The changeset text
mentions "first-party Rust `android-connection` MCP server" but does not clarify
that this is a newly introduced component. Update the changeset text to
explicitly indicate that `android-connection` is a new Rust crate being added in
this PR. You can add a parenthetical clarification such as "new Rust crate
`android-connection`" or include the location context (e.g.,
`crates/android-connection`) to make it clear this is not an existing component
and is being introduced for the first time.

Comment on lines +95 to +105
pub fn is_safe_adb_endpoint(value: &str) -> bool {
!value.is_empty()
&& value.len() <= 255
&& value.contains(':')
&& value.bytes().all(|byte| {
matches!(
byte,
b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'.' | b'-' | b'_' | b':'
)
})
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Сделайте валидацию ADB endpoint строгой как host:port.

Текущая проверка пропускает заведомо невалидные значения (например, ":", "host:", "host:abc"), и ошибка всплывает только поздно в runtime при вызове ADB.

Вариант точечного исправления
 pub fn is_safe_adb_endpoint(value: &str) -> bool {
-    !value.is_empty()
-        && value.len() <= 255
-        && value.contains(':')
-        && value.bytes().all(|byte| {
-            matches!(
-                byte,
-                b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'.' | b'-' | b'_' | b':'
-            )
-        })
+    if value.is_empty() || value.len() > 255 {
+        return false;
+    }
+    let Some((host, port)) = value.rsplit_once(':') else {
+        return false;
+    };
+    !host.is_empty()
+        && !port.is_empty()
+        && host.bytes().all(|byte| {
+            matches!(byte, b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'.' | b'-' | b'_')
+        })
+        && port.bytes().all(|byte| matches!(byte, b'0'..=b'9'))
+        && port.parse::<u16>().is_ok()
 }

Also applies to: 107-115

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/android-connection/src/lib.rs` around lines 95 - 105, The
is_safe_adb_endpoint function currently allows invalid endpoint formats like
":", "host:", and "host:abc". Refactor the validation to enforce strict
host:port format by splitting the input string on the colon character, ensuring
exactly two parts exist, verifying both the host and port parts are non-empty,
validating that the port part contains only digits, and checking that the
numeric port value falls within the valid port range of 1 to 65535.

Comment on lines +68 to +91
fn read_next_message<R: BufRead>(reader: &mut R) -> io::Result<Option<String>> {
loop {
let mut line = String::new();
let bytes_read = reader.read_line(&mut line)?;
if bytes_read == 0 {
return Ok(None);
}

let first_line = line.trim_end_matches(['\r', '\n']);
if first_line.is_empty() {
continue;
}

if let Some(length) = parse_content_length(first_line)? {
read_headers(reader)?;
let mut payload = vec![0_u8; length];
reader.read_exact(&mut payload)?;
return String::from_utf8(payload)
.map(Some)
.map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error));
}

return Ok(Some(first_line.to_string()));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Парсер framed-stdio принимает только случай, когда Content-Length — первая строка заголовков.

На Line 68-91 при первом непустом заголовке, отличном от Content-Length, код трактует строку как JSON payload и ломает обработку. Это делает сервер хрупким к допустимым вариациям порядка заголовков.

Надёжнее: читать заголовки до пустой строки, извлекать Content-Length независимо от порядка, и только потом читать тело.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/android-connection/src/mcp.rs` around lines 68 - 91, The
read_next_message function incorrectly assumes Content-Length is always the
first header and treats any other first non-empty header as the JSON payload,
making the parser fragile to header order variations. Refactor the function to
read all headers in a loop until an empty line is encountered, extract the
Content-Length value from any header line that contains it (regardless of
order), then only after collecting all headers and obtaining the length value,
read the payload. This requires separating the header parsing logic from the
payload reading logic so headers can be processed in any order.

Comment on lines +533 to +547
fn workspace_path(workspace: &Path, value: &str) -> Result<PathBuf, McpToolError> {
let candidate = PathBuf::from(value);
if value.is_empty()
|| candidate.is_absolute()
|| candidate
.components()
.any(|component| component == Component::ParentDir)
{
return Err(McpToolError::InvalidArgument(
"path must be relative, non-empty, and must not contain '..'".to_string(),
));
}

Ok(workspace.join(candidate))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

workspace_path не блокирует обход через symlink-компоненты.

На Line 533-547 фильтруются только абсолютные пути и .., но это не защищает от пути вида screenshots/link/out.png, где link — symlink наружу workspace. Тогда запись на Line 415-419 может уйти за пределы рабочей директории.

Добавьте проверку каждого существующего промежуточного компонента через symlink_metadata и отклоняйте symlink; отдельно нужен регрессионный тест с symlink-кейсом (должен падать до фикса и проходить после).
As per coding guidelines, "Fail if changed files introduce path traversal or writes outside intended project/container state directories."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/android-connection/src/mcp.rs` around lines 533 - 547, The
workspace_path function currently only validates against absolute paths and
parent directory traversal (..) but does not prevent symlink-based path
traversal attacks. To fix this, after validating the initial path conditions,
iterate through each component of the candidate path and use symlink_metadata to
check if any intermediate component is a symlink, rejecting the path if symlinks
are detected. This ensures that even if the path appears valid, it cannot escape
the workspace through symbolic links. Additionally, add a regression test that
attempts to use a path containing a symlink component (which should fail before
the fix and pass after implementation).

Source: Coding guidelines

Comment on lines +26 to +29
Match.when(
"mcpAndroid",
() => `Enable Android MCP (nested Android emulator)? [${renderExplicitBooleanChoice(defaults.enableMcpAndroid)}]`
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Функциональная корректность подтверждена.

Логика соответствует паттерну других boolean-шагов wizard (mcpPlaywright). Использование Match.exhaustive и renderExplicitBooleanChoice обеспечивает типовую безопасность и консистентность отображения.

Опциональное улучшение терминологии: В usage.ts строка 31 использует "Android MCP (android-connection)", но в wizard метке (строка 28) упоминается только "Android MCP (nested Android emulator)" без идентификатора сервера. Для полной согласованности с документацией можно рассмотреть упоминание "(android-connection)" и в wizard, либо принять текущий паттерн (где wizard использует более краткие пользовательские формулировки, а usage.ts — технические детали).

Also applies to: 64-69

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/app/src/docker-git/menu-create-labels.ts` around lines 26 - 29, For
consistency with the technical terminology used in usage.ts (which references
"android-connection"), update the prompt label in the Match.when case for
"mcpAndroid" to include the server identifier alongside the user-friendly
description. Specifically, modify the string template to include
"(android-connection)" in addition to "(nested Android emulator)" to align the
wizard terminology with the technical details referenced in usage.ts at line 31,
ensuring consistent naming across the codebase.

Comment on lines +21 to +75
const shouldSkipAndroidConnectionEntry = (entry: string): boolean => entry === "target" || entry === ".git"

const copyTextFile = (
fs: FileSystem.FileSystem,
path: Path.Path,
sourcePath: string,
targetPath: string
): Effect.Effect<void, PlatformError> =>
Effect.gen(function*(_) {
const contents = yield* _(fs.readFileString(sourcePath))
yield* _(ensureParentDir(path, fs, targetPath))
yield* _(fs.writeFileString(targetPath, contents))
})

const copyTextDirectoryEntry = (
fs: FileSystem.FileSystem,
path: Path.Path,
sourcePath: string,
targetPath: string
): Effect.Effect<void, PlatformError> =>
Effect.gen(function*(_) {
const info = yield* _(fs.stat(sourcePath))
if (info.type === "Directory") {
yield* _(copyTextDirectory(fs, path, sourcePath, targetPath))
return
}
if (info.type === "File") {
yield* _(copyTextFile(fs, path, sourcePath, targetPath))
}
})

const copyTextDirectory = (
fs: FileSystem.FileSystem,
path: Path.Path,
sourcePath: string,
targetPath: string
): Effect.Effect<void, PlatformError> =>
Effect.gen(function*(_) {
yield* _(fs.makeDirectory(targetPath, { recursive: true }))
const entries = yield* _(fs.readDirectory(sourcePath))
for (const entry of entries) {
if (shouldSkipAndroidConnectionEntry(entry)) {
continue
}
yield* _(
copyTextDirectoryEntry(
fs,
path,
path.join(sourcePath, entry),
path.join(targetPath, entry)
)
)
}
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Копирование всего дерева crate в build-context слишком широкое и может утянуть чувствительные файлы.

На Line 21-75 фильтрация исключает только target и .git, поэтому в .docker-git-tools/android-connection попадут любые локальные артефакты (включая потенциально секретные файлы/symlink-цели), что повышает риск утечки и ломает воспроизводимость сборки.

Лучше перейти на allowlist (например Cargo.toml, Cargo.lock, src/**, README.md) и явно исключать symlink/скрытые локальные артефакты.
As per coding guidelines, "Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/lib/src/shell/android-connection-source.ts` around lines 21 - 75,
The shouldSkipAndroidConnectionEntry function uses a blocklist approach that
only excludes "target" and ".git", which is too permissive and risks exposing
sensitive files like credentials or local artifacts. Replace the blocklist logic
with an allowlist approach that only permits necessary files (such as
Cargo.toml, Cargo.lock, src directory, and README.md) to be copied into the
build context. Modify the shouldSkipAndroidConnectionEntry function to return
true (skip) for anything not explicitly allowed, and also reject hidden files
(starting with dot) and symlinks to prevent accidental inclusion of sensitive
local artifacts.

Source: Coding guidelines

baseDir: string
): Effect.Effect<void, PlatformError, FileSystem.FileSystem | Path.Path> =>
Effect.gen(function*(_) {
const workspaceRoot = yield* _(resolveWorkspaceRoot(process.cwd()))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Проверка, есть ли уже абстракция cwd/env в shell-слое
rg -n 'process\.cwd\(' packages/lib/src
rg -n 'CurrentWorkingDirectory|cwd|Env|WorkspaceRoot|resolveWorkspaceRoot' packages/lib/src

Repository: ProverCoderAI/docker-git

Length of output: 50380


🏁 Script executed:

# Check the actual content of android-connection-source.ts around line 125
cat -n packages/lib/src/shell/android-connection-source.ts | head -150 | tail -30

Repository: ProverCoderAI/docker-git

Length of output: 1156


🏁 Script executed:

# Check resolveWorkspaceRoot definition and its usage pattern
ast-grep outline packages/lib/src/shell/ --match resolveWorkspaceRoot --view expanded

Repository: ProverCoderAI/docker-git

Length of output: 176


🏁 Script executed:

# Check if there's a pattern for context-based cwd abstraction (e.g., withFsPathContext usage)
rg -B3 -A3 'withFsPathContext|FsPathContext|cwd.*=' packages/lib/src/shell/ | head -60

Repository: ProverCoderAI/docker-git

Length of output: 2435


🏁 Script executed:

# Find resolveWorkspaceRoot definition
rg -n 'resolveWorkspaceRoot' packages/lib/src --type ts -B2 -A5 | head -40

Repository: ProverCoderAI/docker-git

Length of output: 3078


🏁 Script executed:

# Get the full function signature containing line 125
sed -n '110,135p' packages/lib/src/shell/android-connection-source.ts

Repository: ProverCoderAI/docker-git

Length of output: 1339


🏁 Script executed:

# Check if there's a pattern like withFsPathContext or similar abstraction in shell/
rg -n 'export.*with.*Context|Context\.Tag' packages/lib/src/shell/ --type ts | head -20

Repository: ProverCoderAI/docker-git

Length of output: 162


🏁 Script executed:

# Look at how other files in shell/ handle cwd injection/abstraction
rg -n 'cwd.*:.*string' packages/lib/src/shell/*.ts | head -15

Repository: ProverCoderAI/docker-git

Length of output: 1052


Передайте cwd параметром вместо прямого вызова process.cwd().

На Line 125 функция вызывает process.cwd() напрямую вместо того, чтобы принять его как параметр. Согласно guidelines: "No process direct calls... in product code; all such operations must be abstracted through Layer-based services in SHELL." Добавьте cwd: string в сигнатуру функции (как это сделано в соседних функциях docker-compose.ts, docker-volume.ts и др.) и передавайте его в resolveWorkspaceRoot(cwd). Это повысит тестируемость и консистентность с кодовой базой.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/lib/src/shell/android-connection-source.ts` at line 125, The
function in android-connection-source.ts is calling process.cwd() directly in
the resolveWorkspaceRoot invocation, which violates the guideline that process
operations must be abstracted through Layer-based services. Refactor the
function to accept a cwd parameter of type string in its signature, then pass
that cwd parameter to resolveWorkspaceRoot(cwd) instead of calling process.cwd()
directly. This approach aligns with the pattern already established in related
files and improves testability.

Source: Coding guidelines

// REF: issue-176
yield* _(provisionDockerGitScripts(fs, path, baseDir))
yield* _(provisionDockerGitSessionSyncTool(fs, path, baseDir))
yield* _(provisionDockerGitBuildContext(fs, path, baseDir, normalizedConfig))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Сделайте provisioning build context fail-fast до записи шаблонов.

Сейчас provisioning выполняется после записи specs; если Android source недоступен, падение произойдёт уже после частичной генерации файлов, что оставляет проект в несогласованном состоянии.

Минимальный безопасный рефакторинг
   Effect.gen(function*(_) {
     const { fs, path, resolved: baseDir } = yield* _(resolveBaseDir(outDir))

     yield* _(fs.makeDirectory(baseDir, { recursive: true }))

     const normalizedConfig = withDefaultResourceLimitIntent(config)
+    yield* _(provisionDockerGitBuildContext(fs, path, baseDir, normalizedConfig))
+
     const hostResources = yield* _(loadHostResources())
     const composeResourceLimits = {
       main: resolveComposeResourceLimits(normalizedConfig, hostResources),
       playwright: resolvePlaywrightComposeResourceLimits(normalizedConfig, hostResources)
     }
@@
-    yield* _(provisionDockerGitBuildContext(fs, path, baseDir, normalizedConfig))
-
     return created
   })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/lib/src/shell/files.ts` at line 285, The
provisionDockerGitBuildContext call should be executed earlier in the process
before any template or spec files are written, to implement fail-fast behavior.
Move the yield* _(provisionDockerGitBuildContext(fs, path, baseDir,
normalizedConfig)) statement to the beginning of the generator function, before
any other yield statements that write files or specs, ensuring that if the
Docker Git build context provisioning fails (e.g., due to unavailable Android
source), the failure occurs before the project reaches an inconsistent state
from partial file generation.

Comment on lines +88 to +89
yield* _(ensureDockerDaemonAccess(command.projectDir))
return yield* _(runDockerComposeUpWithPortCheck(command.projectDir))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Проверка: есть ли регрессионный тест, который явно покрывает mcpAndroidUp + projectDir.
# Ожидание: найден тест, где mcpAndroidUp запускается с projectDir, отличным от process.cwd(),
# и мок/стаб CommandExecutor проверяет cwd команд Docker.
rg -n -C 4 'mcpAndroidUp|ensureDockerDaemonAccess|process\.cwd|projectDir' packages/lib/tests

Repository: ProverCoderAI/docker-git

Length of output: 33973


🏁 Script executed:

# First, find the mcp-android.ts file and check its implementation around lines 88-89
fd -type f -name "mcp-android.ts" packages/lib/src

# Then search for mcpAndroidUp specifically in tests
rg -n "mcpAndroidUp" packages/lib/tests

Repository: ProverCoderAI/docker-git

Length of output: 333


🏁 Script executed:

# Correct fd syntax - use -t f instead of -type f, and search more broadly
fd "mcp-android" packages/lib/src

# Also search for mcpAndroidUp in the entire packages/lib directory
rg -n "mcpAndroidUp" packages/lib

Repository: ProverCoderAI/docker-git

Length of output: 277


🏁 Script executed:

# Read the mcp-android.ts file to understand the mcpAndroidUp function
cat -n packages/lib/src/usecases/mcp-android.ts | head -120

Repository: ProverCoderAI/docker-git

Length of output: 4471


🏁 Script executed:

# Search for tests of mcpAndroidUp
rg -n "mcpAndroidUp" packages/lib/tests -A 10 -B 2

# Also check if there's a mcp-android.test.ts file
fd "mcp-android" packages/lib/tests

Repository: ProverCoderAI/docker-git

Length of output: 210


🏁 Script executed:

# Read the mcp-android.test.ts file to see what tests exist
cat -n packages/lib/tests/usecases/mcp-android.test.ts

Repository: ProverCoderAI/docker-git

Length of output: 6620


🏁 Script executed:

# Check the ensureDockerDaemonAccess implementation to understand what cwd it uses
rg -n "ensureDockerDaemonAccess" packages/lib/src/shell/docker.js -A 15

Repository: ProverCoderAI/docker-git

Length of output: 235


🏁 Script executed:

# Find the docker file with ensureDockerDaemonAccess
fd "docker" packages/lib/src/shell

# Then read the correct file
rg -n "ensureDockerDaemonAccess" packages/lib/src -A 15

Repository: ProverCoderAI/docker-git

Length of output: 15799


🏁 Script executed:

# Compare the mcp-playwright.ts implementation to see if it has the same issue
cat -n packages/lib/src/usecases/mcp-playwright.ts | head -95

Repository: ProverCoderAI/docker-git

Length of output: 4559


Закрепите исправление projectDir регрессионным тестом для mcpAndroidUp.

Line 88 исправляет корневую ошибку, используя command.projectDir вместо process.cwd(), как в mcp-playwright.ts (которая ошибочно остаётся на process.cwd()). Однако mcp-android.test.ts не содержит теста функции mcpAndroidUp — нужен тест, где:

  1. command.projectDir отличается от process.cwd()
  2. Мок CommandExecutor проверяет, что docker info (через ensureDockerDaemonAccess) запускается с правильным cwd
  3. docker compose up запускается также из command.projectDir

Без такого теста регрессия остаётся незадокументированной и может повториться при будущих рефакторингах.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/lib/src/usecases/mcp-android.ts` around lines 88 - 89, Add a
regression test for the mcpAndroidUp function in mcp-android.test.ts that
validates the projectDir fix by setting up a test scenario where
command.projectDir differs from process.cwd(). The test should mock the
CommandExecutor to verify that both ensureDockerDaemonAccess (which calls docker
info) and runDockerComposeUpWithPortCheck (which calls docker compose up) are
invoked with the correct working directory from command.projectDir rather than
the current process working directory. This ensures the fix on line 88 using
command.projectDir is properly tested and prevents regression in future
refactorings.

Sources: Coding guidelines, Path instructions

Comment thread README.md

- `--force` пересоздаёт окружение и удаляет volumes проекта.
- `--mcp-playwright` включает Playwright MCP и Chromium sidecar для браузерной автоматизации.
- `--mcp-android` включает first-party Android MCP (`android-connection`) и вложенный sidecar с Android-эмулятором (`docker-android`) для мобильной автоматизации.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Упростите формулировку для параллельности со строкой --mcp-playwright.

Текущая формулировка:

- `--mcp-android` включает first-party Android MCP (`android-connection`) и вложенный sidecar с Android-эмулятором (`docker-android`) для мобильной автоматизации.

содержит больше деталей реализации, чем описание Playwright выше (line 73). Для лучшей параллельности и читаемости рекомендуется:

- `--mcp-android` включает Android MCP и Android-эмулятор sidecar для мобильной автоматизации.

Либо, если детали важны, добавьте аналогичную детализацию для Playwright:

- `--mcp-playwright` включает Playwright MCP (chromium-connection) и Chromium sidecar для браузерной автоматизации.
- `--mcp-android` включает Android MCP (android-connection) и Android-эмулятор sidecar для мобильной автоматизации.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 74, The documentation line describing the --mcp-android
flag contains excessive implementation details (mentioning first-party
designation, specific component names like android-connection and
docker-android) compared to the --mcp-playwright line above it, breaking
parallel structure. Simplify the --mcp-android description by removing the
implementation-specific terminology and details to match the conciseness of the
--mcp-playwright description, keeping only the essential information about what
capabilities are enabled for mobile automation.

Source: Path instructions

@konard

konard commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

✅ Ready to merge

This pull request is now ready to be merged:

  • All CI checks have passed
  • No merge conflicts
  • No pending changes

Monitored by hive-mind with --auto-restart-until-mergeable flag

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Подключить mcp-android так же как работает MCP PLAYRIGHT

2 participants