@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.
- package/bin/awk.js +576 -84
- package/core/CLAUDE.md +1 -1
- package/core/GEMINI.md +148 -167
- package/core/GEMINI.md.bak +149 -116
- package/core/skill-runtime-manifest.json +3 -0
- package/docs/Claude Fable 5.md +3826 -0
- package/docs/android_kotlin_system_instruction.md +210 -0
- package/docs/brainstorm_ponytail_integration.md +146 -0
- package/docs/brainstorm_smart_setup.md +113 -0
- package/docs/deep-research-report (1).md +293 -0
- package/docs/history/GEMINI.v1.md +135 -0
- package/docs/history/brainstorm_antigravity_unified_architecture.v1.md +105 -0
- package/docs/history/implementation_plan.v1.md +58 -0
- package/package.json +4 -1
- package/scripts/artifact-storage.js +130 -0
- package/scripts/automation-gate.js +40 -7
- package/scripts/claude-plan.js +76 -0
- package/scripts/dependency-manager.js +210 -0
- package/scripts/exec-rtk.js +11 -5
- package/scripts/i18n-helper.js +381 -0
- package/scripts/multi-model-pipeline.js +144 -0
- package/skill-packs/mobile-ios/pack.json +4 -2
- package/skill-packs/reverse-engineering/pack.json +1 -0
- package/skills/CATALOG.md +20 -0
- package/skills/GEMINI.md +9 -1
- package/skills/TRIGGER_INDEX.md +10 -0
- package/skills/ai-music/SKILL.md +275 -0
- package/skills/android-re-analyzer/SKILL.md +238 -0
- package/skills/android-re-analyzer/references/api-extraction-patterns.md +119 -0
- package/skills/android-re-analyzer/references/call-flow-analysis.md +176 -0
- package/skills/android-re-analyzer/references/fernflower-usage.md +115 -0
- package/skills/android-re-analyzer/references/jadx-usage.md +116 -0
- package/skills/android-re-analyzer/references/setup-guide.md +221 -0
- package/skills/android-re-analyzer/scripts/check-deps.sh +129 -0
- package/skills/android-re-analyzer/scripts/decompile.sh +375 -0
- package/skills/android-re-analyzer/scripts/find-api-calls.sh +118 -0
- package/skills/android-re-analyzer/scripts/install-dep.sh +448 -0
- package/skills/animal-island-ui-style/SKILL.md +1450 -0
- package/skills/app-store-review-agent/SKILL.md +164 -0
- package/skills/app-store-review-agent/references/guidelines/README.md +154 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/ai_apps.md +37 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/all_apps.md +50 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/crypto_finance.md +31 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/games.md +31 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/health_fitness.md +31 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/kids.md +27 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/macos.md +38 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/social_ugc.md +32 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/subscription_iap.md +34 -0
- package/skills/app-store-review-agent/references/guidelines/by-app-type/vpn.md +18 -0
- package/skills/app-store-review-agent/references/rules/design/minimum_functionality.md +96 -0
- package/skills/app-store-review-agent/references/rules/design/sign_in_with_apple.md +54 -0
- package/skills/app-store-review-agent/references/rules/entitlements/unused_entitlements.md +83 -0
- package/skills/app-store-review-agent/references/rules/metadata/accurate_metadata.md +54 -0
- package/skills/app-store-review-agent/references/rules/metadata/apple_trademark.md +99 -0
- package/skills/app-store-review-agent/references/rules/metadata/china_storefront.md +72 -0
- package/skills/app-store-review-agent/references/rules/metadata/competitor_terms.md +56 -0
- package/skills/app-store-review-agent/references/rules/metadata/subscription_metadata.md +81 -0
- package/skills/app-store-review-agent/references/rules/privacy/privacy_manifest.md +84 -0
- package/skills/app-store-review-agent/references/rules/privacy/unnecessary_data.md +60 -0
- package/skills/app-store-review-agent/references/rules/subscription/misleading_pricing.md +63 -0
- package/skills/app-store-review-agent/references/rules/subscription/missing_tos_pp.md +54 -0
- package/skills/awf-ponytail/SKILL.md +91 -0
- package/skills/awf-ponytail-review/SKILL.md +67 -0
- package/skills/awf-session-restore/SKILL.md +3 -3
- package/skills/brainstorm-agent/SKILL.md +11 -2
- package/skills/brainstorm-agent/templates/brief-template.md +8 -0
- package/skills/claude-planner/SKILL.md +47 -0
- package/skills/code-review/SKILL.md +87 -0
- package/skills/expo-game-development/SKILL.md +163 -0
- package/skills/flutter/LICENSE.txt +202 -0
- package/skills/flutter/SKILL.md +127 -0
- package/skills/flutter-project-creater/LICENSE.txt +202 -0
- package/skills/flutter-project-creater/SKILL.md +106 -0
- package/skills/game-developer/SKILL.md +163 -0
- package/skills/game-developer/references/ecs-patterns.md +501 -0
- package/skills/game-developer/references/multiplayer-networking.md +475 -0
- package/skills/game-developer/references/performance-optimization.md +422 -0
- package/skills/game-developer/references/unity-patterns.md +271 -0
- package/skills/game-developer/references/unreal-cpp.md +352 -0
- package/skills/generate-gui-assets/SKILL.md +305 -0
- package/skills/generate-gui-assets/agents/openai.yaml +4 -0
- package/skills/generate-gui-assets/references/catalog-schema.md +58 -0
- package/skills/generate-gui-assets/references/extraction-techniques.md +21 -0
- package/skills/generate-gui-assets/references/prompt-patterns.md +58 -0
- package/skills/generate-gui-assets/scripts/__pycache__/clean_chroma_edges.cpython-311.pyc +0 -0
- package/skills/generate-gui-assets/scripts/build_gui_contact_sheet.py +51 -0
- package/skills/generate-gui-assets/scripts/clean_chroma_edges.py +262 -0
- package/skills/generate-gui-assets/scripts/copy_approved_icons.py +64 -0
- package/skills/generate-gui-assets/scripts/prepare_gui_asset_run.py +91 -0
- package/skills/generate-gui-assets/scripts/suggest_grid_options.py +63 -0
- package/skills/generate-gui-assets/scripts/validate_gui_catalog.py +50 -0
- package/skills/godot-game-development/SKILL.md +142 -0
- package/skills/hatch-pet/LICENSE.txt +201 -0
- package/skills/hatch-pet/SKILL.md +420 -0
- package/skills/hatch-pet/agents/openai.yaml +4 -0
- package/skills/hatch-pet/references/animation-rows.md +29 -0
- package/skills/hatch-pet/references/codex-pet-contract.md +35 -0
- package/skills/hatch-pet/references/qa-rubric.md +60 -0
- package/skills/hatch-pet/scripts/__pycache__/clean_chroma_edges.cpython-311.pyc +0 -0
- package/skills/hatch-pet/scripts/clean_chroma_edges.py +262 -0
- package/skills/hatch-pet/scripts/compose_atlas.py +150 -0
- package/skills/hatch-pet/scripts/derive_running_left_from_running_right.py +143 -0
- package/skills/hatch-pet/scripts/extract_strip_frames.py +323 -0
- package/skills/hatch-pet/scripts/finalize_pet_run.py +382 -0
- package/skills/hatch-pet/scripts/generate_pet_images.py +287 -0
- package/skills/hatch-pet/scripts/inspect_frames.py +246 -0
- package/skills/hatch-pet/scripts/make_contact_sheet.py +96 -0
- package/skills/hatch-pet/scripts/package_custom_pet.py +108 -0
- package/skills/hatch-pet/scripts/pet_job_status.py +117 -0
- package/skills/hatch-pet/scripts/prepare_pet_run.py +673 -0
- package/skills/hatch-pet/scripts/queue_pet_repairs.py +172 -0
- package/skills/hatch-pet/scripts/record_imagegen_result.py +250 -0
- package/skills/hatch-pet/scripts/render_animation_videos.py +134 -0
- package/skills/hatch-pet/scripts/render_animation_videos.sh +5 -0
- package/skills/hatch-pet/scripts/validate_atlas.py +139 -0
- package/skills/i18n-orchestrator/SKILL.md +37 -0
- package/skills/ios-simulator-skill/SKILL.md +390 -0
- package/skills/ios-simulator-skill/scripts/accessibility_audit.py +300 -0
- package/skills/ios-simulator-skill/scripts/app_launcher.py +326 -0
- package/skills/ios-simulator-skill/scripts/app_state_capture.py +400 -0
- package/skills/ios-simulator-skill/scripts/appearance.py +385 -0
- package/skills/ios-simulator-skill/scripts/build_and_test.py +348 -0
- package/skills/ios-simulator-skill/scripts/clipboard.py +103 -0
- package/skills/ios-simulator-skill/scripts/common/__init__.py +61 -0
- package/skills/ios-simulator-skill/scripts/common/cache_utils.py +289 -0
- package/skills/ios-simulator-skill/scripts/common/device_utils.py +462 -0
- package/skills/ios-simulator-skill/scripts/common/env_config.py +35 -0
- package/skills/ios-simulator-skill/scripts/common/hang_pipeline.py +862 -0
- package/skills/ios-simulator-skill/scripts/common/hang_sessions.py +490 -0
- package/skills/ios-simulator-skill/scripts/common/idb_utils.py +180 -0
- package/skills/ios-simulator-skill/scripts/common/screenshot_utils.py +338 -0
- package/skills/ios-simulator-skill/scripts/container.py +668 -0
- package/skills/ios-simulator-skill/scripts/gesture.py +394 -0
- package/skills/ios-simulator-skill/scripts/hang_watcher.py +1533 -0
- package/skills/ios-simulator-skill/scripts/keyboard.py +391 -0
- package/skills/ios-simulator-skill/scripts/localization_audit.py +483 -0
- package/skills/ios-simulator-skill/scripts/location.py +467 -0
- package/skills/ios-simulator-skill/scripts/log_monitor.py +493 -0
- package/skills/ios-simulator-skill/scripts/model_inspector.py +645 -0
- package/skills/ios-simulator-skill/scripts/navigator.py +461 -0
- package/skills/ios-simulator-skill/scripts/privacy_manager.py +310 -0
- package/skills/ios-simulator-skill/scripts/push_notification.py +240 -0
- package/skills/ios-simulator-skill/scripts/screen_mapper.py +296 -0
- package/skills/ios-simulator-skill/scripts/sim_health_check.sh +245 -0
- package/skills/ios-simulator-skill/scripts/sim_list.py +299 -0
- package/skills/ios-simulator-skill/scripts/simctl_boot.py +312 -0
- package/skills/ios-simulator-skill/scripts/simctl_create.py +316 -0
- package/skills/ios-simulator-skill/scripts/simctl_delete.py +357 -0
- package/skills/ios-simulator-skill/scripts/simctl_erase.py +351 -0
- package/skills/ios-simulator-skill/scripts/simctl_shutdown.py +290 -0
- package/skills/ios-simulator-skill/scripts/simulator_selector.py +375 -0
- package/skills/ios-simulator-skill/scripts/status_bar.py +250 -0
- package/skills/ios-simulator-skill/scripts/test_recorder.py +323 -0
- package/skills/ios-simulator-skill/scripts/visual_diff.py +235 -0
- package/skills/ios-simulator-skill/scripts/xcode/__init__.py +13 -0
- package/skills/ios-simulator-skill/scripts/xcode/builder.py +397 -0
- package/skills/ios-simulator-skill/scripts/xcode/cache.py +204 -0
- package/skills/ios-simulator-skill/scripts/xcode/config.py +178 -0
- package/skills/ios-simulator-skill/scripts/xcode/reporter.py +343 -0
- package/skills/ios-simulator-skill/scripts/xcode/xcresult.py +451 -0
- package/skills/ios-visual-qa-strategist/SKILL.md +111 -0
- package/skills/ios-visual-qa-strategist/agents/openai.yaml +4 -0
- package/skills/ios-visual-qa-strategist/references/ios-tool-selection.md +61 -0
- package/skills/ios-visual-qa-strategist/references/minimal-capture-policy.md +56 -0
- package/skills/ios-visual-qa-strategist/references/visual-reasoning-heuristics.md +53 -0
- package/skills/orchestrator/SKILL.md +0 -20
- package/skills/persistent-storage/SKILL.md +55 -0
- package/skills/short-maker/SKILL.md +23 -0
- package/skills/short-maker/scripts/effects.js +56 -0
- package/skills/short-maker/scripts/shortmaker-bridge.js +332 -0
- package/skills/short-maker/scripts/videomix.js +601 -0
- package/skills/short-maker/templates/hyperframes/cinematic-character.template.html +172 -0
- package/skills/short-maker/templates/hyperframes/index.template.html +194 -0
- package/skills/smali-to-kotlin/SKILL.md +128 -0
- package/skills/smali-to-kotlin/examples/getting-started/tech-stack.md +58 -0
- package/skills/smali-to-kotlin/examples/pipeline/data-ui-parity.md +118 -0
- package/skills/smali-to-kotlin/examples/pipeline/scanner-and-bootstrap.md +106 -0
- package/skills/smali-to-kotlin/library-patterns.md +189 -0
- package/skills/smali-to-kotlin/phase-0-discovery.md +128 -0
- package/skills/smali-to-kotlin/phase-1-architecture.md +166 -0
- package/skills/smali-to-kotlin/phase-2-blueprint-ui.md +347 -0
- package/skills/smali-to-kotlin/phase-2-blueprint.md +228 -0
- package/skills/smali-to-kotlin/phase-3-build.md +248 -0
- package/skills/smali-to-kotlin/phase-3-logic-build.md +268 -0
- package/skills/smali-to-kotlin/smali-reading-guide.md +310 -0
- package/skills/smali-to-kotlin/templates/app-map.md +101 -0
- package/skills/smali-to-kotlin/templates/architecture.md +142 -0
- package/skills/smali-to-kotlin/templates/blueprint.md +145 -0
- package/skills/spec-gate/SKILL.md +6 -2
- package/skills/symphony-enforcer/SKILL.md +8 -0
- package/skills/symphony-enforcer/examples/mindful-stop.md +2 -0
- package/skills/symphony-enforcer/examples/three-phase.md +16 -0
- package/skills/symphony-enforcer/examples/trigger-points.md +7 -1
- package/skills/unity-game-development/SKILL.md +231 -0
- package/skills/verification-gate/SKILL.md +4 -2
- package/skills/video-edit/SKILL.md +36 -0
- package/skills/video-edit/scripts/video_edit.py +324 -0
- package/templates/setup-mapping.json +48 -0
- package/templates/specs/design-template.md +161 -71
- package/templates/specs/requirements-template.md +65 -133
- package/templates/specs/task-spec-template.xml +3 -0
- package/workflows/_uncategorized/critic.md +40 -0
- package/workflows/_uncategorized/git-rebase-flow.md +81 -0
- package/workflows/_uncategorized/image-gen.md +118 -0
- package/workflows/_uncategorized/multi-model-pipeline.md +60 -0
- package/workflows/_uncategorized/pixel-gen.md +86 -0
- package/workflows/_uncategorized/pixel-setup.md +90 -0
- package/workflows/_uncategorized/ponytail-review.md +59 -0
- package/workflows/_uncategorized/reverse-android-build.md +222 -0
- package/workflows/_uncategorized/reverse-android-design.md +139 -0
- package/workflows/_uncategorized/reverse-android-discover.md +150 -0
- package/workflows/_uncategorized/reverse-android-scan.md +158 -0
- package/workflows/_uncategorized/reverse-android.md +143 -0
- package/workflows/_uncategorized/reverse-ios-build.md +240 -0
- package/workflows/_uncategorized/reverse-ios-design.md +112 -0
- package/workflows/_uncategorized/reverse-ios-discover.md +120 -0
- package/workflows/_uncategorized/reverse-ios-scan.md +155 -0
- package/workflows/_uncategorized/reverse-ios.md +152 -0
- package/workflows/_uncategorized/safety-router.md +34 -0
- package/workflows/_uncategorized/teach.md +89 -0
- package/workflows/_uncategorized/verify-ui.md +53 -0
- package/workflows/_uncategorized/visualize-screenshots.md +34 -0
- package/workflows/ads/ads-analyst.md +201 -0
- package/workflows/ads/ads-audit.md +106 -0
- package/workflows/ads/ads-optimize.md +97 -0
- package/workflows/ads/ads-targeting.md +241 -0
- package/workflows/ads/adsExpert.md +160 -0
- package/workflows/ads/smali-ads-config.md +400 -0
- package/workflows/ads/smali-ads-flow.md +331 -0
- package/workflows/ads/smali-ads-interstitial.md +377 -0
- package/workflows/ads/smali-ads-native.md +382 -0
- package/workflows/context/teach.md +89 -0
- package/workflows/gitnexus.md +8 -8
- package/workflows/lifecycle/brainstorm.md +43 -0
- package/workflows/lifecycle/code.md +5 -0
- package/workflows/lifecycle/init.md +23 -5
- package/workflows/lifecycle/multi-model-pipeline.md +60 -0
- package/workflows/quality/ponytail-review.md +59 -0
- package/workflows/roles/critic.md +40 -0
- 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
|