@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,324 @@
1
+ import argparse
2
+ import json
3
+ import subprocess
4
+ from dataclasses import dataclass
5
+ from pathlib import Path
6
+
7
+ from PIL import Image, ImageDraw, ImageFont
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class Caption:
12
+ start: float
13
+ end: float
14
+ text: str
15
+ placement: str
16
+
17
+
18
+ def _wrap_text(text: str, font: ImageFont.FreeTypeFont, max_width: int) -> list[str]:
19
+ words = text.split(" ")
20
+ lines: list[str] = []
21
+ cur = ""
22
+ for w in words:
23
+ test = (cur + " " + w).strip()
24
+ if not cur or font.getlength(test) <= max_width:
25
+ cur = test
26
+ else:
27
+ lines.append(cur)
28
+ cur = w
29
+ if cur:
30
+ lines.append(cur)
31
+ return lines
32
+
33
+
34
+ def _pick_font(project_root: Path) -> str:
35
+ candidates = [
36
+ project_root / "assets" / "fonts" / "BeVietnamPro-Regular.ttf",
37
+ project_root / "assets" / "fonts" / "Inter-Regular.ttf",
38
+ Path("/System/Library/Fonts/Supplemental/Arial.ttf"),
39
+ ]
40
+ for p in candidates:
41
+ if p.exists():
42
+ return str(p)
43
+ raise FileNotFoundError("No font found. Expected assets/fonts/*.ttf or system Arial.")
44
+
45
+
46
+ def _make_caption_overlay(
47
+ *,
48
+ width: int,
49
+ height: int,
50
+ font_path: str,
51
+ text: str,
52
+ placement: str,
53
+ out_path: Path,
54
+ ) -> None:
55
+ img = Image.new("RGBA", (width, height), (0, 0, 0, 0))
56
+ draw = ImageDraw.Draw(img)
57
+
58
+ is_top = placement == "top"
59
+ font_size = 64 if is_top else 54
60
+ font = ImageFont.truetype(font_path, font_size)
61
+
62
+ max_w = int(width * (0.82 if is_top else 0.78))
63
+ lines = _wrap_text(text, font, max_w)
64
+ if not lines:
65
+ img.save(out_path)
66
+ return
67
+
68
+ line_h = int(font_size * 1.25)
69
+ text_h = line_h * len(lines)
70
+ text_w = int(max(font.getlength(line) for line in lines))
71
+
72
+ pad_x = 44 if is_top else 36
73
+ pad_y = 24 if is_top else 22
74
+ box_w = min(width - 120, text_w + pad_x * 2)
75
+ box_h = min(height - 120, text_h + pad_y * 2)
76
+
77
+ cx = width // 2
78
+ box_x0 = cx - box_w // 2
79
+ box_y0 = int(height * 0.10) if is_top else int(height * 0.76)
80
+ box_y0 = min(box_y0, height - box_h - 40)
81
+
82
+ draw.rounded_rectangle(
83
+ [box_x0, box_y0, box_x0 + box_w, box_y0 + box_h],
84
+ radius=26,
85
+ fill=(0, 0, 0, 165),
86
+ )
87
+
88
+ cur_y = box_y0 + pad_y
89
+ for line in lines:
90
+ lw = font.getlength(line)
91
+ x = cx - lw / 2
92
+ draw.text((x, cur_y), line, font=font, fill=(255, 255, 255, 255))
93
+ cur_y += line_h
94
+
95
+ img.save(out_path)
96
+
97
+
98
+ def _load_captions(cfg: dict) -> list[Caption]:
99
+ raw = cfg.get("captions") or []
100
+ caps: list[Caption] = []
101
+ for item in raw:
102
+ start = float(item.get("timelineStart", 0))
103
+ duration = float(item.get("duration", 0))
104
+ text = (item.get("text") or "").strip()
105
+ placement = (item.get("placement") or "bottom").strip().lower()
106
+ if duration <= 0 or not text:
107
+ continue
108
+ caps.append(Caption(start=start, end=start + duration, text=text, placement=placement))
109
+ return caps
110
+
111
+
112
+ def _build_ffmpeg_command(
113
+ *,
114
+ project_root: Path,
115
+ cfg: dict,
116
+ out_mp4: Path,
117
+ preset: str,
118
+ include_captions: bool,
119
+ include_decor: bool,
120
+ crf: int,
121
+ badge: str | None,
122
+ badge_start: float,
123
+ badge_duration: float,
124
+ ) -> list[str]:
125
+ project = cfg["project"]
126
+ width = int(project.get("width", 1080))
127
+ height = int(project.get("height", 1920))
128
+ fps = int(project.get("fps", 30))
129
+
130
+ shots = cfg.get("shots") or []
131
+ if not shots:
132
+ raise ValueError("EDL has no shots")
133
+
134
+ total_duration = float(project.get("duration") or 0)
135
+ if total_duration <= 0:
136
+ total_duration = sum(float(s["duration"]) for s in shots)
137
+
138
+ args: list[str] = ["ffmpeg", "-hide_banner", "-y"]
139
+
140
+ for s in shots:
141
+ args += [
142
+ "-ss",
143
+ f'{float(s.get("sourceStart", 0)):.3f}',
144
+ "-t",
145
+ f'{float(s["duration"]):.3f}',
146
+ "-i",
147
+ str(s["source"]),
148
+ ]
149
+
150
+ music = cfg.get("music") or {}
151
+ if not music.get("path"):
152
+ raise ValueError("EDL is missing music.path")
153
+
154
+ args += [
155
+ "-ss",
156
+ f'{float(music.get("start", 0)):.3f}',
157
+ "-t",
158
+ f"{total_duration:.3f}",
159
+ "-i",
160
+ str(music["path"]),
161
+ ]
162
+
163
+ overlays: list[dict] = []
164
+ overlays_dir = out_mp4.parent / "overlays"
165
+ overlays_dir.mkdir(parents=True, exist_ok=True)
166
+
167
+ if include_decor and preset in ("cinematic", "clean"):
168
+ decor_files = []
169
+ if preset == "cinematic":
170
+ decor_files = [
171
+ project_root / "assets" / "overlays" / "vignette_1080x1920.png",
172
+ project_root / "assets" / "overlays" / "grain_1080x1920.png",
173
+ ]
174
+ if preset == "clean":
175
+ decor_files = [
176
+ project_root / "assets" / "overlays" / "bottom_fade_1080x1920.png",
177
+ project_root / "assets" / "overlays" / "top_fade_1080x1920.png",
178
+ ]
179
+ for p in decor_files:
180
+ if p.exists():
181
+ overlays.append({"file": str(p), "start": 0.0, "end": total_duration})
182
+
183
+ if include_decor and badge and badge != "none" and badge_duration > 0:
184
+ badge_file = project_root / "assets" / "overlays" / f"badge_{badge}_1080x1920.png"
185
+ if badge_file.exists():
186
+ overlays.append(
187
+ {
188
+ "file": str(badge_file),
189
+ "start": max(0.0, badge_start),
190
+ "end": min(total_duration, max(0.0, badge_start + badge_duration)),
191
+ }
192
+ )
193
+
194
+ if include_captions:
195
+ font_path = _pick_font(project_root)
196
+ for i, cap in enumerate(_load_captions(cfg), start=1):
197
+ p = overlays_dir / f"cap_{i:02d}.png"
198
+ _make_caption_overlay(
199
+ width=width,
200
+ height=height,
201
+ font_path=font_path,
202
+ text=cap.text,
203
+ placement=cap.placement,
204
+ out_path=p,
205
+ )
206
+ overlays.append({"file": str(p), "start": cap.start, "end": cap.end})
207
+
208
+ for ov in overlays:
209
+ args += ["-loop", "1", "-t", f"{total_duration:.3f}", "-i", ov["file"]]
210
+
211
+ audio_input_index = len(shots)
212
+ first_overlay_idx = audio_input_index + 1
213
+
214
+ vf_parts: list[str] = []
215
+ for i in range(len(shots)):
216
+ vf_parts.append(
217
+ f"[{i}:v]"
218
+ f"scale={width}:{height}:force_original_aspect_ratio=increase,"
219
+ f"crop={width}:{height},fps={fps},format=yuv420p,setpts=PTS-STARTPTS[v{i}]"
220
+ )
221
+
222
+ concat_in = "".join([f"[v{i}]" for i in range(len(shots))])
223
+ vf_parts.append(f"{concat_in}concat=n={len(shots)}:v=1:a=0[vcat]")
224
+
225
+ v_prev = "[vcat]"
226
+ for j, ov in enumerate(overlays):
227
+ img_idx = first_overlay_idx + j
228
+ v_next = f"[vo{j}]" if j < len(overlays) - 1 else "[vpre]"
229
+ vf_parts.append(
230
+ f"{v_prev}[{img_idx}:v]overlay=0:0:format=auto:shortest=1:"
231
+ f"enable=between(t\\,{ov['start']:.3f}\\,{ov['end']:.3f}){v_next}"
232
+ )
233
+ v_prev = v_next
234
+
235
+ vf_parts.append(f"[vpre]trim=duration={total_duration:.3f},setpts=PTS-STARTPTS[vout]")
236
+
237
+ volume = float(music.get("volume", 0.55))
238
+ fade_in = float(music.get("fadeIn", 0.4))
239
+ fade_out = float(music.get("fadeOut", 1.0))
240
+ fade_out_start = max(0.0, total_duration - fade_out)
241
+
242
+ vf_parts.append(
243
+ f"[{audio_input_index}:a]atrim=0:{total_duration:.3f},asetpts=PTS-STARTPTS,"
244
+ f"volume={volume},"
245
+ f"afade=t=in:st=0:d={fade_in:.3f},"
246
+ f"afade=t=out:st={fade_out_start:.3f}:d={fade_out:.3f},"
247
+ "aformat=sample_fmts=fltp:sample_rates=48000:channel_layouts=stereo[aout]"
248
+ )
249
+
250
+ out_mp4.parent.mkdir(parents=True, exist_ok=True)
251
+
252
+ args += [
253
+ "-filter_complex",
254
+ ";".join(vf_parts),
255
+ "-map",
256
+ "[vout]",
257
+ "-map",
258
+ "[aout]",
259
+ "-shortest",
260
+ "-c:v",
261
+ "libx264",
262
+ "-preset",
263
+ "veryfast",
264
+ "-crf",
265
+ str(crf),
266
+ "-pix_fmt",
267
+ "yuv420p",
268
+ "-c:a",
269
+ "aac",
270
+ "-b:a",
271
+ "192k",
272
+ "-movflags",
273
+ "+faststart",
274
+ str(out_mp4),
275
+ ]
276
+ return args
277
+
278
+
279
+ def cmd_render(args: argparse.Namespace) -> int:
280
+ project_root = Path(args.project_root).resolve()
281
+ edl_path = Path(args.edl).resolve()
282
+ cfg = json.loads(edl_path.read_text("utf-8"))
283
+
284
+ out_mp4 = Path(args.out).resolve() if args.out else (edl_path.parent / "_render" / "final.mp4")
285
+ cmd = _build_ffmpeg_command(
286
+ project_root=project_root,
287
+ cfg=cfg,
288
+ out_mp4=out_mp4,
289
+ preset=args.preset,
290
+ include_captions=not args.no_captions,
291
+ include_decor=not args.no_decor,
292
+ crf=args.crf,
293
+ badge=args.badge,
294
+ badge_start=args.badge_start,
295
+ badge_duration=args.badge_duration,
296
+ )
297
+
298
+ subprocess.run(cmd, cwd=str(project_root), check=True)
299
+ return 0
300
+
301
+
302
+ def main() -> int:
303
+ parser = argparse.ArgumentParser(prog="video_edit")
304
+ sub = parser.add_subparsers(dest="command", required=True)
305
+
306
+ p_render = sub.add_parser("render")
307
+ p_render.add_argument("--edl", required=True)
308
+ p_render.add_argument("--out", default=None)
309
+ p_render.add_argument("--preset", default="cinematic", choices=["cinematic", "clean", "none"])
310
+ p_render.add_argument("--crf", type=int, default=22)
311
+ p_render.add_argument("--badge", default="none", choices=["none", "tip", "warn", "new", "ok"])
312
+ p_render.add_argument("--badge-start", type=float, default=0.3)
313
+ p_render.add_argument("--badge-duration", type=float, default=2.6)
314
+ p_render.add_argument("--project-root", default=str(Path.cwd()))
315
+ p_render.add_argument("--no-captions", action="store_true")
316
+ p_render.add_argument("--no-decor", action="store_true")
317
+ p_render.set_defaults(func=cmd_render)
318
+
319
+ ns = parser.parse_args()
320
+ return int(ns.func(ns))
321
+
322
+
323
+ if __name__ == "__main__":
324
+ raise SystemExit(main())
@@ -0,0 +1,48 @@
1
+ {
2
+ "tech_mappings": {
3
+ "react": {
4
+ "skills": ["visual-design-gate", "animal-island-ui-style"],
5
+ "mcps": ["playwright"],
6
+ "hooks": ["auto-lint"]
7
+ },
8
+ "nextjs": {
9
+ "skills": ["firebase-app-hosting-basics", "visual-design-gate"],
10
+ "mcps": ["playwright"],
11
+ "hooks": ["auto-lint", "pre-build-check"]
12
+ },
13
+ "expo": {
14
+ "skills": ["expo-build-optimizer", "visual-design-gate"],
15
+ "mcps": ["maestro"],
16
+ "hooks": ["auto-lint"]
17
+ },
18
+ "react-native": {
19
+ "skills": ["expo-build-optimizer", "visual-design-gate"],
20
+ "mcps": ["maestro"],
21
+ "hooks": ["auto-lint"]
22
+ },
23
+ "firebase": {
24
+ "skills": ["firebase-basics", "firebase-firestore", "firebase-auth-basics", "firebase-security-rules-auditor"],
25
+ "mcps": ["firebase-mcp-server"]
26
+ },
27
+ "android": {
28
+ "skills": ["android-cli", "android-aso", "android-re-analyzer"],
29
+ "mcps": ["maestro"]
30
+ },
31
+ "ios": {
32
+ "skills": ["ios-engineer", "ios-expert-coder", "swiftui-pro", "xcode-project-setup"],
33
+ "mcps": ["maestro", "ios-simulator"]
34
+ },
35
+ "swift": {
36
+ "skills": ["ios-engineer", "ios-expert-coder", "swiftui-pro"],
37
+ "mcps": ["ios-simulator"]
38
+ },
39
+ "flutter": {
40
+ "skills": ["flutter", "flutter-project-creater"],
41
+ "mcps": ["maestro"]
42
+ }
43
+ },
44
+ "default_hooks": {
45
+ "auto_commit": true,
46
+ "build_preflight": "awkit build"
47
+ }
48
+ }
@@ -1,76 +1,166 @@
1
- # UI/Visual Design Document — [Tính Năng/Giao Diện]
2
- > "[Slogan hoặc Nguyên tắc chủ đạo của giao diện: "Ví dụ: Mỗi tab một sứ mệnh – không overlap"]"
3
-
4
- [⚠️ AI INSTRUCTION: BẮT BUỘC KHÔNG THIẾT KẾ DATA MODELS TẠI ĐÂY. Tập trung 100% vào Đồ Họa, Thông số UI (Hex, Padding), UX (Tap, Hover) và Component UI hierarchy.]
5
-
6
- ## 1. Tổng Quan & Metadata
7
- * **Phiên bản:** [Ví dụ: 1.0]
8
- * **Ngày tạo:** [YYYY-MM-DD]
9
- * **Mục tiêu đồ họa:** [ do thay đổi/Kết quả UI mong muốn]
10
-
11
- ## 2. Nguyên Tắc Thiết Kế (Design Principles)
12
- [Danh sách quy tắc bất biến về mặt đồ họa và trải nghiệm người dùng]
13
- 1. [Nguyên tắc 1: Không overlap chức năng giữa các khu vực].
14
- 2. [Nguyên tắc 2: Tình trạng hiển thị (Visibility) của các thành phần chính].
15
- 3. [Nguyên tắc 3: Hệ thống thông báo/Badge thông minh].
16
- 4. [Nguyên tắc 4: Phân cấp Animation theo tiers (Subtle, Satisfying, v.v.)].
17
-
18
- ## 3. Đặc Tả Hình Ảnh (Component Specs)
19
- ### 3.1 Thông số kỹ thuật (Thẩm mỹ & Layout)
20
- * **Kích thước:** [Ví dụ: Height: 60px + SafeArea].
21
- * **Màu sắc & Shadow:**
22
- - Nền/Border: [Mã màu Background, Border cụ thể].
23
- - Shadow: [Elevation, Offset, Radius].
24
- * **Trạng thái (States):**
25
- - Active: [Màu sắc, font weight, opacity].
26
- - Inactive: [Màu sắc, font weight, opacity].
27
-
28
- ### 3.2 Danh sách Element
29
- [Bảng liệt kê các thành phần hiển thị]:
30
- | # | Tên Item | Mức độ ưu tiên | Icon/Graphic (Màu sắc) | Điều kiện nháy/hiển thị |
31
- |---|----------|----------------|------------------------|-------------------------|
32
- | 1 | [Item A] | [Primary] | [Mã Hex / Vector] | [Condition] |
33
-
34
- ## 4. Chi Tiết Các Màn Hình (Screen Breakdown)
35
- ### 4.1 Layout: [Tên Màn Hình]
36
- * **Vai trò hiển thị:** [Dashboard / Modal / Popup]
37
- * **Cấu trúc đồ họa (Từ trên xuống):**
38
- - **Header:** [Nút back, Tiêu đề, Badge]
39
- - **Hero Section:** [Ảnh chụp, Thông điệp to]
40
- - **Content Grid:** [Spacing dọc ngang, Padding 2 bên]
41
- - **CTA Button:** [Stick bottom, Shadow layer]
42
-
43
- ### 4.2 Component Hierarchy (Cấu trúc giao diện)
44
- [AI: Bắt buộc vẽ sơ đồ Text Tree cho cấu trúc Component React/UI UI-only]
45
- ```text
46
- FeatureView (Root)
47
-
48
- ├── HeaderComponent
49
- │ └── BackButton
50
-
51
- ├── ContentSection
52
- │ ├── ItemCard
53
- │ └── ProgressBar
54
-
55
- └── ActionButtons
56
- └── PrimaryCTA
1
+ # [Feature Name] Design Document
2
+
3
+ ## Overview
4
+
5
+ [High-level description of the feature architecture - describe the overall approach, key design decisions, and how it fits into the larger system]
6
+
7
+ ## Architecture
8
+
9
+ [Description of architectural approach and patterns used]
10
+
11
+ ### Component Hierarchy
12
+
13
+ ```
14
+ [FeatureName]View (Root)
15
+ ├── [HeaderComponent] (Navigation and context)
16
+ ├── [MainContainer] (Primary content)
17
+ │ ├── [ContentSection1]
18
+ │ │ ├── [SubComponent1]
19
+ │ │ └── [SubComponent2]
20
+ │ ├── [ContentSection2]
21
+ │ │ └── [SubComponent3]
22
+ │ └── [ActionSection]
23
+ │ └── [ActionButtons]
24
+ ├── [FloatingElements] (Overlays, FABs)
25
+ └── [ModalComponents] (Sheets, Dialogs)
26
+ ```
27
+
28
+ ## Components and Interfaces
29
+
30
+ ### [MainComponent]
31
+ - **Purpose**: [What this component does and why]
32
+ - **Platform-Specific Design**:
33
+ - iOS: [Apple HIG considerations, SF Symbols, native patterns]
34
+ - Android: [Material Design 3 components, patterns]
35
+ - **Key Features**:
36
+ - [Feature 1 with implementation detail]
37
+ - [Feature 2 with implementation detail]
38
+ - [Animations and transitions]
39
+
40
+ ### [SubComponent1]
41
+ - **Purpose**: [Component purpose]
42
+ - **Visual Design**:
43
+ - [Layout specifications]
44
+ - [Color and typography]
45
+ - [Spacing and sizing]
46
+ - **Interaction Design**:
47
+ - [Touch/click behavior]
48
+ - [Hover states (if applicable)]
49
+ - [Animation specs]
50
+
51
+ ## Data Models
52
+
53
+ ### [PrimaryModel]
54
+ ```swift
55
+ // iOS
56
+ struct [ModelName]: Codable, Identifiable {
57
+ let id: UUID
58
+ let property1: String
59
+ let property2: Int
60
+ let optionalProperty: String?
61
+ let nestedObject: [NestedType]
62
+ let createdAt: Date
63
+ let updatedAt: Date
64
+
65
+ enum CodingKeys: String, CodingKey {
66
+ case id
67
+ case property1 = "property_1"
68
+ // ... mapping for API compatibility
69
+ }
70
+ }
71
+ ```
72
+
73
+ ```kotlin
74
+ // Android
75
+ data class [ModelName](
76
+ val id: String,
77
+ val property1: String,
78
+ val property2: Int,
79
+ val optionalProperty: String?,
80
+ val nestedObject: List<NestedType>,
81
+ val createdAt: Instant,
82
+ val updatedAt: Instant
83
+ )
57
84
  ```
58
85
 
59
- ## 5. Đặc Tả Chuyển Động (Animation & Graphic Logic)
60
- * **Logic thông báo (Badge Status):** [Quy định dấu chấm đỏ nổi lên lúc nào, hiệu ứng thở "breathing" ra sao].
61
- * **Đặc tả chuyển động (Animation Spec):**
62
- - **Kiểu:** [Spring / Linear / Bounce].
63
- - **Thông số:** [Duration: X ms, Damping: Y, Stiffness: Z].
64
- * **Hiệu ứng Haptic (Rung):** [Gõ phím -> Light Haptic; Thành công -> Success Haptic].
86
+ ### [StateModel]
87
+ ```swift
88
+ // iOS - ViewModel State
89
+ enum [Feature]ViewState {
90
+ case idle
91
+ case loading
92
+ case loaded([DataModel])
93
+ case error(Error)
94
+ case empty
95
+ }
96
+ ```
97
+
98
+ ```kotlin
99
+ // Android - UI State
100
+ sealed interface [Feature]UiState {
101
+ data object Loading : [Feature]UiState
102
+ data class Success(val data: List<DataModel>) : [Feature]UiState
103
+ data class Error(val message: String) : [Feature]UiState
104
+ data object Empty : [Feature]UiState
105
+ }
106
+ ```
107
+
108
+ ## Correctness Properties
109
+
110
+ *Properties serve as the bridge between requirements and verifiable correctness guarantees.*
111
+
112
+ **Property 1: [Property Name]**
113
+ *For any* [scenario/input], the system should [expected behavior across all conditions]
114
+ **Validates: Requirements 1.1, 1.2, 1.3**
115
+
116
+ **Property 2: [Property Name]**
117
+ *For any* [scenario/input], the system should [expected behavior]
118
+ **Validates: Requirements 2.1, 2.2**
119
+
120
+ **Property 3: Error Handling Correctness**
121
+ *For any* error condition, the system should [graceful handling, user feedback, recovery options]
122
+ **Validates: Requirements 3.1, 3.2, 3.3**
123
+
124
+ ## UI/UX Design Specifications
125
+
126
+ ### Visual Design System
127
+
128
+ **Colors:**
129
+ | Token | Light Mode | Dark Mode | Usage |
130
+ |-------|------------|-----------|-------|
131
+ | Primary | #[hex] | #[hex] | [usage] |
132
+ | Secondary | #[hex] | #[hex] | [usage] |
133
+ | Background | #[hex] | #[hex] | [usage] |
134
+
135
+ **Typography:**
136
+ | Style | Font | Size | Weight | Usage |
137
+ |-------|------|------|--------|-------|
138
+ | Title | [font] | 24pt | Bold | [usage] |
139
+ | Body | [font] | 16pt | Regular | [usage] |
140
+
141
+ **Spacing:**
142
+ | Token | Value | Usage |
143
+ |-------|-------|-------|
144
+ | xs | 4pt | [usage] |
145
+ | sm | 8pt | [usage] |
146
+ | md | 16pt | [usage] |
147
+
148
+ ### Animation Specifications
149
+
150
+ | Animation | Duration | Easing | Description |
151
+ |-----------|----------|--------|-------------|
152
+ | Appear | 300ms | easeOut | [description] |
153
+ | Disappear | 200ms | easeIn | [description] |
154
+ | Spring | 0.5s/0.7 | spring | [response/damping] |
155
+
156
+ ## Performance Considerations
65
157
 
66
- ## 6. Đồ Routing (Đứng từ góc độ UI)
67
- * **Cấu trúc Thư mục Màn Hình:** [app/(tabs)/home.tsx]
68
- * **Component tái sử dụng:** [ dụ: Dùng chung thẻ UserCard từ design-system sẵn có].
158
+ - **Lazy Loading**: [What should be lazy loaded]
159
+ - **Caching Strategy**: [How data should be cached]
160
+ - **Memory Management**: [Memory considerations]
69
161
 
70
- ## 7. Lộ Trình Triển Khai (Dành riêng cho Frontend/UI)
71
- * **Giai đoạn 1:** Lên layout tĩnh (CSS + HTML/JSX). Gắn Mock Text.
72
- * **Giai đoạn 2:** Apply Animations & Haptics.
73
- * **Giai đoạn 3:** Bọc Component ghép vào Data thật bên ngoài.
162
+ ## Security Considerations
74
163
 
75
- ---
76
- *Tài liệu Đặc Tả Giao Diện (Visual & Graphic Design Only).*
164
+ - **Data Encryption**: [What needs encryption]
165
+ - **Input Validation**: [Validation requirements]
166
+ - **Authentication**: [Auth requirements]