reis-mobile 0.7.3 → 0.8.0

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.
Files changed (44) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +16 -0
  4. package/README.md +37 -19
  5. package/agents/android-architect.md +3 -3
  6. package/agents/android-performance-engineer.md +1 -1
  7. package/agents/flutter-architect.md +3 -3
  8. package/agents/flutter-performance-engineer.md +1 -1
  9. package/agents/ios-architect.md +3 -3
  10. package/agents/ios-performance-engineer.md +1 -1
  11. package/agents/kmp-architect.md +3 -3
  12. package/agents/kmp-performance-engineer.md +1 -1
  13. package/agents/lead-mobile.md +3 -0
  14. package/agents/mobile-release-engineer.md +3 -3
  15. package/agents/mobile-staff-engineer.md +1 -1
  16. package/agents/rn-architect.md +3 -3
  17. package/agents/rn-performance-engineer.md +1 -1
  18. package/core/router/intents.mjs +15 -0
  19. package/package.json +1 -1
  20. package/skills/mobile-accessibility/SKILL.md +3 -0
  21. package/skills/mobile-accessibility/references/localization.md +77 -0
  22. package/skills/mobile-observability/SKILL.md +137 -0
  23. package/skills/mobile-observability/references/android.md +105 -0
  24. package/skills/mobile-observability/references/flutter.md +86 -0
  25. package/skills/mobile-observability/references/ios.md +88 -0
  26. package/skills/mobile-observability/references/kotlin-multiplatform.md +76 -0
  27. package/skills/mobile-observability/references/react-native.md +62 -0
  28. package/skills/mobile-offline-sync/SKILL.md +132 -0
  29. package/skills/mobile-offline-sync/references/android.md +123 -0
  30. package/skills/mobile-offline-sync/references/flutter.md +103 -0
  31. package/skills/mobile-offline-sync/references/ios.md +103 -0
  32. package/skills/mobile-offline-sync/references/kotlin-multiplatform.md +114 -0
  33. package/skills/mobile-offline-sync/references/react-native.md +108 -0
  34. package/skills/mobile-performance/SKILL.md +88 -0
  35. package/skills/mobile-performance/references/android.md +96 -0
  36. package/skills/mobile-performance/references/background.md +87 -0
  37. package/skills/mobile-performance/references/flutter.md +101 -0
  38. package/skills/mobile-performance/references/ios.md +82 -0
  39. package/skills/mobile-performance/references/kotlin-multiplatform.md +62 -0
  40. package/skills/mobile-performance/references/react-native.md +85 -0
  41. package/skills/mobile-release/SKILL.md +2 -1
  42. package/skills/mobile-release/references/billing.md +92 -0
  43. package/skills/mobile-security/SKILL.md +3 -0
  44. package/skills/mobile-security/references/auth.md +92 -0
@@ -5,14 +5,14 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "AI agents for mobile engineering",
8
- "version": "0.7.3"
8
+ "version": "0.8.0"
9
9
  },
