@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
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "@leejungkiin/awkit",
3
- "version": "1.7.0",
3
+ "version": "1.7.4",
4
4
  "description": "Antigravity Workflow Kit v1.6 Unified AI agent orchestration system with Mindful Checkpoints.",
5
5
  "main": "bin/awk.js",
6
6
  "private": false,
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
7
10
  "bin": {
8
11
  "awkit": "bin/awk.js",
9
12
  "ag": "bin/awk.js"
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Artifact Storage Engine for AWKit
3
+ * Manages persistent key-value data for interactive artifacts.
4
+ * Saves data locally to .brain/storage.json.
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ const STORAGE_DIR = path.join(process.cwd(), '.brain');
11
+ const STORAGE_FILE = path.join(STORAGE_DIR, 'storage.json');
12
+
13
+ function ensureStorageDir() {
14
+ if (!fs.existsSync(STORAGE_DIR)) {
15
+ fs.mkdirSync(STORAGE_DIR, { recursive: true });
16
+ }
17
+ }
18
+
19
+ function loadStorage() {
20
+ ensureStorageDir();
21
+ if (!fs.existsSync(STORAGE_FILE)) {
22
+ return { personal: {}, shared: {} };
23
+ }
24
+ try {
25
+ const content = fs.readFileSync(STORAGE_FILE, 'utf8');
26
+ return JSON.parse(content);
27
+ } catch (_) {
28
+ return { personal: {}, shared: {} };
29
+ }
30
+ }
31
+
32
+ function saveStorage(data) {
33
+ ensureStorageDir();
34
+ fs.writeFileSync(STORAGE_FILE, JSON.stringify(data, null, 2) + '\n', 'utf8');
35
+ }
36
+
37
+ function validateKey(key) {
38
+ if (!key || typeof key !== 'string') return 'Key must be a non-empty string.';
39
+ if (key.length > 200) return 'Key must be under 200 characters.';
40
+ if (/\s/.test(key)) return 'Key cannot contain whitespace.';
41
+ if (/[\/\\'"\s]/.test(key)) return 'Key cannot contain path separators or quotes.';
42
+ return null;
43
+ }
44
+
45
+ function cmdStorage(args) {
46
+ const action = args[0];
47
+ const key = args[1];
48
+ const value = args[2];
49
+ const isShared = args.includes('--shared');
50
+
51
+ const type = isShared ? 'shared' : 'personal';
52
+
53
+ if (!action) {
54
+ console.error('Usage: awkit storage <get|set|delete|list> [key] [value] [--shared]');
55
+ process.exit(1);
56
+ }
57
+
58
+ const storage = loadStorage();
59
+
60
+ switch (action.toLowerCase()) {
61
+ case 'set': {
62
+ const err = validateKey(key);
63
+ if (err) {
64
+ console.error(`Error: ${err}`);
65
+ process.exit(1);
66
+ }
67
+ if (value === undefined) {
68
+ console.error('Error: Value is required for set action.');
69
+ process.exit(1);
70
+ }
71
+
72
+ let parsedValue = value;
73
+ try {
74
+ // Try to parse if it is valid JSON
75
+ parsedValue = JSON.parse(value);
76
+ } catch (_) {
77
+ // Keep as raw string if parsing fails
78
+ }
79
+
80
+ storage[type][key] = parsedValue;
81
+ saveStorage(storage);
82
+ console.log(JSON.stringify({ key, value: parsedValue, shared: isShared }, null, 2));
83
+ break;
84
+ }
85
+
86
+ case 'get': {
87
+ if (!key) {
88
+ console.error('Error: Key is required for get action.');
89
+ process.exit(1);
90
+ }
91
+ const found = storage[type][key];
92
+ if (found === undefined) {
93
+ console.error(`Error: Key "${key}" not found in ${type} storage.`);
94
+ process.exit(1);
95
+ }
96
+ console.log(JSON.stringify({ key, value: found, shared: isShared }, null, 2));
97
+ break;
98
+ }
99
+
100
+ case 'delete': {
101
+ if (!key) {
102
+ console.error('Error: Key is required for delete action.');
103
+ process.exit(1);
104
+ }
105
+ if (storage[type][key] === undefined) {
106
+ console.error(`Error: Key "${key}" not found in ${type} storage.`);
107
+ process.exit(1);
108
+ }
109
+ delete storage[type][key];
110
+ saveStorage(storage);
111
+ console.log(JSON.stringify({ key, deleted: true, shared: isShared }, null, 2));
112
+ break;
113
+ }
114
+
115
+ case 'list': {
116
+ const prefix = key || '';
117
+ const keys = Object.keys(storage[type]).filter(k => k.startsWith(prefix));
118
+ console.log(JSON.stringify({ keys, prefix: prefix || null, shared: isShared }, null, 2));
119
+ break;
120
+ }
121
+
122
+ default:
123
+ console.error(`Unknown action: ${action}`);
124
+ process.exit(1);
125
+ }
126
+ }
127
+
128
+ module.exports = {
129
+ cmdStorage
130
+ };
@@ -102,13 +102,13 @@ function checkGate(domain, action) {
102
102
  case 'git': {
103
103
  const gitConfig = automation.git;
104
104
  if (!gitConfig) {
105
- return { allowed: true, config: null, reason: 'No automation.git config — default allow' };
105
+ return { allowed: false, config: null, reason: 'No automation.git config — default block' };
106
106
  }
107
- if (action === 'commit' && gitConfig.autoCommit === false) {
108
- return { allowed: false, config: gitConfig, reason: 'automation.git.autoCommit is false' };
107
+ if (action === 'commit' && gitConfig.autoCommit !== true) {
108
+ return { allowed: false, config: gitConfig, reason: 'automation.git.autoCommit is not true (default off)' };
109
109
  }
110
- if (action === 'push' && gitConfig.autoPush === false) {
111
- return { allowed: false, config: gitConfig, reason: 'automation.git.autoPush is false' };
110
+ if (action === 'push' && gitConfig.autoPush !== true) {
111
+ return { allowed: false, config: gitConfig, reason: 'automation.git.autoPush is not true (default off)' };
112
112
  }
113
113
  return { allowed: true, config: gitConfig, reason: 'automation.git allows this action' };
114
114
  }
@@ -166,6 +166,12 @@ function checkGate(domain, action) {
166
166
 
167
167
  // ─── Git executors ────────────────────────────────────────────────────────────
168
168
 
169
+ /**
170
+ * List of generic commit messages that should be rejected.
171
+ * AI agents MUST provide descriptive conventional commit messages.
172
+ */
173
+ const GENERIC_MSG_PATTERNS = /^(chore: update|update|wip|changes|fix|feat|chore|save|commit|auto commit|update files|chore: update files|feat\([^)]*\): update \w+)$/i;
174
+
169
175
  function execGitCommit(message) {
170
176
  const gate = checkGate('git', 'commit');
171
177
  if (!gate.allowed) {
@@ -174,6 +180,22 @@ function execGitCommit(message) {
174
180
  return false;
175
181
  }
176
182
 
183
+ // BLOCK commits without descriptive messages
184
+ if (!message || !message.trim()) {
185
+ err('🚫 COMMIT BLOCKED: No commit message provided.');
186
+ err(' AI MUST provide a descriptive conventional commit message.');
187
+ err(' Example: awkit gate git auto "feat(auth): add Google sign-in flow"');
188
+ return false;
189
+ }
190
+
191
+ if (GENERIC_MSG_PATTERNS.test(message.trim())) {
192
+ err(`🚫 COMMIT BLOCKED: Generic message detected — "${message}"`);
193
+ err(' AI MUST describe WHAT was changed and WHY.');
194
+ err(' ✅ Good: "feat(home): add hero banner with parallax effect"');
195
+ err(' ❌ Bad: "chore: update", "feat(app): update development"');
196
+ return false;
197
+ }
198
+
177
199
  try {
178
200
  execRtkSync('git add -A', { stdio: 'inherit' });
179
201
  execRtkSync(`git commit -m "${message.replace(/"/g, '\\"')}"`, { stdio: 'inherit' });
@@ -221,6 +243,17 @@ function execGitAuto(message) {
221
243
  log(`${C.cyan}${C.bold}🔒 Automation Gate — Git Auto${C.reset}`);
222
244
  dim(` Checking .project-identity...`);
223
245
 
246
+ // Early exit if working tree is clean to prevent infinite recursion/loops
247
+ try {
248
+ const gitStatus = execSync('git status --porcelain', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
249
+ if (!gitStatus) {
250
+ ok('Working tree clean. No changes to commit or push.');
251
+ return true;
252
+ }
253
+ } catch (_) {
254
+ // Ignore errors if not in a git repo, fallback to standard execution
255
+ }
256
+
224
257
  const committed = execGitCommit(message);
225
258
  if (!committed) return false;
226
259
 
@@ -353,13 +386,13 @@ function cmdGate(args) {
353
386
  case 'git':
354
387
  switch (action) {
355
388
  case 'commit':
356
- execGitCommit(rest.join(' ') || 'chore: update');
389
+ execGitCommit(rest.join(' ') || null);
357
390
  break;
358
391
  case 'push':
359
392
  execGitPush();
360
393
  break;
361
394
  case 'auto':
362
- execGitAuto(rest.join(' ') || 'chore: update');
395
+ execGitAuto(rest.join(' ') || null);
363
396
  break;
364
397
  default:
365
398
  err(`Unknown git action: ${action}`);
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { execSync, spawnSync } = require('child_process');
6
+
7
+ // Parse arguments
8
+ const args = process.argv.slice(2);
9
+ let promptFile = '';
10
+ let outputFile = '';
11
+
12
+ for (let i = 0; i < args.length; i++) {
13
+ if (args[i] === '--prompt-file' && args[i + 1]) {
14
+ promptFile = args[i + 1];
15
+ i++;
16
+ } else if (args[i] === '--output' && args[i + 1]) {
17
+ outputFile = args[i + 1];
18
+ i++;
19
+ }
20
+ }
21
+
22
+ if (!promptFile || !outputFile) {
23
+ console.error('Usage: node scripts/claude-plan.js --prompt-file <file> --output <file>');
24
+ process.exit(1);
25
+ }
26
+
27
+ // 1. Check if claude command is available
28
+ try {
29
+ execSync('which claude', { stdio: 'ignore' });
30
+ } catch (e) {
31
+ console.warn('⚠️ claude CLI not found in PATH');
32
+ process.exit(127);
33
+ }
34
+
35
+ // 2. Check if authenticated (quick test with timeout to avoid hang)
36
+ try {
37
+ execSync('claude -p "echo OK" --max-turns 1 --bare', { stdio: 'ignore', timeout: 5000 });
38
+ } catch (e) {
39
+ console.warn('⚠️ claude CLI is installed but not authenticated or timed out');
40
+ process.exit(2);
41
+ }
42
+
43
+ // 3. Read prompt
44
+ if (!fs.existsSync(promptFile)) {
45
+ console.error(`Error: Prompt file not found: ${promptFile}`);
46
+ process.exit(3);
47
+ }
48
+
49
+ const promptContent = fs.readFileSync(promptFile, 'utf8');
50
+
51
+ // 4. Run Claude CLI
52
+ console.log('🚀 Running planning via Claude CLI...');
53
+ try {
54
+ const result = spawnSync('claude', [
55
+ '-p', promptContent,
56
+ '--model', 'claude-opus-4-8',
57
+ '--max-turns', '3',
58
+ '--output-format', 'text',
59
+ '--bare'
60
+ ], { encoding: 'utf8', timeout: 300000 }); // 5 minutes timeout
61
+
62
+ if (result.status !== 0) {
63
+ console.error('❌ Claude CLI exited with status:', result.status);
64
+ console.error(result.stderr || result.stdout);
65
+ process.exit(result.status || 4);
66
+ }
67
+
68
+ fs.mkdirSync(path.dirname(outputFile), { recursive: true });
69
+ fs.writeFileSync(outputFile, result.stdout);
70
+ console.log(`✅ Plan successfully written to ${outputFile}`);
71
+ process.exit(0);
72
+
73
+ } catch (err) {
74
+ console.error('❌ Exception during Claude execution:', err.message);
75
+ process.exit(5);
76
+ }
@@ -0,0 +1,210 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { execSync } = require('child_process');
4
+ const https = require('https');
5
+ const os = require('os');
6
+
7
+ const HOME = os.homedir();
8
+ const CACHE_DIR = path.join(HOME, '.gemini', 'antigravity');
9
+ const CACHE_FILE = path.join(CACHE_DIR, '.awkit-update-cache.json');
10
+ const CACHE_DURATION_MS = 24 * 60 * 60 * 1000; // 24 hours
11
+
12
+ // Helper colors matching AWKit style
13
+ const C = {
14
+ reset: '\x1b[0m',
15
+ red: '\x1b[31m',
16
+ green: '\x1b[32m',
17
+ yellow: '\x1b[33m',
18
+ cyan: '\x1b[36m',
19
+ gray: '\x1b[90m',
20
+ bold: '\x1b[1m'
21
+ };
22
+
23
+ function logOk(msg) { console.log(`${C.green}✅ ${msg}${C.reset}`); }
24
+ function logWarn(msg) { console.log(`${C.yellow}⚠️ ${msg}${C.reset}`); }
25
+ function logErr(msg) { console.log(`${C.red}❌ ${msg}${C.reset}`); }
26
+ function logInfo(msg) { console.log(`${C.cyan}ℹ️ ${msg}${C.reset}`); }
27
+ function logDim(msg) { console.log(`${C.gray} ${msg}${C.reset}`); }
28
+
29
+ /**
30
+ * Check if rtk is installed.
31
+ */
32
+ function checkRtk() {
33
+ try {
34
+ execSync('which rtk', { stdio: 'ignore' });
35
+ return true;
36
+ } catch (_) {
37
+ return false;
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Get installed rtk version.
43
+ */
44
+ function getRtkVersion() {
45
+ try {
46
+ return execSync('rtk --version', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim().replace(/^rtk\s+/, '');
47
+ } catch (_) {
48
+ return null;
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Check if gitnexus is installed globally or locally.
54
+ */
55
+ function checkGitnexus() {
56
+ try {
57
+ execSync('which gitnexus', { stdio: 'ignore' });
58
+ return true;
59
+ } catch (_) {
60
+ try {
61
+ // Check if npx can resolve it without installing it
62
+ execSync('npx --no-install gitnexus --version', { stdio: 'ignore' });
63
+ return true;
64
+ } catch (_) {
65
+ return false;
66
+ }
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Install RTK using optimal pathways.
72
+ */
73
+ function installRtk() {
74
+ logInfo('Installing RTK (Rust Token Killer)...');
75
+
76
+ // 1. Try Homebrew if on macOS
77
+ if (process.platform === 'darwin') {
78
+ try {
79
+ execSync('which brew', { stdio: 'ignore' });
80
+ logInfo('Homebrew detected, trying brew install...');
81
+ execSync('brew install rtk', { stdio: 'inherit' });
82
+ logOk('RTK installed via Homebrew.');
83
+ return true;
84
+ } catch (_) {
85
+ logDim('Homebrew not available or failed. Trying pre-built script installer.');
86
+ }
87
+ }
88
+
89
+ // 2. Try official curl pre-built installer
90
+ try {
91
+ logInfo('Downloading pre-built RTK binary...');
92
+ execSync('curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh', { stdio: 'inherit' });
93
+ logOk('RTK pre-built binary installed to ~/.local/bin.');
94
+ return true;
95
+ } catch (e) {
96
+ logDim(`Pre-built installer failed: ${e.message}. Trying Cargo compile fallback.`);
97
+ }
98
+
99
+ // 3. Fallback to Cargo compile
100
+ try {
101
+ execSync('which cargo', { stdio: 'ignore' });
102
+ logInfo('Cargo detected, compiling RTK from source...');
103
+ execSync('cargo install --git https://github.com/rtk-ai/rtk', { stdio: 'inherit' });
104
+ logOk('RTK successfully compiled and installed via Cargo.');
105
+ return true;
106
+ } catch (_) {
107
+ logErr('Cargo/Rust not found. Could not compile RTK.');
108
+ }
109
+
110
+ logErr('Failed to install RTK. Please install it manually (see https://www.rtk-ai.app/guide/getting-started/installation).');
111
+ return false;
112
+ }
113
+
114
+ /**
115
+ * Install GitNexus globally.
116
+ */
117
+ function installGitnexus() {
118
+ logInfo('Installing GitNexus globally via npm...');
119
+ try {
120
+ execSync('npm install -g @duytransipher/gitnexus', { stdio: 'inherit' });
121
+ logOk('GitNexus successfully installed globally.');
122
+ return true;
123
+ } catch (e) {
124
+ logErr(`Failed to install GitNexus globally: ${e.message}`);
125
+ logDim('Try running manually: npm install -g @duytransipher/gitnexus');
126
+ return false;
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Perform HTTPS GET request returning parsed JSON.
132
+ */
133
+ function fetchJson(url) {
134
+ return new Promise((resolve, reject) => {
135
+ const options = {
136
+ headers: { 'User-Agent': 'awkit-dependency-manager' },
137
+ timeout: 4000
138
+ };
139
+ https.get(url, options, (res) => {
140
+ if (res.statusCode < 200 || res.statusCode >= 300) {
141
+ return reject(new Error(`HTTP ${res.statusCode}`));
142
+ }
143
+ let data = '';
144
+ res.on('data', chunk => { data += chunk; });
145
+ res.on('end', () => {
146
+ try { resolve(JSON.parse(data)); } catch (e) { reject(e); }
147
+ });
148
+ }).on('error', reject).on('timeout', () => reject(new Error('Request timeout')));
149
+ });
150
+ }
151
+
152
+ /**
153
+ * Check updates with 24h caching.
154
+ */
155
+ async function checkUpdates(currentAwkitVersion) {
156
+ let cache = { lastChecked: 0, latestAwkit: null, latestRtk: null };
157
+
158
+ if (fs.existsSync(CACHE_FILE)) {
159
+ try {
160
+ cache = JSON.parse(fs.readFileSync(CACHE_FILE, 'utf8'));
161
+ } catch (_) {}
162
+ }
163
+
164
+ const now = Date.now();
165
+ if (now - cache.lastChecked < CACHE_DURATION_MS && cache.latestAwkit && cache.latestRtk) {
166
+ return { latestAwkit: cache.latestAwkit, latestRtk: cache.latestRtk, cached: true };
167
+ }
168
+
169
+ logInfo('Checking for updates...');
170
+ let latestAwkit = cache.latestAwkit;
171
+ let latestRtk = cache.latestRtk;
172
+
173
+ // Check AWKit
174
+ try {
175
+ const npmData = await fetchJson('https://registry.npmjs.org/@leejungkiin/awkit/latest');
176
+ if (npmData && npmData.version) {
177
+ latestAwkit = npmData.version;
178
+ }
179
+ } catch (e) {
180
+ logDim(`AWKit update check failed: ${e.message}`);
181
+ }
182
+
183
+ // Check RTK
184
+ try {
185
+ const githubData = await fetchJson('https://api.github.com/repos/rtk-ai/rtk/releases/latest');
186
+ if (githubData && githubData.tag_name) {
187
+ latestRtk = githubData.tag_name.replace(/^v/, '');
188
+ }
189
+ } catch (e) {
190
+ logDim(`RTK update check failed: ${e.message}`);
191
+ }
192
+
193
+ // Save cache
194
+ cache = { lastChecked: now, latestAwkit, latestRtk };
195
+ try {
196
+ fs.mkdirSync(CACHE_DIR, { recursive: true });
197
+ fs.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2) + '\n');
198
+ } catch (_) {}
199
+
200
+ return { latestAwkit, latestRtk, cached: false };
201
+ }
202
+
203
+ module.exports = {
204
+ checkRtk,
205
+ getRtkVersion,
206
+ checkGitnexus,
207
+ installRtk,
208
+ installGitnexus,
209
+ checkUpdates
210
+ };
@@ -24,19 +24,25 @@ function checkRtk() {
24
24
  * @returns {Buffer|string}
25
25
  */
26
26
  function execRtkSync(command, options = {}) {
27
+ const trimmed = command.trim();
28
+
29
+ // Only compress developer commands known to be verbose
30
+ const eligiblePrefixes = ['git ', 'npm ', 'cargo ', 'yarn ', 'pnpm ', 'grep ', 'find ', 'awkit trello '];
31
+ const extendedPrefixes = ['cat ', 'curl ', 'xcodebuild ', './gradlew ', 'swift ', 'flutter ', 'dart ', 'pod ', 'brew '];
32
+ const allEligible = [...eligiblePrefixes, ...extendedPrefixes];
33
+ const isEligible = allEligible.some(prefix => trimmed.startsWith(prefix));
34
+
27
35
  if (!checkRtk()) {
36
+ if (isEligible && !options.stdio) {
37
+ return execSync(`${command} 2>&1 | tail -c 8000`, { ...options, shell: true });
38
+ }
28
39
  return execSync(command, options);
29
40
  }
30
41
 
31
- const trimmed = command.trim();
32
42
  if (trimmed.startsWith('rtk ')) {
33
43
  return execSync(command, options);
34
44
  }
35
45
 
36
- // Only compress developer commands known to be verbose
37
- const eligiblePrefixes = ['git ', 'npm ', 'cargo ', 'yarn ', 'pnpm ', 'grep ', 'find ', 'awkit trello '];
38
- const isEligible = eligiblePrefixes.some(prefix => trimmed.startsWith(prefix));
39
-
40
46
  if (isEligible) {
41
47
  return execSync(`rtk ${command}`, options);
42
48
  }