@leejungkiin/awkit 1.7.0 → 1.7.4

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 (241) hide show
  1. package/bin/awk.js +576 -84
  2. package/core/CLAUDE.md +1 -1
  3. package/core/GEMINI.md +148 -167
  4. package/core/GEMINI.md.bak +149 -116
  5. package/core/skill-runtime-manifest.json +3 -0
  6. package/docs/Claude Fable 5.md +3826 -0
  7. package/docs/android_kotlin_system_instruction.md +210 -0
  8. package/docs/brainstorm_ponytail_integration.md +146 -0
  9. package/docs/brainstorm_smart_setup.md +113 -0
  10. package/docs/deep-research-report (1).md +293 -0
  11. package/docs/history/GEMINI.v1.md +135 -0
  12. package/docs/history/brainstorm_antigravity_unified_architecture.v1.md +105 -0
  13. package/docs/history/implementation_plan.v1.md +58 -0
  14. package/package.json +4 -1
  15. package/scripts/artifact-storage.js +130 -0
  16. package/scripts/automation-gate.js +40 -7
  17. package/scripts/claude-plan.js +76 -0
  18. package/scripts/dependency-manager.js +210 -0
  19. package/scripts/exec-rtk.js +11 -5
  20. package/scripts/i18n-helper.js +381 -0
  21. package/scripts/multi-model-pipeline.js +144 -0
  22. package/skill-packs/mobile-ios/pack.json +4 -2
  23. package/skill-packs/reverse-engineering/pack.json +1 -0
  24. package/skills/CATALOG.md +20 -0
  25. package/skills/GEMINI.md +9 -1
  26. package/skills/TRIGGER_INDEX.md +10 -0
  27. package/skills/ai-music/SKILL.md +275 -0
  28. package/skills/android-re-analyzer/SKILL.md +238 -0
  29. package/skills/android-re-analyzer/references/api-extraction-patterns.md +119 -0
  30. package/skills/android-re-analyzer/references/call-flow-analysis.md +176 -0
  31. package/skills/android-re-analyzer/references/fernflower-usage.md +115 -0
  32. package/skills/android-re-analyzer/references/jadx-usage.md +116 -0
  33. package/skills/android-re-analyzer/references/setup-guide.md +221 -0
  34. package/skills/android-re-analyzer/scripts/check-deps.sh +129 -0
  35. package/skills/android-re-analyzer/scripts/decompile.sh +375 -0
  36. package/skills/android-re-analyzer/scripts/find-api-calls.sh +118 -0
  37. package/skills/android-re-analyzer/scripts/install-dep.sh +448 -0
  38. package/skills/animal-island-ui-style/SKILL.md +1450 -0
  39. package/skills/app-store-review-agent/SKILL.md +164 -0
  40. package/skills/app-store-review-agent/references/guidelines/README.md +154 -0
  41. package/skills/app-store-review-agent/references/guidelines/by-app-type/ai_apps.md +37 -0
  42. package/skills/app-store-review-agent/references/guidelines/by-app-type/all_apps.md +50 -0
  43. package/skills/app-store-review-agent/references/guidelines/by-app-type/crypto_finance.md +31 -0
  44. package/skills/app-store-review-agent/references/guidelines/by-app-type/games.md +31 -0
  45. package/skills/app-store-review-agent/references/guidelines/by-app-type/health_fitness.md +31 -0
  46. package/skills/app-store-review-agent/references/guidelines/by-app-type/kids.md +27 -0
  47. package/skills/app-store-review-agent/references/guidelines/by-app-type/macos.md +38 -0
  48. package/skills/app-store-review-agent/references/guidelines/by-app-type/social_ugc.md +32 -0
  49. package/skills/app-store-review-agent/references/guidelines/by-app-type/subscription_iap.md +34 -0
  50. package/skills/app-store-review-agent/references/guidelines/by-app-type/vpn.md +18 -0
  51. package/skills/app-store-review-agent/references/rules/design/minimum_functionality.md +96 -0
  52. package/skills/app-store-review-agent/references/rules/design/sign_in_with_apple.md +54 -0
  53. package/skills/app-store-review-agent/references/rules/entitlements/unused_entitlements.md +83 -0
  54. package/skills/app-store-review-agent/references/rules/metadata/accurate_metadata.md +54 -0
  55. package/skills/app-store-review-agent/references/rules/metadata/apple_trademark.md +99 -0
  56. package/skills/app-store-review-agent/references/rules/metadata/china_storefront.md +72 -0
  57. package/skills/app-store-review-agent/references/rules/metadata/competitor_terms.md +56 -0
  58. package/skills/app-store-review-agent/references/rules/metadata/subscription_metadata.md +81 -0
  59. package/skills/app-store-review-agent/references/rules/privacy/privacy_manifest.md +84 -0
  60. package/skills/app-store-review-agent/references/rules/privacy/unnecessary_data.md +60 -0
  61. package/skills/app-store-review-agent/references/rules/subscription/misleading_pricing.md +63 -0
  62. package/skills/app-store-review-agent/references/rules/subscription/missing_tos_pp.md +54 -0
  63. package/skills/awf-ponytail/SKILL.md +91 -0
  64. package/skills/awf-ponytail-review/SKILL.md +67 -0
  65. package/skills/awf-session-restore/SKILL.md +3 -3
  66. package/skills/brainstorm-agent/SKILL.md +11 -2
  67. package/skills/brainstorm-agent/templates/brief-template.md +8 -0
  68. package/skills/claude-planner/SKILL.md +47 -0
  69. package/skills/code-review/SKILL.md +87 -0
  70. package/skills/expo-game-development/SKILL.md +163 -0
  71. package/skills/flutter/LICENSE.txt +202 -0
  72. package/skills/flutter/SKILL.md +127 -0
  73. package/skills/flutter-project-creater/LICENSE.txt +202 -0
  74. package/skills/flutter-project-creater/SKILL.md +106 -0
  75. package/skills/game-developer/SKILL.md +163 -0
  76. package/skills/game-developer/references/ecs-patterns.md +501 -0
  77. package/skills/game-developer/references/multiplayer-networking.md +475 -0
  78. package/skills/game-developer/references/performance-optimization.md +422 -0
  79. package/skills/game-developer/references/unity-patterns.md +271 -0
  80. package/skills/game-developer/references/unreal-cpp.md +352 -0
  81. package/skills/generate-gui-assets/SKILL.md +305 -0
  82. package/skills/generate-gui-assets/agents/openai.yaml +4 -0
  83. package/skills/generate-gui-assets/references/catalog-schema.md +58 -0
  84. package/skills/generate-gui-assets/references/extraction-techniques.md +21 -0
  85. package/skills/generate-gui-assets/references/prompt-patterns.md +58 -0
  86. package/skills/generate-gui-assets/scripts/__pycache__/clean_chroma_edges.cpython-311.pyc +0 -0
  87. package/skills/generate-gui-assets/scripts/build_gui_contact_sheet.py +51 -0
  88. package/skills/generate-gui-assets/scripts/clean_chroma_edges.py +262 -0
  89. package/skills/generate-gui-assets/scripts/copy_approved_icons.py +64 -0
  90. package/skills/generate-gui-assets/scripts/prepare_gui_asset_run.py +91 -0
  91. package/skills/generate-gui-assets/scripts/suggest_grid_options.py +63 -0
  92. package/skills/generate-gui-assets/scripts/validate_gui_catalog.py +50 -0
  93. package/skills/godot-game-development/SKILL.md +142 -0
  94. package/skills/hatch-pet/LICENSE.txt +201 -0
  95. package/skills/hatch-pet/SKILL.md +420 -0
  96. package/skills/hatch-pet/agents/openai.yaml +4 -0
  97. package/skills/hatch-pet/references/animation-rows.md +29 -0
  98. package/skills/hatch-pet/references/codex-pet-contract.md +35 -0
  99. package/skills/hatch-pet/references/qa-rubric.md +60 -0
  100. package/skills/hatch-pet/scripts/__pycache__/clean_chroma_edges.cpython-311.pyc +0 -0
  101. package/skills/hatch-pet/scripts/clean_chroma_edges.py +262 -0
  102. package/skills/hatch-pet/scripts/compose_atlas.py +150 -0
  103. package/skills/hatch-pet/scripts/derive_running_left_from_running_right.py +143 -0
  104. package/skills/hatch-pet/scripts/extract_strip_frames.py +323 -0
  105. package/skills/hatch-pet/scripts/finalize_pet_run.py +382 -0
  106. package/skills/hatch-pet/scripts/generate_pet_images.py +287 -0
  107. package/skills/hatch-pet/scripts/inspect_frames.py +246 -0
  108. package/skills/hatch-pet/scripts/make_contact_sheet.py +96 -0
  109. package/skills/hatch-pet/scripts/package_custom_pet.py +108 -0
  110. package/skills/hatch-pet/scripts/pet_job_status.py +117 -0
  111. package/skills/hatch-pet/scripts/prepare_pet_run.py +673 -0
  112. package/skills/hatch-pet/scripts/queue_pet_repairs.py +172 -0
  113. package/skills/hatch-pet/scripts/record_imagegen_result.py +250 -0
  114. package/skills/hatch-pet/scripts/render_animation_videos.py +134 -0
  115. package/skills/hatch-pet/scripts/render_animation_videos.sh +5 -0
  116. package/skills/hatch-pet/scripts/validate_atlas.py +139 -0
  117. package/skills/i18n-orchestrator/SKILL.md +37 -0
  118. package/skills/ios-simulator-skill/SKILL.md +390 -0
  119. package/skills/ios-simulator-skill/scripts/accessibility_audit.py +300 -0
  120. package/skills/ios-simulator-skill/scripts/app_launcher.py +326 -0
  121. package/skills/ios-simulator-skill/scripts/app_state_capture.py +400 -0
  122. package/skills/ios-simulator-skill/scripts/appearance.py +385 -0
  123. package/skills/ios-simulator-skill/scripts/build_and_test.py +348 -0
  124. package/skills/ios-simulator-skill/scripts/clipboard.py +103 -0
  125. package/skills/ios-simulator-skill/scripts/common/__init__.py +61 -0
  126. package/skills/ios-simulator-skill/scripts/common/cache_utils.py +289 -0
  127. package/skills/ios-simulator-skill/scripts/common/device_utils.py +462 -0
  128. package/skills/ios-simulator-skill/scripts/common/env_config.py +35 -0
  129. package/skills/ios-simulator-skill/scripts/common/hang_pipeline.py +862 -0
  130. package/skills/ios-simulator-skill/scripts/common/hang_sessions.py +490 -0
  131. package/skills/ios-simulator-skill/scripts/common/idb_utils.py +180 -0
  132. package/skills/ios-simulator-skill/scripts/common/screenshot_utils.py +338 -0
  133. package/skills/ios-simulator-skill/scripts/container.py +668 -0
  134. package/skills/ios-simulator-skill/scripts/gesture.py +394 -0
  135. package/skills/ios-simulator-skill/scripts/hang_watcher.py +1533 -0
  136. package/skills/ios-simulator-skill/scripts/keyboard.py +391 -0
  137. package/skills/ios-simulator-skill/scripts/localization_audit.py +483 -0
  138. package/skills/ios-simulator-skill/scripts/location.py +467 -0
  139. package/skills/ios-simulator-skill/scripts/log_monitor.py +493 -0
  140. package/skills/ios-simulator-skill/scripts/model_inspector.py +645 -0
  141. package/skills/ios-simulator-skill/scripts/navigator.py +461 -0
  142. package/skills/ios-simulator-skill/scripts/privacy_manager.py +310 -0
  143. package/skills/ios-simulator-skill/scripts/push_notification.py +240 -0
  144. package/skills/ios-simulator-skill/scripts/screen_mapper.py +296 -0
  145. package/skills/ios-simulator-skill/scripts/sim_health_check.sh +245 -0
  146. package/skills/ios-simulator-skill/scripts/sim_list.py +299 -0
  147. package/skills/ios-simulator-skill/scripts/simctl_boot.py +312 -0
  148. package/skills/ios-simulator-skill/scripts/simctl_create.py +316 -0
  149. package/skills/ios-simulator-skill/scripts/simctl_delete.py +357 -0
  150. package/skills/ios-simulator-skill/scripts/simctl_erase.py +351 -0
  151. package/skills/ios-simulator-skill/scripts/simctl_shutdown.py +290 -0
  152. package/skills/ios-simulator-skill/scripts/simulator_selector.py +375 -0
  153. package/skills/ios-simulator-skill/scripts/status_bar.py +250 -0
  154. package/skills/ios-simulator-skill/scripts/test_recorder.py +323 -0
  155. package/skills/ios-simulator-skill/scripts/visual_diff.py +235 -0
  156. package/skills/ios-simulator-skill/scripts/xcode/__init__.py +13 -0
  157. package/skills/ios-simulator-skill/scripts/xcode/builder.py +397 -0
  158. package/skills/ios-simulator-skill/scripts/xcode/cache.py +204 -0
  159. package/skills/ios-simulator-skill/scripts/xcode/config.py +178 -0
  160. package/skills/ios-simulator-skill/scripts/xcode/reporter.py +343 -0
  161. package/skills/ios-simulator-skill/scripts/xcode/xcresult.py +451 -0
  162. package/skills/ios-visual-qa-strategist/SKILL.md +111 -0
  163. package/skills/ios-visual-qa-strategist/agents/openai.yaml +4 -0
  164. package/skills/ios-visual-qa-strategist/references/ios-tool-selection.md +61 -0
  165. package/skills/ios-visual-qa-strategist/references/minimal-capture-policy.md +56 -0
  166. package/skills/ios-visual-qa-strategist/references/visual-reasoning-heuristics.md +53 -0
  167. package/skills/orchestrator/SKILL.md +0 -20
  168. package/skills/persistent-storage/SKILL.md +55 -0
  169. package/skills/short-maker/SKILL.md +23 -0
  170. package/skills/short-maker/scripts/effects.js +56 -0
  171. package/skills/short-maker/scripts/shortmaker-bridge.js +332 -0
  172. package/skills/short-maker/scripts/videomix.js +601 -0
  173. package/skills/short-maker/templates/hyperframes/cinematic-character.template.html +172 -0
  174. package/skills/short-maker/templates/hyperframes/index.template.html +194 -0
  175. package/skills/smali-to-kotlin/SKILL.md +128 -0
  176. package/skills/smali-to-kotlin/examples/getting-started/tech-stack.md +58 -0
  177. package/skills/smali-to-kotlin/examples/pipeline/data-ui-parity.md +118 -0
  178. package/skills/smali-to-kotlin/examples/pipeline/scanner-and-bootstrap.md +106 -0
  179. package/skills/smali-to-kotlin/library-patterns.md +189 -0
  180. package/skills/smali-to-kotlin/phase-0-discovery.md +128 -0
  181. package/skills/smali-to-kotlin/phase-1-architecture.md +166 -0
  182. package/skills/smali-to-kotlin/phase-2-blueprint-ui.md +347 -0
  183. package/skills/smali-to-kotlin/phase-2-blueprint.md +228 -0
  184. package/skills/smali-to-kotlin/phase-3-build.md +248 -0
  185. package/skills/smali-to-kotlin/phase-3-logic-build.md +268 -0
  186. package/skills/smali-to-kotlin/smali-reading-guide.md +310 -0
  187. package/skills/smali-to-kotlin/templates/app-map.md +101 -0
  188. package/skills/smali-to-kotlin/templates/architecture.md +142 -0
  189. package/skills/smali-to-kotlin/templates/blueprint.md +145 -0
  190. package/skills/spec-gate/SKILL.md +6 -2
  191. package/skills/symphony-enforcer/SKILL.md +8 -0
  192. package/skills/symphony-enforcer/examples/mindful-stop.md +2 -0
  193. package/skills/symphony-enforcer/examples/three-phase.md +16 -0
  194. package/skills/symphony-enforcer/examples/trigger-points.md +7 -1
  195. package/skills/unity-game-development/SKILL.md +231 -0
  196. package/skills/verification-gate/SKILL.md +4 -2
  197. package/skills/video-edit/SKILL.md +36 -0
  198. package/skills/video-edit/scripts/video_edit.py +324 -0
  199. package/templates/setup-mapping.json +48 -0
  200. package/templates/specs/design-template.md +161 -71
  201. package/templates/specs/requirements-template.md +65 -133
  202. package/templates/specs/task-spec-template.xml +3 -0
  203. package/workflows/_uncategorized/critic.md +40 -0
  204. package/workflows/_uncategorized/git-rebase-flow.md +81 -0
  205. package/workflows/_uncategorized/image-gen.md +118 -0
  206. package/workflows/_uncategorized/multi-model-pipeline.md +60 -0
  207. package/workflows/_uncategorized/pixel-gen.md +86 -0
  208. package/workflows/_uncategorized/pixel-setup.md +90 -0
  209. package/workflows/_uncategorized/ponytail-review.md +59 -0
  210. package/workflows/_uncategorized/reverse-android-build.md +222 -0
  211. package/workflows/_uncategorized/reverse-android-design.md +139 -0
  212. package/workflows/_uncategorized/reverse-android-discover.md +150 -0
  213. package/workflows/_uncategorized/reverse-android-scan.md +158 -0
  214. package/workflows/_uncategorized/reverse-android.md +143 -0
  215. package/workflows/_uncategorized/reverse-ios-build.md +240 -0
  216. package/workflows/_uncategorized/reverse-ios-design.md +112 -0
  217. package/workflows/_uncategorized/reverse-ios-discover.md +120 -0
  218. package/workflows/_uncategorized/reverse-ios-scan.md +155 -0
  219. package/workflows/_uncategorized/reverse-ios.md +152 -0
  220. package/workflows/_uncategorized/safety-router.md +34 -0
  221. package/workflows/_uncategorized/teach.md +89 -0
  222. package/workflows/_uncategorized/verify-ui.md +53 -0
  223. package/workflows/_uncategorized/visualize-screenshots.md +34 -0
  224. package/workflows/ads/ads-analyst.md +201 -0
  225. package/workflows/ads/ads-audit.md +106 -0
  226. package/workflows/ads/ads-optimize.md +97 -0
  227. package/workflows/ads/ads-targeting.md +241 -0
  228. package/workflows/ads/adsExpert.md +160 -0
  229. package/workflows/ads/smali-ads-config.md +400 -0
  230. package/workflows/ads/smali-ads-flow.md +331 -0
  231. package/workflows/ads/smali-ads-interstitial.md +377 -0
  232. package/workflows/ads/smali-ads-native.md +382 -0
  233. package/workflows/context/teach.md +89 -0
  234. package/workflows/gitnexus.md +8 -8
  235. package/workflows/lifecycle/brainstorm.md +43 -0
  236. package/workflows/lifecycle/code.md +5 -0
  237. package/workflows/lifecycle/init.md +23 -5
  238. package/workflows/lifecycle/multi-model-pipeline.md +60 -0
  239. package/workflows/quality/ponytail-review.md +59 -0
  240. package/workflows/roles/critic.md +40 -0
  241. package/workflows/roles/safety-router.md +34 -0
