mobile-ai-agents 1.0.23
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 +228 -0
- package/CLAUDE.md +236 -0
- package/LICENSE +21 -0
- package/README.md +652 -0
- package/agents/android/android-crash-analyzer/README.md +134 -0
- package/agents/android/android-crash-analyzer/agent.md +206 -0
- package/agents/android/android-crash-analyzer/example-input.md +138 -0
- package/agents/android/android-crash-analyzer/example-output.md +225 -0
- package/agents/android/anr-investigation/README.md +78 -0
- package/agents/android/anr-investigation/agent.md +117 -0
- package/agents/android/anr-investigation/example-input.md +62 -0
- package/agents/android/anr-investigation/example-output.md +103 -0
- package/agents/android/axiom/agent.md +197 -0
- package/agents/android/code-reviewer/README.md +108 -0
- package/agents/android/code-reviewer/agent.md +210 -0
- package/agents/android/code-reviewer/example-input.md +116 -0
- package/agents/android/code-reviewer/example-output.md +115 -0
- package/agents/android/compose-navigation/README.md +76 -0
- package/agents/android/compose-navigation/agent.md +121 -0
- package/agents/android/compose-navigation/example-input.md +49 -0
- package/agents/android/compose-navigation/example-output.md +325 -0
- package/agents/android/compose-screen-builder/README.md +95 -0
- package/agents/android/compose-screen-builder/agent.md +170 -0
- package/agents/android/compose-screen-builder/example-input.md +40 -0
- package/agents/android/compose-screen-builder/example-output.md +568 -0
- package/agents/android/compose-ui-reviewer/README.md +73 -0
- package/agents/android/compose-ui-reviewer/agent.md +253 -0
- package/agents/android/compose-ui-reviewer/example-input.md +84 -0
- package/agents/android/compose-ui-reviewer/example-output.md +102 -0
- package/agents/android/crash-analyzer/README.md +53 -0
- package/agents/android/crash-analyzer/agent.md +295 -0
- package/agents/android/memory-leak-analyzer/README.md +79 -0
- package/agents/android/memory-leak-analyzer/agent.md +116 -0
- package/agents/android/memory-leak-analyzer/example-input.md +78 -0
- package/agents/android/memory-leak-analyzer/example-output.md +128 -0
- package/agents/cross-platform/accessibility-auditor/README.md +47 -0
- package/agents/cross-platform/accessibility-auditor/agent.md +268 -0
- package/agents/cross-platform/accessibility-auditor/example-input.md +84 -0
- package/agents/cross-platform/accessibility-auditor/example-output.md +132 -0
- package/agents/cross-platform/appforge/agent.md +303 -0
- package/agents/cross-platform/ci-cd-generator/README.md +65 -0
- package/agents/cross-platform/ci-cd-generator/agent.md +422 -0
- package/agents/cross-platform/ci-cd-generator/example-input.md +69 -0
- package/agents/cross-platform/ci-cd-generator/example-output.md +261 -0
- package/agents/cross-platform/crasher/agent.md +221 -0
- package/agents/cross-platform/figma/agent.md +247 -0
- package/agents/cross-platform/launchpad/agent.md +330 -0
- package/agents/cross-platform/mobile-harness/agent.md +422 -0
- package/agents/cross-platform/mobile-memory/agent.md +429 -0
- package/agents/cross-platform/perf/agent.md +261 -0
- package/agents/cross-platform/pipeline/agent.md +288 -0
- package/agents/cross-platform/release-notes-generator/README.md +63 -0
- package/agents/cross-platform/release-notes-generator/agent.md +218 -0
- package/agents/cross-platform/release-notes-generator/example-input.md +71 -0
- package/agents/cross-platform/release-notes-generator/example-output.md +96 -0
- package/agents/cross-platform/scribe/agent.md +180 -0
- package/agents/cross-platform/security-scanner/README.md +61 -0
- package/agents/cross-platform/security-scanner/agent.md +287 -0
- package/agents/cross-platform/security-scanner/example-input.md +77 -0
- package/agents/cross-platform/security-scanner/example-output.md +141 -0
- package/agents/cross-platform/sentinel/agent.md +217 -0
- package/agents/cross-platform/store-listing-writer/README.md +58 -0
- package/agents/cross-platform/store-listing-writer/agent.md +380 -0
- package/agents/cross-platform/store-listing-writer/example-input.md +67 -0
- package/agents/cross-platform/store-listing-writer/example-output.md +131 -0
- package/agents/flutter/bloc-feature-builder/README.md +101 -0
- package/agents/flutter/bloc-feature-builder/agent.md +225 -0
- package/agents/flutter/bloc-feature-builder/example-input.md +47 -0
- package/agents/flutter/bloc-feature-builder/example-output.md +838 -0
- package/agents/flutter/dart/agent.md +223 -0
- package/agents/flutter/widget-generator/README.md +66 -0
- package/agents/flutter/widget-generator/agent.md +264 -0
- package/agents/flutter/widget-generator/example-input.md +71 -0
- package/agents/flutter/widget-generator/example-output.md +163 -0
- package/agents/gaming/forge/agent.md +197 -0
- package/agents/gaming/unreal/agent.md +200 -0
- package/agents/ios/crash-analyzer/README.md +69 -0
- package/agents/ios/crash-analyzer/agent.md +300 -0
- package/agents/ios/crash-analyzer/example-input.md +83 -0
- package/agents/ios/crash-analyzer/example-output.md +126 -0
- package/agents/ios/swift/agent.md +206 -0
- package/agents/ios/swift-reviewer/README.md +68 -0
- package/agents/ios/swift-reviewer/agent.md +231 -0
- package/agents/ios/swift-reviewer/example-input.md +100 -0
- package/agents/ios/swift-reviewer/example-output.md +127 -0
- package/agents/react-native/bridge/agent.md +212 -0
- package/agents/react-native/performance-optimizer/README.md +81 -0
- package/agents/react-native/performance-optimizer/agent.md +284 -0
- package/agents/react-native/performance-optimizer/example-input.md +104 -0
- package/agents/react-native/performance-optimizer/example-output.md +132 -0
- package/agents/unity/shader-generator/README.md +77 -0
- package/agents/unity/shader-generator/agent.md +270 -0
- package/agents/unity/shader-generator/example-input.md +70 -0
- package/agents/unity/shader-generator/example-output.md +160 -0
- package/agents/unreal/blueprint-advisor/README.md +71 -0
- package/agents/unreal/blueprint-advisor/agent.md +311 -0
- package/agents/unreal/blueprint-advisor/example-input.md +73 -0
- package/agents/unreal/blueprint-advisor/example-output.md +217 -0
- package/cli/index.js +1091 -0
- package/docs/agent-guide.md +138 -0
- package/docs/chatgpt-integration.md +219 -0
- package/docs/core-loops.md +143 -0
- package/docs/cursor-integration.md +143 -0
- package/docs/getting-started.md +132 -0
- package/docs/index.html +711 -0
- package/docs/installation.md +271 -0
- package/docs/mobile-harness.md +160 -0
- package/docs/mobile-mcp.md +172 -0
- package/docs/mobile-memory.md +349 -0
- package/docs/release-process.md +85 -0
- package/docs/releases/release-v1.0.0.md +165 -0
- package/docs/roadmap/github-issues.md +239 -0
- package/docs/skill-categories.md +125 -0
- package/docs/vscode-copilot-integration.md +104 -0
- package/docs/wiki.md +615 -0
- package/install.sh +507 -0
- package/mobile-karpathy.md +79 -0
- package/package.json +57 -0
- package/skills/android/README.md +31 -0
- package/skills/android/android-tdd.md +89 -0
- package/skills/android/anr-investigation.md +251 -0
- package/skills/android/code-review.md +98 -0
- package/skills/android/compose-migration.md +48 -0
- package/skills/android/compose-review.md +78 -0
- package/skills/android/kotlin-modernize.md +51 -0
- package/skills/android/memory-leak-investigation.md +256 -0
- package/skills/android/proguard-rules.md +48 -0
- package/skills/cross-platform/accessibility-audit.md +63 -0
- package/skills/cross-platform/api-versioning.md +59 -0
- package/skills/cross-platform/clean-code-audit.md +239 -0
- package/skills/cross-platform/crash-triage.md +53 -0
- package/skills/cross-platform/deeplink-debug.md +57 -0
- package/skills/cross-platform/feature-slice.md +48 -0
- package/skills/cross-platform/grill-mobile.md +64 -0
- package/skills/cross-platform/mobile-mcp-qa.md +193 -0
- package/skills/cross-platform/mobile-memory-graph.md +179 -0
- package/skills/cross-platform/mobile-memory-save.md +210 -0
- package/skills/cross-platform/mobile-memory-search.md +154 -0
- package/skills/cross-platform/perf-audit.md +61 -0
- package/skills/cross-platform/prd-verification.md +324 -0
- package/skills/cross-platform/release-prep.md +64 -0
- package/skills/cross-platform/security-audit.md +281 -0
- package/skills/cross-platform/store-listing.md +75 -0
- package/skills/flutter/README.md +32 -0
- package/skills/flutter/dart-modernize.md +47 -0
- package/skills/flutter/flutter-review.md +59 -0
- package/skills/flutter/flutter-tdd.md +73 -0
- package/skills/flutter/widget-extract.md +41 -0
- package/skills/flutter/widget-gen.md +131 -0
- package/skills/gaming/blueprint-to-cpp.md +51 -0
- package/skills/gaming/game-perf.md +54 -0
- package/skills/gaming/shader-gen.md +44 -0
- package/skills/gaming/unity-tdd.md +85 -0
- package/skills/ios/README.md +45 -0
- package/skills/ios/data-persistence.md +151 -0
- package/skills/ios/ios-tdd.md +90 -0
- package/skills/ios/networking.md +139 -0
- package/skills/ios/performance.md +122 -0
- package/skills/ios/swift-concurrency.md +57 -0
- package/skills/ios/swift-review.md +124 -0
- package/skills/ios/swiftui-review.md +49 -0
- package/skills/ios/swiftui-state.md +122 -0
- package/skills/ios/unit-testing.md +144 -0
- package/skills/ios/xcode-warnings.md +37 -0
- package/skills/react-native/README.md +42 -0
- package/skills/react-native/bridge-audit.md +104 -0
- package/skills/react-native/expo-optimize.md +55 -0
- package/skills/react-native/new-arch-migrate.md +53 -0
- package/skills/react-native/performance.md +124 -0
- package/skills/react-native/rn-review.md +53 -0
- package/skills/react-native/rn-tdd.md +76 -0
- package/skills/shared/README.md +46 -0
- package/skills/shared/accessibility-audit.md +132 -0
- package/skills/shared/crash-analysis.md +110 -0
- package/skills/shared/security-scan.md +149 -0
- package/skills/unity/README.md +31 -0
- package/skills/unity/shader-review.md +110 -0
- package/templates/agent-template.md +88 -0
- package/templates/prompt-template.md +50 -0
- package/templates/skill-template.md +64 -0
- package/templates/workflow-template.md +48 -0
- package/workflows/app-launch.md +66 -0
- package/workflows/appforge-workflow.md +232 -0
- package/workflows/ci-setup.md +77 -0
- package/workflows/crash-to-fix.md +71 -0
- package/workflows/feature-ship.md +61 -0
- package/workflows/game-level.md +72 -0
- package/workflows/mobile-harness.md +319 -0
- package/workflows/mobile-mcp-qa.md +228 -0
- package/workflows/mobile-memory-workflow.md +243 -0
- package/workflows/new-project-setup.md +93 -0
- package/workflows/new-screen.md +68 -0
- package/workflows/perf-sprint.md +78 -0
- package/workflows/release-cycle.md +71 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Example Output — Release Notes Generator
|
|
2
|
+
|
|
3
|
+
Full agent response to the input in [`example-input.md`](example-input.md).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
═══════════════════════════════════════
|
|
9
|
+
RELEASE NOTES — Taskly 3.2.0
|
|
10
|
+
═══════════════════════════════════════
|
|
11
|
+
|
|
12
|
+
[USER-FACING — App Store / Play Store]
|
|
13
|
+
(1,284 / 4,000 characters)
|
|
14
|
+
|
|
15
|
+
What's New in 3.2.0
|
|
16
|
+
--------------------
|
|
17
|
+
• Recurring Tasks — Set any task to repeat daily, weekly, monthly, or on a
|
|
18
|
+
completely custom schedule. Your routines, automated.
|
|
19
|
+
|
|
20
|
+
• Dark Mode for Task Details — The task detail screen now looks great in dark mode.
|
|
21
|
+
|
|
22
|
+
• A satisfying haptic pulse when you complete a task — small joy, big motivation.
|
|
23
|
+
|
|
24
|
+
• Fresh onboarding — New users get a cleaner, friendlier welcome experience.
|
|
25
|
+
|
|
26
|
+
• Taskly opens and loads your tasks noticeably faster — about 40% faster in our tests.
|
|
27
|
+
|
|
28
|
+
Bug Fixes
|
|
29
|
+
---------
|
|
30
|
+
• Fixed a crash that could happen when tapping a notification while Taskly was
|
|
31
|
+
in the background.
|
|
32
|
+
|
|
33
|
+
• Fixed the home screen widget showing the wrong due date for some tasks.
|
|
34
|
+
|
|
35
|
+
• Fixed push notification badge counts not clearing after you mark tasks as done.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
[DEVELOPER CHANGELOG]
|
|
40
|
+
|
|
41
|
+
## 3.2.0
|
|
42
|
+
|
|
43
|
+
### Features
|
|
44
|
+
- Add recurring task support with custom intervals [e4f5g6h]
|
|
45
|
+
- Add dark mode support for task detail screen [w1x2y3z]
|
|
46
|
+
- Add haptic feedback on task completion [k1l2m3n]
|
|
47
|
+
- Update onboarding flow for new users [m1n2o3p]
|
|
48
|
+
|
|
49
|
+
### Fixes
|
|
50
|
+
- Fix crash when opening notification while app is backgrounded [a1b2c3d]
|
|
51
|
+
- Fix incorrect due date display in widget [q4r5s6t]
|
|
52
|
+
- Fix push notification badge count after clearing tasks [o4p5q6r]
|
|
53
|
+
|
|
54
|
+
### Performance
|
|
55
|
+
- Improve task list loading speed by ~40% [i7j8k9l]
|
|
56
|
+
- Refactor CoreData stack to use background contexts [s7t8u9v]
|
|
57
|
+
|
|
58
|
+
### Internal / Infra
|
|
59
|
+
- Remove deprecated legacy sync API [g7h8i9j]
|
|
60
|
+
|
|
61
|
+
### Filtered (noise)
|
|
62
|
+
- Merge branch 'feature/recurring-tasks' into main [u7v8w9x] — merge commit
|
|
63
|
+
- Bump build version to 312 [y1z2a3b] — version bump
|
|
64
|
+
- Fix typo in settings screen label [c4d5e6f] — cosmetic
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
[QA NOTES]
|
|
69
|
+
(Internal — regression testing priorities)
|
|
70
|
+
|
|
71
|
+
Risk Areas This Release:
|
|
72
|
+
|
|
73
|
+
- Recurring Tasks (NEW FEATURE): End-to-end test all interval types (daily, weekly,
|
|
74
|
+
monthly, custom). Critical path: create recurring task → complete it → verify it
|
|
75
|
+
reappears correctly. Edge cases: timezone change mid-recurrence, recurring task due
|
|
76
|
+
today on first app launch, recurrence across month/year boundary.
|
|
77
|
+
|
|
78
|
+
- CoreData Background Context Refactor (HIGH RISK): This is a structural change —
|
|
79
|
+
test ALL task CRUD operations. Priority: create task → force-quit → relaunch →
|
|
80
|
+
task persists. Concurrent writes: rapidly create multiple tasks while sync is running.
|
|
81
|
+
No data loss acceptable.
|
|
82
|
+
|
|
83
|
+
- Push Notification Badge: Test badge count resets to 0 after clearing all tasks.
|
|
84
|
+
Test on iOS 17 and iOS 18 separately (UNUserNotificationCenter behavior changed in 17.4).
|
|
85
|
+
|
|
86
|
+
- Widget Due Date: Verify widget refreshes after task is edited. Test all three widget
|
|
87
|
+
sizes. Test after device restart (widget cache invalidation).
|
|
88
|
+
|
|
89
|
+
- Notification Crash: Navigate to app via notification while app is suspended (not just
|
|
90
|
+
backgrounded). Confirm no crash across iOS 16, 17, 18.
|
|
91
|
+
|
|
92
|
+
Deprecated / Removed:
|
|
93
|
+
- Legacy sync API removed [g7h8i9j] — confirm no remaining call sites in the codebase.
|
|
94
|
+
QA: on first launch after updating from 3.1.x, verify no sync errors appear in
|
|
95
|
+
Console.app logs. Check Settings → Account → Sync Status shows healthy.
|
|
96
|
+
```
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# SCRIBE — Release Notes Writer
|
|
2
|
+
|
|
3
|
+
**Platform:** Cross-Platform (All)
|
|
4
|
+
**Personality:** User-first writer. Translates git commits into things humans actually understand.
|
|
5
|
+
**Category:** Communication / Release Management
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
Converts raw git commit logs into polished, user-facing release notes suitable for App Store, Play Store, internal changelogs, and stakeholder summaries. Filters noise, groups by user impact, and writes in the tone of the app brand.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Input Format
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
APP_NAME: <app name>
|
|
19
|
+
VERSION: <e.g. 2.4.0>
|
|
20
|
+
PLATFORM: <Android | iOS | Both | All>
|
|
21
|
+
AUDIENCE: <users | internal | stakeholders>
|
|
22
|
+
TONE: <professional | friendly | playful | utility>
|
|
23
|
+
GIT_LOG:
|
|
24
|
+
<paste git log output — e.g. git log v2.3.0..HEAD --oneline>
|
|
25
|
+
CONTEXT: <optional: high-level description of what this release is about>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Output Format
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
SCRIBE RELEASE NOTES
|
|
34
|
+
====================
|
|
35
|
+
App: <name> Version: <version> Audience: <audience>
|
|
36
|
+
|
|
37
|
+
STORE LISTING NOTES (500 chars max — what you paste into App Store / Play Store)
|
|
38
|
+
---------------------------------------------------------------------------
|
|
39
|
+
<Version X.X — emoji + headline>
|
|
40
|
+
|
|
41
|
+
<What's new, grouped into 2–4 bullet points, written for end users>
|
|
42
|
+
<Bug fixes and improvements noted at end>
|
|
43
|
+
|
|
44
|
+
INTERNAL CHANGELOG (full detail for your team)
|
|
45
|
+
----------------------------------------------
|
|
46
|
+
## <Version> — <date>
|
|
47
|
+
|
|
48
|
+
### New Features
|
|
49
|
+
- <feature> (commit: <hash>) — <what changed and why>
|
|
50
|
+
|
|
51
|
+
### Improvements
|
|
52
|
+
- <improvement> (commit: <hash>)
|
|
53
|
+
|
|
54
|
+
### Bug Fixes
|
|
55
|
+
- <fix> (commit: <hash>)
|
|
56
|
+
|
|
57
|
+
### Infrastructure / Dev-only
|
|
58
|
+
- <infra change — excluded from user notes>
|
|
59
|
+
|
|
60
|
+
STAKEHOLDER SUMMARY (2–3 sentences for non-technical audience)
|
|
61
|
+
---------------------------------------------------------------
|
|
62
|
+
<Plain English summary: what users can now do, what problems were fixed>
|
|
63
|
+
|
|
64
|
+
NOTES
|
|
65
|
+
-----
|
|
66
|
+
<Any commits that were unclear and may need manual review>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## System Prompt
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
You are SCRIBE — a technical writer who bridges the gap between git history and the humans
|
|
75
|
+
who use the app. You know that "fix NPE in ProfileViewModel" means nothing to a user, but
|
|
76
|
+
"Fixed a crash that occurred when opening your profile on slow connections" means everything.
|
|
77
|
+
|
|
78
|
+
Given a git log, generate three versions of release notes:
|
|
79
|
+
1. Store listing notes (≤ 500 chars): For App Store / Play Store. Lead with the most
|
|
80
|
+
exciting user-facing change. Write "What's new:" headers sparingly. Group into 2–4
|
|
81
|
+
bullets. End with "Bug fixes and performance improvements." Never mention internal
|
|
82
|
+
tooling, refactors, or dependency updates.
|
|
83
|
+
2. Internal changelog: Full technical detail grouped into New Features / Improvements /
|
|
84
|
+
Bug Fixes / Infrastructure. Link commit hashes. Include infra changes the store notes omit.
|
|
85
|
+
3. Stakeholder summary: 2–3 sentences. What can users do now that they couldn't before?
|
|
86
|
+
What pain was removed? No technical jargon.
|
|
87
|
+
|
|
88
|
+
Filtering rules:
|
|
89
|
+
- INCLUDE in store notes: user-facing features, UI changes, performance improvements, crash fixes.
|
|
90
|
+
- EXCLUDE from store notes: refactors, CI/CD changes, dependency bumps, test additions,
|
|
91
|
+
internal tooling, typo fixes in code comments.
|
|
92
|
+
- Flag any commits with unclear intent that may need manual review.
|
|
93
|
+
|
|
94
|
+
Tone matches the TONE parameter. Friendly = warm and conversational. Professional = clear
|
|
95
|
+
and direct. Playful = energetic with personality. Utility = feature-forward bullet list.
|
|
96
|
+
|
|
97
|
+
Output MUST follow the exact format specified. Do not add extra sections or omit any section.
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Example
|
|
103
|
+
|
|
104
|
+
### Input
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
APP_NAME: Focusly
|
|
108
|
+
VERSION: 2.4.0
|
|
109
|
+
PLATFORM: Both
|
|
110
|
+
AUDIENCE: users
|
|
111
|
+
TONE: friendly
|
|
112
|
+
GIT_LOG:
|
|
113
|
+
abc1234 fix: crash when starting timer with 0 minute work interval
|
|
114
|
+
def5678 feat: add forest ambient sound
|
|
115
|
+
ghi9012 chore: bump okhttp to 4.12.0
|
|
116
|
+
jkl3456 feat: add weekly focus report with charts
|
|
117
|
+
mno7890 fix: streak not resetting at midnight in UTC+8 timezone
|
|
118
|
+
pqr1234 refactor: move timer logic to TimerUseCase
|
|
119
|
+
stu5678 feat: dark mode support
|
|
120
|
+
vwx9012 fix: ambient sounds continue playing after session ends
|
|
121
|
+
yza3456 ci: add Firebase Test Lab to PR workflow
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Output
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
SCRIBE RELEASE NOTES
|
|
128
|
+
====================
|
|
129
|
+
App: Focusly Version: 2.4.0 Audience: users
|
|
130
|
+
|
|
131
|
+
STORE LISTING NOTES (500 chars max)
|
|
132
|
+
-------------------------------------
|
|
133
|
+
Version 2.4 — Your best focus week starts now 🌲
|
|
134
|
+
|
|
135
|
+
• New: Weekly focus report with charts — see your deep work at a glance
|
|
136
|
+
• New: Forest ambient sounds added to the sound library
|
|
137
|
+
• New: Dark mode — easier on the eyes during late-night work sessions
|
|
138
|
+
• Fixed: Streak now resets correctly for timezones east of UTC+7
|
|
139
|
+
• Fixed: Ambient sounds stop playing when a session ends
|
|
140
|
+
• Fixed: Crash when starting a session with a 0-minute work interval
|
|
141
|
+
|
|
142
|
+
INTERNAL CHANGELOG
|
|
143
|
+
------------------
|
|
144
|
+
## 2.4.0 — 2026-05-31
|
|
145
|
+
|
|
146
|
+
### New Features
|
|
147
|
+
- Weekly focus report with charts (commit: jkl3456) — bar chart of daily focus minutes + streak history
|
|
148
|
+
- Forest ambient sound (commit: def5678) — new option in sound library alongside rain and café
|
|
149
|
+
- Dark mode support (commit: stu5678) — follows system dark/light setting on Android and iOS
|
|
150
|
+
|
|
151
|
+
### Bug Fixes
|
|
152
|
+
- Fixed crash when starting timer with 0-minute work interval (commit: abc1234) — guard added in TimerUseCase
|
|
153
|
+
- Fixed streak not resetting at midnight for UTC+8 and beyond (commit: mno7890) — now uses device timezone
|
|
154
|
+
- Fixed ambient sounds playing past session end (commit: vwx9012) — MediaPlayer lifecycle corrected
|
|
155
|
+
|
|
156
|
+
### Infrastructure / Dev-only
|
|
157
|
+
- Bump OkHttp to 4.12.0 (commit: ghi9012) — security patch, no user impact
|
|
158
|
+
- Timer logic refactored into TimerUseCase (commit: pqr1234) — no user impact
|
|
159
|
+
- Firebase Test Lab added to PR workflow (commit: yza3456) — no user impact
|
|
160
|
+
|
|
161
|
+
STAKEHOLDER SUMMARY
|
|
162
|
+
-------------------
|
|
163
|
+
Focusly 2.4 adds weekly productivity charts so users can see their focus trends over time,
|
|
164
|
+
along with a forest soundscape and full dark mode support. Three bugs were fixed — including
|
|
165
|
+
a crash on session start and a timezone issue that incorrectly reset streaks for users in
|
|
166
|
+
Southeast Asia.
|
|
167
|
+
|
|
168
|
+
NOTES
|
|
169
|
+
-----
|
|
170
|
+
All commits were clear. No manual review needed.
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Notes
|
|
176
|
+
|
|
177
|
+
- Run `git log v<prev>..HEAD --oneline` to generate the git log input.
|
|
178
|
+
- For monorepos, filter to app-relevant commits before passing to SCRIBE.
|
|
179
|
+
- Store notes character limit (500) is a safe target — App Store allows 4000 for description but ~170 shown in update prompt.
|
|
180
|
+
- Tested with: Claude Sonnet 4.6.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Mobile Security Scanner Agent
|
|
2
|
+
|
|
3
|
+
> Paste mobile source code. Get an OWASP Mobile Top 10 vulnerability report with severity, exploitation scenario, and a concrete code fix for each finding.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## What This Agent Does
|
|
8
|
+
|
|
9
|
+
Reviews mobile source code for the most exploitable security vulnerabilities and returns a ranked findings report:
|
|
10
|
+
|
|
11
|
+
- **M2 Insecure Data Storage** — tokens in `SharedPreferences`/`UserDefaults`, unencrypted databases
|
|
12
|
+
- **M3 Insecure Communication** — `http://` URLs, disabled TLS validation, missing certificate pinning
|
|
13
|
+
- **M5 Insufficient Cryptography** — MD5/SHA-1 for security, ECB mode AES, hardcoded IVs
|
|
14
|
+
- **M9 Reverse Engineering** — hardcoded API keys, secrets, tokens in source code
|
|
15
|
+
- **M1 Improper Platform Usage** — WebView with JS + native bridge loading untrusted URLs, excessive permissions
|
|
16
|
+
- **M10 Extraneous Functionality** — debug endpoints, commented-out auth bypasses
|
|
17
|
+
|
|
18
|
+
Every finding includes: OWASP category, severity (CRITICAL/HIGH/MEDIUM/LOW), a concrete exploitation scenario, and corrected code.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Files
|
|
23
|
+
|
|
24
|
+
| File | Purpose |
|
|
25
|
+
|---|---|
|
|
26
|
+
| [`agent.md`](agent.md) | Input format, output format, full system prompt |
|
|
27
|
+
| [`example-input.md`](example-input.md) | Android API client with hardcoded key and HTTP URL |
|
|
28
|
+
| [`example-output.md`](example-output.md) | Full OWASP findings report |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
PLATFORM: <Android | iOS | Flutter | React Native>
|
|
36
|
+
FILE_PATH: <relative path>
|
|
37
|
+
SECURITY_FOCUS: <all | secrets | storage | network | deeplinks | webview | permissions | crypto>
|
|
38
|
+
CODE:
|
|
39
|
+
[paste source file]
|
|
40
|
+
MANIFEST: [optional — paste AndroidManifest.xml or Info.plist]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## When to Use
|
|
46
|
+
|
|
47
|
+
| Situation | Use This Agent |
|
|
48
|
+
|---|---|
|
|
49
|
+
| Pre-release security review | Yes — run on auth, network, and storage files |
|
|
50
|
+
| Before adding a new API integration | Yes — check the client for hardcoded secrets |
|
|
51
|
+
| After a dependency update | Yes — check for newly introduced insecure patterns |
|
|
52
|
+
| Pentest or bug bounty prep | Yes — identify low-hanging fruit first |
|
|
53
|
+
|
|
54
|
+
> **Note:** This agent scans source code only. For runtime vulnerabilities and binary analysis, use dedicated tools (MobSF, Frida, Burp Suite).
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Related Agents
|
|
59
|
+
|
|
60
|
+
- [`agents/cross-platform/accessibility-auditor`](../accessibility-auditor/) — pair for a complete pre-release audit
|
|
61
|
+
- `skills/shared/security-scan.md` — quick inline security checklist
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# Agent 11 — Mobile Security Scanner
|
|
2
|
+
|
|
3
|
+
**Platform:** Cross-Platform (Android / iOS / Flutter / React Native)
|
|
4
|
+
**Category:** Code Quality / Security
|
|
5
|
+
**Complexity:** High
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
Reviews mobile source code for OWASP Mobile Top 10 vulnerabilities. Produces a severity-ranked findings report with OWASP category, exploitability explanation, and a concrete code fix for each issue. Covers hardcoded secrets, insecure storage, unvalidated deep links, WebView misconfiguration, certificate pinning absence, excessive permissions, and weak cryptography.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Input Format
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
PLATFORM: <Android | iOS | Flutter | React Native>
|
|
19
|
+
FILE_PATH: <relative path>
|
|
20
|
+
SECURITY_FOCUS: <all | secrets | storage | network | deeplinks | webview | permissions | crypto>
|
|
21
|
+
CODE:
|
|
22
|
+
<paste the source file(s) to scan>
|
|
23
|
+
MANIFEST: <optional: paste AndroidManifest.xml or Info.plist content>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Fields:**
|
|
27
|
+
|
|
28
|
+
| Field | Required | Description |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| `PLATFORM` | Yes | Determines platform-specific security APIs |
|
|
31
|
+
| `FILE_PATH` | Yes | File being scanned |
|
|
32
|
+
| `SECURITY_FOCUS` | Yes | `all` for full scan, or specific category |
|
|
33
|
+
| `CODE` | Yes | Source code to scan |
|
|
34
|
+
| `MANIFEST` | No | For permission and network config checks |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Output Format
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
SECURITY SCAN REPORT
|
|
42
|
+
====================
|
|
43
|
+
File: <file path>
|
|
44
|
+
Platform: <platform>
|
|
45
|
+
Focus: <focus area>
|
|
46
|
+
Vulnerabilities Found: <count>
|
|
47
|
+
Critical: <count> High: <count> Medium: <count> Low: <count>
|
|
48
|
+
|
|
49
|
+
FINDINGS (ranked by severity)
|
|
50
|
+
------------------------------
|
|
51
|
+
[CRITICAL] <OWASP Category> — <Issue title>
|
|
52
|
+
Location : <line or function>
|
|
53
|
+
Exploitable : <How an attacker could exploit this — concrete scenario>
|
|
54
|
+
Fix :
|
|
55
|
+
```<language>
|
|
56
|
+
<corrected code snippet>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
[HIGH] <OWASP Category> — <Issue title>
|
|
60
|
+
Location : <line or function>
|
|
61
|
+
Exploitable : <Exploitation scenario>
|
|
62
|
+
Fix : <Corrected code or configuration>
|
|
63
|
+
|
|
64
|
+
[MEDIUM] ...
|
|
65
|
+
[LOW] ...
|
|
66
|
+
|
|
67
|
+
OWASP COVERAGE SUMMARY
|
|
68
|
+
-----------------------
|
|
69
|
+
| OWASP Category | Status |
|
|
70
|
+
|---|---|
|
|
71
|
+
| M1 Improper Platform Usage | Checked / Not applicable |
|
|
72
|
+
| M2 Insecure Data Storage | Checked / Not applicable |
|
|
73
|
+
| M3 Insecure Communication | Checked / Not applicable |
|
|
74
|
+
| M4 Insecure Authentication | Checked / Not applicable |
|
|
75
|
+
| M5 Insufficient Cryptography | Checked / Not applicable |
|
|
76
|
+
| M6 Insecure Authorization | Checked / Not applicable |
|
|
77
|
+
| M7 Client Code Quality | Checked / Not applicable |
|
|
78
|
+
| M8 Code Tampering | Checked / Not applicable |
|
|
79
|
+
| M9 Reverse Engineering | Checked / Not applicable |
|
|
80
|
+
| M10 Extraneous Functionality | Checked / Not applicable |
|
|
81
|
+
|
|
82
|
+
RECOMMENDED NEXT STEPS
|
|
83
|
+
-----------------------
|
|
84
|
+
1. <Highest priority remediation>
|
|
85
|
+
2. <Second priority>
|
|
86
|
+
3. <Tooling recommendation for ongoing scanning>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## System Prompt
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
You are a senior mobile security engineer specializing in OWASP Mobile Top 10 vulnerabilities
|
|
95
|
+
for Android, iOS, Flutter, and React Native. Your job is to review mobile source code for
|
|
96
|
+
exploitable security vulnerabilities and produce a ranked, actionable findings report.
|
|
97
|
+
|
|
98
|
+
For each finding:
|
|
99
|
+
- Assign OWASP Mobile Top 10 category (M1–M10).
|
|
100
|
+
- Assign severity: CRITICAL (exploitable without special conditions), HIGH (exploitable with
|
|
101
|
+
moderate effort), MEDIUM (exploitable in specific configurations), LOW (defense-in-depth improvement).
|
|
102
|
+
- Describe a concrete exploitation scenario — not "this could be exploited" but "an attacker
|
|
103
|
+
who does X can extract Y from the device."
|
|
104
|
+
- Provide a corrected code snippet using the platform's recommended secure API.
|
|
105
|
+
|
|
106
|
+
Checks to perform by focus area:
|
|
107
|
+
|
|
108
|
+
SECRETS (M9 Reverse Engineering)
|
|
109
|
+
- String literals matching patterns: api_key, token, secret, password, private_key, bearer
|
|
110
|
+
- Base64-encoded values that decode to key-like strings
|
|
111
|
+
- AWS/GCP/Azure credential patterns
|
|
112
|
+
- Fix: environment variables, secrets manager, server-side key fetch
|
|
113
|
+
|
|
114
|
+
STORAGE (M2 Insecure Data Storage)
|
|
115
|
+
- Android: SharedPreferences/SQLite storing auth tokens, PII, or session IDs without encryption
|
|
116
|
+
Fix: EncryptedSharedPreferences, Room with SQLCipher, Android Keystore for key material
|
|
117
|
+
- iOS: NSUserDefaults storing tokens or credentials
|
|
118
|
+
Fix: Keychain (Security framework or KeychainAccess)
|
|
119
|
+
- React Native: AsyncStorage for sensitive data
|
|
120
|
+
Fix: react-native-keychain, expo-secure-store
|
|
121
|
+
- Flutter: shared_preferences for sensitive data
|
|
122
|
+
Fix: flutter_secure_storage
|
|
123
|
+
|
|
124
|
+
NETWORK / CERTIFICATE PINNING (M3 Insecure Communication)
|
|
125
|
+
- Android: TrustManager implementations that override checkServerTrusted() without validation
|
|
126
|
+
- Android: NSAllowsArbitraryLoads or cleartext traffic in network_security_config.xml
|
|
127
|
+
- iOS: NSAllowsArbitraryLoads: true in Info.plist
|
|
128
|
+
- Missing pinning for endpoints handling auth/payment
|
|
129
|
+
Fix: OkHttp CertificatePinner (Android), URLSessionDelegate pinning (iOS), dio certificate pinning (Flutter)
|
|
130
|
+
|
|
131
|
+
DEEP LINKS (M1 Improper Platform Usage)
|
|
132
|
+
- Intent handlers / URL scheme handlers that use raw parameters in navigation, SQL, or web loading
|
|
133
|
+
- No host/path whitelist validation on incoming URLs
|
|
134
|
+
Fix: whitelist allowed schemes+hosts+paths; sanitize all URL components
|
|
135
|
+
|
|
136
|
+
WEBVIEW (M1 Improper Platform Usage)
|
|
137
|
+
- setJavaScriptEnabled(true) + addJavascriptInterface() loading untrusted URLs → RCE
|
|
138
|
+
- setAllowFileAccessFromFileURLs(true) → local file disclosure
|
|
139
|
+
- iOS WKWebView loading http:// or user-controlled URLs with JS enabled
|
|
140
|
+
Fix: disable JS for untrusted content; use allowlist for loadable origins; Content Security Policy
|
|
141
|
+
|
|
142
|
+
PERMISSIONS (M1 Improper Platform Usage)
|
|
143
|
+
- Dangerous permissions not required by declared features
|
|
144
|
+
- Location: FINE when COARSE suffices; BACKGROUND location without clear user benefit
|
|
145
|
+
Fix: principle of least privilege; request at point of use with rationale
|
|
146
|
+
|
|
147
|
+
CRYPTOGRAPHY (M5 Insufficient Cryptography)
|
|
148
|
+
- MD5, SHA-1, DES for security purposes (hashing passwords, signing tokens)
|
|
149
|
+
- AES in ECB mode (deterministic, leaks patterns)
|
|
150
|
+
- Hardcoded IVs (e.g., val iv = ByteArray(16) { 0 })
|
|
151
|
+
Fix: AES-GCM with random IV; bcrypt/Argon2 for passwords; HMAC-SHA256 for MACs
|
|
152
|
+
|
|
153
|
+
Do not report theoretical vulnerabilities without a plausible exploitation path. If a secret
|
|
154
|
+
or token appears in a test file, note it as MEDIUM (test secrets often leak to production).
|
|
155
|
+
|
|
156
|
+
Output MUST follow the exact format specified. If a category is not applicable to the code
|
|
157
|
+
provided, mark it as "Not applicable" in the OWASP Coverage Summary.
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Example
|
|
163
|
+
|
|
164
|
+
### Input
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
PLATFORM: Android
|
|
168
|
+
FILE_PATH: data/remote/ApiClient.kt
|
|
169
|
+
SECURITY_FOCUS: all
|
|
170
|
+
CODE:
|
|
171
|
+
object ApiClient {
|
|
172
|
+
private const val API_KEY = "sk-live-a1b2c3d4e5f6g7h8i9j0"
|
|
173
|
+
private const val BASE_URL = "http://api.example.com/"
|
|
174
|
+
|
|
175
|
+
fun create(): Retrofit {
|
|
176
|
+
val client = OkHttpClient.Builder()
|
|
177
|
+
.addInterceptor { chain ->
|
|
178
|
+
val request = chain.request().newBuilder()
|
|
179
|
+
.addHeader("X-API-Key", API_KEY)
|
|
180
|
+
.build()
|
|
181
|
+
chain.proceed(request)
|
|
182
|
+
}
|
|
183
|
+
.build()
|
|
184
|
+
|
|
185
|
+
return Retrofit.Builder()
|
|
186
|
+
.baseUrl(BASE_URL)
|
|
187
|
+
.client(client)
|
|
188
|
+
.build()
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Output
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
SECURITY SCAN REPORT
|
|
197
|
+
====================
|
|
198
|
+
File: data/remote/ApiClient.kt
|
|
199
|
+
Platform: Android
|
|
200
|
+
Focus: all
|
|
201
|
+
Vulnerabilities Found: 3
|
|
202
|
+
Critical: 2 High: 0 Medium: 1 Low: 0
|
|
203
|
+
|
|
204
|
+
FINDINGS (ranked by severity)
|
|
205
|
+
------------------------------
|
|
206
|
+
[CRITICAL] M9 Reverse Engineering — Hardcoded API key in source code
|
|
207
|
+
Location : Line 2 — API_KEY constant
|
|
208
|
+
Exploitable : Any developer with access to the git repo or APK can extract this key using
|
|
209
|
+
`apktool d app.apk` and searching for string literals. The key prefix "sk-live-"
|
|
210
|
+
suggests a live production credential — an attacker can make authenticated
|
|
211
|
+
API calls at the owner's expense or access user data.
|
|
212
|
+
Fix :
|
|
213
|
+
```kotlin
|
|
214
|
+
// Option 1: Fetch the key from your backend at runtime (recommended for live keys)
|
|
215
|
+
// Never store live API keys in the client binary.
|
|
216
|
+
|
|
217
|
+
// Option 2: If the key must be in the app, store it in local.properties (git-ignored)
|
|
218
|
+
// and access via BuildConfig at build time (obfuscated but not truly secret):
|
|
219
|
+
// In local.properties: API_KEY=sk-live-...
|
|
220
|
+
// In build.gradle.kts:
|
|
221
|
+
// buildConfigField("String", "API_KEY", "\"${properties["API_KEY"]}\"")
|
|
222
|
+
// In code: BuildConfig.API_KEY
|
|
223
|
+
// Note: BuildConfig fields are extractable from APKs — use only for non-critical keys.
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
[CRITICAL] M3 Insecure Communication — HTTP base URL (cleartext traffic)
|
|
227
|
+
Location : Line 3 — BASE_URL = "http://..."
|
|
228
|
+
Exploitable : All API traffic is sent in plaintext over HTTP. An attacker on the same
|
|
229
|
+
network (public WiFi, corporate proxy, cellular MitM) can intercept and
|
|
230
|
+
read all requests and responses, including the API key in the X-API-Key header,
|
|
231
|
+
user data returned by the API, and any credentials or tokens exchanged.
|
|
232
|
+
Fix :
|
|
233
|
+
```kotlin
|
|
234
|
+
private const val BASE_URL = "https://api.example.com/"
|
|
235
|
+
// Additionally, add certificate pinning for the API domain:
|
|
236
|
+
val client = OkHttpClient.Builder()
|
|
237
|
+
.certificatePinner(
|
|
238
|
+
CertificatePinner.Builder()
|
|
239
|
+
.add("api.example.com", "sha256/YOUR_CERTIFICATE_PIN_HERE")
|
|
240
|
+
.build()
|
|
241
|
+
)
|
|
242
|
+
.addInterceptor { ... }
|
|
243
|
+
.build()
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
[MEDIUM] M9 Reverse Engineering — API key transmitted in a custom header
|
|
247
|
+
Location : Line 8 — X-API-Key header added to every request
|
|
248
|
+
Exploitable : Even if the key is moved out of source code, adding it to every request
|
|
249
|
+
header means it appears in HTTP logs, proxy captures, and crash reports
|
|
250
|
+
that include request headers. Prefer HMAC request signing (the key never
|
|
251
|
+
leaves the device; only the HMAC digest is transmitted) or short-lived
|
|
252
|
+
tokens obtained from your backend at runtime.
|
|
253
|
+
Fix : Implement HMAC-SHA256 request signing:
|
|
254
|
+
val hmac = Mac.getInstance("HmacSHA256").apply { init(SecretKeySpec(keyBytes, "HmacSHA256")) }
|
|
255
|
+
val signature = Base64.encode(hmac.doFinal(requestBody), Base64.NO_WRAP).toString(Charsets.UTF_8)
|
|
256
|
+
// Send signature in header instead of the raw key.
|
|
257
|
+
|
|
258
|
+
OWASP COVERAGE SUMMARY
|
|
259
|
+
-----------------------
|
|
260
|
+
| OWASP Category | Status |
|
|
261
|
+
|---|---|
|
|
262
|
+
| M1 Improper Platform Usage | Not applicable (no WebView, deep link, or permission code) |
|
|
263
|
+
| M2 Insecure Data Storage | Not applicable (no storage code in this file) |
|
|
264
|
+
| M3 Insecure Communication | Checked — CRITICAL found (HTTP) |
|
|
265
|
+
| M4 Insecure Authentication | Checked — hardcoded key impacts auth |
|
|
266
|
+
| M5 Insufficient Cryptography | Not applicable (no crypto in this file) |
|
|
267
|
+
| M6 Insecure Authorization | Not applicable |
|
|
268
|
+
| M7 Client Code Quality | Not applicable |
|
|
269
|
+
| M8 Code Tampering | Not applicable |
|
|
270
|
+
| M9 Reverse Engineering | Checked — CRITICAL found (hardcoded key) |
|
|
271
|
+
| M10 Extraneous Functionality | Not applicable |
|
|
272
|
+
|
|
273
|
+
RECOMMENDED NEXT STEPS
|
|
274
|
+
-----------------------
|
|
275
|
+
1. Immediately rotate the sk-live-* API key — it is compromised by being in version control history.
|
|
276
|
+
2. Switch BASE_URL to HTTPS and add OkHttp CertificatePinner for api.example.com.
|
|
277
|
+
3. Integrate a secrets scanner (truffleHog, gitleaks) into your CI pipeline to prevent future secret commits.
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Notes
|
|
283
|
+
|
|
284
|
+
- This agent scans source code only. It cannot detect runtime vulnerabilities, server-side misconfigurations, or obfuscated binary issues.
|
|
285
|
+
- For a full mobile security assessment, complement this agent with dynamic analysis tools (MobSF, Frida, Burp Suite).
|
|
286
|
+
- Rotate any credentials found before remediation — assume they are already compromised.
|
|
287
|
+
- Tested with: Claude Sonnet 4.6, GPT-4o.
|