Receptury natywne: iOS i Android
Natywny rozwój aplikacji na iOS i Androida z agentem AI działa wtedy, gdy każda platforma ma jeden skrypt, który buduje aplikację, uruchamia testy na przypiętym symulatorze lub emulatorze i zapisuje wyniki jako dowody. Claude Code, Codex i Cursor iterują względem tego skryptu, a serwer MCP, taki jak MobileBuildMCP lub mobile-mcp, pokazuje agentowi działającą aplikację.
Prosisz agenta o nowy ekran ustawień w SwiftUI. Agent pisze czysty kod w Swifcie, ogłasza „gotowe”, a projekt się nie buduje, bo nowy plik nigdy nie trafił do targetu Xcode. Po stronie Androida agent przy każdej zmianie odpala ./gradlew clean build, czeka minutami na wynik i wkleja do własnego kontekstu tysiące linii logu Gradle. Żaden z nich nie spojrzał na ekran, który zbudował. Ta strona zamyka te trzy luki: informację zwrotną z builda, szybkość i dowód.
Co daje projekt natywny przygotowany pod agenta
Dział zatytułowany „Co daje projekt natywny przygotowany pod agenta”- Dwa skrypty do skopiowania,
scripts/ios-check.shiscripts/android-check.sh. Każdy uruchamia przypięte urządzenie, odpala testy, wypisuje agentowi krótkie podsumowanie i zapisuje pełne dowody wbuild/evidence/. - Blok instrukcji do
AGENTS.md,CLAUDE.mdlub reguły Cursora, który definiuje „gotowe” jako „skrypt zakończył się kodem 0”. - Zweryfikowane komendy instalacji dwóch mobilnych serwerów MCP oraz wtyczek Codeksa dla iOS i Androida, osobno dla każdego narzędzia.
- Zasady skracające wewnętrzną pętlę agenta: wąski wybór testów, rozgrzane urządzenia i cache.
- Receptury na ekran w SwiftUI, ekran w Jetpack Compose i reprodukcję crasha, każda zakończona dowodem z testów UI zamiast diffem do przeczytania.
Dlaczego aplikacje natywne potrzebują innej pętli agenta
Dział zatytułowany „Dlaczego aplikacje natywne potrzebują innej pętli agenta”Agent webowy dostaje tanią informację zwrotną: serwer deweloperski przeładowuje się w sekundę, a przeglądarkowy MCP pokazuje stronę. Projekt natywny daje tę informację wolniej, z trzech powodów:
- Plik projektu jest częścią builda. Xcode decyduje, co się kompiluje, na podstawie przynależności do targetu w
project.pbxproj, a Gradle na podstawie układu modułów. Agent, który zapisze poprawny plik w złym miejscu, dostaje błąd builda albo, co gorsze, plik, który po cichu nigdy się nie kompiluje. - Buildy są wolne i głośne. Czysty
xcodebuildalbo build Gradle wypisuje tysiące linii. Wpuszczone do kontekstu agenta kosztują tokeny i wypychają z pola widzenia instrukcje zadania. - UI działa w osobnym procesie. Symulator i emulator to osobne programy. Bez runnera testów albo serwera MCP agent nie ma jak sprawdzić, czy ekran się renderuje. Ty też nie.
Dlatego receptury na tej stronie nie zaczynają się od promptu z funkcją. Zaczynają się od dania agentowi jednej, cichej i niezawodnej komendy na platformę, a agenta ocenia się po tym, co ta komenda udowadnia.
Skonfiguruj pętlę: build, testy, dowody
Dział zatytułowany „Skonfiguruj pętlę: build, testy, dowody”-
Przypnij jeden symulator i jeden emulator. Dostępne urządzenia wypiszesz przez
xcrun simctl list devices availableiemulator -list-avds(binarkaemulatorleży w$ANDROID_HOME/emulator). Wybierz po jednym i wpisz ich nazwy do skryptów poniżej. Przypięte urządzenie oznacza, że czerwony test mówi coś o twoim kodzie, a nie o tym, który telefon agent akurat uruchomił. -
Dodaj
scripts/ios-check.sh. Skrypt trzyma DerivedData w repozytorium, zapisuje pełny log do pliku i wypisuje tylko linie potrzebne agentowi:#!/usr/bin/env bash# scripts/ios-check.sh — build, test and collect evidence on one pinned simulator.# Usage: scripts/ios-check.sh [TestTarget/TestClass ...] (no argument = all tests)set -euo pipefailSCHEME="${SCHEME:-App}"SIM="${SIM:-iPhone 17}"OUT="build/evidence/ios"rm -rf "$OUT" && mkdir -p "$OUT"ONLY=()for t in "$@"; do ONLY+=("-only-testing:$t"); donexcrun simctl bootstatus "$SIM" -b >/dev/null # boots the simulator if needed, waits until readyset +excodebuild test \-scheme "$SCHEME" \-destination "platform=iOS Simulator,name=$SIM" \-derivedDataPath build/DerivedData \-resultBundlePath "$OUT/tests.xcresult" \${ONLY[@]+"${ONLY[@]}"} > "$OUT/xcodebuild.log" 2>&1STATUS=$?set -excrun xcresulttool get test-results summary --path "$OUT/tests.xcresult" > "$OUT/summary.json" 2>/dev/null || truegrep -E "error:|\*\* (BUILD|TEST) (SUCCEEDED|FAILED)|failed" "$OUT/xcodebuild.log" | tail -40echo "exit=$STATUS evidence=$OUT"exit $STATUSZapis
${ONLY[@]+...}jest istotny: macOS nadal dostarcza Basha 3.2, w którym pusta tablica przyset -uprzerywa skrypt.xcresulttool get test-resultswymaga Xcode 16 lub nowszego. -
Dodaj
scripts/android-check.sh. Skrypt korzysta z już działającego emulatora, czyści logcat, żeby log obejmował tylko ten przebieg, i kopiuje raporty testów Gradle do katalogu z dowodami:#!/usr/bin/env bash# scripts/android-check.sh — unit + instrumented tests on one pinned emulator, evidence collected.# Usage: scripts/android-check.sh [com.example.app.SomeUiTest] (no argument = all tests)set -euo pipefailAVD="${AVD:-Pixel_8_API_35}"MODULE="${MODULE:-app}"OUT="build/evidence/android"rm -rf "$OUT" && mkdir -p "$OUT"if ! adb get-state >/dev/null 2>&1; thenemulator -avd "$AVD" -no-window -no-audio -no-boot-anim > "$OUT/emulator.log" 2>&1 &adb wait-for-deviceuntil [ "$(adb shell getprop sys.boot_completed | tr -d '\r')" = "1" ]; do sleep 2; donefiadb logcat -cFILTER=()if [ $# -gt 0 ]; then FILTER=("-Pandroid.testInstrumentationRunnerArguments.class=$1"); fiset +e./gradlew ":$MODULE:testDebugUnitTest" ":$MODULE:connectedDebugAndroidTest" \${FILTER[@]+"${FILTER[@]}"} > "$OUT/gradle.log" 2>&1STATUS=$?set -eadb logcat -d > "$OUT/logcat.txt"cp -R "$MODULE/build/reports" "$OUT/reports" 2>/dev/null || truecp -R "$MODULE/build/outputs/androidTest-results" "$OUT/androidTest-results" 2>/dev/null || truegrep -E "FAILED|BUILD (SUCCESSFUL|FAILED)|e: " "$OUT/gradle.log" | tail -40echo "exit=$STATUS evidence=$OUT"exit $STATUSOpcjonalny argument zawęża do jednej klasy tylko testy instrumentacyjne. Testy jednostkowe zawsze idą w całości, bo są tanie.
-
Przekaż agentowi zasady. Wklej ten blok do
AGENTS.mddla Codeksa, doCLAUDE.mddla Claude Code albo do reguły projektu w Cursorze. Claude Code czytaAGENTS.md, gdy w repozytorium nie maCLAUDE.md(od v2.1.277, na kanale wydańlatestwedług stanu na 2026-09-26; użytkownicy kanałustablenadal potrzebują plikuCLAUDE.md, który odsyła doAGENTS.md), więc jeden plik może obsłużyć oba CLI. Jeśli nie pisałeś jeszcze pliku instrukcji, zacznij od artykułu AGENTS.md i CLAUDE.md:## Native build and test loop- iOS: run `scripts/ios-check.sh`, optionally with a test class such as `AppUITests/SettingsUITests`.Never call `xcodebuild` without `-derivedDataPath build/DerivedData`.- Android: run `scripts/android-check.sh`, optionally with a fully qualified test class.Never run `./gradlew clean` unless the user asks.- A task is done only when the relevant script prints `exit=0`. Quote its summary lines in your final message.- Every control a test touches gets a stable ID: `.accessibilityIdentifier(...)` in SwiftUI,`Modifier.testTag(...)` in Compose. Never locate elements by visible text alone.- Never edit snapshot references (`__Snapshots__/`, `src/test/snapshots/`) or weaken an existingassertion to make a test pass. Stop and report the failure instead.- New Swift files go inside an existing synchronized folder; do not edit `project.pbxproj` by hand. -
Zacommituj skrypty i uruchom je raz samodzielnie. Skrypt, który pada na czystym checkoucie, uczy agenta, że można go ignorować. Uruchom oba, zajrzyj do
build/evidence/i dopiszbuild/do.gitignore, jeśli jeszcze go tam nie ma.
Podłącz agenta do symulatora i emulatora
Dział zatytułowany „Podłącz agenta do symulatora i emulatora”Testy dowodzą zachowania, które opisałeś. Do pracy eksploracyjnej (czy ekran wygląda dobrze, co się stanie po dotknięciu tutaj) agent musi widzieć urządzenie i nim sterować. Obsługują to dwa serwery MCP. Jeśli nigdy nie dodawałeś serwera MCP, przeczytaj najpierw wprowadzenie do MCP:
- MobileBuildMCP (wcześniej XcodeBuildMCP, utrzymywany przez Sentry) buduje, uruchamia i debuguje projekty iOS i macOS na symulatorach i urządzeniach. Wymaga macOS 14.5+ i Xcode 16+. Najczęściej używane narzędzie to
build_run_sim: buduje schemat, instaluje aplikację na uruchomionym symulatorze, startuje ją i przechwytuje logi. - mobile-mcp (Mobile Next) steruje symulatorami iOS, emulatorami Androida i fizycznymi urządzeniami przez jeden zestaw narzędzi:
mobile_list_elements_on_screendo zrzutu drzewa dostępności,mobile_take_screenshot,mobile_click_on_screen_at_coordinates,mobile_get_device_logs,mobile_get_crashi inne. Wersja 1.0.5 udostępnia 32 narzędzia.
Popularność: 2026-09-26 MobileBuildMCP miał 6,4 tys. gwiazdek na GitHubie i pakiet npm mobilebuildmcp 2.7.1 (opublikowany 2026-09-23); 2026-09-28 mobile-mcp miał 7958 gwiazdek na GitHubie i pakiet npm @mobilenext/mobile-mcp 1.0.5 (opublikowany 2026-09-23). Źródła: repozytoria getsentry/MobileBuildMCP i mobile-next/mobile-mcp na GitHubie oraz rejestr npm.
Dodaj serwery z terminala. Domyślny zakres local nie wpuszcza ich do sesji współpracowników, dopóki nie udostępnisz ich przez -s project:
claude mcp add mobilebuild -- npx -y mobilebuildmcp@latest mcpclaude mcp add mobile-mcp -- npx -y @mobilenext/mobile-mcp@latestAplikacja desktopowa Claude Code na macOS ma też panel iOS Simulator (beta od lipca 2026), więc symulator widzisz obok sesji. Żeby agent nie ruszał referencji snapshotów, dodaj reguły deny do .claude/settings.json:
{ "permissions": { "deny": [ "Edit(**/__Snapshots__/**)", "Edit(**/src/test/snapshots/**)" ] }}Dodaj serwery przez codex mcp add (-- oddziela komendę serwera):
codex mcp add mobilebuild -- npx -y mobilebuildmcp@latest mcpcodex mcp add mobile-mcp -- npx -y @mobilenext/mobile-mcp@latestBuild na symulatorze potrafi trwać dłużej niż domyślny limit czasu narzędzia MCP. Dokumentacja klientów MobileBuildMCP każe użytkownikom Codeksa podnieść go osobno dla serwera w ~/.codex/config.toml, bo Codex ignoruje tool_timeout_sec ustawione na najwyższym poziomie dla wywołań MCP:
[mcp_servers.mobilebuild]command = "npx"args = ["-y", "mobilebuildmcp@2.7.1", "mcp"] # pinned, like the committed configstool_timeout_sec = 600Oficjalny marketplace wtyczek Codeksa zawiera też build-ios-apps (skille takie jak ios-debugger-agent, swiftui-ui-patterns i swiftui-performance-audit, z konfiguracją XcodeBuildMCP) oraz test-android-apps (skille android-emulator-qa i android-performance); sprawdzone w openai/plugins 2026-09-26. Zainstalujesz je z TUI: uruchom /plugins i wyszukaj po nazwie.
Dwa szczegóły z plików wtyczek (w obu wersja 0.1.2): build-ios-apps uruchamia serwer pod starą nazwą pakietu, xcodebuildmcp@latest, z czterema włączonymi workflow (simulator,ui-automation,debugging,logging) i potrafi wyświetlić obraz symulatora w przeglądarce wbudowanej w Codeksa. Jeśli dodałeś też mobilebuild ręcznie, wyłącz jeden z nich, bo inaczej agent widzi każde narzędzie builda dwa razy.
Dodaj plik .cursor/mcp.json w zakresie projektu, żeby każdy, kto otworzy repozytorium, dostał te same serwery:
{ "mcpServers": { "mobilebuild": { "command": "npx", "args": ["-y", "mobilebuildmcp@2.7.1", "mcp"] }, "mobile-mcp": { "command": "npx", "args": ["-y", "@mobilenext/mobile-mcp@1.0.5"] } }}Wersje są przypięte, bo ten plik trafia do repozytorium: z @latest następna sesja każdej osoby w zespole po cichu uruchamia to, co opublikowano w nocy. Podbijaj wersje w pull requeście, jak każdą inną zależność.
Agent Cursora uruchamia scripts/ios-check.sh i scripts/android-check.sh w swoim terminalu jak każdą inną komendę. Wskazówki mobilne specyficzne dla Cursora znajdziesz w artykule programowanie mobilne w Cursorze.
Który wybrać. MobileBuildMCP, gdy problemem jest sam build w Xcode (schematy, podpisywanie, makro w Swifcie, crash przy starcie). mobile-mcp, gdy problemem jest zachowanie na ekranie, na dowolnej platformie. Włączaj tylko serwer potrzebny w danej sesji: definicja każdego udostępnionego narzędzia zajmuje kontekst w każdej turze. mobile-mcp 1.0.5 udostępnia od razu wszystkie 32 narzędzia. MobileBuildMCP domyślnie wystawia tylko workflow simulator; poszerzaj go zmienną środowiskową MOBILEBUILDMCP_ENABLED_WORKFLOWS (na przykład simulator,ui-automation,debugging,logging) dopiero wtedy, gdy zadanie wymaga automatyzacji UI albo debuggera. W Claude Code wygląda to tak: claude mcp add mobilebuild -e MOBILEBUILDMCP_ENABLED_WORKFLOWS=simulator,ui-automation -- npx -y mobilebuildmcp@latest mcp. Wtyczka Codeksa build-ios-apps ustawia zamiast tego XCODEBUILDMCP_ENABLED_WORKFLOWS tylko dlatego, że uruchamia stary pakiet xcodebuildmcp@latest; mobilebuildmcp 2.7.1 ignoruje tę nazwę.
Praca w Xcode zamiast w terminalu. Dokumentacja klientów MobileBuildMCP (sprawdzona 2026-09-26) opisuje, jak Xcode 26.3 i nowsze wersje uruchamiają agentów Codex i Claude Code w Xcode Settings > Intelligence. Ci agenci startują z okrojonym PATH, więc serwer uruchamiany przez npx często się nie podnosi; dokumentacja opakowuje komendę w /bin/zsh -lc z Homebrew i nvm w PATH. Skrypty kontrolne z tej strony działają tak samo w obu miejscach.
Jak zmieścić czas natywnego builda w pętli agenta
Dział zatytułowany „Jak zmieścić czas natywnego builda w pętli agenta”Wolna pętla zmienia zachowanie agenta: między buildami zbiera wiele edycji naraz, a błąd ma potem wiele możliwych przyczyn. Utrzymuj trzy pętle, każdą z własnym kosztem:
| Pętla | Co się uruchamia | Komenda | Kiedy agent ją odpala |
|---|---|---|---|
| Wewnętrzna | Testy jednostkowe zmienionego modułu (Swift Testing lub XCTest; JUnit) | xcodebuild test ... -only-testing:AppTests/CartTests · ./gradlew :feature:cart:testDebugUnitTest --tests '*CartViewModelTest' | Po każdej edycji |
| Środkowa | Jedna klasa testów UI na przypiętym urządzeniu | scripts/ios-check.sh AppUITests/CartUITests · scripts/android-check.sh com.example.cart.CartScreenTest | Zanim ogłosi „gotowe” |
| Zewnętrzna | Wszystkie zestawy, weryfikacja snapshotów, obie platformy | Te same dwa skrypty bez argumentów, w CI | Przy każdym pull requeście |
Zasady, które utrzymują szybką pętlę wewnętrzną i środkową:
- Nie czyść odruchowo. Zapisz agentowi w pliku instrukcji, że
cleanjest zakazany, chyba że o to poprosisz. Większość odruchów „naprawmy to czystym buildem” bierze się z nieaktualnego DerivedData albo cache Gradle, a lista awarii poniżej podaje dla nich punktową naprawę. - Trzymaj urządzenia rozgrzane. Oba skrypty uruchamiają urządzenie tylko wtedy, gdy nie działa. Zostaw symulator i emulator włączone przez całą sesję.
- Włącz cache Gradle. Dodaj
org.gradle.caching=trueiorg.gradle.configuration-cache=truedogradle.properties. Configuration cache pomija ponowne wykonywanie skryptów builda, gdy nic się w nich nie zmieniło. - Rozdziel build i test na iOS przy powtórkach.
xcodebuild build-for-testing, a potemxcodebuild test-without-buildingponawia niestabilny test bez rekompilacji. Używaj tego tylko do diagnozy: po zmianie kodu agent musi zbudować projekt od nowa. - Zmierz, zanim zaczniesz stroić.
xcodebuild -showBuildTimingSummarypokazuje, gdzie poszedł czas, a./gradlew --profilezapisuje lokalny raport HTML wbuild/reports/profile/. Poproś agenta, żeby przeczytał raport i zaproponował jedną zmianę, a potem zmierz ponownie.
Receptura: ekran w SwiftUI z dowodem z testów UI
Dział zatytułowany „Receptura: ekran w SwiftUI z dowodem z testów UI”Poniższy prompt najpierw prosi o zachowanie zapisane jako testy, a metą czyni kod wyjścia skryptu.
Zrzuty ekranu trafiają do build/evidence/ios/tests.xcresult, obok testu, który je wykonał. Kod załącznika, który agent powinien wygenerować, wygląda tak:
let app = XCUIApplication()
func snap(_ name: String) { let shot = XCTAttachment(screenshot: app.screenshot()) shot.name = name shot.lifetime = .keepAlways // keep it even when the test passes add(shot)}
func testEnablingReminderEnablesTimePicker() { app.launchArguments = ["-uiTesting"] app.launch() app.buttons["settings.open"].tap() snap("1-settings-open") app.switches["settings.reminderToggle"].tap() snap("2-reminder-on") XCTAssertTrue(app.datePickers["settings.reminderTime"].isEnabled) snap("3-time-picker-enabled")}Sprawdź jedną rzecz, którą agent często psuje: argument startowy -uiTesting musi zmieniać zachowanie aplikacji (zestaw UserDefaults w pamięci, brak onboardingu). Jeśli nic w aplikacji go nie czyta, test UI zależy od stanu zostawionego przez poprzedni przebieg i będzie niestabilny.
Receptura: ekran w Jetpack Compose z dowodem z testów UI
Dział zatytułowany „Receptura: ekran w Jetpack Compose z dowodem z testów UI”Poprawny test w Compose szuka węzłów po tagu, nie po tekście, więc zmiana copy go nie psuje:
@get:Rule val composeRule = createAndroidComposeRule<MainActivity>()
@Testfun incrementUpdatesTotal() { composeRule.onNodeWithTag("cart.line.0.increment").performClick() composeRule.onNodeWithTag("cart.total").assertTextEquals("Total: 24.00")}Dowód wizualny na Androidzie bez emulatora da biblioteka testów zrzutów ekranu, na przykład Paparazzi: ./gradlew :app:recordPaparazziDebug nagrywa obrazy referencyjne, a ./gradlew :app:verifyPaparazziDebug pada, gdy renderowanie się zmieni. Na iOS tę samą rolę pełni swift-snapshot-testing z assertSnapshot(of: view, as: .image). Obie biblioteki nagrywają referencje przy pierwszym uruchomieniu, więc te referencje przejrzyj i zacommituj sam.
Receptura: odtwórz crasha, którego agent nie widzi
Dział zatytułowany „Receptura: odtwórz crasha, którego agent nie widzi”Raport crasha ze stack trace’em to specyfikacja czerwonego testu. Przekaż go agentowi z podłączonym serwerem urządzeń:
Kolejność ma znaczenie. Test, który przed poprawką był czerwony, a po niej jest zielony, to dowód. Poprawka bez wcześniejszego czerwonego testu to zgadywanie, które akurat się skompilowało.
Jak zweryfikować natywną pracę agenta bez czytania każdej linii
Dział zatytułowany „Jak zweryfikować natywną pracę agenta bez czytania każdej linii”Skrypty zamieniają każdą zmianę w ten sam zestaw artefaktów, a przegląd zaczyna się od tego zestawu, nie od diffa:
| Dowód | Gdzie leży | Co sprawdza recenzent |
|---|---|---|
| Werdykt testów | Ostatnie linie wyjścia skryptu, summary.json, JUnit XML w androidTest-results/ | exit=0 na obu platformach; liczba testów rośnie, nigdy nie maleje |
| Zrzuty ekranu UI | Załączniki w tests.xcresult (otwierane w Xcode), obrazy Paparazzi lub snapshot-testing | Ekrany zgadzają się ze specyfikacją; różnice w snapshotach są zamierzone |
| Logi z działania | xcodebuild.log, logcat.txt | Brak nowych crashy, ANR-ów i zalewu błędów podczas testów UI |
| Zmiany w testach | Pliki testów w diffie | Nowe testy sprawdzają kryteria akceptacji; żadna asercja nie została osłabiona, żaden snapshot nie został przenagrany bez powodu |
Trzy zasady sprawiają, że można temu ufać:
-
CI uruchamia te same skrypty. Zielony wynik w sesji agenta to deklaracja; ten sam skrypt w CI na czystym runnerze macOS to dowód. Trzymaj skrypty w repozytorium, żeby te dwa przebiegi nie mogły się rozjechać.
-
Agent nie może edytować wyroczni. Referencje snapshotów i testy kodujące kryteria akceptacji są chronione, tak jak opisuje to artykuł o ochronie wyroczni testowej. Claude Code dostaje reguły deny dla ścieżek (zakładka Claude Code wyżej). W Codeksie i Cursorze ta strona opiera się zamiast tego na zabezpieczeniu niezależnym od narzędzia, które przy okazji wspiera też Claude Code: CODEOWNERS na katalogach z referencjami oraz krok CI, który pada, gdy zmieniają się one bez etykiety.
# .github/CODEOWNERS**/__Snapshots__/ @your-org/mobile-leads**/src/test/snapshots/ @your-org/mobile-leads# CI job step (check out with fetch-depth: 0 so origin/main is available)- name: Block unlabelled snapshot changesif: ${{ !contains(github.event.pull_request.labels.*.name, 'snapshot-update') }}run: |if git diff --name-only origin/main... | grep -E '__Snapshots__/|src/test/snapshots/'; thenecho "Snapshot references changed without the snapshot-update label"; exit 1fi -
Konkretna osoba zatwierdza dowody. Deweloper, który zlecił zadanie, przegląda zestaw dowodów i diff testów. Diff kodu człowiek czyta w całości tylko tam, gdzie wymaga tego ryzyko: podpisywanie, entitlements, płatności i wszystko, co dotyka uprawnień w
Info.plistlubAndroidManifest.xml.
Kontrakt pull requesta dla tego zestawu opisuje artykuł o pakiecie dowodów, a uzasadnienie przeglądu dowodów zamiast diffów — artykuł czytanie dowodów zamiast kodu.
Kiedy natywna pętla agenta się psuje
Dział zatytułowany „Kiedy natywna pętla agenta się psuje”Model i poziom wysiłku (effort) przy pracy natywnej
Dział zatytułowany „Model i poziom wysiłku (effort) przy pracy natywnej”Zacznij od domyślnego modelu swojego narzędzia i podnieś poziom effort, zanim zmienisz model; aktualne ustawienia domyślne i ceny są w przeglądzie modeli. Zadania natywne częściej ogranicza informacja zwrotna z builda niż model, więc najpierw napraw pętlę.