@@ -0,0 +1,296 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ iOS Screen Mapper - Current Screen Analyzer
4
+
5
+ Maps the current screen's UI elements for navigation decisions.
6
+ Provides token-efficient summaries of available interactions.
7
+
8
+ This script analyzes the iOS simulator screen using IDB's accessibility tree
9
+ and provides a compact, actionable summary of what's currently visible and
10
+ interactive on the screen. Perfect for AI agents making navigation decisions.
11
+
12
+ Key Features:
13
+ - Token-efficient output (5-7 lines by default)
14
+ - Identifies buttons, text fields, navigation elements
15
+ - Counts interactive and focusable elements
16
+ - Progressive detail with --verbose flag
17
+ - Navigation hints with --hints flag
18
+
19
+ Usage Examples:
20
+ # Quick summary (default)
21
+ python scripts/screen_mapper.py --udid <device-id>
22
+
23
+ # Detailed element breakdown
24
+ python scripts/screen_mapper.py --udid <device-id> --verbose
25
+
26
+ # Include navigation suggestions
27
+ python scripts/screen_mapper.py --udid <device-id> --hints
28
+
29
+ # Full JSON output for parsing
30
+ python scripts/screen_mapper.py --udid <device-id> --json
31
+
32
+ Output Format (default):
33
+ Screen: LoginViewController (45 elements, 7 interactive)
34
+ Buttons: "Login", "Cancel", "Forgot Password"
35
+ TextFields: 2 (0 filled)
36
+ Navigation: NavBar: "Sign In"
37
+ Focusable: 7 elements
38
+
39
+ Technical Details:
40
+ - Uses IDB's accessibility tree via `idb ui describe-all --json --nested`
41
+ - Parses IDB's array format: [{ root element with children }]
42
+ - Identifies element types: Button, TextField, NavigationBar, TabBar, etc.
43
+ - Extracts labels from AXLabel, AXValue, and AXUniqueId fields
44
+ """
45
+
46
+ import argparse
47
+ import json
48
+ import subprocess
49
+ import sys
50
+ from collections import defaultdict
51
+
52
+ from common import get_accessibility_tree, resolve_udid
53
+ from common.env_config import env_int
54
+
55
+ BUTTONS_PREVIEW = env_int("IOS_SIM_SCREEN_BUTTONS_PREVIEW", 15)
56
+ SECTION_ITEMS_PREVIEW = env_int("IOS_SIM_SCREEN_SECTION_ITEMS", 10)
57
+
58
+
59
+ class ScreenMapper:
60
+ """
61
+ Analyzes current screen for navigation decisions.
62
+
63
+ This class fetches the iOS accessibility tree from IDB and analyzes it
64
+ to provide actionable summaries for navigation. It categorizes elements
65
+ by type, counts interactive elements, and identifies key UI patterns.
66
+
67
+ Attributes:
68
+ udid (Optional[str]): Device UDID to target, or None for booted device
69
+ INTERACTIVE_TYPES (Set[str]): Element types that users can interact with
70
+
71
+ Design Philosophy:
72
+ - Token efficiency: Provide minimal but complete information
73
+ - Progressive disclosure: Summary by default, details on request
74
+ - Navigation-focused: Highlight elements relevant for automation
75
+ """
76
+
77
+ # Element types we care about for navigation
78
+ # These are the accessibility element types that indicate user interaction points
79
+ INTERACTIVE_TYPES = {
80
+ "Button",
81
+ "Link",
82
+ "TextField",
83
+ "SecureTextField",
84
+ "Cell",
85
+ "Switch",
86
+ "Slider",
87
+ "Stepper",
88
+ "SegmentedControl",
89
+ "TabBar",
90
+ "NavigationBar",
91
+ "Toolbar",
92
+ }
93
+
94
+ def __init__(self, udid: str | None = None):
95
+ """
96
+ Initialize screen mapper.
97
+
98
+ Args:
99
+ udid: Optional device UDID. If None, uses booted simulator.
100
+
101
+ Example:
102
+ mapper = ScreenMapper(udid="656DC652-1C9F-4AB2-AD4F-F38E65976BDA")
103
+ mapper = ScreenMapper() # Uses booted device
104
+ """
105
+ self.udid = udid
106
+
107
+ def get_accessibility_tree(self) -> dict:
108
+ """
109
+ Fetch accessibility tree from iOS simulator via IDB.
110
+
111
+ Delegates to shared utility for consistent tree fetching across all scripts.
112
+ """
113
+ return get_accessibility_tree(self.udid, nested=True)
114
+
115
+ def analyze_tree(self, node: dict, depth: int = 0) -> dict:
116
+ """Analyze accessibility tree for navigation info."""
117
+ analysis = {
118
+ "elements_by_type": defaultdict(list),
119
+ "total_elements": 0,
120
+ "interactive_elements": 0,
121
+ "text_fields": [],
122
+ "buttons": [],
123
+ "navigation": {},
124
+ "screen_name": None,
125
+ "focusable": 0,
126
+ }
127
+
128
+ self._analyze_recursive(node, analysis, depth)
129
+
130
+ # Post-process for clean output
131
+ analysis["elements_by_type"] = dict(analysis["elements_by_type"])
132
+
133
+ return analysis
134
+
135
+ def _analyze_recursive(self, node: dict, analysis: dict, depth: int):
136
+ """Recursively analyze tree nodes."""
137
+ elem_type = node.get("type")
138
+ label = node.get("AXLabel", "")
139
+ value = node.get("AXValue", "")
140
+ identifier = node.get("AXUniqueId", "")
141
+
142
+ # Count element
143
+ if elem_type:
144
+ analysis["total_elements"] += 1
145
+
146
+ # Track by type
147
+ if elem_type in self.INTERACTIVE_TYPES:
148
+ analysis["interactive_elements"] += 1
149
+
150
+ # Store concise info (label only, not full node)
151
+ elem_info = label or value or identifier or "Unnamed"
152
+ analysis["elements_by_type"][elem_type].append(elem_info)
153
+
154
+ # Special handling for common types
155
+ if elem_type == "Button":
156
+ analysis["buttons"].append(elem_info)
157
+ elif elem_type in ("TextField", "SecureTextField"):
158
+ analysis["text_fields"].append(
159
+ {"type": elem_type, "label": elem_info, "has_value": bool(value)}
160
+ )
161
+ elif elem_type == "NavigationBar":
162
+ analysis["navigation"]["nav_title"] = label or "Navigation"
163
+ elif elem_type == "TabBar":
164
+ # Count tab items
165
+ tab_count = len(node.get("children", []))
166
+ analysis["navigation"]["tab_count"] = tab_count
167
+
168
+ # Track focusable elements
169
+ if node.get("enabled", False) and elem_type in self.INTERACTIVE_TYPES:
170
+ analysis["focusable"] += 1
171
+
172
+ # Try to identify screen name from view controller
173
+ if not analysis["screen_name"] and identifier:
174
+ if "ViewController" in identifier or "Screen" in identifier:
175
+ analysis["screen_name"] = identifier
176
+
177
+ # Process children
178
+ for child in node.get("children", []):
179
+ self._analyze_recursive(child, analysis, depth + 1)
180
+
181
+ def format_summary(self, analysis: dict, verbose: bool = False) -> str:
182
+ """Format analysis as token-efficient summary."""
183
+ lines = []
184
+
185
+ # Screen identification (1 line)
186
+ screen = analysis["screen_name"] or "Unknown Screen"
187
+ total = analysis["total_elements"]
188
+ interactive = analysis["interactive_elements"]
189
+ lines.append(f"Screen: {screen} ({total} elements, {interactive} interactive)")
190
+
191
+ # Buttons summary (1 line)
192
+ if analysis["buttons"]:
193
+ button_list = ", ".join(f'"{b}"' for b in analysis["buttons"][:BUTTONS_PREVIEW])
194
+ if len(analysis["buttons"]) > BUTTONS_PREVIEW:
195
+ button_list += f" +{len(analysis['buttons']) - BUTTONS_PREVIEW} more"
196
+ lines.append(f"Buttons: {button_list}")
197
+
198
+ # Text fields summary (1 line)
199
+ if analysis["text_fields"]:
200
+ field_count = len(analysis["text_fields"])
201
+ [f["type"] for f in analysis["text_fields"]]
202
+ filled = sum(1 for f in analysis["text_fields"] if f["has_value"])
203
+ lines.append(f"TextFields: {field_count} ({filled} filled)")
204
+
205
+ # Navigation summary (1 line)
206
+ nav_parts = []
207
+ if "nav_title" in analysis["navigation"]:
208
+ nav_parts.append(f"NavBar: \"{analysis['navigation']['nav_title']}\"")
209
+ if "tab_count" in analysis["navigation"]:
210
+ nav_parts.append(f"TabBar: {analysis['navigation']['tab_count']} tabs")
211
+ if nav_parts:
212
+ lines.append(f"Navigation: {', '.join(nav_parts)}")
213
+
214
+ # Focusable count (1 line)
215
+ lines.append(f"Focusable: {analysis['focusable']} elements")
216
+
217
+ # Verbose mode adds element type breakdown
218
+ if verbose:
219
+ lines.append("\nElements by type:")
220
+ for elem_type, items in analysis["elements_by_type"].items():
221
+ if items: # Only show types that exist
222
+ lines.append(f" {elem_type}: {len(items)}")
223
+ for item in items[:SECTION_ITEMS_PREVIEW]:
224
+ lines.append(f" - {item}")
225
+ if len(items) > SECTION_ITEMS_PREVIEW:
226
+ lines.append(f" ... +{len(items) - SECTION_ITEMS_PREVIEW} more")
227
+
228
+ return "\n".join(lines)
229
+
230
+ def get_navigation_hints(self, analysis: dict) -> list[str]:
231
+ """Generate navigation hints based on screen analysis."""
232
+ hints = []
233
+
234
+ # Check for common patterns
235
+ if "Login" in str(analysis.get("buttons", [])):
236
+ hints.append("Login screen detected - find TextFields for credentials")
237
+
238
+ if analysis["text_fields"]:
239
+ unfilled = [f for f in analysis["text_fields"] if not f["has_value"]]
240
+ if unfilled:
241
+ hints.append(f"{len(unfilled)} empty text field(s) - may need input")
242
+
243
+ if not analysis["buttons"] and not analysis["text_fields"]:
244
+ hints.append("No interactive elements - try swiping or going back")
245
+
246
+ if "tab_count" in analysis.get("navigation", {}):
247
+ hints.append(f"Tab bar available with {analysis['navigation']['tab_count']} tabs")
248
+
249
+ return hints
250
+
251
+
252
+ def main():
253
+ """Main entry point."""
254
+ parser = argparse.ArgumentParser(description="Map current screen UI elements")
255
+ parser.add_argument("--verbose", action="store_true", help="Show detailed element breakdown")
256
+ parser.add_argument("--json", action="store_true", help="Output raw JSON analysis")
257
+ parser.add_argument("--hints", action="store_true", help="Include navigation hints")
258
+ parser.add_argument(
259
+ "--udid",
260
+ help="Device UDID (auto-detects booted simulator if not provided)",
261
+ )
262
+
263
+ args = parser.parse_args()
264
+
265
+ # Resolve UDID with auto-detection
266
+ try:
267
+ udid = resolve_udid(args.udid)
268
+ except RuntimeError as e:
269
+ print(f"Error: {e}")
270
+ sys.exit(1)
271
+
272
+ # Create mapper and analyze
273
+ mapper = ScreenMapper(udid=udid)
274
+ tree = mapper.get_accessibility_tree()
275
+ analysis = mapper.analyze_tree(tree)
276
+
277
+ # Output based on format
278
+ if args.json:
279
+ # Full JSON (verbose)
280
+ print(json.dumps(analysis, indent=2, default=str))
281
+ else:
282
+ # Token-efficient summary (default)
283
+ summary = mapper.format_summary(analysis, verbose=args.verbose)
284
+ print(summary)
285
+
286
+ # Add hints if requested
287
+ if args.hints:
288
+ hints = mapper.get_navigation_hints(analysis)
289
+ if hints:
290
+ print("\nHints:")
291
+ for hint in hints:
292
+ print(f" - {hint}")
293
+
294
+
295
+ if __name__ == "__main__":
296
+ main()
@@ -0,0 +1,245 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # iOS Simulator Testing Environment Health Check
4
+ #
5
+ # Verifies that all required tools and dependencies are properly installed
6
+ # and configured for iOS simulator testing.
7
+ #
8
+ # Usage: bash scripts/sim_health_check.sh [--help]
9
+
10
+ set -e
11
+
12
+ # Color codes for output
13
+ RED='\033[0;31m'
14
+ GREEN='\033[0;32m'
15
+ YELLOW='\033[1;33m'
16
+ BLUE='\033[0;34m'
17
+ NC='\033[0m' # No Color
18
+
19
+ # Check flags
20
+ SHOW_HELP=false
21
+
22
+ # Parse arguments
23
+ for arg in "$@"; do
24
+ case $arg in
25
+ --help|-h)
26
+ SHOW_HELP=true
27
+ shift
28
+ ;;
29
+ esac
30
+ done
31
+
32
+ if [ "$SHOW_HELP" = true ]; then
33
+ cat <<EOF
34
+ iOS Simulator Testing - Environment Health Check
35
+
36
+ Verifies that your environment is properly configured for iOS simulator testing.
37
+
38
+ Usage: bash scripts/sim_health_check.sh [options]
39
+
40
+ Options:
41
+ --help, -h Show this help message
42
+
43
+ This script checks for:
44
+ - Xcode Command Line Tools installation
45
+ - iOS Simulator availability
46
+ - IDB (iOS Development Bridge) installation
47
+ - Available simulator devices
48
+ - Python 3 installation (for scripts)
49
+
50
+ Exit codes:
51
+ 0 - All checks passed
52
+ 1 - One or more checks failed (see output for details)
53
+ EOF
54
+ exit 0
55
+ fi
56
+
57
+ echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
58
+ echo -e "${BLUE} iOS Simulator Testing - Environment Health Check${NC}"
59
+ echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
60
+ echo ""
61
+
62
+ CHECKS_PASSED=0
63
+ CHECKS_FAILED=0
64
+
65
+ # Function to print check status
66
+ check_passed() {
67
+ echo -e "${GREEN}✓${NC} $1"
68
+ CHECKS_PASSED=$((CHECKS_PASSED + 1))
69
+ }
70
+
71
+ check_failed() {
72
+ echo -e "${RED}✗${NC} $1"
73
+ CHECKS_FAILED=$((CHECKS_FAILED + 1))
74
+ }
75
+
76
+ check_warning() {
77
+ echo -e "${YELLOW}⚠${NC} $1"
78
+ }
79
+
80
+ # Check 1: macOS
81
+ echo -e "${BLUE}[1/8]${NC} Checking operating system..."
82
+ if [[ "$OSTYPE" == "darwin"* ]]; then
83
+ OS_VERSION=$(sw_vers -productVersion)
84
+ check_passed "macOS detected (version $OS_VERSION)"
85
+ else
86
+ check_failed "Not running on macOS (detected: $OSTYPE)"
87
+ echo " iOS Simulator testing requires macOS"
88
+ fi
89
+ echo ""
90
+
91
+ # Check 2: Xcode Command Line Tools
92
+ echo -e "${BLUE}[2/8]${NC} Checking Xcode Command Line Tools..."
93
+ if command -v xcrun &> /dev/null; then
94
+ XCODE_PATH=$(xcode-select -p 2>/dev/null || echo "not found")
95
+ if [ "$XCODE_PATH" != "not found" ]; then
96
+ XCODE_VERSION=$(xcodebuild -version 2>/dev/null | head -n 1 || echo "Unknown")
97
+ check_passed "Xcode Command Line Tools installed"
98
+ echo " Path: $XCODE_PATH"
99
+ echo " Version: $XCODE_VERSION"
100
+ else
101
+ check_failed "Xcode Command Line Tools path not set"
102
+ echo " Run: xcode-select --install"
103
+ fi
104
+ else
105
+ check_failed "xcrun command not found"
106
+ echo " Install Xcode Command Line Tools: xcode-select --install"
107
+ fi
108
+ echo ""
109
+
110
+ # Check 3: simctl availability
111
+ echo -e "${BLUE}[3/8]${NC} Checking simctl (Simulator Control)..."
112
+ if command -v xcrun &> /dev/null && xcrun simctl help &> /dev/null; then
113
+ check_passed "simctl is available"
114
+ else
115
+ check_failed "simctl not available"
116
+ echo " simctl comes with Xcode Command Line Tools"
117
+ fi
118
+ echo ""
119
+
120
+ # Check 4: IDB installation
121
+ echo -e "${BLUE}[4/8]${NC} Checking IDB (iOS Development Bridge)..."
122
+ if command -v idb &> /dev/null; then
123
+ IDB_PATH=$(which idb)
124
+ IDB_VERSION=$(idb --version 2>/dev/null || echo "Unknown")
125
+ check_passed "IDB is installed"
126
+ echo " Path: $IDB_PATH"
127
+ echo " Version: $IDB_VERSION"
128
+ else
129
+ check_warning "IDB not found in PATH"
130
+ echo " IDB is optional but provides advanced UI automation"
131
+ echo " Install: https://fbidb.io/docs/installation"
132
+ echo " Recommended: brew tap facebook/fb && brew install idb-companion"
133
+ fi
134
+ echo ""
135
+
136
+ # Check 5: Python 3.12+ installation
137
+ echo -e "${BLUE}[5/8]${NC} Checking Python 3.12+..."
138
+ if command -v python3 &> /dev/null; then
139
+ PYTHON_MAJOR=$(python3 -c "import sys; print(sys.version_info.major)")
140
+ PYTHON_MINOR=$(python3 -c "import sys; print(sys.version_info.minor)")
141
+ if [ "$PYTHON_MAJOR" -lt 3 ] || { [ "$PYTHON_MAJOR" -eq 3 ] && [ "$PYTHON_MINOR" -lt 12 ]; }; then
142
+ check_failed "Python $PYTHON_MAJOR.$PYTHON_MINOR found — Python 3.12+ required"
143
+ echo " Upgrade: brew install python@3.12"
144
+ else
145
+ check_passed "Python $PYTHON_MAJOR.$PYTHON_MINOR (>= 3.12 required)"
146
+ fi
147
+ else
148
+ check_failed "Python 3 not found"
149
+ echo " Python 3.12+ is required for testing scripts"
150
+ echo " Install: brew install python@3.12"
151
+ fi
152
+ echo ""
153
+
154
+ # Check 6: Available simulators
155
+ echo -e "${BLUE}[6/8]${NC} Checking available iOS Simulators..."
156
+ if command -v xcrun &> /dev/null; then
157
+ SIMULATOR_COUNT=$(xcrun simctl list devices available 2>/dev/null | grep -c "iPhone\|iPad" || echo "0")
158
+
159
+ if [ "$SIMULATOR_COUNT" -gt 0 ]; then
160
+ check_passed "Found $SIMULATOR_COUNT available simulator(s)"
161
+
162
+ # Show first 5 simulators
163
+ echo ""
164
+ echo " Available simulators (showing up to 5):"
165
+ xcrun simctl list devices available 2>/dev/null | grep "iPhone\|iPad" | head -5 | while read -r line; do
166
+ echo " - $line"
167
+ done
168
+ else
169
+ check_warning "No simulators found"
170
+ echo " Create simulators via Xcode or simctl"
171
+ echo " Example: xcrun simctl create 'iPhone 15' 'iPhone 15'"
172
+ fi
173
+ else
174
+ check_failed "Cannot check simulators (simctl not available)"
175
+ fi
176
+ echo ""
177
+
178
+ # Check 7: Booted simulators
179
+ echo -e "${BLUE}[7/8]${NC} Checking booted simulators..."
180
+ if command -v xcrun &> /dev/null; then
181
+ BOOTED_SIMS=$(xcrun simctl list devices booted 2>/dev/null | grep -c "iPhone\|iPad" || echo "0")
182
+
183
+ if [ "$BOOTED_SIMS" -gt 0 ]; then
184
+ check_passed "$BOOTED_SIMS simulator(s) currently booted"
185
+
186
+ echo ""
187
+ echo " Booted simulators:"
188
+ xcrun simctl list devices booted 2>/dev/null | grep "iPhone\|iPad" | while read -r line; do
189
+ echo " - $line"
190
+ done
191
+ else
192
+ check_warning "No simulators currently booted"
193
+ echo " Boot a simulator to begin testing"
194
+ echo " Example: xcrun simctl boot <device-udid>"
195
+ echo " Or: open -a Simulator"
196
+ fi
197
+ else
198
+ check_failed "Cannot check booted simulators (simctl not available)"
199
+ fi
200
+ echo ""
201
+
202
+ # Check 8: Required Python packages (optional check)
203
+ echo -e "${BLUE}[8/8]${NC} Checking Python packages..."
204
+ if command -v python3 &> /dev/null; then
205
+ MISSING_PACKAGES=()
206
+
207
+ # Check for PIL/Pillow (for visual_diff.py)
208
+ if python3 -c "import PIL" 2>/dev/null; then
209
+ check_passed "Pillow (PIL) installed - visual diff available"
210
+ else
211
+ MISSING_PACKAGES+=("pillow")
212
+ check_warning "Pillow (PIL) not installed - visual diff won't work"
213
+ fi
214
+
215
+ if [ ${#MISSING_PACKAGES[@]} -gt 0 ]; then
216
+ echo ""
217
+ echo " Install missing packages:"
218
+ echo " pip3 install ${MISSING_PACKAGES[*]}"
219
+ fi
220
+ else
221
+ check_warning "Cannot check Python packages (Python 3 not available)"
222
+ fi
223
+ echo ""
224
+
225
+ # Summary
226
+ echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
227
+ echo -e "${BLUE} Summary${NC}"
228
+ echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
229
+ echo ""
230
+ echo -e "Checks passed: ${GREEN}$CHECKS_PASSED${NC}"
231
+ if [ "$CHECKS_FAILED" -gt 0 ]; then
232
+ echo -e "Checks failed: ${RED}$CHECKS_FAILED${NC}"
233
+ echo ""
234
+ echo -e "${YELLOW}Action required:${NC} Fix the failed checks above before testing"
235
+ exit 1
236
+ else
237
+ echo ""
238
+ echo -e "${GREEN}✓ Environment is ready for iOS simulator testing${NC}"
239
+ echo ""
240
+ echo "Next steps:"
241
+ echo " 1. Boot a simulator: open -a Simulator"
242
+ echo " 2. Launch your app: xcrun simctl launch booted <bundle-id>"
243
+ echo " 3. Run accessibility audit: python scripts/accessibility_audit.py"
244
+ exit 0
245
+ fi