10
10
  "plugins": [
11
11
  {
12
12
  "name": "reis-mobile",
13
13
  "source": "./",
14
14
  "description": "AI agents, skills and workflows for Flutter, Android, iOS and React Native development.",
15
- "version": "0.7.3",
15
+ "version": "0.8.0",
16
16
  "author": {
17
17
  "name": "Warleson Reis"
18
18
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reis-mobile",
3
- "version": "0.7.3",
3
+ "version": "0.8.0",
4
4
  "description": "AI agents, skills and workflows for Flutter, Android, iOS and React Native development. Use /reis-mobile:doctor, /reis-mobile:review and /reis-mobile:test.",
5
5
  "author": {
6
6
  "name": "Warleson Reis"
package/CHANGELOG.md CHANGED
@@ -4,6 +4,22 @@ Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). The pr
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.8.0] - 2026-09-23
8
+
9
+ ### Added
10
+
11
+ - `mobile-performance` topic skill: measurement before optimization, budgets for startup, rendering, memory, battery and app size, and regression detection in CI, with a reference per stack (Flutter DevTools and `integration_test` summaries, Android Macrobenchmark, Baseline Profiles and vitals, iOS Instruments, MetricKit and `XCTMetric` baselines, React Native Hermes profiling and list tuning, KMP shared-versus-host isolation) plus a cross-stack guide to background execution and battery.
12
+ - `mobile-offline-sync` topic skill: local store as the source of truth, a durable outbox with client-generated idempotency keys, ordering and operation collapsing, retry with backoff, conflict strategies per entity, reconnection triggers, offline UX and nine failure cases to test, with a reference per stack (drift and workmanager, Room and WorkManager, Core Data/SwiftData and `BGTaskScheduler`, SQLite with NetInfo and OTA-aware drains, SQLDelight and Ktor in `commonMain`).
13
+ - `mobile-observability` topic skill: the signals that explain a production failure, mandatory segmentation by version and cohort, error context and grouping, correlation ids shared with the backend, rate-based alerting per version, sampling and cost, and what must never be collected, with a reference per stack (Flutter's three capture layers and Dart symbol upload, Android vitals and `ApplicationExitInfo`, MetricKit and Organizer, React Native source maps and OTA update ids, KMP `Telemetry` boundary and Kotlin/Native crash hooks).
14
+ - `offline` and `observability` intents in the router. `offline` goes to the stack's architect and falls back to `mobile-staff-engineer`; `observability` goes to `mobile-release-engineer`.
15
+ - `mobile-security/references/auth.md`: OAuth 2.0 and OIDC for native apps following RFC 8252 — authorization code with PKCE (`S256`), no client secret, system browser instead of a WebView, redirect URI choices, token rotation with reuse detection, and biometrics gating a key rather than a boolean.
16
+ - `mobile-release/references/billing.md`: in-app purchase and subscription lifecycle — server-side entitlement, store server notifications, the states between active and expired, acknowledgement deadlines and automatic refunds, restore and account mapping, and the per-stack client libraries.
17
+ - `mobile-accessibility/references/localization.md`: strings, CLDR plurals, locale-aware formatting, right-to-left layout and icon mirroring, translation growth, per-app language settings and pseudolocalization.
18
+
19
+ ### Changed
20
+
21
+ - The five `*-architect` agents also serve the `offline` intent, and `mobile-release-engineer` also serves `observability`; `mobile-staff-engineer` covers both when no stack is detected.
22
+
7
23
  ## [0.7.3] - 2026-09-21
8
24
 
9
25
  ### Added
package/README.md CHANGED
@@ -23,7 +23,7 @@ A mobile app is not a generic project. A code review that does not know about `B
23
23
 
24
24
  🔎 **Detects the stack on its own.** Flutter (app or plugin), React Native (including Expo), Kotlin Multiplatform, native Android and iOS, with languages and target platforms. A Flutter app with `android/` and `ios/` is still Flutter.
25
25
 
26
- 👥 **21 agents and 14 mobile skills.** Architect, performance and test engineers for Flutter, native Android, native iOS, React Native and Kotlin Multiplatform, plus a staff engineer, a native plugin specialist, a code reviewer, an accessibility auditor, a release engineer and a lead. Topic skills cover the five stacks with focused references for debugging, tests, security, Firebase, accessibility and releases.
26
+ 👥 **21 agents and 17 mobile skills.** Architect, performance and test engineers for Flutter, native Android, native iOS, React Native and Kotlin Multiplatform, plus a staff engineer, a native plugin specialist, a code reviewer, an accessibility auditor, a release engineer and a lead. Topic skills cover the five stacks with focused references for debugging, tests, security, Firebase, accessibility, releases, performance budgets, offline sync and production observability.
27
27
 
28
28
  🧩 **Project-specific context.** `/reis-mobile:project` records real app symbols, owners, boundaries and validation commands in `.reis-mobile/project.md`; the team can add product rules that code cannot reveal. Refreshing the verified map preserves team-authored text.
29
29
 
@@ -44,12 +44,21 @@ A mobile app is not a generic project. A code review that does not know about `B
44
44
  ## What's new
45
45
 
46
46
  <!-- reis-mobile:latest-release:start -->
47
- ### v0.7.3
47
+ ### v0.8.0
48
48
 
49
49
  #### Added
50
50
 
51
- - `/reis-mobile:release [request]` and entry-command forwarding audit mobile store readiness with per-target identity, pass/fail/unknown evidence gates and GO/GO WITH RISKS/NO-GO verdicts. A packaged helper rejects incomplete evidence; audits remain read-only by default.
52
- - `reis-mobile release` prepares routing, redacted git context, diagnostics and release references for all five stacks, including both native artifacts in cross-platform apps. A public Flutter sample audit demonstrates the report and external verification limits.
51
+ - `mobile-performance` topic skill: measurement before optimization, budgets for startup, rendering, memory, battery and app size, and regression detection in CI, with a reference per stack (Flutter DevTools and `integration_test` summaries, Android Macrobenchmark, Baseline Profiles and vitals, iOS Instruments, MetricKit and `XCTMetric` baselines, React Native Hermes profiling and list tuning, KMP shared-versus-host isolation) plus a cross-stack guide to background execution and battery.
52
+ - `mobile-offline-sync` topic skill: local store as the source of truth, a durable outbox with client-generated idempotency keys, ordering and operation collapsing, retry with backoff, conflict strategies per entity, reconnection triggers, offline UX and nine failure cases to test, with a reference per stack (drift and workmanager, Room and WorkManager, Core Data/SwiftData and `BGTaskScheduler`, SQLite with NetInfo and OTA-aware drains, SQLDelight and Ktor in `commonMain`).
53
+ - `mobile-observability` topic skill: the signals that explain a production failure, mandatory segmentation by version and cohort, error context and grouping, correlation ids shared with the backend, rate-based alerting per version, sampling and cost, and what must never be collected, with a reference per stack (Flutter's three capture layers and Dart symbol upload, Android vitals and `ApplicationExitInfo`, MetricKit and Organizer, React Native source maps and OTA update ids, KMP `Telemetry` boundary and Kotlin/Native crash hooks).
54
+ - `offline` and `observability` intents in the router. `offline` goes to the stack's architect and falls back to `mobile-staff-engineer`; `observability` goes to `mobile-release-engineer`.
55
+ - `mobile-security/references/auth.md`: OAuth 2.0 and OIDC for native apps following RFC 8252 — authorization code with PKCE (`S256`), no client secret, system browser instead of a WebView, redirect URI choices, token rotation with reuse detection, and biometrics gating a key rather than a boolean.
56
+ - `mobile-release/references/billing.md`: in-app purchase and subscription lifecycle — server-side entitlement, store server notifications, the states between active and expired, acknowledgement deadlines and automatic refunds, restore and account mapping, and the per-stack client libraries.
57
+ - `mobile-accessibility/references/localization.md`: strings, CLDR plurals, locale-aware formatting, right-to-left layout and icon mirroring, translation growth, per-app language settings and pseudolocalization.
58
+
59
+ #### Changed
60
+
61
+ - The five `*-architect` agents also serve the `offline` intent, and `mobile-release-engineer` also serves `observability`; `mobile-staff-engineer` covers both when no stack is detected.
53
62
 
54
63
  <!-- reis-mobile:latest-release:end -->
55
64
 
@@ -68,6 +77,8 @@ A mobile app is not a generic project. A code review that does not know about `B
68
77
 
69
78
  | Version | Highlights |
70
79
  |--------|-----------|
80
+ | **v0.7.3** | `/reis-mobile:release` audits store readiness per target, with evidence gates and a GO / GO WITH RISKS / NO-GO verdict. |
81
+ | **v0.7.2** | Kotlin Multiplatform specialists and a `mobile-kmp` skill; `/reis-mobile:project` records the app's real objects. |
71
82
  | **v0.7.1** | Update notices on Claude Code and Codex session start, plus a single-source version and CI-driven release process. |
72
83
  | **v0.7.0** | `/reis-mobile:test`, native XCTest and Espresso guidance, and project-specific contracts for the 18 specialists. |
73
84
  | **v0.6.0** | `mobile-accessibility-auditor` and `mobile-release-engineer` agents with the new `mobile-accessibility` and `mobile-release` skills: accessibility audits on every stack, release readiness with a go/no-go verdict, release notes and store copy, CI/CD. `mobile-debug` gains guides for ANRs, Android memory leaks and deep links. |
@@ -326,6 +337,9 @@ The router never invents a specialist: if no agent serves the intent, it warns y
326
337
  | Build a plugin or debug MethodChannel/EventChannel | agent `plugin-native-expert` | ✅ |
327
338
  | Audit a screen for TalkBack, VoiceOver, touch targets and text scaling | agent `mobile-accessibility-auditor` | ✅ |
328
339
  | Check release readiness, write release notes or set up CI/CD | agent `mobile-release-engineer` | ✅ |
340
+ | Set startup, frame, memory and battery budgets and guard them in CI | skill `mobile-performance` | ✅ |
341
+ | Make the app work offline, queue writes and resolve conflicts | skill `mobile-offline-sync` | ✅ |
342
+ | Get usable crashes, errors, traces and release-health alerts in production | skill `mobile-observability` | ✅ |
329
343
  | Full audit with several specialists | agent `lead-mobile` | ✅ |
330
344
  | Decide between two architectures with a real trade-off | `/reis-mobile:debate` | ✅ |
331
345
  | Dedicated test command (including XCTest and Espresso) | `/reis-mobile:test` | ✅ |
@@ -341,8 +355,8 @@ The router never invents a specialist: if no agent serves the intent, it warns y
341
355
  | **Project context** | You explain the stack | Deterministic detection of stack, platform and variant |
342
356
  | **Review** | Generic | Mobile checklists: lifecycle, `BuildContext`, MASVS, manifest, ATS |
343
357
  | **Secrets in the diff** | Sent as they are | Masked before reaching the model |
344
- | **Specialists** | None | 21 agents and 14 mobile skills |
345
- | **Context cost** | Zero | ~4,300 fixed tokens (agent and skill descriptions), no hooks |
358
+ | **Specialists** | None | 21 agents and 17 mobile skills |
359
+ | **Context cost** | Zero | ~4,700 fixed tokens (agent and skill descriptions), no hooks |
346
360
  | **Best for** | General tasks | Teams and developers working on mobile apps |
347
361
 
348
362
  **In short:** Claude Code already knows how to code. reis-mobile makes it look at what matters in a mobile app.
@@ -385,28 +399,28 @@ For domain knowledge that code cannot reveal, optionally commit `.reis-mobile/pr
385
399
  | Agent | Stack | Triggered for | What it does |
386
400
  |-------|-------|---------------|-----------|
387
401
  | `mobile-code-reviewer` | all | review | Review with `file:line` evidence, focused on what breaks in production |
388
- | `flutter-architect` | Flutter | architecture | Layers, feature-first, coupling, misplaced logic, refactoring plan |
402
+ | `flutter-architect` | Flutter | architecture, offline | Layers, feature-first, coupling, misplaced logic, refactoring plan |
389
403
  | `flutter-performance-engineer` | Flutter | performance | Rebuilds, jank, lists, leaks, paint, startup, with a score and top 3 fixes |
390
404
  | `flutter-test-engineer` | Flutter | test | Unit, BLoC/Cubit, widget and integration, coverage audit and fragile tests |
391
- | `android-architect` | Android | architecture | UI, domain and data layers, Gradle modules, ViewModel and DI boundaries |
405
+ | `android-architect` | Android | architecture, offline | UI, domain and data layers, Gradle modules, ViewModel and DI boundaries |
392
406
  | `android-performance-engineer` | Android | performance | Compose recomposition, lists, ANRs, startup, leaks, app size |
393
407
  | `android-test-engineer` | Android | test | ViewModel and coroutine tests, Compose and Espresso UI tests, flaky tests |
394
- | `ios-architect` | iOS | architecture | SwiftUI and UIKit structure, packages, navigation, concurrency boundaries |
408
+ | `ios-architect` | iOS | architecture, offline | SwiftUI and UIKit structure, packages, navigation, concurrency boundaries |
395
409
  | `ios-performance-engineer` | iOS | performance | Hangs, SwiftUI updates, lists, launch time, retain cycles, memory |
396
410
  | `ios-test-engineer` | iOS | test | Swift Testing and XCTest unit tests, async code, XCUITest flows |
397
- | `rn-architect` | React Native | architecture | Feature structure, server vs client state, navigation, native modules |
411
+ | `rn-architect` | React Native | architecture, offline | Feature structure, server vs client state, navigation, native modules |
398
412
  | `rn-performance-engineer` | React Native | performance | Re-renders, lists, JavaScript thread, animations, startup, bundle size |
399
413
  | `rn-test-engineer` | React Native | test | Jest, React Native Testing Library, native module mocks, Detox or Maestro |
400
- | `kmp-architect` | Kotlin Multiplatform | architecture | Shared source-set ownership, Android/iOS callers and Swift-facing contracts |
414
+ | `kmp-architect` | Kotlin Multiplatform | architecture, offline | Shared source-set ownership, Android/iOS callers and Swift-facing contracts |
401
415
  | `kmp-performance-engineer` | Kotlin Multiplatform | performance | Shared Kotlin cost versus Android/iOS host traces and bridge overhead |
402
416
  | `kmp-test-engineer` | Kotlin Multiplatform | test | `commonTest`, target tests and Android/iOS host coverage |
403
417
  | `mobile-accessibility-auditor` | all | accessibility | Screen reader labels, roles and states, touch targets, text scaling, focus and announcements, with fixes per platform |
404
- | `mobile-release-engineer` | all | release, deployment | Go/no-go readiness, versions and signing, crash symbols, release notes and store copy, CI/CD, staged rollout |
405
- | `mobile-staff-engineer` | all | debug, architecture, performance, test, security, migration, dependency, build | Cross-toolchain diagnosis and migrations when no stack specialist owns the intent |
418
+ | `mobile-release-engineer` | all | release, deployment, observability | Go/no-go readiness, versions and signing, crash symbols, release notes and store copy, CI/CD, staged rollout, production crash and release-health signals |
419
+ | `mobile-staff-engineer` | all | debug, architecture, performance, test, security, migration, dependency, build, offline, observability | Cross-toolchain diagnosis and migrations when no stack specialist owns the intent |
406
420
  | `plugin-native-expert` | Flutter | on demand | MethodChannel, EventChannel, Pigeon and Kotlin/Swift bridges, threading and lifecycle |
407
421
  | `lead-mobile` | all | on demand | Coordinates the other agents and consolidates a single action plan |
408
422
 
409
- When more than one agent serves the intent, the stack-specific one wins. In a Flutter app, `performance` goes to `flutter-performance-engineer`; in a KMP app, to `kmp-performance-engineer`. `accessibility` goes to `mobile-accessibility-auditor` and `release` or `deployment` to `mobile-release-engineer` on every stack. Other intents without a stack specialist, such as `debug`, go to `mobile-staff-engineer`.
423
+ When more than one agent serves the intent, the stack-specific one wins. In a Flutter app, `performance` goes to `flutter-performance-engineer`; in a KMP app, to `kmp-performance-engineer`. `accessibility` goes to `mobile-accessibility-auditor`, `release`, `deployment` and `observability` to `mobile-release-engineer` on every stack, and `offline` to the stack's architect. Other intents without a stack specialist, such as `debug`, go to `mobile-staff-engineer`.
410
424
 
411
425
  ### Skills
412
426
 
@@ -418,9 +432,12 @@ Every skill starts with `mobile-`. **Topic** skills cover every stack with one r
418
432
  | `mobile-code-review` | Review process and checklists | review, performance | Flutter (PR review, widgets, project audit, static analysis), Android, iOS, React Native, KMP |
419
433
  | `mobile-debug` | Failing builds and runtime errors | debug, build, dependency, migration | Flutter (build, runtime, layout, packages), Android (Gradle, crashes, ANRs, memory leaks), iOS (Xcode, CocoaPods, crash logs), React Native (Metro, native modules), KMP, deep links |
420
434
  | `mobile-test` | Unit, UI, integration and end-to-end tests | test | Flutter (widget, integration, Patrol, mocks, coverage), Android, iOS, React Native, KMP |
421
- | `mobile-security` | OWASP MASVS security checks | review, security, release | Flutter (token storage), Android (intents), iOS, React Native, KMP |
422
- | `mobile-accessibility` | Screen readers, touch targets, text scaling, contrast | accessibility | Flutter (Semantics), Android (Compose and Views), iOS (SwiftUI and UIKit), React Native, KMP |
423
- | `mobile-release` | Release readiness, store copy and CI/CD | release, deployment | Flutter, Android, iOS, React Native, KMP, release notes and store listing, CI/CD |
435
+ | `mobile-security` | OWASP MASVS security checks | review, security, release | Flutter (token storage), Android (intents), iOS, React Native, KMP, OAuth/OIDC and PKCE |
436
+ | `mobile-accessibility` | Screen readers, touch targets, text scaling, contrast, localization | accessibility | Flutter (Semantics), Android (Compose and Views), iOS (SwiftUI and UIKit), React Native, KMP, localization and RTL |
437
+ | `mobile-release` | Release readiness, store copy, billing and CI/CD | release, deployment | Flutter, Android, iOS, React Native, KMP, release notes and store listing, in-app purchases, CI/CD |
438
+ | `mobile-performance` | Startup, rendering, memory, battery, app size and regression gates | performance | Flutter, Android, iOS, React Native, KMP, background execution and battery |
439
+ | `mobile-offline-sync` | Local store, outbox, idempotency, conflict resolution, reconnection | offline | Flutter, Android, iOS, React Native, KMP |
440
+ | `mobile-observability` | Crashes, errors, breadcrumbs, traces, alerts, sampling and privacy | observability | Flutter, Android, iOS, React Native, KMP |
424
441
  | `mobile-firebase` | Firebase setup and 13 products | — | Flutter, Android, iOS, React Native, KMP; check installed SDK support |
425
442
  | `mobile-flutter` | Flutter and Dart specifics | review, performance, accessibility, migration | UI and navigation, data, native code, performance, accessibility and i18n, Dart, setup |
426
443
  | `mobile-android` | Native Android specifics, from the Android team | performance, release, migration, build, dependency | Compose UI, AGP 9 and R8, profiling, Google Play, identity, camera and media, on-device AI, Wear OS, TV, XR |
@@ -445,7 +462,7 @@ About 85 guides come from [flutter/skills](https://github.com/flutter/skills), [
445
462
 
446
463
  **Exception: `/reis-mobile:debate --external`.** This flag, and only this flag, sends the debate context — including excerpts of the files mentioned in the question — to the `codex` and `gemini` CLIs, which are third-party and have their own data policies. Without the flag, the debate context stays in your session. The `review` diff is masked by `redact.mjs`, but the context you cite in a debate question does not go through that layer: check what you are sending before using `--external`.
447
464
 
448
- **Context cost.** Claude Code loads the descriptions of 21 agents and 14 skills; the full content of each skill is loaded only when it is used. The exact description cost depends on the host and plugin version.
465
+ **Context cost.** Claude Code loads the descriptions of 21 agents and 17 skills; the full content of each skill is loaded only when it is used. The exact description cost depends on the host and plugin version.
449
466
 
450
467
  **One session hook.** On session startup or resume, the plugin checks for a newer release and warns only when the installed plugin is outdated. It does not read the project or modify the plugin installation.
451
468
 
@@ -472,7 +489,8 @@ About 85 guides come from [flutter/skills](https://github.com/flutter/skills), [
472
489
  | v0.6.0 | Accessibility auditor and release engineer agents, `mobile-accessibility` and `mobile-release` skills, ANR, memory leak and deep link debugging guides | ✅ |
473
490
  | v0.7.0 | `/reis-mobile:test`, native tests (XCTest, Espresso) and project-specific specialist contracts | ✅ |
474
491
  | v0.7.1 | Update notices, single-source version and release automation | ✅ |
475
- | Unreleased | `/reis-mobile:release` with per-target evidence, required gates and deterministic readiness verdicts (previously planned for v0.8.0) | ✅ |
492
+ | v0.7.3 | `/reis-mobile:release` with per-target evidence, required gates and deterministic readiness verdicts (previously planned for v0.8.0) | ✅ |
493
+ | v0.8.0 | `mobile-performance`, `mobile-offline-sync` and `mobile-observability` topic skills with a reference per stack, plus background execution, OAuth/PKCE, billing lifecycle and localization references | ✅ |
476
494
  | v0.9.0 | MCP server | ⏳ |
477
495
  | v0.10.0 | Multi-provider (OpenAI, Gemini, OpenRouter, Ollama) beyond the debate's `--external` | ⏳ |
478
496
  | v1.0.0 | First stable version: Flutter, Android, iOS and React Native | ⏳ |
@@ -1,16 +1,16 @@
1
1
  ---
2
2
  name: android-architect
3
- description: Use this agent to analyze or design the architecture of a native Android app — UI, domain and data layers, unidirectional data flow, ViewModel and state boundaries, Gradle modularization (feature and core modules, convention plugins, version catalog), dependency injection with Hilt or Koin, navigation and misplaced business logic in Activities, Fragments or Composables. Typical triggers are "review the architecture of this Android app", planning a new feature module and validating a modularization refactor.
3
+ description: Use this agent to analyze or design the architecture of a native Android app — UI, domain and data layers, unidirectional data flow, ViewModel and state boundaries, Gradle modularization (feature and core modules, convention plugins, version catalog), dependency injection with Hilt or Koin, navigation and misplaced business logic in Activities, Fragments or Composables. Typical triggers are "review the architecture of this Android app", planning a new feature module, validating a modularization refactor and placing offline storage, WorkManager queues and synchronization in the right layer.
4
4
  model: inherit
5
5
  color: cyan
6
6
  tools: ["Read", "Grep", "Glob"]
7
- intents: [architecture]
7
+ intents: [architecture, offline]
8
8
  stacks: [android]
9
9
  ---
10
10
 
11
11
  You own native Android module, state and lifecycle boundaries. Work read-only and leave a design grounded in the project's Gradle graph and actual Kotlin types.
12
12
 
13
- Use the [project brief](../docs/agent-context.md) once per task, or reuse the caller's brief. Load [mobile-architecture](../skills/mobile-architecture/SKILL.md) and its [Android reference](../skills/mobile-architecture/references/android.md).
13
+ Use the [project brief](../docs/agent-context.md) once per task, or reuse the caller's brief. Load [mobile-architecture](../skills/mobile-architecture/SKILL.md) and its [Android reference](../skills/mobile-architecture/references/android.md). When the design involves working offline, queued writes or synchronization, add [mobile-offline-sync](../skills/mobile-offline-sync/SKILL.md) and its [Android reference](../skills/mobile-offline-sync/references/android.md).
14
14
 
15
15
  ## Establish the real dependency graph
16
16
 
@@ -10,7 +10,7 @@ stacks: [android]
10
10
 
11
11
  You isolate Android latency, frame, memory, energy or size regressions to a Kotlin/native call path and a repeatable experiment. Your deliverable is evidence plus a targeted fix proposal.
12
12
 
13
- Use the [project brief](../docs/agent-context.md) once per task or reuse it from the caller. Load [mobile-android](../skills/mobile-android/SKILL.md) and its [build and performance reference](../skills/mobile-android/references/build-and-performance.md).
13
+ Use the [project brief](../docs/agent-context.md) once per task or reuse it from the caller. Load [mobile-android](../skills/mobile-android/SKILL.md) and its [build and performance reference](../skills/mobile-android/references/build-and-performance.md). For budgets, the benchmark harness and CI regression gates, add [mobile-performance](../skills/mobile-performance/SKILL.md) and its [Android reference](../skills/mobile-performance/references/android.md); battery and background work are in its [background reference](../skills/mobile-performance/references/background.md).
14
14
 
15
15
  ## Fix the measurement conditions
16
16
 
@@ -1,16 +1,16 @@
1
1
  ---
2
2
  name: flutter-architect
3
- description: Use this agent to analyze or design the architecture of a Flutter app — layer separation (presentation, domain, data), feature-first modularization, coupling between features, misplaced business logic, oversized widgets, state management boundaries and dependency injection. Typical triggers are "review the architecture of this Flutter app", planning a new feature module and validating a Clean Architecture refactor.
3
+ description: Use this agent to analyze or design the architecture of a Flutter app — layer separation (presentation, domain, data), feature-first modularization, coupling between features, misplaced business logic, oversized widgets, state management boundaries and dependency injection. Typical triggers are "review the architecture of this Flutter app", planning a new feature module, validating a Clean Architecture refactor and deciding where offline state, queues and synchronization belong.
4
4
  model: inherit
5
5
  color: cyan
6
6
  tools: ["Read", "Grep", "Glob"]
7
- intents: [architecture]
7
+ intents: [architecture, offline]
8
8
  stacks: [flutter]
9
9
  ---
10
10
 
11
11
  You own Flutter state and package boundaries for the requested change. Work read-only: deliver a design that an implementer can apply to this app.
12
12
 
13
- Start with the [project brief](../docs/agent-context.md), read once per task or reuse the supplied brief. Apply [mobile-architecture](../skills/mobile-architecture/SKILL.md) and its [Flutter reference](../skills/mobile-architecture/references/flutter.md) for the state library actually installed.
13
+ Start with the [project brief](../docs/agent-context.md), read once per task or reuse the supplied brief. Apply [mobile-architecture](../skills/mobile-architecture/SKILL.md) and its [Flutter reference](../skills/mobile-architecture/references/flutter.md) for the state library actually installed. When the design involves working offline, queued writes or synchronization, add [mobile-offline-sync](../skills/mobile-offline-sync/SKILL.md) and its [Flutter reference](../skills/mobile-offline-sync/references/flutter.md).
14
14
 
15
15
  ## Trace the feature
16
16
 
@@ -10,7 +10,7 @@ stacks: [flutter]
10
10
 
11
11
  You investigate a measured Flutter rendering, memory or startup regression. Produce a focused diagnosis and patch proposal; do not turn the task into a generic optimization audit.
12
12
 
13
- Read the [project brief](../docs/agent-context.md) once or reuse the supplied context. Use [mobile-flutter](../skills/mobile-flutter/SKILL.md) and its [performance reference](../skills/mobile-flutter/references/performance.md) for the relevant tool.
13
+ Read the [project brief](../docs/agent-context.md) once or reuse the supplied context. Use [mobile-flutter](../skills/mobile-flutter/SKILL.md) and its [performance reference](../skills/mobile-flutter/references/performance.md) for the relevant tool. For budgets, the benchmark harness and CI regression gates, add [mobile-performance](../skills/mobile-performance/SKILL.md) and its [Flutter reference](../skills/mobile-performance/references/flutter.md); battery and background work are in its [background reference](../skills/mobile-performance/references/background.md).
14
14
 
15
15
  ## Establish the experiment
16
16
 
@@ -1,16 +1,16 @@
1
1
  ---
2
2
  name: ios-architect
3
- description: Use this agent to analyze or design the architecture of a native iOS app — SwiftUI and UIKit presentation patterns (MVVM, coordinators), navigation, layering between views, view models, services and persistence, modularization with local Swift packages, dependency injection, Swift concurrency boundaries (actors, @MainActor) and misplaced business logic in views or view controllers. Typical triggers are "review the architecture of this iOS app", planning a new feature module and validating a migration from UIKit to SwiftUI.
3
+ description: Use this agent to analyze or design the architecture of a native iOS app — SwiftUI and UIKit presentation patterns (MVVM, coordinators), navigation, layering between views, view models, services and persistence, modularization with local Swift packages, dependency injection, Swift concurrency boundaries (actors, @MainActor) and misplaced business logic in views or view controllers. Typical triggers are "review the architecture of this iOS app", planning a new feature module, validating a migration from UIKit to SwiftUI and deciding how offline persistence and background synchronization are owned.
4
4
  model: inherit
5
5
  color: cyan
6
6
  tools: ["Read", "Grep", "Glob"]
7
- intents: [architecture]
7
+ intents: [architecture, offline]
8
8
  stacks: [ios]
9
9
  ---
10
10
 
11
11
  You own iOS object ownership, navigation and isolation boundaries. Analyze SwiftUI/UIKit and Swift packages without editing the project.
12
12
 
13
- Read the [project brief](../docs/agent-context.md) once per task or reuse one supplied by the caller. Use [mobile-architecture](../skills/mobile-architecture/SKILL.md) and its [iOS reference](../skills/mobile-architecture/references/ios.md).
13
+ Read the [project brief](../docs/agent-context.md) once per task or reuse one supplied by the caller. Use [mobile-architecture](../skills/mobile-architecture/SKILL.md) and its [iOS reference](../skills/mobile-architecture/references/ios.md). When the design involves working offline, queued writes or synchronization, add [mobile-offline-sync](../skills/mobile-offline-sync/SKILL.md) and its [iOS reference](../skills/mobile-offline-sync/references/ios.md).
14
14
 
15
15
  ## Map ownership before proposing types
16
16
 
@@ -10,7 +10,7 @@ stacks: [ios]
10
10
 
11
11
  You diagnose iOS hangs, view-update cost, launch latency and retained memory using the app's concrete object graph and profiler evidence. Return a focused experiment and fix proposal.
12
12
 
13
- Read the [project brief](../docs/agent-context.md) once, or reuse the supplied brief. Apply [mobile-ios](../skills/mobile-ios/SKILL.md) and its [performance reference](../skills/mobile-ios/references/performance-release.md).
13
+ Read the [project brief](../docs/agent-context.md) once, or reuse the supplied brief. Apply [mobile-ios](../skills/mobile-ios/SKILL.md) and its [performance reference](../skills/mobile-ios/references/performance-release.md). For budgets, the benchmark harness and CI regression gates, add [mobile-performance](../skills/mobile-performance/SKILL.md) and its [iOS reference](../skills/mobile-performance/references/ios.md); battery and background work are in its [background reference](../skills/mobile-performance/references/background.md).
14
14
 
15
15
  ## Pin the observation
16
16
 
@@ -1,16 +1,16 @@
1
1
  ---
2
2
  name: kmp-architect
3
- description: Use this agent to design or review Kotlin Multiplatform architecture across `commonMain`, Android/iOS source sets and host apps. It traces real shared domain types, `expect`/`actual` or injected interfaces, framework exports and state ownership before choosing what to share. Typical triggers are moving a feature into a shared module, untangling `iosMain`/`androidMain`, and deciding whether UI or only logic should be shared.
3
+ description: Use this agent to design or review Kotlin Multiplatform architecture across `commonMain`, Android/iOS source sets and host apps. It traces real shared domain types, `expect`/`actual` or injected interfaces, framework exports and state ownership before choosing what to share. Typical triggers are moving a feature into a shared module, untangling `iosMain`/`androidMain`, deciding whether UI or only logic should be shared, and placing an offline queue and conflict resolution in shared code.
4
4
  model: inherit
5
5
  color: cyan
6
6
  tools: ["Read", "Grep", "Glob"]
7
- intents: [architecture]
7
+ intents: [architecture, offline]
8
8
  stacks: [kotlin-multiplatform]
9
9
  ---
10
10
 
11
11
  You own the shared-versus-target boundary, not an Android module diagram with an iOS folder appended. Produce a read-only design based on the targets and symbols this project actually builds.
12
12
 
13
- Read the [project brief](../docs/agent-context.md) once or reuse the caller's verified brief. Apply [mobile-kmp](../skills/mobile-kmp/SKILL.md), its [source-set guide](../skills/mobile-kmp/references/source-sets.md) and [mobile-architecture](../skills/mobile-architecture/SKILL.md) with the [KMP architecture reference](../skills/mobile-architecture/references/kotlin-multiplatform.md).
13
+ Read the [project brief](../docs/agent-context.md) once or reuse the caller's verified brief. Apply [mobile-kmp](../skills/mobile-kmp/SKILL.md), its [source-set guide](../skills/mobile-kmp/references/source-sets.md) and [mobile-architecture](../skills/mobile-architecture/SKILL.md) with the [KMP architecture reference](../skills/mobile-architecture/references/kotlin-multiplatform.md). When the design involves working offline, queued writes or synchronization, add [mobile-offline-sync](../skills/mobile-offline-sync/SKILL.md) and its [KMP reference](../skills/mobile-offline-sync/references/kotlin-multiplatform.md).
14
14
 
15
15
  ## Trace the contract
16
16
 
@@ -10,7 +10,7 @@ stacks: [kotlin-multiplatform]
10
10
 
11
11
  You isolate one measured KMP regression and its target-specific consequence. Return a falsifiable cause and a bounded fix proposal, not a generic performance checklist.
12
12
 
13
- Read or reuse the [project brief](../docs/agent-context.md). Apply [mobile-kmp](../skills/mobile-kmp/SKILL.md), its [build/performance guide](../skills/mobile-kmp/references/build-performance.md), and the [KMP review reference](../skills/mobile-code-review/references/kotlin-multiplatform.md).
13
+ Read or reuse the [project brief](../docs/agent-context.md). Apply [mobile-kmp](../skills/mobile-kmp/SKILL.md), its [build/performance guide](../skills/mobile-kmp/references/build-performance.md), and the [KMP review reference](../skills/mobile-code-review/references/kotlin-multiplatform.md). For budgets, the benchmark harness and CI regression gates, add [mobile-performance](../skills/mobile-performance/SKILL.md) and its [KMP reference](../skills/mobile-performance/references/kotlin-multiplatform.md); battery and background work are in its [background reference](../skills/mobile-performance/references/background.md).
14
14
 
15
15
  ## Split the cost by boundary
16
16
 
@@ -36,9 +36,12 @@ Agents use the `reis-mobile:` prefix in the Agent tool. Choose by stack and deli
36
36
  | Diff regression with concrete trigger and consequence | `reis-mobile:mobile-code-reviewer` |
37
37
  | Assistive-technology journey and control semantics | `reis-mobile:mobile-accessibility-auditor` |
38
38
  | Release identity, artifact gates, notes or pipeline | `reis-mobile:mobile-release-engineer` |
39
+ | Production crash, error and release-health signals | `reis-mobile:mobile-release-engineer` |
39
40
  | Flutter channel/Pigeon contract and detach lifecycle | `reis-mobile:plugin-native-expert` |
40
41
  | Cross-toolchain cause, compatibility or migration | `reis-mobile:mobile-staff-engineer` |
41
42
 
43
+ An offline store, mutation queue or conflict strategy is an architecture assignment: give it to the detected stack's `*-architect`.
44
+
42
45
  Reuse the router/detector result; if missing, detect from the app root with `node "${CLAUDE_PLUGIN_ROOT}/bin/reis-mobile.mjs" detect`. Native specialists join a Flutter/React Native task only for implicated native paths. Do not launch the whole table for a single-file task.
43
46
 
44
47
  ## Delegation contract
@@ -1,16 +1,16 @@
1
1
  ---
2
2
  name: mobile-release-engineer
3
- description: Use this agent to get a mobile app version out safely on any stack (Flutter, native Android, native iOS, React Native and Expo) — release readiness audits with a go/no-go verdict, version and build number checks, signing and crash symbol setup (R8 mappings, dSYMs, Dart debug info, source maps), store requirements, staged rollout and rollback plans, release notes and store listing text written from the git history, and CI/CD pipelines with GitHub Actions, fastlane, EAS or Codemagic. Typical triggers are "are we ready to ship 2.3?", "write the release notes since the last tag", "set up a pipeline that uploads to TestFlight and the Play internal track" and a rejected or broken store submission.
3
+ description: Use this agent to get a mobile app version out safely on any stack (Flutter, native Android, native iOS, React Native and Expo) — release readiness audits with a go/no-go verdict, version and build number checks, signing and crash symbol setup (R8 mappings, dSYMs, Dart debug info, source maps), store requirements, staged rollout and rollback plans, release notes and store listing text written from the git history, and CI/CD pipelines with GitHub Actions, fastlane, EAS or Codemagic. It also owns production observability for a release: crash and error reporting, release-scoped metrics, alerting and sampling. Typical triggers are "are we ready to ship 2.3?", "write the release notes since the last tag", "set up a pipeline that uploads to TestFlight and the Play internal track", "why is the crash-free rate dropping on this rollout?" and a rejected or broken store submission.
4
4
  model: inherit
5
5
  color: green
6
6
  tools: ["Read", "Grep", "Glob", "Bash"]
7
- intents: [release, deployment]
7
+ intents: [release, deployment, observability]
8
8
  stacks: ["*"]
9
9
  ---
10
10
 
11
11
  You connect a proposed mobile release to the exact binary, source revision, store destination and verification evidence. Deliver a release decision or concrete release artifact appropriate to the request.
12
12
 
13
- Use the [project brief](../docs/agent-context.md) once or reuse the supplied brief. Load [mobile-release](../skills/mobile-release/SKILL.md) plus only the needed platform, store-copy or CI references. Cross-platform binaries also need their native release reference.
13
+ Use the [project brief](../docs/agent-context.md) once or reuse the supplied brief. Load [mobile-release](../skills/mobile-release/SKILL.md) plus only the needed platform, store-copy or CI references. Cross-platform binaries also need their native release reference. For production crash, error and release-health signals, add [mobile-observability](../skills/mobile-observability/SKILL.md) and its reference for the stacks in scope.
14
14
 
15
15
  ## Establish release identity
16
16
 
@@ -4,7 +4,7 @@ description: Use this agent for senior-level guidance across Flutter/Dart, Andro
4
4
  model: inherit
5
5
  color: blue
6
6
  tools: ["Read", "Grep", "Glob", "Bash"]
7
- intents: [debug, architecture, performance, test, security, migration, dependency, build]
7
+ intents: [debug, architecture, performance, test, security, migration, dependency, build, offline, observability]
8
8
  stacks: ["*"]
9
9
  ---
10
10
 
@@ -1,16 +1,16 @@
1
1
  ---
2
2
  name: rn-architect
3
- description: Use this agent to analyze or design the architecture of a React Native or Expo app — feature-based structure, separation of UI, state and data access, server state versus client state, navigation with React Navigation or Expo Router, platform-specific code, native modules and the New Architecture boundary, TypeScript contracts and monorepo setup. Typical triggers are "review the architecture of this React Native app", planning a new feature module and deciding where state and API calls should live.
3
+ description: Use this agent to analyze or design the architecture of a React Native or Expo app — feature-based structure, separation of UI, state and data access, server state versus client state, navigation with React Navigation or Expo Router, platform-specific code, native modules and the New Architecture boundary, TypeScript contracts and monorepo setup. Typical triggers are "review the architecture of this React Native app", planning a new feature module, deciding where state and API calls should live and designing offline persistence and mutation queues.
4
4
  model: inherit
5
5
  color: cyan
6
6
  tools: ["Read", "Grep", "Glob"]
7
- intents: [architecture]
7
+ intents: [architecture, offline]
8
8
  stacks: [react-native]
9
9
  ---
10
10
 
11
11
  You own React Native feature contracts, navigation and state ownership across JavaScript and native code. Produce a read-only design for the actual Expo or bare React Native project.
12
12
 
13
- Reuse the supplied brief or read the [project brief contract](../docs/agent-context.md) once. Use [mobile-architecture](../skills/mobile-architecture/SKILL.md) and its [React Native reference](../skills/mobile-architecture/references/react-native.md).
13
+ Reuse the supplied brief or read the [project brief contract](../docs/agent-context.md) once. Use [mobile-architecture](../skills/mobile-architecture/SKILL.md) and its [React Native reference](../skills/mobile-architecture/references/react-native.md). When the design involves working offline, queued writes or synchronization, add [mobile-offline-sync](../skills/mobile-offline-sync/SKILL.md) and its [React Native reference](../skills/mobile-offline-sync/references/react-native.md).
14
14
 
15
15
  ## Follow one complete interaction
16
16
 
@@ -10,7 +10,7 @@ stacks: [react-native]
10
10
 
11
11
  You identify whether a React Native slowdown comes from React work, JavaScript execution or the native UI path. Produce a diagnosis for one real journey and a measurable fix proposal.
12
12
 
13
- Reuse the caller's context or read the [project brief](../docs/agent-context.md) once. Follow [mobile-rn](../skills/mobile-rn/SKILL.md) and its [performance reference](../skills/mobile-rn/references/performance-release.md).
13
+ Reuse the caller's context or read the [project brief](../docs/agent-context.md) once. Follow [mobile-rn](../skills/mobile-rn/SKILL.md) and its [performance reference](../skills/mobile-rn/references/performance-release.md). For budgets, the benchmark harness and CI regression gates, add [mobile-performance](../skills/mobile-performance/SKILL.md) and its [React Native reference](../skills/mobile-performance/references/react-native.md); battery and background work are in its [background reference](../skills/mobile-performance/references/background.md).
14
14
 
15
15
  ## Establish the runtime
16
16
 
@@ -28,6 +28,21 @@ export const INTENTS = {
28
28
  'feature first', 'estrutura de pastas', 'state management', 'gerenciamento de estado',
29
29
  'injecao de dependencia', 'dependency injection', 'design pattern', 'camada',
30
30
  ],
31
+ offline: [
32
+ 'offline', 'off-line', 'sem conexao', 'sem internet', 'sem rede', 'modo aviao',
33
+ 'airplane mode', 'sincroniza', 'sync', 'dessincroniz', 'out of sync', 'conflito',
34
+ 'conflict', 'idempot', 'fila de operac', 'operation queue', 'outbox', 'reconect',
35
+ 'reconnect', 'local-first', 'local first', 'cache local', 'last write wins',
36
+ 'ultima escrita vence', 'replica',
37
+ ],
38
+ observability: [
39
+ 'observab', 'telemetri', 'telemetry', 'opentelemetry', 'crashlytics', 'sentry',
40
+ 'datadog', 'new relic', 'firebase analytics', 'analytics', 'monitorament', 'monitoring',
41
+ 'structured log', 'log estruturad', 'logging', 'alerta', 'alert', 'sampling',
42
+ 'amostragem', 'distributed trac', 'trace distribu', 'correlation id', 'correlation-id',
43
+ 'crash-free', 'crash free', 'error reporting', 'relatorio de erro', 'breadcrumb',
44
+ 'slo', 'sli',
45
+ ],
31
46
  release: [
32
47
  'release', 'publica', 'publish', 'loja', 'app store', 'play store', 'testflight',
33
48
  'lancamento', 'submission', 'store review', 'rejeita', 'reject',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reis-mobile",
3
- "version": "0.7.3",
3
+ "version": "0.8.0",
4
4
  "description": "AI agents and skills for Flutter, Android, iOS, React Native and Kotlin Multiplatform — a Claude Code and Codex plugin for reviews, debugging, tests, architecture, security and Firebase.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -18,9 +18,12 @@ One accessibility process for every mobile stack. This file holds what is true e
18
18
  | Native iOS: SwiftUI or UIKit | [references/ios.md](references/ios.md) |
19
19
  | React Native or Expo | [references/react-native.md](references/react-native.md) |
20
20
  | Kotlin Multiplatform with shared Compose UI or native host UI | [references/kotlin-multiplatform.md](references/kotlin-multiplatform.md) |
21
+ | Localization, plurals, formatting and right-to-left layout, on any stack | [references/localization.md](references/localization.md) |
21
22
 
22
23
  In Flutter and React Native apps, the native reference applies only to screens or components written natively (platform views, native modules with UI).
23
24
 
25
+ Localization is reviewed with accessibility because it breaks the same things — a layout that assumed one text length, a fixed-height label, text baked into an image. When the app ships in more than one language, or in a right-to-left one, read [references/localization.md](references/localization.md) alongside this file.
26
+
24
27
  ## 2. What a screen reader user needs
25
28
 
26
29
  Every interactive element exposes four things to the accessibility tree. Check them in this order:
@@ -0,0 +1,77 @@
1
+ # Localization and internationalization
2
+
3
+ Applies to every stack. Localization sits next to accessibility because it breaks the same things: a layout that assumed one text length, a string that assumed one grammar, and a date that assumed one calendar. An app that survives the largest accessibility font size usually survives German; one that does not, does not.
4
+
5
+ ## The rules that hold on every platform
6
+
7
+ **No user-visible string in code.** Every string lives in the platform's resource system, keyed, with the source language as the base. A hard-coded string is not translatable and will not be found by review; grep for string literals inside UI code as the first pass of an audit.
8
+
9
+ **Never build a sentence by concatenation.** `"You have " + n + " messages"` cannot be translated: word order, pluralization and grammatical gender all differ. Use a parameterized string with named placeholders, so the translator can reorder them:
10
+
11
+ ```
12
+ "order_shipped_on": "Your order {orderId} ships on {date}"
13
+ ```
14
+
15
+ **Plurals are a category, not a number.** English has two forms; Polish has four; Arabic has six; Japanese has one. `if (n == 1)` is wrong in most languages. Every platform implements the CLDR plural categories (`zero`, `one`, `two`, `few`, `many`, `other`) — use them:
16
+
17
+ | Stack | Mechanism |
18
+ |---|---|
19
+ | Android | `<plurals>` resources and `getQuantityString` |
20
+ | iOS | A stringsdict / the `String Catalog`'s plural variations, with `NSLocalizedString` |
21
+ | Flutter | ICU message syntax in ARB files (`{count, plural, =0{...} one{...} other{...}}`) with `flutter_localizations` and `gen_l10n` |
22
+ | React Native | `i18next` with the ICU or plural suffix conventions, `react-intl`, or `Intl.PluralRules` directly |
23
+ | Kotlin Multiplatform | Compose Multiplatform resources, or host resources through `expect`/`actual` — check the plural support of the version in use |
24
+
25
+ **Never format data by hand.** Dates, times, numbers, currencies, percentages, lists and relative times all have locale rules, and `"$" + amount` is wrong in most of the world. Use the platform formatter (`NumberFormat`/`DateTimeFormatter`, `Intl.*`, `NumberFormat`/`DateFormat` in Dart's `intl`, `FormatStyle` in Swift). Currency in particular: the symbol, its position, the decimal separator and the number of decimal places are all per-locale, and the currency itself is a property of the *price*, not of the user.
26
+
27
+ **Device locale, app language, and region are three things.** A user can read Portuguese, live in Japan and want metric units. Recent platforms support a per-app language setting (Android's per-app language preferences, iOS's app language in Settings) — support it rather than reading only the device's first locale, and never infer language from the country or from a SIM.
28
+
29
+ ## Right-to-left
30
+
31
+ Arabic, Hebrew, Persian and Urdu mirror the interface. Getting this right is mostly a matter of never expressing a direction as "left" or "right":
32
+
33
+ - Use **start/end** everywhere: `paddingStart`, `layoutDirection`-aware `EdgeInsets.directional`, `marginStart`, SwiftUI's automatic leading/trailing. A `paddingLeft` is a bug in RTL.
34
+ - **Icons that imply direction mirror; icons that depict objects do not.** A back arrow and a progress chevron mirror; a play button, a clock and a logo do not. Both platforms have a flag for automatic mirroring (`autoMirrored` in Android vector drawables and Material icons, `flipsForRightToLeftLayoutDirection` on iOS images, `matchTextDirection` in Flutter); set it deliberately per icon.
35
+ - **Numbers and embedded Latin text inside RTL** follow the bidirectional algorithm and can render in a surprising order. Test with real strings containing a phone number, a price and a URL.
36
+ - Test it without waiting for a translation: Android's "Force RTL layout direction" developer option, Xcode's right-to-left pseudolanguage, and Flutter's `Directionality` widget in a test all show the layout before any Arabic exists.
37
+
38
+ ## Layout that survives translation
39
+
40
+ - **Assume text grows.** German, Finnish and Russian commonly run 30–50% longer than English, and short strings grow proportionally more. Buttons and tabs with fixed widths, and single-line labels with `maxLines: 1` and no ellipsis, are where this shows.
41
+ - **No fixed heights on text containers**, for the same reason as text scaling in [the accessibility checklist](../SKILL.md).
42
+ - **Do not put text into images.** It cannot be translated, it does not scale with the font size setting, and screen readers cannot read it.
43
+ - **Pseudolocalization** finds these before translation exists: both platforms can render the app in an accented, expanded pseudo-language that makes truncation and hard-coded strings obvious at a glance. Run it in the normal review pass.
44
+
45
+ ## Giving translators what they need
46
+
47
+ A translator sees a key and a string, not the screen. Ambiguous strings become wrong translations:
48
+
49
+ - **Comments on every non-obvious string.** "Open" as a verb on a button and "Open" as a status adjective are different words in most languages, and the resource comment is the only way the translator knows which.
50
+ - **Character limits** where the UI constrains the text, declared with the string.
51
+ - **Stable keys** that describe the role (`checkout_confirm_button`), not the English text — renaming the English copy should not orphan the translation.
52
+ - **Keep the placeholders documented**: what `{count}` counts, what `{name}` names.
53
+
54
+ ## Reviewing
55
+
56
+ - [ ] No user-visible string literals in UI code.
57
+ - [ ] No sentence assembled by concatenation or string interpolation of fragments.
58
+ - [ ] Plurals use the platform's plural resources, not `if (n == 1)`.
59
+ - [ ] Dates, numbers and currencies use a locale-aware formatter; no manual symbol or separator.
60
+ - [ ] Layout uses start/end, not left/right; directional icons are marked as mirrorable.
61
+ - [ ] No fixed widths or heights on text containers; no text baked into images.
62
+ - [ ] The per-app language setting is supported, and the app does not infer language from the region.
63
+ - [ ] Strings carry comments and, where relevant, length limits.
64
+ - [ ] The app has been seen in pseudolocale and in forced RTL, at the largest font size.
65
+ - [ ] Anything untranslated falls back to the base language rather than showing a key.
66
+
67
+ The last three are the ones that catch real defects. Everything else can pass review and still produce a broken screen in Arabic at 200% font size, which is why the check is visual.
68
+
69
+ ## Official documentation
70
+
71
+ - Android localization: https://developer.android.com/guide/topics/resources/localization
72
+ - Android per-app language preferences: https://developer.android.com/guide/topics/resources/app-languages
73
+ - Android bidirectional text support: https://developer.android.com/training/basics/supporting-devices/languages
74
+ - Apple localization: https://developer.apple.com/documentation/xcode/localization
75
+ - Flutter internationalization: https://docs.flutter.dev/ui/accessibility-and-internationalization/internationalization
76
+ - React Native right-to-left and localization: https://reactnative.dev/blog/2016/08/19/right-to-left-support-for-react-native-apps
77
+ - Unicode CLDR plural rules: https://cldr.unicode.org/index/cldr-spec/plural-rules