[2026-10-15] eagle: work/.DS_Store work/projects/macos-cloud-autofix-plan-2026-10-15.md
This commit is contained in:
1 parent
fb5215cabc
commit
aa85662551
2 files changed
+189
-189
No files matched your search
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'macOS: cloud flow для автофикса багов и тестов (Claude/Codex) — план'
|
||||
title: 'macOS: cloud flow for automatically fixing and validating bugs and tests (Claude/Codex) — plan'
|
||||
date: '2026-10-15'
|
||||
status: proposal
|
||||
tags:
|
||||
@@ -11,275 +11,275 @@ tags:
|
||||
- sentry
|
||||
- virfield
|
||||
---
|
||||
# macOS: cloud flow для автоматического фикса и валидации багов и тестов
|
||||
# macOS: cloud flow for automatically fixing and validating bugs and tests
|
||||
|
||||
Статус: **предложение**, не реализовано. Собрано 2026-10-15 из: Asana (AI Agent Infrastructure / O-T), Obsidian (Virfield, Personal OS, macos-tests-worktrees-2026-10-14, ci-pipeline), `.github/workflows` и `.claude/skills` в apple-browsers, документации Anthropic / OpenAI / Sentry / Bitrise.
|
||||
Status: **proposal**, not implemented. Compiled on 2026-10-15 from: Asana (AI Agent Infrastructure / O-T), Obsidian (Virfield, Personal OS, macos-tests-worktrees-2026-10-14, ci-pipeline), `.github/workflows` and `.claude/skills` in apple-browsers, and Anthropic / OpenAI / Sentry / Bitrise documentation.
|
||||
|
||||
Пометки: ✅ подтверждено источником, ⚠️ не проверено / нужен spike.
|
||||
Legend: ✅ confirmed by a source, ⚠️ not verified / needs a spike.
|
||||
|
||||
---
|
||||
|
||||
## 1. Что уже есть (чтобы не строить второй раз)
|
||||
## 1. What already exists (so we don't build it twice)
|
||||
|
||||
### 1.1 В Asana (опыт компании)
|
||||
### 1.1 In Asana (company experience)
|
||||
|
||||
| Что | Суть | Урок для нас |
|
||||
| What | Summary | Lesson for us |
|
||||
|---|---|---|
|
||||
| **Windows crash-triage** ([1214714826035263](https://app.asana.com/1/137249556945/task/1214714826035263)) | Prefect job тянет Sentry через MCP → Claude agent → ежедневный stability report → Release DRI. ~$8/день (~$250–500/мес). Сначала Cursor self-hosted, затем Claude на **GitHub-hosted Windows runner**, который Prefect запускает как GHA. Prefect-variable хранит «память» между запусками → дешевеет день ото дня. | Рабочая схема: **pre-fetch в доверенном контуре → artifact → агент на runner'е**. Агент не ходит в Sentry сам. |
|
||||
| Там же: отношение разработчиков к авто-PR | В апреле авто-PR встретили враждебно («проверять PR дороже, чем идею»). Решение: каждая находка **валидируется unit/UI-тестом-репродьюсером**, отчёт = root cause + направление + тест. После этого 2 AI-PR влились без комментариев, команда согласилась на авто-PR; ~20 CPMN деградации предотвращено. | Нельзя начинать с авто-PR. Лестница доверия: report → proposal → draft PR. **Без failing-теста фикс не предлагается.** |
|
||||
| **Find an alternative to Cursor Cloud Agents** ([1216757783325568](https://app.asana.com/1/137249556945/project/72649045549333/task/1216757783325568), DRI Chris Clarke) | 3 класса workflow: analyze-and-report / **build-and-fix** / drive-browser. Interactive Claude runners для Android, SERP, generic уже есть (claude.ai/code). Linux/Windows self-hosted GHA runners — в работе ([1218221113915359](https://app.asana.com/1/137249556945/task/1218221113915359)). **macOS — главный пробел**: в Azure нет macOS, поэтому нет пути к внутренней сети (dub, ClickHouse, Sentry). Проект «Provision Mac Machines» ([1215557028847084](https://app.asana.com/1/137249556945/project/1211983163358654/task/1215557028847084), AWS EC2 Mac) — **ON HOLD**. | Мы закрываем именно этот пробел. Нужно встроиться в проект AI Agent Infrastructure, а не делать параллельный. |
|
||||
| Context transfer PoC ([1217164276206833](https://app.asana.com/1/137249556945/task/1217164276206833)) | GHA run не resumable → в ZIP-artifact кладут transcript + prompt + metadata, skill восстанавливает контекст в новом чате. Предложено стандартизировать как company-wide GHA. | Решает «человек хочет вмешаться» без интерактивных сессий. |
|
||||
| **Bitrise** ([1218829288858490](https://app.asana.com/1/137249556945/project/1219113011535833/task/1218829288858490)) | Apple team уже использует **Bitrise как провайдера macOS-раннеров для GHA** (GitHub macOS слишком медленные), 360-мин лимит GHA. Bitrise RDE (remote dev env: SSH/VNC, suspend/resume) в trial: 1 concurrent session, баг Bitrise GitHub App с private repos (Bitrise чинит). | Для автоматических запусков берём то, что уже работает (GHA + Bitrise). RDE — для интерактива. |
|
||||
| **Security triage Bitrise RDE** ([1219413380003457](https://app.asana.com/1/137249556945/project/1199892415909552/task/1219413380003457), ответ 2026-10-14) | (AT1) прямой доступ Bitrise → внутренние системы **не жизнеспособен** (пришлось бы открывать все пулы Bitrise). (AT2) использовать RDE MCP, локальный Claude — оркестратор; `SSH_AUTH_SOCK` обнулить (forward ключей). (AT3) не auto-approve RDE tools в сессии с ClickHouse/Sentry MCP; всё, что вернулось из RDE, — untrusted. Сами RDE-сессии изолированы. | **Жёсткое ограничение дизайна:** агент на Bitrise-машине не видит Sentry/ClickHouse/dub. Данные приходят артефактом. |
|
||||
| Bug Squisher / Duck.ai | SERP: `[🤖 Bug Squisher]` PR'ы в ddg. Duck.ai: инженер вручную `$auto fix this bug` (порт pstack) → готовый PR → ревью. Автоматизацию добавят после доказанной надёжности. Artur (Chromium): агент не управляет браузером напрямую, а **пишет воспроизводимый journey-скрипт**, который прогоняется на base и fix коммитах — агент не может «соврать» в валидации. | Берём этот приём для валидации (см. §5). Согласовать с flux/pstack, чтобы не плодить 5-й параллельный фреймворк (см. комментарий о пересечениях в [1213572946361338](https://app.asana.com/1/137249556945/project/1209667197557478/task/1213572946361338)). |
|
||||
| Модель гейтов (из того же обсуждения) | Consensus-гейты (kick-off, tech design, post-mortem) — людям; unattended agent их пропускает. Review-гейты (privacy/security triage, ship review) обязательны — «стекаются» в конец, коррекции возвращают агента в цикл. | Агентский flow = draft PR + обязательные review-гейты, без consensus. |
|
||||
| Windows release quality ([1215834564874913](https://app.asana.com/1/137249556945/task/1215834564874913)) | Windows — пилот; **macOS идёт следом**. Preview ловит краши, но их не превращают в bug с owner'ом («conversion problem»). | Наш flow = «конвертер» crash → воспроизведённый тест → draft PR для macOS. |
|
||||
| **Windows crash triage** ([1214714826035263](https://app.asana.com/1/137249556945/task/1214714826035263)) | A Prefect job pulls Sentry via MCP → Claude agent → daily stability report → Release DRI. ~$8/day (~$250–500/month). Started on Cursor self-hosted, then moved to Claude on a **GitHub-hosted Windows runner** that Prefect triggers as a GHA. A Prefect variable stores "memory" between runs, so cost drops day over day. | A working pattern: **pre-fetch in a trusted zone → artifact → agent on the runner**. The agent does not call Sentry itself. |
|
||||
| Same task: developer attitude to auto-PRs | In April auto-PRs were met with hostility ("reviewing a PR costs more than checking the idea"). The fix: every finding is **validated with a unit/UI reproducer test**, and the report is root cause + direction + test. After that 2 AI PRs landed with no review comments, the team agreed to auto-PRs, and ~20 CPMN of degradation was prevented. | Do not start with auto-PRs. Trust ladder: report → proposal → draft PR. **No fix is proposed without a failing test.** |
|
||||
| **Find an alternative to Cursor Cloud Agents** ([1216757783325568](https://app.asana.com/1/137249556945/project/72649045549333/task/1216757783325568), DRI Chris Clarke) | 3 workflow classes: analyze-and-report / **build-and-fix** / drive-browser. Interactive Claude runners for Android, SERP and generic work already exist (claude.ai/code). Linux/Windows self-hosted GHA runners are in progress ([1218221113915359](https://app.asana.com/1/137249556945/task/1218221113915359)). **macOS is the main gap**: Azure has no macOS, so there is no path to the internal network (dub, ClickHouse, Sentry). The "Provision Mac Machines" project ([1215557028847084](https://app.asana.com/1/137249556945/project/1211983163358654/task/1215557028847084), AWS EC2 Mac) is **ON HOLD**. | We are closing exactly this gap. We need to plug into the AI Agent Infrastructure project rather than run a parallel one. |
|
||||
| Context-transfer PoC ([1217164276206833](https://app.asana.com/1/137249556945/task/1217164276206833)) | A GHA run is not resumable, so a ZIP artifact holds transcript + prompt + metadata, and a skill restores the context in a new chat. Proposed as a company-wide GHA. | Solves "a human wants to step in" without interactive sessions. |
|
||||
| **Bitrise** ([1218829288858490](https://app.asana.com/1/137249556945/project/1219113011535833/task/1218829288858490)) | The Apple team already uses **Bitrise as the macOS runner provider for GHA** (GitHub macOS runners are too slow); GHA has a 360-minute cap. Bitrise RDE (remote dev environment: SSH/VNC, suspend/resume) is in trial: 1 concurrent session, and a Bitrise GitHub App bug with private repos (Bitrise is fixing it). | For automated runs use what already works (GHA + Bitrise). RDE is for interactive work. |
|
||||
| **Security triage: Bitrise RDE** ([1219413380003457](https://app.asana.com/1/137249556945/project/1199892415909552/task/1219413380003457), reply 2026-10-14) | (AT1) Direct access from Bitrise to internal systems is **not viable** (all Bitrise address pools would have to be opened). (AT2) Use the RDE MCP with a local Claude as orchestrator; set `SSH_AUTH_SOCK` to empty (it forwards keys). (AT3) Do not auto-approve RDE tools in a session that also has the ClickHouse/Sentry MCP; anything coming back from RDE is untrusted. RDE sessions themselves are isolated. | **Hard design constraint:** an agent on a Bitrise machine cannot see Sentry/ClickHouse/dub. Data arrives as an artifact. |
|
||||
| Bug Squisher / Duck.ai | SERP: `[🤖 Bug Squisher]` PRs in ddg. Duck.ai: an engineer manually runs `$auto fix this bug` (a pstack port) → a ready PR → review. Automation comes later, once reliability is proven. Artur (Chromium): the agent does not drive the browser directly but **writes a reproducible journey script** that is run on the base and fix commits, so the agent cannot "lie" in validation. | Reuse this trick for validation (see §5). Align with flux/pstack so we don't add a fifth parallel framework (see the overlap comment in [1213572946361338](https://app.asana.com/1/137249556945/project/1209667197557478/task/1213572946361338)). |
|
||||
| Gate model (same discussion) | Consensus gates (kick-off, tech design, post-mortem) belong to humans; an unattended agent skips them. Review gates (privacy/security triage, ship review) are mandatory — they stack at the end, and corrections send the agent back into the loop. | Agent flow = draft PR + mandatory review gates, no consensus gates. |
|
||||
| Windows release quality ([1215834564874913](https://app.asana.com/1/137249556945/task/1215834564874913)) | Windows is the pilot; **macOS follows**. Preview catches crashes, but they are not turned into bugs with an owner (a "conversion problem"). | Our flow is the "converter" crash → reproduced test → draft PR for macOS. |
|
||||
|
||||
⚠️ Отдельной задачи именно про **Android cloud AI bug fixing** в Asana не нашлось — только упоминание, что Claude runners доступны для Android/SERP/generic. Если есть конкретная ссылка, надо дочитать.
|
||||
⚠️ Отдельного «Sentry crash report → Claude cloud» для Apple нет: сегодня это ручной skill `ddg-sentry-report` (пользователь вызывает сам, пишет в Asana).
|
||||
⚠️ I found no separate Asana task about **Android cloud AI bug fixing** — only the mention that Claude runners are available for Android/SERP/generic. If there is a specific link, it needs reading.
|
||||
⚠️ There is no "Sentry crash report → Claude cloud" flow for Apple either: today it is the manual `ddg-sentry-report` skill (the user invokes it, it writes to Asana).
|
||||
|
||||
### 1.2 В репозитории apple-browsers
|
||||
### 1.2 In the apple-browsers repo
|
||||
|
||||
- `macos_pr_checks.yml` (unit + integration на `macos-26` / `macos-26-xlarge`, release build, retry), `macos_ui_tests.yml` (matrix по классам × macOS 14/15/26, ночью 03:00 UTC, **`workflow_dispatch` с `single_test_class`**, `user_modes`, `workflow_call`), `macos_run_ui_test.yml`, `macos_build_notarized.yml` (UI-тесты требуют notarized Review app), `danger.yml`, `conflict_watch.yml`, `.github/actions/bitrise-build-cache`, `process-test-results`, `asana-failed-pr-checks`.
|
||||
- Skills: `ddg-diagnose-ci-failure` (JUnit XML из артефактов, классификация, flaky vs deterministic, регрессионная timeline), `ddg-sentry-report`. Оба **user-initiated**: трогают Asana → «lethal trifecta» блокирует прочие MCP.
|
||||
- `AGENTS.md`, `CLAUDE.md`, `REVIEW.md` — инструкции уже есть.
|
||||
- `.xcode-version` = 26.4 (ci-pipeline note). У Virfield профиль `uitest-27-v1` = macOS 27 / Xcode 27 → **расхождение**, надо иметь образ под 26.4.
|
||||
- `macos_pr_checks.yml` (unit + integration on `macos-26` / `macos-26-xlarge`, release build, retry), `macos_ui_tests.yml` (class × macOS 14/15/26 matrix, nightly 03:00 UTC, **`workflow_dispatch` with `single_test_class`**, `user_modes`, `workflow_call`), `macos_run_ui_test.yml`, `macos_build_notarized.yml` (UI tests need the notarized Review app), `danger.yml`, `conflict_watch.yml`, `.github/actions/bitrise-build-cache`, `process-test-results`, `asana-failed-pr-checks`.
|
||||
- Skills: `ddg-diagnose-ci-failure` (JUnit XML from artifacts, classification, flaky vs deterministic, regression timeline) and `ddg-sentry-report`. Both are **user-initiated**: they touch Asana, so the "lethal trifecta" policy blocks other MCPs afterwards.
|
||||
- `AGENTS.md`, `CLAUDE.md`, `REVIEW.md` already exist.
|
||||
- `.xcode-version` = 26.4 (ci-pipeline note). The Virfield profile `uitest-27-v1` = macOS 27 / Xcode 27, so there is a **mismatch**; we need an image for 26.4.
|
||||
|
||||
### 1.3 Наши локальные достижения (Obsidian)
|
||||
### 1.3 Our local achievements (Obsidian)
|
||||
|
||||
**Virfield** (Tart + SSH nodes, Go, MCP из 18 tools: `vm_acquire/vm_lease/vm_release/vm_tunnel`, `image_*`):
|
||||
- ✅ Disposable macOS VM по lease, pinned SSH, экспорт артефактов, cleanup; golden Xcode 15.2 / 13.4.1 / 27.0.
|
||||
- ✅ Исправлены вещи, на которых падают DDG UI-тесты: locked keychain (login + default, GUI и SSH контексты), 1920×1080, ASIF/Recovery, SSH banner timeout. Реальный `DownloadsUITests.testDownloadFinishesThenPopupIsShown` — 2 прогона 0 failures (Xcode 27.1 products → guest 27.0).
|
||||
- ⚠️ Не принято: Broker/Runner → apple-browsers UI suite целиком; установленный `aee89c1` ≠ source `9a740c0`; `vm_drift` ложные срабатывания; admission quirks (storage reserve); **пул = 2 VM на одном Mac**, GitHub CI отложен. Это хорошая **dev/acceptance площадка**, но не production-флот.
|
||||
**Virfield** (Tart + SSH nodes, Go, MCP with 18 tools: `vm_acquire/vm_lease/vm_release/vm_tunnel`, `image_*`):
|
||||
- ✅ Disposable macOS VM per lease, pinned SSH, artifact export, cleanup; goldens for Xcode 15.2 / 13.4.1 / 27.0.
|
||||
- ✅ Fixed the things DDG UI tests fail on: locked keychain (login + default, GUI and SSH contexts), 1920×1080, ASIF/Recovery, SSH banner timeout. A real `DownloadsUITests.testDownloadFinishesThenPopupIsShown` ran twice with 0 failures (Xcode 27.1 products → guest 27.0).
|
||||
- ⚠️ Not accepted yet: Broker/Runner → the full apple-browsers UI suite; installed `aee89c1` ≠ source `9a740c0`; false `vm_drift` events; admission quirks (storage reserve); **pool = 2 VMs on one Mac**; GitHub CI deferred. It is a good **dev/acceptance sandbox**, not a production fleet.
|
||||
|
||||
**Personal OS / Executor** (3 попытки, 2026-04…10):
|
||||
- Executor v1 (автономный LLM-оркестратор) → **инцидент** (писал в Asana, утечки задач в Discord). Executor v2 (bash runner/analyzer + 5 worker-промптов: queued / in_progress / fix_ci / fix_comments / pr_review; state machine `queued→in_progress→pr→complete/abandoned`; no-output watchdog 30 мин, hard 3 ч; lockfile; фильтры analyzer'а) — реализован, но кроны на паузе.
|
||||
- Сквозные уроки: (1) **детерминированный слой работал, агентный — нет**; (2) агенту нельзя писать во внешние системы и иметь канал наружу с рабочими данными; human-in-the-loop — обязательный гейт; (4) слабое железо не тянет агентный стек; (7) провайдер модели — конфиг, не архитектура; Codex bwrap не стартует в Docker; подписочные OAuth-токены не проксировать.
|
||||
**Personal OS / Executor** (3 attempts, 2026-04…10):
|
||||
- Executor v1 (autonomous LLM orchestrator) → **incident** (wrote to Asana, task data leaked to Discord). Executor v2 (bash runner/analyzer + 5 worker prompts: queued / in_progress / fix_ci / fix_comments / pr_review; state machine `queued→in_progress→pr→complete/abandoned`; no-output watchdog 30 min, hard limit 3 h; lockfile; analyzer filters) was implemented, but the crons are paused.
|
||||
- Cross-cutting lessons: (1) **the deterministic layer worked, the agentic one did not**; (2) an agent must not write to external systems or have an outbound channel carrying work data, and human-in-the-loop is a mandatory gate; (4) weak hardware cannot carry an agent stack; (7) the model provider is config, not architecture; Codex bwrap does not start in Docker; do not proxy subscription OAuth tokens.
|
||||
|
||||
**Тестовые фиксы 2026-10-14** ([[work/projects/macos-tests-worktrees-2026-10-14]]) — готовый эталон качества и eval-набор:
|
||||
- AddressBarTests: корень = `ensureObjectDeallocated(.interrupt)` шлёт SIGINT при живом объекте; 2 причины (autorelease в `TestRunHelper`, strong `self` в animation completion). Валидация: **main 10/10 FAIL → fix 15/15 PASS**, 7/7 изолированно, полный Integration ×2.
|
||||
- Fire Window video leak: **не воспроизведено**, итог = 4 guard-теста без фикса (проверка валидности: намеренная утечка → тест падает). «Не воспроизвелось» — легитимный исход.
|
||||
- Наблюдения среды: **display sleep** ломает dealloc-проверки (display-link анимации стоят) → VM/раннер должен держать дисплей бодрым; `async` тесты маскируют release; нужны мок сети (OHHTTPStubs) и изоляция настроек пользователя.
|
||||
**Test fixes of 2026-10-14** ([[work/projects/macos-tests-worktrees-2026-10-14]]) — a ready quality reference and eval set:
|
||||
- AddressBarTests: root cause = `ensureObjectDeallocated(.interrupt)` sends SIGINT while an object is still alive; two causes (autorelease in `TestRunHelper`, strong `self` in an animation completion). Validation: **main 10/10 FAIL → fix 15/15 PASS**, 7/7 isolated, full Integration ×2.
|
||||
- Fire Window video leak: **not reproduced**; outcome = 4 guard tests, no fix (validity check: an intentional leak makes the test fail). "Not reproduced" is a legitimate outcome.
|
||||
- Environment observations: **display sleep** breaks dealloc checks (display-link animations stall), so the VM/runner must keep the display awake; `async` tests mask releases; network mocking (OHHTTPStubs) and isolation of user settings are required.
|
||||
|
||||
### 1.4 Внешнее (проверено по документации)
|
||||
### 1.4 External (checked against documentation)
|
||||
|
||||
| Платформа | Что умеет | Ограничение для нас |
|
||||
| Platform | What it does | Limitation for us |
|
||||
|---|---|---|
|
||||
| **`anthropics/claude-code-action@v1`** | Automation mode (`prompt`), триггеры: schedule / dispatch / issue / PR; `claude_args` (`--max-turns`, `--allowedTools`, `--model`); skills из `.claude/skills`; auth: API key, OAuth, **OIDC federation (без долгоживущих секретов)**; по умолчанию создаёт ветку, PR — по ссылке (человек жмёт). Коммиты токеном `GITHUB_TOKEN` не запускают CI → нужен GitHub App/custom token. | ⚠️ Документация говорит «runs on GitHub-hosted runners»; работа на macOS/Bitrise-label **явно не описана** → spike. Ничего не мешает использовать `claude -p` напрямую в job. |
|
||||
| **`openai/codex-action@v1`** | `codex exec` в job; **Linux или macOS runner**; `sandbox`, `safety-strategy: drop-sudo`, `allow-users`. | Примеров fix-CI нет (только ревью PR). |
|
||||
| **Claude Code cloud (claude.ai/code, routines)** | Сессии на VM Anthropic; routines: schedule / **API trigger (`POST /fire`, поле `text` = payload алёрта)** / GitHub events; Auto-fix PR (реагирует на CI failures и комментарии). | Anthropic-VM не собирает Xcode. Лимиты routines: 30 fire/час на routine. `text` оборачивается как untrusted. |
|
||||
| **Claude self-hosted environments** (public beta, Team/Enterprise) | Runner на **нашем** хосте; outbound-only; routines и claude.ai/code роутятся на него; ephemeral runner (`--drain-grace-sec 0` → чистый диск); сессии **resumable с любого устройства**. Runner «лочится» на одного owner'а. | ⚠️ macOS-runner в доках не описан (рецепты — Kubernetes/Compose); Chris Clarke: «supports macOS, but we don't have any provisioned». Спросить Anthropic (в проекте есть похожая подзадача по Windows). |
|
||||
| **Sentry Seer** | Автоматический Issue Fix: ≥10 events, активность ≤14 дней, fixability score; уровни: stop after RCA / solution / PR / **hand-off в Claude Agent** (или Cursor, Copilot); Seer **никогда не мерджит**. Рекомендуют начинать с «Stop after Solution». | Не собирает macOS-проект; нужен GitHub integration + code mappings; приватность (крэш-данные → внешний агент) — нужен privacy triage. |
|
||||
| **Bitrise Build Hub (GHA)** | `runs-on: <bitrise-label>`, M4 Pro, Xcode в течение 24 ч после релиза, on-demand ephemeral с GitHub App, US/EU. | Нет явных гарантий egress-контроля. |
|
||||
| **Bitrise RDE** | SSH/VNC, suspend/resume, MCP server. | См. security triage выше; trial = 1 сессия. |
|
||||
| **Bitrise AI Build Fixer** | Анализ упавшего билда → PR → ре-билд (Pro/Enterprise). | ⚠️ Описан для Bitrise CI; для «Build Hub под GHA» не подтверждено. Покрывает только build failures, не flaky/crash. |
|
||||
| **Tart / Orchard / Tartelet / Cilicon** | OSS ephemeral macOS VM на Apple silicon для self-hosted GHA runners. | ⚠️ Новость о закрытии Cirrus CI — из блога конкурента, не проверена; Tart OSS от этого не зависит. |
|
||||
| **`anthropics/claude-code-action@v1`** | Automation mode (`prompt`); triggers: schedule / dispatch / issue / PR; `claude_args` (`--max-turns`, `--allowedTools`, `--model`); skills from `.claude/skills`; auth: API key, OAuth, **OIDC federation (no long-lived secrets)**; by default creates a branch and the PR is created via a link (a human clicks). Commits made with `GITHUB_TOKEN` do not trigger CI, so a GitHub App/custom token is needed. | ⚠️ The docs say "runs on GitHub-hosted runners"; running on macOS/a Bitrise label is **not explicitly described** → spike. Nothing prevents using `claude -p` directly in a job. |
|
||||
| **`openai/codex-action@v1`** | `codex exec` in a job; **Linux or macOS runner**; `sandbox`, `safety-strategy: drop-sudo`, `allow-users`. | No fix-CI examples (only PR review). |
|
||||
| **Claude Code cloud (claude.ai/code, routines)** | Sessions on Anthropic VMs; routines: schedule / **API trigger (`POST /fire`, the `text` field = alert payload)** / GitHub events; Auto-fix PR (reacts to CI failures and comments). | Anthropic VMs do not build Xcode. Routine limits: 30 fires/hour per routine. `text` is wrapped as untrusted. |
|
||||
| **Claude self-hosted environments** (public beta, Team/Enterprise) | A runner on **our** host; outbound-only; routines and claude.ai/code route to it; ephemeral runner (`--drain-grace-sec 0` → clean disk); sessions are **resumable from any device**. A runner locks to one owner. | ⚠️ A macOS runner is not described in the docs (recipes are Kubernetes/Compose); Chris Clarke: "supports macOS, but we don't have any provisioned". Ask Anthropic (the project has a similar subtask for Windows). |
|
||||
| **Sentry Seer** | Automatic Issue Fix: ≥10 events, activity within 14 days, fixability score; levels: stop after RCA / solution / PR / **hand-off to Claude Agent** (or Cursor, Copilot); Seer **never merges**. They recommend starting with "Stop after Solution". | Does not build the macOS project; needs the GitHub integration + code mappings; privacy (crash data → an external agent) needs a privacy triage. |
|
||||
| **Bitrise Build Hub (GHA)** | `runs-on: <bitrise-label>`, M4 Pro, Xcode within 24 h of release, on-demand ephemeral with the GitHub App, US/EU. | No explicit egress-control guarantees. |
|
||||
| **Bitrise RDE** | SSH/VNC, suspend/resume, MCP server. | See the security triage above; trial = 1 session. |
|
||||
| **Bitrise AI Build Fixer** | Analyzes a failed build → PR → rebuild (Pro/Enterprise). | ⚠️ Described for Bitrise CI; not confirmed for "Build Hub under GHA". Covers only build failures, not flaky tests or crashes. |
|
||||
| **Tart / Orchard / Tartelet / Cilicon** | OSS ephemeral macOS VMs on Apple silicon for self-hosted GHA runners. | ⚠️ The news about Cirrus CI shutting down comes from a competitor's blog and is unverified; Tart is OSS and does not depend on it. |
|
||||
|
||||
---
|
||||
|
||||
## 2. Постановка
|
||||
## 2. Problem statement
|
||||
|
||||
**Цель:** по сигналу (упал/флакает тест на main; новый крэш в Sentry; баг) получить **draft PR с доказательствами**, что фикс работает (до: красный N/N, после: зелёный N/N, lint, нужные схемы собираются), либо **обоснованный отказ** («не воспроизведено», «нужен человек»). Человек ревьюит и мерджит.
|
||||
**Goal:** given a signal (a test fails/flakes on main; a new crash in Sentry; a bug), produce a **draft PR with evidence** that the fix works (before: red N/N, after: green N/N, lint, required schemes build), or a **reasoned refusal** ("not reproduced", "needs a human"). A human reviews and merges.
|
||||
|
||||
**Не цели:** auto-merge; запись в Asana/чаты самим агентом; фиксы фич/UX без владельца; релизные ветки на первом этапе.
|
||||
**Non-goals:** auto-merge; the agent writing to Asana/chats; fixing features/UX without an owner; release branches in the first stage.
|
||||
|
||||
**Классы задач (по возрастанию сложности и риска):**
|
||||
1. Flaky/failing unit & integration test (чистый macOS, без секретов).
|
||||
2. Failing UI test (нужен notarized Review build, UITestCase, matrix по OS).
|
||||
3. Crash из Sentry (нужен репродьюсер; данные из внутреннего контура).
|
||||
4. Bug из Asana (нужны repro steps; наибольший риск prompt injection и архитектурных ошибок).
|
||||
**Task classes (increasing complexity and risk):**
|
||||
1. Flaky/failing unit & integration test (plain macOS, no secrets).
|
||||
2. Failing UI test (needs the notarized Review build, UITestCase, OS matrix).
|
||||
3. Crash from Sentry (needs a reproducer; data comes from the internal zone).
|
||||
4. Bug from Asana (needs repro steps; highest prompt-injection risk and risk of architectural mistakes).
|
||||
|
||||
---
|
||||
|
||||
## 3. Целевая архитектура (общая для всех вариантов)
|
||||
## 3. Target architecture (shared by all options)
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph Signals[Сигналы]
|
||||
A[CI: JUnit из main/ночных runs]
|
||||
B[Sentry: new-in-release, >=N events]
|
||||
C[Asana bug / ручной запуск]
|
||||
subgraph Signals["Signals"]
|
||||
A["CI: JUnit from main / nightly runs"]
|
||||
B["Sentry: new in release, N+ events"]
|
||||
C["Asana bug / manual trigger"]
|
||||
end
|
||||
subgraph Trusted[Доверенный контур - Linux, есть dub/Sentry]
|
||||
D[Детерминированный intake:\nфингерпринт, dedupe, eligibility,\nбюджет, scrub PII]
|
||||
E[signal.json + артефакты]
|
||||
subgraph Trusted["Trusted zone - Linux, has dub and Sentry access"]
|
||||
D["Deterministic intake:<br/>fingerprint, dedupe, eligibility,<br/>budget, PII scrub"]
|
||||
E["signal.json + artifacts"]
|
||||
end
|
||||
subgraph Mac[macOS runner - эфемерный, без внутренней сети]
|
||||
F[Agent job: analyze -> repro -> fix -> validate]
|
||||
G[evidence bundle:\nxcresult, before/after, summary.json]
|
||||
subgraph Mac["macOS runner - ephemeral, no internal network"]
|
||||
F["Agent job: analyze, repro, fix, validate"]
|
||||
G["Evidence bundle:<br/>xcresult, before/after, summary.json"]
|
||||
end
|
||||
H[Draft PR ai/fix/fingerprint\nлейбл ai-generated]
|
||||
I[Существующий PR CI:\nunit+integration+UI на Bitrise]
|
||||
J[Человек: ревью, мердж]
|
||||
K[Notifier: Mattermost / Asana-комментарий\n(детерминированный, узкий токен)]
|
||||
A-->D
|
||||
B-->D
|
||||
C-->D
|
||||
D-->E-->F-->G-->H-->I-->J
|
||||
H-->K
|
||||
I-->|падение CI|F
|
||||
H["Draft PR ai/fix/fingerprint<br/>label ai-generated"]
|
||||
I["Existing PR CI:<br/>unit + integration + UI on Bitrise"]
|
||||
J["Human: review and merge"]
|
||||
K["Notifier: Mattermost / Asana comment<br/>deterministic, narrow token"]
|
||||
A --> D
|
||||
B --> D
|
||||
C --> D
|
||||
D --> E --> F --> G --> H --> I --> J
|
||||
H --> K
|
||||
I -->|"CI failure"| F
|
||||
```
|
||||
|
||||
Принципы (из уроков Executor и security triage):
|
||||
1. **Детерминированный каркас, LLM только в узком worker-шаге.** Очередь, дедуп, бюджет, ретраи, нотификации — код, не агент.
|
||||
2. **Агент не получает ни Asana, ни Sentry, ни ClickHouse.** Вход — файлы (`signal.json`), выход — ветка `ai/fix/<fingerprint>` + `summary.json`.
|
||||
3. **Запись только draft PR в ветку `ai/*`** (GitHub App; ruleset: пушить можно только `ai/*`, `main` закрыт). Нотификации и Asana-комментарии делает отдельный детерминированный шаг.
|
||||
4. **Секреты подписи/notarization не в agent-job.** Агентский job гоняет unit/integration без секретов; UI-тесты запускаются **оркестратором** на ветке агента через существующий `macos_run_ui_test` (как для обычного PR).
|
||||
5. **Провайдер = конфиг:** `agent: claude|codex`, один prompt/skills/schema (`AGENTS.md` ↔ `CLAUDE.md`).
|
||||
6. Вход — **untrusted** (стектрейсы, bug-тексты, комментарии PR): передаём как данные, `--allowedTools` минимальный, никаких write-MCP.
|
||||
7. Всё идемпотентно: один fingerprint = одна ветка/PR; повтор не плодит дубли.
|
||||
Principles (from the Executor lessons and the security triage):
|
||||
1. **A deterministic skeleton, with the LLM only in a narrow worker step.** Queue, dedupe, budget, retries and notifications are code, not an agent.
|
||||
2. **The agent gets no Asana, Sentry or ClickHouse access.** Input is files (`signal.json`); output is a branch `ai/fix/<fingerprint>` + `summary.json`.
|
||||
3. **Write access only as a draft PR on an `ai/*` branch** (GitHub App; ruleset: only `ai/*` may be pushed, `main` is closed). Notifications and Asana comments are done by a separate deterministic step.
|
||||
4. **Signing/notarization secrets are not in the agent job.** The agent job runs unit/integration without secrets; UI tests are launched by the **orchestrator** on the agent's branch through the existing `macos_run_ui_test` (like any human PR).
|
||||
5. **Provider = config:** `agent: claude|codex`, one prompt/skills/schema (`AGENTS.md` ↔ `CLAUDE.md`).
|
||||
6. Input is **untrusted** (stack traces, bug texts, PR comments): pass it as data, minimal `--allowedTools`, no write MCPs.
|
||||
7. Everything is idempotent: one fingerprint = one branch/PR; a retry does not create duplicates.
|
||||
|
||||
---
|
||||
|
||||
## 4. Варианты исполнения (venue)
|
||||
## 4. Execution options (venue)
|
||||
|
||||
| | Описание | Плюсы | Минусы / риски | Когда |
|
||||
| | Description | Pros | Cons / risks | When |
|
||||
|---|---|---|---|---|
|
||||
| **A. GHA + Bitrise Build Hub + `claude -p` / action (рекомендуемый старт)** | Workflow в apple-browsers: `dispatch/schedule` → Linux job (intake) → macOS job на Bitrise-label с агентом. | Уже используем для CI; ничего нового не покупаем; эфемерность; артефакты и OIDC из коробки; PR-цикл как у людей; тот же Xcode, что CI (ключевое для воспроизводимости). | Атомарно (без чата) → context-transfer ZIP; 360-мин лимит; нет внутренней сети (ok — данные приходят артефактом); egress на runner не контролируем → in-VM sandbox (Seatbelt) и prompt-hardening; ⚠️ claude-action на macOS не документирован → spike. | Фазы 1–3. Классы 1, 2, 3. |
|
||||
| **B. Self-hosted Tart-раннеры (Virfield как база образов)** | Свои Mac mini + Tart + (Orchard/Tartelet/Cilicon) как GHA runner, образ с Xcode 26.4 из нашего image pipeline. | Полный контроль сети (egress allowlist → можно и внутренние данные); интерактивный доступ по SSH-туннелю; нет per-minute. | Нужно железо DDG (проект «Provision Mac» on hold; AWS EC2 Mac — дорого, 24ч минимум аренды dedicated host ⚠️); ops-нагрузка; Virfield не принят и сейчас = личный Mac с 2 VM (bus factor 1). | Фаза 4+, если A упрётся в стоимость/сеть. Virfield остаётся **dev/acceptance песочницей**. |
|
||||
| **C. Claude self-hosted environment на Mac (Tart VM на сессию)** | Runner Anthropic на macOS-хосте; триггеры: routines `POST /fire` (из Sentry/GHA), claude.ai/code. | **Resumable интерактив** с любого устройства (закрывает главный минус A); routines/API-триггер; ephemeral runner = чистый диск. | Beta, Team/Enterprise, ⚠️ macOS не подтверждён; owner-lock → нужен сервисный аккаунт; privacy/security triage Claude self-hosted уже «revisit»; зависимость от Anthropic control plane. | Фаза 4, после ответа Anthropic. Интерактивный «человек подключается». |
|
||||
| **D. Bitrise RDE + Claude** | Долгоживущая macOS-VM с SSH/VNC и MCP. | Интерактив, suspend/resume, скриншоты/VNC. | Trial 1 сессия, баг private repos, нет внутренней сети, SSH-agent forwarding (обнулить), не масштабируется, оркестратор = локальный Claude. | Разовые сложные баги / UI-репро, не конвейер. |
|
||||
| **E. Облачные Linux-агенты + CI как оракул** | Claude auto-fix PR / Seer hand-off / Codex cloud правят код без сборки; Bitrise CI валидирует. | Ноль инфраструктуры; быстро стартовать; хорош для lint/compile/очевидных тестов. | Не воспроизводят и не отлаживают flaky (нет Xcode); каждая итерация = полный CI-цикл (дорого/долго); авто-fix реагирует на CI, но не заменяет репродьюсер. | **Дополнение** к A: (1) Seer RCA как вход, (2) auto-fix на уже открытых AI-PR. |
|
||||
| **F. Bitrise AI Build Fixer** | Готовая фича Bitrise. | Ничего не писать. | ⚠️ Только build failures и, вероятно, только Bitrise CI; Pro/Enterprise; закрытая логика/валидация. | Не основа. Проверить, если есть частые build-поломки. |
|
||||
| **A. GHA + Bitrise Build Hub + `claude -p` / action (recommended start)** | A workflow in apple-browsers: `dispatch/schedule` → Linux job (intake) → macOS job on a Bitrise label with the agent. | Already used for CI; nothing new to buy; ephemeral; artifacts and OIDC out of the box; same PR loop as humans; same Xcode as CI (key for reproducibility). | Atomic (no chat) → context-transfer ZIP; 360-min cap; no internal network (fine, data arrives as an artifact); runner egress is not controlled → in-VM sandbox (Seatbelt) and prompt hardening; ⚠️ claude-action on macOS is not documented → spike. | Phases 1–3. Classes 1, 2, 3. |
|
||||
| **B. Self-hosted Tart runners (Virfield as the image base)** | Our own Mac minis + Tart + (Orchard/Tartelet/Cilicon) as GHA runners, an image with Xcode 26.4 from our image pipeline. | Full network control (egress allowlist → internal data possible); interactive access over an SSH tunnel; no per-minute cost. | Needs DDG hardware (the "Provision Mac" project is on hold; AWS EC2 Mac is expensive, with a 24 h dedicated-host minimum ⚠️); ops load; Virfield is not accepted and is currently a personal Mac with 2 VMs (bus factor 1). | Phase 4+, if A hits cost/network limits. Virfield stays a **dev/acceptance sandbox**. |
|
||||
| **C. Claude self-hosted environment on Mac (Tart VM per session)** | An Anthropic runner on a macOS host; triggers: routines `POST /fire` (from Sentry/GHA), claude.ai/code. | **Resumable interactive sessions** from any device (closes A's main gap); routines/API trigger; ephemeral runner = clean disk. | Beta, Team/Enterprise, ⚠️ macOS unconfirmed; owner lock → needs a service account; privacy/security triage for Claude self-hosted is already marked "revisit"; depends on the Anthropic control plane. | Phase 4, after Anthropic answers. Interactive "human joins". |
|
||||
| **D. Bitrise RDE + Claude** | A long-lived macOS VM with SSH/VNC and MCP. | Interactive, suspend/resume, screenshots/VNC. | Trial = 1 session, private-repo bug, no internal network, SSH agent forwarding (blank it), does not scale, orchestrator = local Claude. | One-off hard bugs / UI repro, not a pipeline. |
|
||||
| **E. Cloud Linux agents + CI as the oracle** | Claude auto-fix PR / Seer hand-off / Codex cloud edit code without building; Bitrise CI validates. | Zero infrastructure; quick to start; good for lint/compile/obvious tests. | Cannot reproduce or debug flaky tests (no Xcode); every iteration is a full CI cycle (slow/expensive); auto-fix reacts to CI but does not replace a reproducer. | **Complement** to A: (1) Seer RCA as input, (2) auto-fix on already-open AI PRs. |
|
||||
| **F. Bitrise AI Build Fixer** | A ready-made Bitrise feature. | Nothing to write. | ⚠️ Build failures only and probably Bitrise CI only; Pro/Enterprise; closed logic/validation. | Not a base. Check it if build breakages are frequent. |
|
||||
|
||||
**Рекомендация:** **A как основа + E как дополнение (Seer RCA / auto-fix)**, затем по данным выбрать **C или B** для интерактива и снижения стоимости. Virfield — для разработки/приёмки образов и промптов локально, чтобы не жечь Bitrise-минуты на отладку.
|
||||
**Recommendation:** **A as the base + E as a complement (Seer RCA / auto-fix)**, then choose **C or B** for interactivity and cost reduction based on data. Virfield is for developing/accepting images and prompts locally, so we don't burn Bitrise minutes on debugging.
|
||||
|
||||
### Claude vs Codex
|
||||
- Один harness, два backend'а: `scripts/ai-fix/run-agent.sh --agent claude|codex`. Одинаковые вход/выход (`signal.json` → `summary.json` + ветка).
|
||||
- Claude — первым (корпоративные ключи/плагины, `ddg-required-config`, OIDC federation, наши skills). Codex — как A/B-сравнение на одном eval-наборе и страховка от смены провайдера. Codex-action поддерживает macOS runner и `drop-sudo`; Codex cloud (Linux-контейнер) для Xcode не подходит ⚠️ (документация о macOS молчит).
|
||||
- Сравнивать по метрикам §8 на одинаковых задачах, не «по ощущениям».
|
||||
- One harness, two backends: `scripts/ai-fix/run-agent.sh --agent claude|codex`. Same input/output (`signal.json` → `summary.json` + branch).
|
||||
- Claude first (corporate keys/plugins, `ddg-required-config`, OIDC federation, our skills). Codex as an A/B comparison on the same eval set and insurance against a provider change. The Codex action supports a macOS runner and `drop-sudo`; Codex cloud (a Linux container) is not suitable for Xcode ⚠️ (the docs are silent about macOS).
|
||||
- Compare by the §8 metrics on identical tasks, not by feel.
|
||||
|
||||
---
|
||||
|
||||
## 5. Валидация (ядро плана)
|
||||
## 5. Validation (the core of the plan)
|
||||
|
||||
### 5.1 Лестница по типу сигнала
|
||||
### 5.1 Ladder by signal type
|
||||
|
||||
| Тип | Репро | Фикс считается валидным, если |
|
||||
| Type | Repro | A fix counts as valid if |
|
||||
|---|---|---|
|
||||
| Flaky unit/integration | `-test-iterations N` / `-run-tests-until-failure` на том же Xcode/OS, **display awake** (иначе ложные dealloc-флаки, см. 10/14). Старт — данные из CI history (rate падений). | Красный до (≥K из N), зелёный **M/M** после (M≥15–20); не маскируется (`async`); весь класс + соседи зелёные; mocks сети/настроек; `swiftlint --strict` 0; собираются схемы `macOS Browser` и `macOS Browser App Store`. |
|
||||
| Failing test на main | bisect по last-green CI sha | Причина — тест или продукт? Если продукт — фикс + тест; после — unit полностью. |
|
||||
| Failing UI test | запуск `single_test_class` на notarized Review build через существующий workflow | Зелёный на target OS; потом по запросу matrix 14/15/26; `-retry-tests-on-failure` не считается за «зелёный». |
|
||||
| Crash (Sentry) | **обязательный репродьюсер** (unit/UI/stress-тест). Нет репродьюсера → только RCA + гипотеза, без PR. | Тест красный до фикса и зелёный после; симптом из stack trace совпадает; нет новых крашей в соседних тестах. |
|
||||
| Bug (Asana) | journey-скрипт, написанный агентом | Один и тот же скрипт, запущенный на base и на fix, показывает разницу; acceptance criteria из тикета; человек подтверждает направление до PR (двухшаговый режим). |
|
||||
| Flaky unit/integration | `-test-iterations N` / `-run-tests-until-failure` on the same Xcode/OS, **display awake** (otherwise false dealloc flakes, see 10/14). Start from CI history (failure rate). | Red before (≥K of N), green **M/M** after (M ≥ 15–20); not masked (`async`); whole class + neighbours green; network/settings mocked; `swiftlint --strict` 0; schemes `macOS Browser` and `macOS Browser App Store` build. |
|
||||
| Failing test on main | bisect against the last-green CI sha | Is the cause the test or the product? If the product — fix + test; afterwards the full unit suite. |
|
||||
| Failing UI test | run `single_test_class` on the notarized Review build through the existing workflow | Green on the target OS; then the 14/15/26 matrix on request; `-retry-tests-on-failure` does not count as "green". |
|
||||
| Crash (Sentry) | **a mandatory reproducer** (unit/UI/stress test). No reproducer → RCA + hypothesis only, no PR. | The test is red before the fix and green after; the symptom matches the stack trace; no new crashes in neighbouring tests. |
|
||||
| Bug (Asana) | a journey script written by the agent | The same script run on base and on fix shows a difference; acceptance criteria from the ticket; a human confirms the direction before the PR (two-step mode). |
|
||||
|
||||
### 5.2 Обязательный evidence bundle
|
||||
`summary.json` по схеме: `signal_id`, `classification`, `root_cause`, `confidence`, `repro: {command, before: k/n fail, after: m/n pass}`, `validation: {schemes, lint, test_classes}`, `files_changed`, `outcome: fix | guard_tests_only | not_reproduced | needs_human`, `risks`, `commands_run`, плюс `.xcresult`/логи. PR-описание генерируется детерминированно из этого файла.
|
||||
### 5.2 Mandatory evidence bundle
|
||||
`summary.json` by schema: `signal_id`, `classification`, `root_cause`, `confidence`, `repro: {command, before: k/n fail, after: m/n pass}`, `validation: {schemes, lint, test_classes}`, `files_changed`, `outcome: fix | guard_tests_only | not_reproduced | needs_human`, `risks`, `commands_run`, plus `.xcresult`/logs. The PR description is generated deterministically from this file.
|
||||
|
||||
### 5.3 Защита от «агент врёт»
|
||||
- Валидацию выполняет **скрипт**, а не LLM: агент даёт команду/тест, harness сам гоняет N раз и сам считает.
|
||||
- Приём Artur'а: **единый journey-скрипт для base и fix**.
|
||||
- Мутационная проверка (как 10/14): намеренно вернуть баг → тест обязан упасть.
|
||||
- Второй агент в чистом контексте — reviewer по `REVIEW.md` (`/code-review`), результат — комментарий в PR, не блокер.
|
||||
- **Ограничение диффа:** лимит файлов/строк; изменение тестовой инфраструктуры/assertions без причины → `needs_human`; запрет ослаблять assertions и удалять тесты (как в skill `macos-uitest`).
|
||||
### 5.3 Protection against "the agent lies"
|
||||
- Validation is done by a **script**, not by the LLM: the agent supplies a command/test, the harness runs it N times and counts itself.
|
||||
- Artur's trick: **a single journey script for base and fix**.
|
||||
- Mutation check (as on 10/14): deliberately reintroduce the bug → the test must fail.
|
||||
- A second agent in a clean context as reviewer per `REVIEW.md` (`/code-review`); the result is a PR comment, not a blocker.
|
||||
- **Diff limits:** file/line caps; changes to test infrastructure/assertions without reason → `needs_human`; weakening assertions and deleting tests are forbidden (as in the `macos-uitest` skill).
|
||||
|
||||
### 5.4 Eval-набор до включения автоматики
|
||||
Золотые кейсы (известный «правильный» фикс): AddressBarTests flake (корень в 2 местах), Ask AI Chat button animation leak, DeallocationTests display-sleep crash, Fire Window leak (**ожидаемый исход = not_reproduced**), плюс 5–10 исторических фиксов из `git log`/Asana «Apple CI Failing Tests». Метрики: найден ли корень, валиден ли фикс, **не придуман ли фикс там, где его нет**. Порог включения расписания — оговорённый заранее.
|
||||
### 5.4 Eval set before enabling automation
|
||||
Golden cases (known "correct" fix): the AddressBarTests flake (root cause in 2 places), the Ask AI Chat button animation leak, the DeallocationTests display-sleep crash, the Fire Window leak (**expected outcome = not_reproduced**), plus 5–10 historical fixes from `git log` / the Asana "Apple CI Failing Tests" project. Metrics: was the root cause found, is the fix valid, **was a fix not invented where none exists**. The threshold for enabling the schedule is agreed in advance.
|
||||
|
||||
---
|
||||
|
||||
## 6. Безопасность и приватность
|
||||
## 6. Security and privacy
|
||||
|
||||
Угрозы и меры:
|
||||
- **Prompt injection** через Sentry/Asana/PR-комментарии → входы как данные; минимальный `--allowedTools`; нет write-MCP; бюджет `--max-turns`; запрет сети кроме allowlist.
|
||||
- **Exfiltration:** агент без секретов приложения; GitHub App-токен узкий (`ai/*`); OIDC вместо статических ключей; **внутренние данные только в `signal.json` после scrub** (user data, URLs, PII) в доверенном Linux job; для Windows-версии уже открыт privacy follow-up по передаче blob → завести аналогичный triage для Apple.
|
||||
- **Egress на Bitrise-раннерах** не контролируем → in-VM **Seatbelt sandbox** (Claude Code / Codex на macOS) + proxy allowlist (github.com, api.anthropic.com/api.openai.com, нужные registry/CDN); в варианте B — pf на хосте.
|
||||
- **SSH forwarding** (из triage): не пробрасывать `SSH_AUTH_SOCK`; в RDE-варианте — как в AT2/AT3.
|
||||
- **Подпись:** build-with-secrets и agent — разные jobs; UI-тесты на ветке `ai/*` идут тем же путём, что человеческий PR (ruleset + environment approvals для secrets).
|
||||
- **Kill switch:** `vars.AI_FIX_ENABLED`, дневной бюджет $, `maxActiveRuns`, allowlist классов/путей (по умолчанию не трогаем: подписи, entitlements, `Package.swift` внешних зависимостей, релизные workflows, `.github/**`).
|
||||
- **Аудит:** transcript + commands в артефакт 30 дней (по аналогии с Virfield journal).
|
||||
- Review-гейты: privacy-triage на изменение (если PR трогает pixels/privacy — Danger/`privacy-review.yml` уже есть); PR template требует Asana-ссылку → **задачу Asana создаёт/привязывает человек или детерминированный сервис**, не агент.
|
||||
- Не повторять: автономный LLM-оркестратор; запись в Asana/Discord из агента; прокси подписочных OAuth-токенов.
|
||||
Threats and mitigations:
|
||||
- **Prompt injection** via Sentry/Asana/PR comments → inputs as data; minimal `--allowedTools`; no write MCPs; `--max-turns` budget; network denied except the allowlist.
|
||||
- **Exfiltration:** the agent has no application secrets; the GitHub App token is narrow (`ai/*`); OIDC instead of static keys; **internal data only in `signal.json` after scrubbing** (user data, URLs, PII) in a trusted Linux job; for the Windows version a privacy follow-up on blob transfer is already open, so open a similar triage for Apple.
|
||||
- **Egress on Bitrise runners** is not controlled → in-VM **Seatbelt sandbox** (Claude Code / Codex on macOS) + proxy allowlist (github.com, api.anthropic.com / api.openai.com, required registries/CDNs); in option B — pf on the host.
|
||||
- **SSH forwarding** (from the triage): do not forward `SSH_AUTH_SOCK`; in the RDE option — per AT2/AT3.
|
||||
- **Signing:** build-with-secrets and agent are separate jobs; UI tests on an `ai/*` branch go the same way as a human PR (ruleset + environment approvals for secrets).
|
||||
- **Kill switch:** `vars.AI_FIX_ENABLED`, a daily $ budget, `maxActiveRuns`, an allowlist of classes/paths (by default do not touch: signing, entitlements, `Package.swift` of external dependencies, release workflows, `.github/**`).
|
||||
- **Audit:** transcript + commands kept as an artifact for 30 days (like the Virfield journal).
|
||||
- Review gates: privacy triage for changes (if a PR touches pixels/privacy — Danger/`privacy-review.yml` already exist); the PR template requires an Asana link → **the Asana task is created/linked by a human or a deterministic service**, not by the agent.
|
||||
- Do not repeat: an autonomous LLM orchestrator; writes to Asana/Discord from the agent; proxying subscription OAuth tokens.
|
||||
|
||||
Нужные согласования (параллельно с Phase 0): privacy triage + security triage на (а) Bitrise-runner + Anthropic/OpenAI API с кодом apple-browsers, (б) передачу scrubbed Sentry-данных, (в) Claude self-hosted (если C).
|
||||
Approvals needed (in parallel with Phase 0): privacy + security triage for (a) a Bitrise runner + Anthropic/OpenAI API with apple-browsers code, (b) passing scrubbed Sentry data, (c) Claude self-hosted (if C).
|
||||
|
||||
---
|
||||
|
||||
## 7. Поэтапный план
|
||||
## 7. Phased plan
|
||||
|
||||
### Phase 0 — выравнивание (≈1 нед, 2–3 чел-дня)
|
||||
- Прийти в «AI Agent Infrastructure» ([проект](https://app.asana.com/1/137249556945/project/1219113011535833)) и к Chris Clarke: зафиксировать, что apple-browsers = build-and-fix на macOS через GHA + Bitrise (то, о чём уже договорились в комментариях), а не новый стек.
|
||||
- Свести с Artur/Sebastien/Tim (flux/pstack, verification) и Bárdi (Prefect crash flow, Windows runner) — взять **их** harness/skills, не писать свой; наш вклад — macOS-специфика (Xcode, XCTest, display sleep, UITestCase).
|
||||
- Открыть privacy/security triage (§6). Заказать dedicated API key (форма из тикетов) или OIDC federation.
|
||||
- Baseline-метрики: доля retry в CI, топ-N flaky-тестов за 30 дней (из JUnit), открытые «Apple CI Failing Tests».
|
||||
- Результат: решение по venue A, список stakeholders, согласованные guardrails.
|
||||
### Phase 0 — alignment (≈1 week, 2–3 person-days)
|
||||
- Join "AI Agent Infrastructure" ([project](https://app.asana.com/1/137249556945/project/1219113011535833)) and talk to Chris Clarke: record that apple-browsers = build-and-fix on macOS via GHA + Bitrise (what the comments already agree on), not a new stack.
|
||||
- Sync with Artur/Sebastien/Tim (flux/pstack, verification) and Bárdi (Prefect crash flow, Windows runner) — take **their** harness/skills instead of writing our own; our contribution is the macOS specifics (Xcode, XCTest, display sleep, UITestCase).
|
||||
- Open the privacy/security triage (§6). Order a dedicated API key (the form from the tickets) or OIDC federation.
|
||||
- Baseline metrics: CI retry share, top-N flaky tests over 30 days (from JUnit), open "Apple CI Failing Tests".
|
||||
- Result: a decision on venue A, a stakeholder list, agreed guardrails.
|
||||
|
||||
### Phase 1 — детерминированный каркас + report-only (≈2 нед, ~8 чел-дней)
|
||||
- Workflow `ai_triage_macos.yml` (schedule + dispatch): собирает JUnit из последних main/ночных запусков (`process-test-results`, `gh api` — как `ddg-diagnose-ci-failure`), считает fail-rate, фингерпринты, дедуп, eligibility; публикует отчёт (Mattermost/job summary). **Без LLM-записи.**
|
||||
- Схемы `signal.json` / `summary.json`; `run-agent.sh` (claude|codex), allowlist путей, бюджет.
|
||||
- Eval-набор из §5.4 + harness локально на **Virfield** (дешёвая отладка промптов на образе Xcode 26.4; при необходимости собрать образ из `image_create`).
|
||||
- Spike S1 (claude/codex CLI на Bitrise-раннере: установка, auth, Seatbelt, стоимость минуты на одном тесте).
|
||||
- Exit: отчёт ежедневно; eval-harness прогоняется; S1 дал цифры времени/стоимости.
|
||||
### Phase 1 — deterministic skeleton + report-only (≈2 weeks, ~8 person-days)
|
||||
- Workflow `ai_triage_macos.yml` (schedule + dispatch): collects JUnit from recent main/nightly runs (`process-test-results`, `gh api` — like `ddg-diagnose-ci-failure`), computes failure rate, fingerprints, dedupe, eligibility; publishes a report (Mattermost/job summary). **No LLM writes.**
|
||||
- `signal.json` / `summary.json` schemas; `run-agent.sh` (claude|codex), path allowlist, budget.
|
||||
- The §5.4 eval set + harness locally on **Virfield** (cheap prompt debugging on an Xcode 26.4 image; build the image with `image_create` if needed).
|
||||
- Spike S1 (claude/codex CLI on a Bitrise runner: install, auth, Seatbelt, cost per minute on a single test).
|
||||
- Exit: a daily report; the eval harness runs; S1 gave time/cost numbers.
|
||||
|
||||
### Phase 2 — агент для тестов: draft PR по запросу (≈3 нед, ~12 чел-дней)
|
||||
- `ai_fix_test.yml` (`workflow_dispatch`: `test_id`, `agent`, `mode`): Linux intake → macOS agent job (analyze → repro N раз → fix → validate) → evidence bundle → draft PR `ai/fix/<fp>` с лейблом.
|
||||
- Человек запускает вручную (как `$auto` у Duck.ai). Дальше — существующий PR CI; UI-тесты — отдельный dispatch оркестратора.
|
||||
- A/B Claude vs Codex на eval-наборе.
|
||||
- Цикл PR-feedback: комментарий `@ai-fix` или повторный dispatch → тот же ветка + context-transfer ZIP; опционально Claude auto-fix для CI-падений на `ai/*` (вариант E).
|
||||
- Exit: ≥ порога по eval (корень найден, нет ложных фиксов); 5 реальных PR прошли ревью; средняя стоимость фикса измерена.
|
||||
### Phase 2 — test agent: draft PR on request (≈3 weeks, ~12 person-days)
|
||||
- `ai_fix_test.yml` (`workflow_dispatch`: `test_id`, `agent`, `mode`): Linux intake → macOS agent job (analyze → repro N times → fix → validate) → evidence bundle → draft PR `ai/fix/<fp>` with a label.
|
||||
- A human triggers it manually (like `$auto` in Duck.ai). Then the existing PR CI; UI tests via a separate orchestrator dispatch.
|
||||
- A/B Claude vs Codex on the eval set.
|
||||
- PR-feedback loop: an `@ai-fix` comment or a repeat dispatch → same branch + context-transfer ZIP; optionally Claude auto-fix for CI failures on `ai/*` (option E).
|
||||
- Exit: ≥ the threshold on the eval (root cause found, no false fixes); 5 real PRs passed review; average cost per fix measured.
|
||||
|
||||
### Phase 3 — крэши: Sentry → proposal → draft PR (≈3 нед, ~12 чел-дней)
|
||||
- Pre-fetch в доверенном Linux job (Sentry MCP/API; репозитории `apple-ios`, `apple-macos`; фильтр `firstRelease`, `app_version`, события ≥N; переиспользовать логику `ddg-sentry-report`) → scrub → `signal.json`.
|
||||
- Параллельно **trial Seer** на `apple-macos` в режиме «Stop after Solution» (если approve privacy): использовать RCA как дополнительный вход/бенчмарк; сравнить с нашим агентом.
|
||||
- Двухшаговый режим по умолчанию: proposal (root cause + репродьюсер-тест + направление) → комментарий владельцу → после «да» агент делает PR. После накопления доверия (как в Windows-кейсе) — авто draft PR для краш-классов с воспроизведённым тестом.
|
||||
- Exit: ≥X краш-находок с репродьюсером; доля принятых владельцами направлений.
|
||||
### Phase 3 — crashes: Sentry → proposal → draft PR (≈3 weeks, ~12 person-days)
|
||||
- Pre-fetch in a trusted Linux job (Sentry MCP/API; projects `apple-ios`, `apple-macos`; filters `firstRelease`, `app_version`, events ≥ N; reuse the `ddg-sentry-report` logic) → scrub → `signal.json`.
|
||||
- In parallel a **Seer trial** on `apple-macos` in "Stop after Solution" mode (if privacy approves): use the RCA as an extra input/benchmark; compare with our agent.
|
||||
- Two-step mode by default: proposal (root cause + reproducer test + direction) → comment to the owner → after a "yes" the agent makes the PR. After trust accumulates (as in the Windows case) — automatic draft PRs for crash classes with a reproduced test.
|
||||
- Exit: ≥ X crash findings with a reproducer; share of directions accepted by owners.
|
||||
|
||||
### Phase 4 — автоматизация и интерактив (≈4–6 нед, по результатам)
|
||||
- Включить расписание (ночной запуск top-K eligible), лимиты/бюджет, дашборд метрик.
|
||||
- Выбор интерактива по данным: **C** (если Anthropic подтвердит macOS), **B** (если стоимость Bitrise-минут/сеть упрутся), или оставить D для редких случаев.
|
||||
- Багфиксы из Asana (класс 4) — только после доказанной надёжности на 1–3 и в связке с flux/pstack.
|
||||
- Решение о релизных ветках — отдельно.
|
||||
### Phase 4 — automation and interactivity (≈4–6 weeks, depending on results)
|
||||
- Enable the schedule (nightly top-K eligible), limits/budget, a metrics dashboard.
|
||||
- Choose interactivity by data: **C** (if Anthropic confirms macOS), **B** (if Bitrise minutes cost/network become a problem), or keep D for rare cases.
|
||||
- Asana bug fixes (class 4) only after proven reliability on 1–3 and together with flux/pstack.
|
||||
- A decision on release branches is separate.
|
||||
|
||||
Ориентировочно до Phase 3 включительно: ~**8–10 недель календарно, ~35–45 чел-дней** (оценка грубая; сильно зависит от triage и результатов S1).
|
||||
Rough estimate through Phase 3: ~**8–10 weeks elapsed, ~35–45 person-days** (rough; depends heavily on triage and the S1 results).
|
||||
|
||||
---
|
||||
|
||||
## 8. Метрики и критерии остановки
|
||||
## 8. Metrics and stop criteria
|
||||
|
||||
- **Acceptance rate:** доля AI-PR, вмёрдженных без существенной переделки.
|
||||
- **Precision:** доля фиксов, прошедших эксплуатацию без регрессии; доля `not_reproduced`, которые на самом деле были реальными (false negative).
|
||||
- **Cost per merged fix** (токены + Bitrise-минуты), **time-to-PR**, **reviewer-minutes per PR**.
|
||||
- **Flaky rate / CI retry rate** в main до/после; для крэшей — CPMN/crash-free дельта по затронутым сигнатурам.
|
||||
- Стоп-условия: acceptance < порога два цикла подряд; любой инцидент утечки; бюджет превышен → автоматический kill switch.
|
||||
- **Acceptance rate:** share of AI PRs merged without major rework.
|
||||
- **Precision:** share of fixes that survived production without regression; share of `not_reproduced` outcomes that were actually real (false negatives).
|
||||
- **Cost per merged fix** (tokens + Bitrise minutes), **time-to-PR**, **reviewer-minutes per PR**.
|
||||
- **Flaky rate / CI retry rate** on main before/after; for crashes — the CPMN/crash-free delta for affected signatures.
|
||||
- Stop conditions: acceptance below threshold two cycles in a row; any leak incident; budget exceeded → automatic kill switch.
|
||||
|
||||
---
|
||||
|
||||
## 9. Риски
|
||||
## 9. Risks
|
||||
|
||||
| Риск | Митигирование |
|
||||
| Risk | Mitigation |
|
||||
|---|---|
|
||||
| Агент «чинит» симптом (ослабляет assertion, добавляет sleep/retry) | Запрет в prompt + diff-политика + harness сам считает N/N + мутационная проверка |
|
||||
| Ложные фиксы flaky (сломали тест, а не продукт) | Классификатор «test bug vs product bug» + review-агент + owner |
|
||||
| Display sleep/окружение даёт другое поведение, чем CI | Тот же образ/Xcode, `caffeinate`/display awake, сравнение с CI-историей |
|
||||
| Xcode-расхождение (26.4 vs 27) | Образ строго по `.xcode-version`; Virfield-профиль 26.4 |
|
||||
| Стоимость Bitrise-минут/токенов | Бюджеты, top-K, ночной режим, Claude-sonnet по умолчанию, кэш (Bitrise build cache action) |
|
||||
| Prompt injection через Sentry/Asana | Scrub + data-only + минимальные tools + sandbox |
|
||||
| Дублирование чужих усилий (flux/pstack/Prefect/Bug Squisher) | Phase 0, общий harness, наш вклад — macOS-слой |
|
||||
| Бесконтрольный рост PR'ов | Один fingerprint = один PR, лимит открытых AI-PR, stale-auto-close |
|
||||
| Зависимость от личной инфраструктуры (Virfield на одном Mac) | Virfield не в production-пути |
|
||||
| Beta-фичи Anthropic (self-hosted, routines `experimental` header) | Не ставим на критический путь до GA |
|
||||
| The agent fixes the symptom (weakens an assertion, adds a sleep/retry) | Prompt prohibition + diff policy + the harness counts N/N itself + mutation check |
|
||||
| False flaky fixes (the test was broken, not the product) | "test bug vs product bug" classifier + review agent + owner |
|
||||
| Display sleep/environment behaves differently from CI | Same image/Xcode, `caffeinate`/display awake, compare with CI history |
|
||||
| Xcode mismatch (26.4 vs 27) | Image strictly per `.xcode-version`; a 26.4 Virfield profile |
|
||||
| Bitrise minutes/token cost | Budgets, top-K, nightly mode, a Sonnet-class model by default, caching (Bitrise build cache action) |
|
||||
| Prompt injection via Sentry/Asana | Scrub + data-only + minimal tools + sandbox |
|
||||
| Duplicating others' efforts (flux/pstack/Prefect/Bug Squisher) | Phase 0, a shared harness, our contribution is the macOS layer |
|
||||
| Uncontrolled PR growth | One fingerprint = one PR, a cap on open AI PRs, stale auto-close |
|
||||
| Dependence on personal infrastructure (Virfield on one Mac) | Virfield is not on the production path |
|
||||
| Anthropic beta features (self-hosted, routines `experimental` header) | Not on the critical path until GA |
|
||||
|
||||
---
|
||||
|
||||
## 10. Открытые вопросы (нужны решения/данные)
|
||||
## 10. Open questions (need decisions/data)
|
||||
|
||||
1. Подтвердить venue A: кто DRI по macOS в AI Agent Infrastructure и можно ли выделить runner-label Bitrise под agent-jobs.
|
||||
2. ⚠️ S1: работает ли `claude -p`/claude-code-action на Bitrise macOS runner (auth, Seatbelt, сеть)? Сколько стоит минута/задача?
|
||||
3. ⚠️ Ответ Anthropic: macOS runner для self-hosted environments — сроки и поддержка.
|
||||
4. Privacy/security: можно ли отправлять scrubbed Sentry-стектрейсы и код apple-browsers агенту на Bitrise-раннере (OpenAI — отдельное согласование).
|
||||
5. Где живёт конвейер: apple-browsers (`.github/workflows`) vs отдельный репозиторий + общий flux-плагин.
|
||||
6. Кто владеет Asana-привязкой PR (шаблон требует ссылку на Asana): детерминированный сервис или человек.
|
||||
7. Android: уточнить, есть ли отдельный проект (не нашёлся) — возможно, паттерн можно просто переиспользовать.
|
||||
8. Нужен ли пилотный режим «только iOS/macOS unit-flaky» перед крэшами (рекомендую да).
|
||||
1. Confirm venue A: who is the DRI for macOS in AI Agent Infrastructure, and can a Bitrise runner label be allocated for agent jobs.
|
||||
2. ⚠️ S1: do `claude -p` / claude-code-action work on a Bitrise macOS runner (auth, Seatbelt, network)? What does a minute/task cost?
|
||||
3. ⚠️ Anthropic's answer: a macOS runner for self-hosted environments — timing and support.
|
||||
4. Privacy/security: may scrubbed Sentry stack traces and apple-browsers code be sent to an agent on a Bitrise runner (OpenAI needs a separate approval).
|
||||
5. Where the pipeline lives: apple-browsers (`.github/workflows`) vs a separate repo + a shared flux plugin.
|
||||
6. Who owns the Asana linking of the PR (the template requires an Asana link): a deterministic service or a human.
|
||||
7. Android: clarify whether a separate project exists (none found) — maybe the pattern can simply be reused.
|
||||
8. Whether to run a pilot with "iOS/macOS unit flaky only" before crashes (I recommend yes).
|
||||
|
||||
---
|
||||
|
||||
## 11. Первые конкретные шаги (на эту неделю)
|
||||
## 11. First concrete steps (this week)
|
||||
|
||||
1. Написать короткий комментарий/таск в AI Agent Infrastructure с этим планом и вопросами 1–3 (без дублирования проектов).
|
||||
2. Собрать eval-набор (4–5 кейсов из 10/14 + 5 из истории) и описать «ожидаемый исход».
|
||||
3. Локально на Virfield (или на dev-Mac) прогнать `claude -p` по одному кейсу с harness'ом «N× до/после» — получить baseline качества и стоимости до любых CI-интеграций.
|
||||
4. Сделать spike S1 на Bitrise runner в отдельной ветке (workflow_dispatch, один тест).
|
||||
5. Подготовить draft privacy/security triage для (а) и (б).
|
||||
1. Write a short comment/task in AI Agent Infrastructure with this plan and questions 1–3 (without duplicating projects).
|
||||
2. Assemble the eval set (4–5 cases from 10/14 + 5 from history) and describe the "expected outcome" for each.
|
||||
3. Locally on Virfield (or a dev Mac) run `claude -p` on one case with the "N× before/after" harness — get a baseline of quality and cost before any CI integration.
|
||||
4. Do spike S1 on a Bitrise runner in a separate branch (workflow_dispatch, a single test).
|
||||
5. Prepare a draft privacy/security triage for (a) and (b).
|
||||
|
||||
Связанные: [[work/wiki/apple-browsers/ci-pipeline]], [[work/wiki/apple-browsers/vm-ui-testing]], [[personal/projects/virfield]], [[personal/projects/personal-os/executor-v2-redesign]], [[personal/projects/personal-os/executor-security-analysis]], [[personal/projects/personal-os/personal-os-failed-approaches]], [[work/projects/macos-tests-worktrees-2026-10-14]], [[Research/Isolation of Agent Execution - OS and Container Level]].
|
||||
Related: [[work/wiki/apple-browsers/ci-pipeline]], [[work/wiki/apple-browsers/vm-ui-testing]], [[personal/projects/virfield]], [[personal/projects/personal-os/executor-v2-redesign]], [[personal/projects/personal-os/executor-security-analysis]], [[personal/projects/personal-os/personal-os-failed-approaches]], [[work/projects/macos-tests-worktrees-2026-10-14]], [[Research/Isolation of Agent Execution - OS and Container Level]].
|
||||
Reference in new issue
Block a user