Imported from Kaguara/emerging-market-skills (
AGENTS.md). Install upstream withnpx skills add Kaguara/emerging-market-skills. Copyright stays with the author.
Building for emerging markets
Drop this file at the root of your project. Every rule below is a constraint for software used on entry-level devices, over intermittent and expensive connections, by people whose first computer is the phone in their hand.
Full guidance, worked code, and runnable validators: https://github.com/Kaguara/emerging-market-skills
The design target
Unless told otherwise, assume tier C: an entry-level Android phone with 1–2GB of RAM shared with the OS, a CPU roughly a quarter as fast as a current flagship, storage permanently near full, an ageing battery, on congested 3G with frequent handover, paid for from a prepaid bundle bought in small increments.
The four constraints
- Network — not slow, but intermittent, ambiguous, and dishonest. Requests that neither succeed nor fail. Connectivity flags reporting a live link that carries no traffic to your origin.
- Device — memory and CPU that fall off cliffs rather than degrading smoothly. Your process is a candidate for termination whenever it backgrounds.
- Cost — two meters running: yours per SMS, per API call, per token; theirs per megabyte, prepaid.
- Interface — read in a language with longer words than English, sometimes by someone using a smartphone for the first time.
How to apply this
Severity means: critical — the product does not work for the target user. warning — measurable degradation. advisory — a better default.
When you flag something, cite the rule ID. When something is wrong and no rule covers it, say so and label it judgment rather than inventing a citation.
Emerging market review
| ID | Rule | Severity |
|---|---|---|
| REVIEW-001 | Establish the target market, device tier, and network profile before reviewing. | critical |
| REVIEW-002 | Every finding cites a rule ID, or is labelled as unsourced judgment. | critical |
| REVIEW-003 | Locate every finding in the artifact before reporting it. | critical |
| REVIEW-004 | Rank findings by user impact at the target tier, not by ease of fix. | warning |
| REVIEW-005 | State what was not checked. | warning |
Network resilience
The connection is not slow. It is intermittent, asymmetric, and dishonest — it disappears mid-request, reports itself as live while carrying no traffic to your
| ID | Rule | Severity |
|---|---|---|
| NET-001 | Render from local state first; never block first paint on a network call. | critical |
| NET-002 | Queue every state-changing request durably before attempting it. | critical |
| NET-003 | Every state-changing request carries a client-generated idempotency key. | critical |
| NET-004 | Pending, queued, and failed states are visible and honest in the UI. | critical |
| NET-005 | Set explicit request timeouts sized for the target network, not the default. | warning |
| NET-006 | Retry with capped exponential backoff and jitter; never tight-loop. | warning |
| NET-007 | Treat the connectivity flag as a hint, not a fact. | warning |
| NET-008 | Honour metered-connection and data-saver signals. | warning |
| NET-009 | Declare a conflict-resolution policy for every entity that syncs. | warning |
| NET-010 | Batch and compress; minimise round trips over payload elegance. | advisory |
| NET-011 | Size a partner integration for their slowest component, not for their API's stated limits. | critical |
| NET-012 | Never let a third party's connectivity probe decide whether your app may call your API. | critical |
Payload budgets
Bytes cost money that the user paid in advance, arrive over a link that drops, and land on a device that is already full. A download that fails at 80% is
| ID | Rule | Severity |
|---|---|---|
| SIZE-001 | Declare a byte budget per platform before writing the feature. | critical |
| SIZE-002 | Keep the Android initial download at or below 15MB. | critical |
| SIZE-003 | Budgets are enforced by CI and fail the build when exceeded. | critical |
| SIZE-004 | Measure the cold-cache first visit on a tier C device, not a warm reload. | warning |
| SIZE-005 | Serve images sized to the rendered box, in a modern format, responsively. | warning |
| SIZE-006 | Cap first-load JavaScript on the critical path at 200KB compressed. | warning |
| SIZE-007 | Every third-party script has a named owner and counts against the budget. | warning |
| SIZE-008 | Load secondary features on demand rather than at install or first paint. | warning |
| SIZE-009 | Never block first paint on a web font. | warning |
| SIZE-010 | Budget the installed storage footprint, not only the download. | advisory |
Low end device performance
The reference device has 1–2GB of RAM shared with the operating system, a CPU roughly a quarter as fast as the phone in your pocket, storage that is almost
| ID | Rule | Severity |
|---|---|---|
| PERF-001 | Name a reference device at tier C and make it the definition of "works". | critical |
| PERF-002 | Assume the process will be killed at any moment and restore state on return. | critical |
| PERF-003 | Bound every in-memory cache, especially image caches. | critical |
| PERF-004 | Keep long tasks off the main thread; never block input for more than 200ms. | warning |
| PERF-005 | Recycle or virtualise any list that can exceed one screen. | warning |
| PERF-006 | Precompute on the server what the device would otherwise compute. | warning |
| PERF-007 | Cap background work, wake locks, and polling. | warning |
| PERF-008 | Animate only compositor-friendly properties, and honour reduced motion. | advisory |
| PERF-009 | Give any on-device inference or heavy computation a server or static fallback. | advisory |
| PERF-010 | Test every bottom-anchored control with three-button navigation and the OEM skin of the reference device. | warning |
Integration cost modeling
Two meters are running. Yours: per SMS, per verification, per API call, per thousand tokens, per gigabyte of egress. Theirs: a prepaid data bundle bought in
| ID | Rule | Severity |
|---|---|---|
| COST-001 | Every user-facing action has a stated marginal cost before it is built. | critical |
| COST-002 | Choose the delivery channel by cost per delivered outcome, not by convenience. | critical |
| COST-003 | Rate-limit and de-duplicate every paid outbound message. | warning |
| COST-004 | Cap AI and inference spend per session with a hard ceiling and a fallback. | warning |
| COST-005 | Never spend the user's data allowance on telemetry or prefetch you chose. | warning |
| COST-006 | Cache and batch third-party calls against a known per-call price. | warning |
| COST-007 | Decide fail-open or fail-closed for every paid dependency, in writing. | warning |
| COST-008 | Serve from a region near the user and count egress. | warning |
| COST-009 | Re-check unit costs against real usage within a month of launch. | warning |
| COST-010 | Find out whether the operator will zero-rate your traffic before you spend a quarter optimising bytes. | warning |
Localization and literacy ux
The interface will be read in a language whose words are longer than English's, by someone who may be literate in a different language than the one on screen,
| ID | Rule | Severity |
|---|---|---|
| LOC-001 | Text containers stretch; never fix the height or width of a box holding a string. | critical |
| LOC-002 | Build sentences with a message formatter, never string concatenation. | critical |
| LOC-003 | Format numbers, dates, currency, and names with locale data, never by hand. | warning |
| LOC-004 | Run pseudo-localization in CI at the expansion factor of your longest language. | warning |
| LOC-005 | Never let an icon carry meaning on its own. | warning |
| LOC-006 | Use logical layout properties so right-to-left works without a second layout. | warning |
| LOC-007 | Every critical flow is completable without reading a paragraph. | warning |
| LOC-008 | Language is an explicit, persisted user choice, not an inference. | warning |
| LOC-009 | Do not hardcode the shape of names, addresses, or phone numbers. | warning |
| LOC-010 | Error messages name the cause and the next action, in plain translated language. | advisory |
Identity and onboarding
The identifier is rented: prepaid SIMs are recycled, users carry several, and the number on the account may already belong to someone else. The authority you
| ID | Rule | Severity |
|---|---|---|
| IDN-001 | Treat the phone number as a rented identifier, not as an identity. | critical |
| IDN-002 | Give every identity-authority call an explicit deadline and a defined outcome at that deadline. | critical |
| IDN-003 | Publish upstream authority status to the people depending on it, in real time. | critical |
| IDN-004 | Evaluate biometric capture stratified by skin tone, using the Monk Skin Tone scale. | critical |
| IDN-005 | Gate capture quality on the device, before anything is uploaded. | critical |
| IDN-006 | Design capture for a poor camera in poor light, and say what to fix. | warning |
| IDN-007 | Never assume the OTP arrived. | warning |
| IDN-008 | Account recovery must not depend on one channel or one device. | warning |
| IDN-009 | Do not block onboarding on a document a legitimate user may not hold. | warning |
| IDN-010 | Assume the device is shared. | warning |
Before you claim any of this is verified
Static rules find structure, not truth. The device finds the truth:
- Measure the cold-cache first visit on a real entry-level device, not a warm reload on a developer machine.
- Kill the process mid-flow (
adb shell am kill <package>) and confirm the user's work survived. - Throttle to ~400kbps with 400ms RTT and drop the connection mid-request — that is the case that finds bugs, not airplane mode.
- Segment every metric by device tier. A p50 pooling flagship and entry-level users describes a device population that does not exist.
Rules carry evidence tags in the source repository — field (observed shipping a product), published (research), or vendor (platform documentation). Critical rules cannot be merged without one.