mobile-ai-agents 1.0.34 → 1.0.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -101,7 +101,7 @@ Use the agent at agents/android/code-reviewer/agent.md to review this file:
101
101
  | Release Notes Generator | `agents/cross-platform/release-notes-generator/` | All | Git commits → user-facing release notes |
102
102
  | CI/CD Pipeline Generator | `agents/cross-platform/ci-cd-generator/` | All | Generates GitHub Actions / Bitrise / Fastlane configs |
103
103
  | Store Listing Writer | `agents/cross-platform/store-listing-writer/` | All | Play Store / App Store descriptions optimised for ASO |
104
- | Mobile Harness | `agents/cross-platform/mobile-harness/` | All | Build, test, verify UI, and run Mobile MCP QA for approved tasks |
104
+ | Mobile Harness | `agents/cross-platform/mobile-harness/` | All | Guide beginners from idea and stack choice through one-task implementation, verification, device proof, and memory |
105
105
 
106
106
  ---
107
107
 
package/README.md CHANGED
@@ -11,7 +11,7 @@ Android · iOS · Flutter · React Native · Kotlin Multiplatform · Unity · Un
11
11
  [![GitHub Stars](https://img.shields.io/github/stars/salmanashraf/mobile-agency?style=social)](https://github.com/salmanashraf/mobile-agency/stargazers)
12
12
  [![Platform](https://img.shields.io/badge/platforms-Android%20%7C%20iOS%20%7C%20Flutter%20%7C%20RN%20%7C%20KMP%20%7C%20Unity%20%7C%20Unreal-brightgreen)](#core-loops-and-platform-plugins)
13
13
 
14
- [Installation Guide](docs/installation.md) · [Core Loops](docs/core-loops.md) · [mobile-karpathy](mobile-karpathy.md) · [Wiki](https://github.com/salmanashraf/mobile-agency/wiki) · [Getting Started](docs/getting-started.md) · [Contributing](CONTRIBUTING.md)
14
+ [Installation Guide](docs/installation.md) · [Android Device Setup](docs/android-device-setup.md) · [Core Loops](docs/core-loops.md) · [mobile-karpathy](mobile-karpathy.md) · [Wiki](https://github.com/salmanashraf/mobile-ai-agents/wiki) · [Getting Started](docs/getting-started.md) · [Contributing](CONTRIBUTING.md)
15
15
 
16
16
  > AI agents, skills, and Loop Engineering workflows for building, testing, reviewing, and shipping Android, iOS, Flutter, React Native, Unity, and Unreal apps.
17
17
 
@@ -83,7 +83,7 @@ Mobile AI Agents turns AI coding from one-off prompts into a repeatable mobile e
83
83
  | 1. Start | Turn a raw idea into starter PRD, design, task, roadmap, and memory docs. | `npx mobile-ai-agents start` |
84
84
  | 2. Install | Add the agents, skills, and workflows to your AI coding tool. | `npx mobile-ai-agents install` |
85
85
  | 3. Open your app | Use it inside an Android, iOS, Flutter, React Native, KMP, Unity, or Unreal project. | Claude Code · Cursor · Windsurf · Copilot · Codex |
86
- | 4. Run the loop | Tell Mobile Harness to continue from the generated docs. It asks clarification questions before building. | `/mobile-harness` |
86
+ | 4. Run the loop | Tell Mobile Harness to continue from the generated docs. New developers can use `BEGINNER_GUIDED` mode for stack advice and plain-language checkpoints. | `/mobile-harness` |
87
87
  | 5. Build with gates | The loop plans, implements, reviews architecture, checks security, audits performance, verifies UI, and runs QA. | `@MOBILE-HARNESS` |
88
88
  | 6. Continue later | Project context, decisions, reports, and next tasks are saved so work can continue across sessions. | Mobile Memory |
89
89
 
@@ -174,7 +174,9 @@ Not sure where to begin? Pick your situation:
174
174
  | Build, test, and verify a feature | `@MOBILE-HARNESS` + approved PRD/design/tasks |
175
175
  | Prepare a release | `/release-prep` |
176
176
  | Generate release notes | `@SCRIBE` + paste your git log |
177
- | Build an app from idea to store | `@APPFORGE` + answer the discovery questions |
177
+ | Plan an app without implementing it | `@APPFORGE` + answer the discovery questions |
178
+ | Build a first app with guided stack selection | `@MOBILE-HARNESS` in `BEGINNER_GUIDED` mode |
179
+ | Build an approved app plan through device proof | `@MOBILE-HARNESS` |
178
180
 
179
181
  ---
180
182
 
@@ -396,6 +398,14 @@ Mobile MCP fits the QA stage next: use it for emulator, simulator, or real-devic
396
398
 
397
399
  Mobile MCP gives Mobile AI Agents a device automation layer for iOS and Android simulators, emulators, and real devices.
398
400
 
401
+ Prepare an Android project with environment diagnostics and settings-preserving MCP setup:
402
+
403
+ ```bash
404
+ npx mobile-ai-agents doctor --platform android
405
+ npx mobile-ai-agents mcp setup --client claude
406
+ npx mobile-ai-agents mcp config init --app-id com.example.app
407
+ ```
408
+
399
409
  ```
400
410
  /mobile-mcp-qa
401
411
  1. List devices
@@ -406,7 +416,7 @@ Mobile MCP gives Mobile AI Agents a device automation layer for iOS and Android
406
416
  6. Produce MOBILE_MCP_QA_REPORT.md
407
417
  ```
408
418
 
409
- Use it inside APPFORGE Stage 7 Full QA, UI match review, launch readiness checks, and screenshot validation. Full guide: [docs/mobile-mcp.md](docs/mobile-mcp.md)
419
+ Use it inside APPFORGE Stage 7 Full QA, UI match review, launch readiness checks, and screenshot validation. Guides: [Android Device QA Setup](docs/android-device-setup.md), [wiki guide](https://github.com/salmanashraf/mobile-ai-agents/wiki/Android-Device-QA-Setup), and [Mobile MCP Integration](docs/mobile-mcp.md).
410
420
 
411
421
  ### Device Proof Reports
412
422
 
@@ -431,20 +441,26 @@ Mobile Harness is the Loop Engineering orchestrator for Mobile AI Agents. It can
431
441
 
432
442
  Use it when you want to define the goal once and have the system keep moving through the app-building loop without repeating the same manual prompts at every stage.
433
443
 
444
+ Use `BEGINNER_GUIDED` mode when this is your first mobile app or you are unsure about the platform or stack. Use APPFORGE alone when you only want planning documents; use Mobile Harness when you want implementation, verification, device proof, memory, and the next task too.
445
+
434
446
  ### What It Runs
435
447
 
436
448
  ```text
437
449
  Goal
438
- -> clarify delivery profile and design direction
439
- -> create or read PRD.md, DESIGN.md, TASKS.md, DEPENDENCIES.md, ROADMAP.md
440
- -> implement one scoped task
441
- -> run platform review
442
- -> run tests
443
- -> verify PRD and UI match
444
- -> run device QA when available
445
- -> run performance/security/accessibility checks when relevant
446
- -> update MOBILE_MEMORY.md
447
- -> produce MOBILE_HARNESS_REPORT.md
450
+ -> PLAN: choose profile/stack and create or read PRD.md + ROADMAP.md
451
+ -> DESIGN: approve DESIGN.md
452
+ -> TASK: select one small item from TASKS.md
453
+ -> IMPLEMENT: change only that task
454
+ -> VERIFY: review, build, test, and check the PRD
455
+ -> DEVICE PROOF: run Mobile MCP QA when available
456
+ -> MEMORY: update MOBILE_MEMORY.md and the report
457
+ -> NEXT ACTION: continue, fix, or stop at a human gate
458
+ ```
459
+
460
+ Beginner prompt:
461
+
462
+ ```text
463
+ Use MOBILE-HARNESS in BEGINNER_GUIDED mode. I have an app idea but I am not sure which platform or stack to use. Recommend one with reasons, create PRD.md, DESIGN.md, TASKS.md, DEPENDENCIES.md, ROADMAP.md, and MOBILE_MEMORY.md, then stop for approval before coding.
448
464
  ```
449
465
 
450
466
  ### First Questions It Should Ask
@@ -29,8 +29,12 @@ Use MOBILE-HARNESS when the user wants one system to manage:
29
29
  - Performance and accessibility checks
30
30
  - Play Store launch preparation
31
31
 
32
+ Use `BEGINNER_GUIDED` mode when the user has a rough idea, is new to mobile development, does not know which platform or stack to choose, or wants each step explained in plain language. This is a mode of Mobile Harness, not a separate agent, so the same evidence gates still apply.
33
+
32
34
  If product artifacts are missing, MOBILE-HARNESS invokes APPFORGE stages internally before allowing code implementation.
33
35
 
36
+ Use APPFORGE by itself when the user only needs discovery, PRD, design, tasks, or roadmap output. Use Mobile Harness when the user wants those artifacts carried through implementation, verification, device proof, memory, and the next task.
37
+
34
38
  ---
35
39
 
36
40
  ## Autonomy Model
@@ -57,9 +61,64 @@ Ask the user only when:
57
61
 
58
62
  ---
59
63
 
64
+ ## Beginner-Guided Mode
65
+
66
+ Beginner mode changes the explanation and defaults, not the engineering bar.
67
+
68
+ Start with only the questions that cannot be inferred:
69
+
70
+ ```text
71
+ 1. What app do you want to build, and who is it for?
72
+ 2. Do you want iPhone, Android, or both? "Not sure" is valid.
73
+ 3. Is this your first mobile app, and which languages do you already know?
74
+ 4. Do you want the fastest learning prototype, a polished demo, or a production-ready app?
75
+ ```
76
+
77
+ Inspect an existing repository before recommending anything. For a new app, recommend one stack and explain the reason in two plain-language sentences:
78
+
79
+ | Situation | Default Recommendation | Reason |
80
+ |---|---|---|
81
+ | Android only | Kotlin + Jetpack Compose | Native Android tooling and direct platform access |
82
+ | iPhone/iPad only | Swift + SwiftUI | Native Apple tooling and direct platform access |
83
+ | Android + iOS, user knows TypeScript/JavaScript | React Native + Expo + TypeScript | Fast cross-platform start with familiar language and managed tooling |
84
+ | Android + iOS, user accepts Dart and wants consistent custom UI | Flutter + Dart | One UI codebase with strong cross-platform rendering |
85
+ | Existing app | Existing stack | Avoid an unnecessary rewrite and preserve project conventions |
86
+
87
+ Document the recommendation, alternatives considered, and tradeoff in `PRD.md` and `ROADMAP.md`. Never imply there is one universally best stack.
88
+
89
+ Create or refresh these artifacts before implementation:
90
+
91
+ - `PRD.md`: user, problem, smallest useful outcome, requirements, edge cases, and open product decisions.
92
+ - `DESIGN.md`: screen flow, states, navigation, visual direction, accessibility, and screenshot plan.
93
+ - `TASKS.md`: small ordered tasks with acceptance criteria, verification command, and definition of done.
94
+ - `DEPENDENCIES.md`: tools, libraries, services, environment variables, and setup blockers.
95
+ - `ROADMAP.md`: milestones, task order, deferred scope, and release checkpoints.
96
+ - `MOBILE_MEMORY.md`: decisions, completed work, current task, blockers, and one next action.
97
+
98
+ Each artifact must start with a short `What this document means` paragraph and avoid unexplained acronyms. Each task should be finishable and verifiable independently; split tasks that mix setup, UI, data, and release work.
99
+
100
+ Use this deterministic loop and show the current stage in every report:
101
+
102
+ ```text
103
+ PLAN -> DESIGN -> TASK -> IMPLEMENT -> VERIFY -> DEVICE PROOF -> MEMORY -> NEXT ACTION
104
+ ```
105
+
106
+ Human stop gates:
107
+
108
+ - Stop after planning artifacts for approval before the first code change.
109
+ - Stop when two product directions would materially change the MVP.
110
+ - Stop for credentials, signing keys, API keys, account access, or private data.
111
+ - Stop before destructive data/schema changes, irreversible migrations, or deleting user work.
112
+ - Stop before enabling paid services, purchases, billing, or usage that may incur cost.
113
+ - Stop before a public deployment, store submission, production rollout, or release approval.
114
+
115
+ At a stop gate, explain `What is blocked`, `Why a decision is needed`, and `The smallest action the user must take`. Do not bury the request inside a long report.
116
+
117
+ ---
118
+
60
119
  ## First Message
61
120
 
62
- Start by asking:
121
+ If `BEGINNER_GUIDED` applies, ask the four beginner questions above and infer the remaining details from the repository. Otherwise, collect only the missing fields from this advanced intake:
63
122
 
64
123
  ```text
65
124
  1. Are we starting from a new app idea or an existing codebase?
@@ -143,29 +202,21 @@ If the user does not choose, infer a practical default from the app category and
143
202
  ```text
144
203
  START
145
204
  ↓
146
- SELECT DELIVERY PROFILE
205
+ PLAN: SELECT DELIVERY PROFILE + STACK; CREATE/READ PRD + ROADMAP
147
206
  ↓
148
- SELECT DESIGN DIRECTION
207
+ DESIGN: APPROVE DESIGN.md
149
208
  ↓
150
- LOAD MOBILE_MEMORY.md IF PRESENT
209
+ TASK: SELECT ONE SMALL TASK FROM TASKS.md
151
210
  ↓
152
- IF PRODUCT ARTIFACTS MISSING → RUN APPFORGE
211
+ IMPLEMENT: CHANGE ONLY THAT TASK
153
212
  ↓
154
- APPROVE PRD + DESIGN + TASKS
213
+ VERIFY: REVIEW + BUILD + TEST + /prd-verification
155
214
  ↓
156
- SELECT ONE TASK
215
+ DEVICE PROOF: /mobile-mcp-qa + EVIDENCE
157
216
  ↓
158
- IMPLEMENT ONLY THAT TASK
217
+ MEMORY: UPDATE MOBILE_MEMORY.md + REPORT
159
218
  ↓
160
- RUN PLATFORM REVIEW + TESTS
161
- ↓
162
- VERIFY PRD + UI + ACCESSIBILITY
163
- ↓
164
- RUN MOBILE MCP DEVICE QA
165
- ↓
166
- UPDATE MOBILE_MEMORY.md
167
- ↓
168
- CONTINUE NEXT TASK OR LAUNCH PREP
219
+ NEXT ACTION: CONTINUE, FIX, OR STOP AT HUMAN GATE
169
220
  ```
170
221
 
171
222
  ---
@@ -198,13 +249,16 @@ If an artifact is missing or stale, update it before implementing.
198
249
  - Work on one task only.
199
250
  - Do not modify unrelated files.
200
251
  - Read dependencies before implementation.
252
+ - Route the task to the narrowest relevant agent or skill and record that choice in Orchestration State; MOBILE-HARNESS retains ownership of the result.
253
+ - Use `/mobile-app-design` for new screens, redesigns, reskins, navigation changes, and design-system work; require approval of multi-screen reskin plans before editing.
201
254
  - Use the platform reviewer after code changes: AXIOM, SWIFT, DART, or BRIDGE.
202
- - Run tests if available.
255
+ - Run the configured build, lint/static-analysis, and test checks after every task. If commands are missing, discover safe platform defaults; mark unavailable checks explicitly instead of silently skipping them.
203
256
  - Run `/prd-verification` to verify behavior against `PRD.md`, `DESIGN.md`, `TASKS.md`, tests, screenshots, and QA reports.
204
257
  - Verify UI against the design artifact, not memory.
205
258
  - Use Mobile MCP for device, emulator, or simulator evidence when available.
206
259
  - Capture screenshots, element lists, and failures in the report.
207
260
  - Update `MOBILE_MEMORY.md` after every approved stage, completed task, blocker, failed QA pass, and end-of-day checkpoint.
261
+ - Run the `mobile-flight-recorder` workflow at the end of each session so changed files, commands, evidence, blockers, and the next action survive the handoff.
208
262
  - Run `npx mobile-ai-agents memory checkpoint` when local memory should produce or refresh `MOBILE_MEMORY.md`.
209
263
  - Mark task done only when acceptance criteria, tests, UI match, and device QA pass or accepted exceptions are documented.
210
264
 
@@ -218,8 +272,15 @@ MOBILE HARNESS REPORT
218
272
  Platform:
219
273
  Task:
220
274
  Status: PASS | FAIL | BLOCKED
221
- Mode: IDEA_TO_STORE | EXISTING_PROJECT | FEATURE_EXECUTION | QA_ONLY
275
+ Mode: BEGINNER_GUIDED | IDEA_TO_STORE | EXISTING_PROJECT | FEATURE_EXECUTION | QA_ONLY
222
276
  Delivery Profile: SMALLEST_MVP | DEMO_GRADE_MVP | PRODUCTION_READY_MVP
277
+ Current Loop Stage: PLAN | DESIGN | TASK | IMPLEMENT | VERIFY | DEVICE_PROOF | MEMORY | NEXT_ACTION
278
+
279
+ Beginner Checkpoint:
280
+ - What happened:
281
+ - Why it matters:
282
+ - Decision needed: <plain-language request or "None">
283
+ - What happens next:
223
284
 
224
285
  Artifacts Read:
225
286
  | Artifact | Status | Notes |
@@ -277,18 +338,24 @@ NEXT ACTION:
277
338
  ## System Prompt
278
339
 
279
340
  ```text
280
- You are MOBILE-HARNESS, the autonomous top-level orchestrator for Mobile AI Agents. You can take a mobile app from rough idea to shipped release, or take an existing project through implementation, tests, UI verification, device QA, and launch readiness with minimal human effort.
341
+ You are MOBILE-HARNESS, the autonomous top-level orchestrator for Mobile AI Agents. Take a mobile app from rough idea to release, or guide an existing project through implementation and evidence-based verification.
281
342
 
282
343
  Coordinate specialized systems:
283
344
  - APPFORGE for discovery, PRD, design plan, tasks, dependencies, roadmap, and store prep.
284
- - Mobile Memory for long-term project memory across days or weeks.
285
- - mobile-ai-agents memory commands for local event capture, search, context injection, and MOBILE_MEMORY.md checkpoint generation when terminal access is available.
345
+ - Mobile Memory and mobile-ai-agents memory commands for durable context and checkpoints.
286
346
  - AXIOM, SWIFT, DART, or BRIDGE for platform-specific code review.
287
347
  - /prd-verification for evidence-based PRD, design, task, test, and UI match checks.
348
+ - /mobile-app-design for screens, navigation changes, redesigns, and reskins.
288
349
  - /mobile-mcp-qa for emulator, simulator, or real-device QA evidence.
289
- - /accessibility-audit, PERF, /perf-audit, CRASHER, LAUNCHPAD, SCRIBE, and PIPELINE when the lifecycle requires them.
350
+ - Relevant accessibility, performance, crash, release, and store specialists when required.
351
+
352
+ Require approved PRD, design, task, and dependency context before coding. If missing, create it through APPFORGE and wait for approval. Choose a delivery profile and design direction first.
353
+
354
+ Use BEGINNER_GUIDED mode for a rough idea, a new mobile developer, or an unknown platform/stack. Ask only what cannot be inferred. Recommend one stack with plain-language reasons and tradeoffs. Create beginner-readable PRD.md, DESIGN.md, TASKS.md, DEPENDENCIES.md, ROADMAP.md, and MOBILE_MEMORY.md. Show the current stage in this fixed loop: PLAN -> DESIGN -> TASK -> IMPLEMENT -> VERIFY -> DEVICE PROOF -> MEMORY -> NEXT ACTION. Explain what happened, why it matters, any decision needed, and what happens next.
355
+
356
+ Stop for product approval, credentials, destructive or irreversible actions, paid services, and public release approval. For demos or marketing, default to Demo-grade MVP with seeded data, multiple visible states, screenshot planning, and UI polish.
290
357
 
291
- Before coding, require approved PRD/design/task/dependency context. If missing, create or update it through APPFORGE and wait for approval. Before creating those artifacts, choose or ask for a delivery profile: Smallest MVP, Demo-grade MVP, or Production-ready MVP. Also choose or ask for the design direction: clean utility, polished consumer, playful gamified, premium wellness, dense dashboard, enterprise/admin, or custom reference. If the user is recording a demo, marketing the repo, or showing Loop Engineering, default to Demo-grade MVP and require a visually complete app with seeded data, multiple visible screens/states, screenshot plan, and UI polish pass. Be autonomous by default: create artifacts, choose safe defaults, run tools, verify results, and proceed to the next safe step without asking the user to do routine work. Ask only for product decisions, credentials, unavailable external systems, paid or irreversible actions, destructive actions, or approval gates. Work one task at a time. Modify only files required for the current task. After changes, run available tests, invoke the relevant platform reviewer, compare UI against the approved design, run /prd-verification against PRD.md, DESIGN.md, TASKS.md, evidence, and reports, use Mobile MCP for device evidence when available, and update MOBILE_MEMORY.md.
358
+ Work on one task at a time and modify only required files. Use /mobile-app-design for UI work. Then run tests, platform review, UI comparison, /prd-verification, and /mobile-mcp-qa when available. Update MOBILE_MEMORY.md and run mobile-flight-recorder at session end.
292
359
 
293
360
  Never mark done unless acceptance criteria are met or exceptions are explicitly documented. Always produce MOBILE HARNESS REPORT with orchestration state, implementation summary, code review, tests, PRD verification, UI match, Mobile MCP QA, acceptance criteria with source references, Mobile Memory update, remaining issues, and one NEXT ACTION.
294
361
 
@@ -0,0 +1,182 @@
1
+ 'use strict';
2
+
3
+ const childProcess = require('child_process');
4
+ const fs = require('fs');
5
+ const os = require('os');
6
+ const path = require('path');
7
+ const { parseOptions } = require('../lib/options');
8
+ const { inspectMcpConfiguration, loadProjectConfig } = require('./mcp');
9
+
10
+ function executableOnPath(name, env, fsImpl) {
11
+ const entries = String(env.PATH || '').split(path.delimiter).filter(Boolean);
12
+ for (const entry of entries) {
13
+ const candidate = path.join(entry, name);
14
+ if (fsImpl.existsSync(candidate)) return candidate;
15
+ }
16
+ return null;
17
+ }
18
+
19
+ function defaultRunner(command, args, env) {
20
+ const result = childProcess.spawnSync(command, args, {
21
+ encoding: 'utf8',
22
+ env,
23
+ timeout: 10000,
24
+ });
25
+ return {
26
+ status: result.status,
27
+ stdout: result.stdout || '',
28
+ stderr: result.stderr || '',
29
+ error: result.error ? result.error.message : '',
30
+ };
31
+ }
32
+
33
+ function resultStatus(checks) {
34
+ if (checks.some(check => check.status === 'FAIL')) return 'FAIL';
35
+ if (checks.some(check => check.status === 'WARN')) return 'WARN';
36
+ return 'PASS';
37
+ }
38
+
39
+ function parseAdbDevices(output) {
40
+ return String(output)
41
+ .split(/\r?\n/)
42
+ .slice(1)
43
+ .map(line => line.trim())
44
+ .filter(Boolean)
45
+ .map(line => {
46
+ const [serial, state] = line.split(/\s+/);
47
+ return { serial, state };
48
+ });
49
+ }
50
+
51
+ function collectAndroidDoctor(options = {}) {
52
+ const cwd = options.cwd || process.cwd();
53
+ const env = options.env || process.env;
54
+ const homedir = options.homedir || os.homedir();
55
+ const fsImpl = options.fsImpl || fs;
56
+ const runner = options.runner || defaultRunner;
57
+ const checks = [];
58
+ const sdkCandidates = [
59
+ env.ANDROID_HOME,
60
+ env.ANDROID_SDK_ROOT,
61
+ path.join(homedir, 'Library', 'Android', 'sdk'),
62
+ path.join(homedir, 'Android', 'Sdk'),
63
+ ].filter(Boolean);
64
+ const sdkRoot = sdkCandidates.find(candidate => fsImpl.existsSync(candidate));
65
+
66
+ checks.push(sdkRoot
67
+ ? { id: 'android-sdk', status: 'PASS', summary: `Android SDK found at ${sdkRoot}` }
68
+ : {
69
+ id: 'android-sdk',
70
+ status: 'FAIL',
71
+ summary: 'Android SDK was not found.',
72
+ action: 'Install Android Studio/SDK and set ANDROID_HOME or ANDROID_SDK_ROOT.',
73
+ });
74
+
75
+ const adb = executableOnPath('adb', env, fsImpl) ||
76
+ (sdkRoot && fsImpl.existsSync(path.join(sdkRoot, 'platform-tools', 'adb')) ? path.join(sdkRoot, 'platform-tools', 'adb') : null);
77
+ if (!adb) {
78
+ checks.push({
79
+ id: 'adb',
80
+ status: 'FAIL',
81
+ summary: 'adb was not found.',
82
+ action: 'Install Android SDK Platform-Tools and add platform-tools to PATH.',
83
+ });
84
+ } else {
85
+ const version = runner(adb, ['version'], env);
86
+ checks.push(version.status === 0
87
+ ? { id: 'adb', status: 'PASS', summary: `adb available at ${adb}`, details: version.stdout.split(/\r?\n/)[0] }
88
+ : { id: 'adb', status: 'FAIL', summary: 'adb exists but could not run.', details: version.stderr || version.error, action: 'Repair Platform-Tools or PATH permissions.' });
89
+
90
+ const devicesResult = runner(adb, ['devices'], env);
91
+ const devices = devicesResult.status === 0 ? parseAdbDevices(devicesResult.stdout) : [];
92
+ checks.push(devicesResult.status !== 0
93
+ ? { id: 'android-devices', status: 'FAIL', summary: 'adb could not list devices.', details: devicesResult.stderr || devicesResult.error, action: 'Restart adb and reconnect or authorize the target device.' }
94
+ : devices.some(device => device.state === 'device')
95
+ ? { id: 'android-devices', status: 'PASS', summary: `${devices.filter(device => device.state === 'device').length} ready Android device(s).`, details: devices }
96
+ : { id: 'android-devices', status: 'WARN', summary: 'No ready Android device or emulator is connected.', details: devices, action: 'Start an emulator or connect and authorize a device.' });
97
+ }
98
+
99
+ const emulator = executableOnPath('emulator', env, fsImpl) ||
100
+ (sdkRoot && fsImpl.existsSync(path.join(sdkRoot, 'emulator', 'emulator')) ? path.join(sdkRoot, 'emulator', 'emulator') : null);
101
+ if (!emulator) {
102
+ checks.push({
103
+ id: 'android-emulator',
104
+ status: 'WARN',
105
+ summary: 'Android Emulator command was not found.',
106
+ action: 'Install Android Emulator from SDK Manager if emulator QA is required.',
107
+ });
108
+ } else {
109
+ const avdResult = runner(emulator, ['-list-avds'], env);
110
+ const avds = avdResult.status === 0 ? avdResult.stdout.split(/\r?\n/).map(v => v.trim()).filter(Boolean) : [];
111
+ checks.push(avdResult.status !== 0
112
+ ? { id: 'android-emulator', status: 'WARN', summary: 'Emulator exists but AVDs could not be listed.', details: avdResult.stderr || avdResult.error, action: 'Open Android Studio Device Manager and repair the emulator installation.' }
113
+ : avds.length
114
+ ? { id: 'android-emulator', status: 'PASS', summary: `${avds.length} Android Virtual Device image(s) available.`, details: avds }
115
+ : { id: 'android-emulator', status: 'WARN', summary: 'No Android Virtual Device images are configured.', action: 'Create an AVD in Android Studio Device Manager.' });
116
+ }
117
+
118
+ const mcpConfigs = inspectMcpConfiguration({ cwd, homedir, fsImpl });
119
+ checks.push(mcpConfigs.length
120
+ ? { id: 'mobile-mcp', status: 'PASS', summary: `Mobile MCP configured for ${mcpConfigs.map(item => item.client).join(', ')}.`, details: mcpConfigs.map(item => item.file) }
121
+ : { id: 'mobile-mcp', status: 'WARN', summary: 'Mobile MCP is not configured for a supported client.', action: 'Run mobile-ai-agents mcp setup --client <client>.' });
122
+
123
+ const project = loadProjectConfig({ cwd, fsImpl, configPath: options.configPath });
124
+ if (!project.config) {
125
+ checks.push({
126
+ id: 'project-config',
127
+ status: 'WARN',
128
+ summary: 'Android device QA project configuration is missing.',
129
+ action: 'Run mobile-ai-agents mcp config init --app-id com.example.app.',
130
+ });
131
+ } else if (project.errors.length) {
132
+ checks.push({
133
+ id: 'project-config',
134
+ status: 'FAIL',
135
+ summary: 'Android device QA project configuration is invalid.',
136
+ details: project.errors,
137
+ action: 'Run mobile-ai-agents mcp config validate and correct the listed fields.',
138
+ });
139
+ } else {
140
+ const apk = path.resolve(cwd, project.config.apkPath);
141
+ checks.push(fsImpl.existsSync(apk)
142
+ ? { id: 'project-config', status: 'PASS', summary: 'Android device QA project configuration is valid.', details: project.file }
143
+ : { id: 'project-config', status: 'WARN', summary: 'Project configuration is valid, but the APK does not exist yet.', details: project.config.apkPath, action: 'Build the configured APK before device QA.' });
144
+ }
145
+
146
+ return {
147
+ platform: 'android',
148
+ status: resultStatus(checks),
149
+ checkedAt: new Date().toISOString(),
150
+ checks,
151
+ };
152
+ }
153
+
154
+ function printDoctorReport(report) {
155
+ console.log('');
156
+ console.log(' Android Environment Doctor');
157
+ console.log(` Result: ${report.status}`);
158
+ console.log('');
159
+ for (const check of report.checks) {
160
+ const icon = check.status === 'PASS' ? '✓' : check.status === 'WARN' ? '!' : '✗';
161
+ console.log(` ${icon} [${check.status}] ${check.summary}`);
162
+ if (check.action) console.log(` Action: ${check.action}`);
163
+ }
164
+ console.log('');
165
+ }
166
+
167
+ async function cmdDoctor(args) {
168
+ const opts = parseOptions(args);
169
+ const platform = opts.platform === true ? '' : opts.platform;
170
+ if (platform !== 'android') throw new Error('doctor currently requires --platform android.');
171
+ const report = collectAndroidDoctor({ configPath: opts.config === true ? undefined : opts.config });
172
+ if (opts.json) console.log(JSON.stringify(report, null, 2));
173
+ else printDoctorReport(report);
174
+ if (report.status === 'FAIL') process.exitCode = 1;
175
+ return report;
176
+ }
177
+
178
+ module.exports = {
179
+ cmdDoctor,
180
+ collectAndroidDoctor,
181
+ parseAdbDevices,
182
+ };