@leejungkiin/awkit 1.7.6 → 1.7.8

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 (69) hide show
  1. package/bin/awk.js +213 -92
  2. package/bin/codex-generators.js +32 -3
  3. package/core/GEMINI.md +18 -5
  4. package/core/GEMINI.md.bak +20 -7
  5. package/core/skill-runtime-manifest.json +1 -0
  6. package/package.json +1 -1
  7. package/scripts/exec-progress.js +116 -0
  8. package/scripts/exec-rtk.js +105 -10
  9. package/skills/CATALOG.md +1 -1
  10. package/skills/awf-caveman/SKILL.md +13 -1
  11. package/skills/code-review/SKILL.md +40 -68
  12. package/skills/generate-gui-assets/SKILL.md +5 -5
  13. package/skills/hatch-pet/SKILL.md +2 -2
  14. package/skills/review/SKILL.md +40 -68
  15. package/skills/threejs-animation/SKILL.md +86 -0
  16. package/skills/threejs-animation/examples/workflow-mixer-action.md +20 -0
  17. package/skills/threejs-animation/references/official-sections.md +19 -0
  18. package/skills/threejs-audio/SKILL.md +112 -0
  19. package/skills/threejs-audio/examples/workflow-positional-audio.md +15 -0
  20. package/skills/threejs-audio/references/official-sections.md +16 -0
  21. package/skills/threejs-camera/SKILL.md +96 -0
  22. package/skills/threejs-camera/examples/workflow-perspective-resize.md +13 -0
  23. package/skills/threejs-controls/SKILL.md +101 -0
  24. package/skills/threejs-controls/examples/workflow-orbit-damping.md +15 -0
  25. package/skills/threejs-dev-setup/SKILL.md +102 -0
  26. package/skills/threejs-dev-setup/examples/workflow-scaffold.md +24 -0
  27. package/skills/threejs-geometries/SKILL.md +108 -0
  28. package/skills/threejs-geometries/examples/workflow-extrude-shape.md +13 -0
  29. package/skills/threejs-helpers/SKILL.md +103 -0
  30. package/skills/threejs-helpers/examples/workflow-light-camera-helpers.md +13 -0
  31. package/skills/threejs-lights/SKILL.md +103 -0
  32. package/skills/threejs-lights/examples/workflow-directional-shadow.md +17 -0
  33. package/skills/threejs-loaders/SKILL.md +89 -0
  34. package/skills/threejs-loaders/examples/workflow-gltf-draco.md +22 -0
  35. package/skills/threejs-loaders/references/official-sections.md +27 -0
  36. package/skills/threejs-materials/SKILL.md +102 -0
  37. package/skills/threejs-materials/examples/workflow-pbr-transparent.md +15 -0
  38. package/skills/threejs-math/SKILL.md +102 -0
  39. package/skills/threejs-math/examples/workflow-ray-aabb.md +11 -0
  40. package/skills/threejs-node-tsl/SKILL.md +83 -0
  41. package/skills/threejs-node-tsl/examples/workflow-tsl-entry.md +13 -0
  42. package/skills/threejs-node-tsl/references/official-links.md +8 -0
  43. package/skills/threejs-node-tsl/references/tsl-vs-classic.md +23 -0
  44. package/skills/threejs-objects/SKILL.md +111 -0
  45. package/skills/threejs-objects/examples/workflow-raycaster-pick.md +17 -0
  46. package/skills/threejs-postprocessing/SKILL.md +116 -0
  47. package/skills/threejs-postprocessing/examples/workflow-composer-bloom.md +15 -0
  48. package/skills/threejs-renderers/SKILL.md +91 -0
  49. package/skills/threejs-renderers/examples/workflow-renderer-resize.md +21 -0
  50. package/skills/threejs-renderers/references/official-sections.md +14 -0
  51. package/skills/threejs-scenes/SKILL.md +90 -0
  52. package/skills/threejs-scenes/examples/workflow-fog-background.md +13 -0
  53. package/skills/threejs-textures/SKILL.md +83 -0
  54. package/skills/threejs-textures/examples/workflow-pmrem-env.md +19 -0
  55. package/skills/threejs-webxr/SKILL.md +104 -0
  56. package/skills/threejs-webxr/examples/workflow-xr-button.md +15 -0
  57. package/workflows/_uncategorized/generate-gui-assets.md +111 -0
  58. package/workflows/_uncategorized/goal.md +86 -0
  59. package/workflows/_uncategorized/hatch-pet.md +116 -0
  60. package/workflows/_uncategorized/office-hours.md +38 -0
  61. package/workflows/_uncategorized/plan-ceo-review.md +34 -0
  62. package/workflows/_uncategorized/plan-design-review.md +38 -0
  63. package/workflows/_uncategorized/plan-eng-review.md +43 -0
  64. package/workflows/quality/plan-ceo-review.md +34 -0
  65. package/workflows/quality/plan-design-review.md +38 -0
  66. package/workflows/quality/plan-eng-review.md +43 -0
  67. package/workflows/roles/office-hours.md +38 -0
  68. package/workflows/ui/generate-gui-assets.md +111 -0
  69. package/workflows/ui/hatch-pet.md +116 -0
package/bin/awk.js CHANGED
@@ -48,6 +48,7 @@ const { cmdI18n } = require('../scripts/i18n-helper');
48
48
  const { cmdStorage } = require('../scripts/artifact-storage');
49
49
  const { cmdPipeline } = require('../scripts/multi-model-pipeline');
50
50
  const depManager = require('../scripts/dependency-manager');
51
+ const rtkRuntime = require('../scripts/exec-rtk');
51
52
 
52
53
 
53
54
  // ─── Platform Definitions ──────────────────────────────────────────────────
@@ -67,16 +68,18 @@ const PLATFORMS = {
67
68
  },
68
69
  supportsCustomModes: false,
69
70
  supportsSubagents: false,
71
+ isGlobal: true,
70
72
  },
71
73
  cline: {
72
74
  name: 'Cline (VS Code)',
73
- globalRoot: process.cwd(), // Local to project
75
+ globalRoot: path.join(HOME, '.cline'),
74
76
  rulesFile: path.join(HOME, '.cline', 'rules', 'antigravity-rules.md'),
75
77
  versionFile: path.join(HOME, '.cline', 'awk_version'),
76
78
  dirs: {
77
- workflows: '.clinerules',
78
- skills: '.clinerules/skills',
79
+ workflows: 'rules',
80
+ skills: 'rules',
79
81
  },
82
+ isGlobal: true,
80
83
  },
81
84
  codex: {
82
85
  name: 'Codex (OpenAI)',
@@ -87,15 +90,17 @@ const PLATFORMS = {
87
90
  agents: 'agents',
88
91
  skills: '../.agents/skills',
89
92
  },
93
+ isGlobal: true,
90
94
  },
91
95
  claude: {
92
96
  name: 'Claude Code',
93
- globalRoot: process.cwd(), // Local to project
97
+ globalRoot: path.join(HOME, '.claude'),
94
98
  rulesFile: 'CLAUDE.md',
95
- versionFile: '.claude/awk_version',
99
+ versionFile: 'awk_version',
96
100
  dirs: {
97
- skills: '.claude/skills',
101
+ skills: 'skills',
98
102
  },
103
+ isGlobal: true,
99
104
  },
100
105
  qwen: {
101
106
  name: 'Qwen Code',
@@ -105,15 +110,17 @@ const PLATFORMS = {
105
110
  dirs: {
106
111
  skills: 'skills',
107
112
  },
113
+ isGlobal: true,
108
114
  },
109
115
  cursor: {
110
116
  name: 'Cursor AI',
111
- globalRoot: process.cwd(), // Local to project
112
- rulesFile: '.cursor/rules/antigravity-rules.mdc',
113
- versionFile: '.cursor/awk_version',
117
+ globalRoot: path.join(HOME, '.cursor'),
118
+ rulesFile: path.join(HOME, '.cursor', 'rules', 'antigravity-rules.mdc'),
119
+ versionFile: path.join(HOME, '.cursor', 'awk_version'),
114
120
  dirs: {
115
- skills: '.cursor/rules',
121
+ skills: 'rules',
116
122
  },
123
+ isGlobal: true,
117
124
  }
118
125
  };
119
126
 
@@ -482,32 +489,31 @@ function flattenWorkflows(srcBase, destDir) {
482
489
  }
483
490
 
484
491
  /**
485
- * Install or update GEMINI.md into ~/.gemini/
492
+ * Install or update GEMINI.md into Antigravity rule locations.
486
493
  */
487
494
  function syncGeminiMd() {
488
495
  const srcGemini = path.join(AWK_ROOT, 'core', 'GEMINI.md');
489
- const destGemini = TARGETS.geminiMd;
496
+ const primaryDest = TARGETS.geminiMd;
497
+ const legacyDest = path.join(PLATFORMS.antigravity.globalRoot, 'GEMINI.md');
498
+ const destinations = [...new Set([primaryDest, legacyDest])];
490
499
 
491
- const destDir = path.dirname(destGemini);
492
- if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
500
+ for (const destGemini of destinations) {
501
+ const destDir = path.dirname(destGemini);
502
+ if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
493
503
 
494
- // Read existing GEMINI.md if present
495
- let existingContent = '';
496
- if (fs.existsSync(destGemini)) {
497
- existingContent = fs.readFileSync(destGemini, 'utf8');
504
+ if (fs.existsSync(destGemini)) {
505
+ const backupDir = path.join(PLATFORMS.antigravity.globalRoot, 'backup');
506
+ if (!fs.existsSync(backupDir)) fs.mkdirSync(backupDir, { recursive: true });
498
507
 
499
- // Backup existing
500
- const backupDir = path.join(destDir, 'antigravity', 'backup');
501
- if (!fs.existsSync(backupDir)) fs.mkdirSync(backupDir, { recursive: true });
508
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
509
+ const label = destGemini === legacyDest ? 'GEMINI_legacy' : 'GEMINI';
510
+ const backupPath = path.join(backupDir, `${label}_${timestamp}.md.bak`);
511
+ fs.copyFileSync(destGemini, backupPath);
512
+ dim(`Backup: ${backupPath}`);
513
+ }
502
514
 
503
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
504
- const backupPath = path.join(backupDir, `GEMINI_${timestamp}.md.bak`);
505
- fs.copyFileSync(destGemini, backupPath);
506
- dim(`Backup: ${backupPath}`);
515
+ fs.copyFileSync(srcGemini, destGemini);
507
516
  }
508
-
509
- // Copy new GEMINI.md
510
- fs.copyFileSync(srcGemini, destGemini);
511
517
  ok('GEMINI.md updated');
512
518
  }
513
519
 
@@ -538,8 +544,19 @@ function cmdInstall(args = []) {
538
544
  const isUpdate = args.includes('--update');
539
545
  let selectedPlatforms = [];
540
546
 
541
- if (args.includes('--all') || args.includes('-a') || args.includes('all')) {
542
- selectedPlatforms = Object.keys(PLATFORMS);
547
+ const hasAll = args.includes('--all') || args.includes('-a') || args.includes('all');
548
+ const hasLocal = args.includes('--local') || args.includes('-l') || args.includes('local');
549
+
550
+ if (hasAll) {
551
+ // Mặc định --all chỉ cài đặt các platform Global
552
+ selectedPlatforms = Object.keys(PLATFORMS).filter(p => PLATFORMS[p].isGlobal);
553
+ if (hasLocal) {
554
+ // Nếu có cả --local thì cài tất cả các platform
555
+ selectedPlatforms = Object.keys(PLATFORMS);
556
+ }
557
+ } else if (hasLocal) {
558
+ // Chỉ cài các platform Local
559
+ selectedPlatforms = Object.keys(PLATFORMS).filter(p => !PLATFORMS[p].isGlobal);
543
560
  } else {
544
561
  if (args.includes('--gemini') || args.includes('-g') || args.includes('antigravity')) selectedPlatforms.push('antigravity');
545
562
  if (args.includes('--cline') || args.includes('cline')) selectedPlatforms.push('cline');
@@ -552,7 +569,7 @@ function cmdInstall(args = []) {
552
569
  let legacyArg = null;
553
570
  if (pIdx !== -1 && args[pIdx + 1]) {
554
571
  legacyArg = args[pIdx + 1];
555
- } else if (args.length > 0 && !args[0].startsWith('-') && args[0] !== 'all' && args[0] !== '--update') {
572
+ } else if (args.length > 0 && !args[0].startsWith('-') && args[0] !== 'all' && args[0] !== '--update' && args[0] !== 'local') {
556
573
  legacyArg = args[0];
557
574
  }
558
575
 
@@ -569,17 +586,17 @@ function cmdInstall(args = []) {
569
586
  const defaultPlatform = getActivePlatform();
570
587
  const defaultChoice = String(Math.max(platformOrder.indexOf(defaultPlatform), 0) + 1);
571
588
  log(`${C.cyan}Select platforms to install (e.g., type "1,2", "all", or "1-6"):${C.reset}`);
572
- log(` 1. Gemini Code Assist (antigravity)`);
573
- log(` 2. Cline (VS Code)`);
574
- log(` 3. Codex CLI (codex)`);
575
- log(` 4. Claude Code (.claude/)`);
576
- log(` 5. Qwen Code (~/.qwen/)`);
577
- log(` 6. Cursor AI (.cursor/rules/)`);
578
- log(` 7. All of the above`);
589
+ log(` 1. Gemini Code Assist (antigravity) [Global]`);
590
+ log(` 2. Cline (VS Code) [Global]`);
591
+ log(` 3. Codex CLI (codex) [Global]`);
592
+ log(` 4. Claude Code (.claude/) [Global]`);
593
+ log(` 5. Qwen Code (~/.qwen/) [Global]`);
594
+ log(` 6. Cursor AI (.cursor/rules/) [Global]`);
595
+ log(` 7. All platforms (1-6)`);
579
596
  log(`${C.gray}Press Enter to install only the active platform: ${PLATFORMS[defaultPlatform].name}.${C.reset}`);
580
597
  const choice = promptChoice('Choice', defaultChoice).trim().toLowerCase();
581
598
 
582
- if (choice === '7' || choice === 'all') {
599
+ if (choice === '7' || choice === 'all' || choice === '1-6') {
583
600
  selectedPlatforms = Object.keys(PLATFORMS);
584
601
  } else {
585
602
  if (choice.includes('1')) selectedPlatforms.push('antigravity');
@@ -704,6 +721,8 @@ function cmdInstall(args = []) {
704
721
  generateClineSkills(skillsSrc, skillsDest, coreSkills);
705
722
  } else if (platform === 'codex') {
706
723
  generateCodexSkills(skillsSrc, skillsDest, coreSkills);
724
+ const codexSkillsDest = path.join(target, 'skills');
725
+ generateCodexSkills(skillsSrc, codexSkillsDest, coreSkills);
707
726
  const agentsDest = path.join(target, plat.dirs.agents);
708
727
  generateCodexAgents(skillsSrc, agentsDest, coreSkills);
709
728
  } else if (platform === 'claude') {
@@ -1011,16 +1030,12 @@ async function cmdDoctor() {
1011
1030
  warn('schemas/ directory missing'); issues++;
1012
1031
  }
1013
1032
 
1014
- // 4.5. Check RTK & GitNexus Integration
1033
+ // 4.5. Check optional RTK & GitNexus Integration
1015
1034
  if (depManager.checkRtk()) {
1016
- ok(`RTK (Rust Token Killer) is installed (v${depManager.getRtkVersion() || 'unknown'})`);
1035
+ const rtkMode = rtkRuntime.getRtkMode();
1036
+ ok(`RTK (Rust Token Killer) is installed (v${depManager.getRtkVersion() || 'unknown'}, mode: ${rtkMode.mode})`);
1017
1037
  } else {
1018
- warn('RTK (Rust Token Killer) not found.');
1019
- if (promptYN('Would you like to install RTK automatically now?')) {
1020
- depManager.installRtk();
1021
- } else {
1022
- issues++;
1023
- }
1038
+ warn('RTK (Rust Token Killer) not found. Optional: run `awkit rtk setup`.');
1024
1039
  }
1025
1040
 
1026
1041
  if (depManager.checkGitnexus()) {
@@ -1054,7 +1069,8 @@ async function cmdDoctor() {
1054
1069
  ok('AWKit is up-to-date');
1055
1070
  }
1056
1071
 
1057
- const currentRtk = depManager.getRtkVersion();
1072
+ const currentRtkMode = rtkRuntime.getRtkMode();
1073
+ const currentRtk = currentRtkMode.mode === 'off' ? null : depManager.getRtkVersion();
1058
1074
  if (updates.latestRtk && currentRtk && isNewerVersion(updates.latestRtk, currentRtk)) {
1059
1075
  warn(`RTK update available: v${updates.latestRtk} (current: v${currentRtk})`);
1060
1076
  } else if (currentRtk) {
@@ -1067,7 +1083,8 @@ async function cmdDoctor() {
1067
1083
  log('');
1068
1084
  log(`${C.bold}Runtime Profile:${C.reset}`);
1069
1085
  log(` Profile: ${C.cyan}${installState.profile}${C.reset}`);
1070
- log(` Optional packs: ${installState.enabledPacks?.length ? installState.enabledPacks.join(', ') : C.gray + 'none' + C.reset}`);
1086
+ const visiblePacks = (installState.enabledPacks || []).filter(p => p !== 'reverse-engineering');
1087
+ log(` Optional packs: ${visiblePacks.length ? visiblePacks.join(', ') : C.gray + 'none' + C.reset}`);
1071
1088
 
1072
1089
  // Summary
1073
1090
  log('');
@@ -1929,7 +1946,8 @@ function cmdStatus() {
1929
1946
  }
1930
1947
 
1931
1948
  log(` ${C.gray}Profile:${C.reset} ${installState.profile}`);
1932
- log(` ${C.gray}Optional packs:${C.reset} ${installState.enabledPacks?.length ? installState.enabledPacks.join(', ') : 'none'}`);
1949
+ const visiblePacksStatus = (installState.enabledPacks || []).filter(p => p !== 'reverse-engineering');
1950
+ log(` ${C.gray}Optional packs:${C.reset} ${visiblePacksStatus.length ? visiblePacksStatus.join(', ') : 'none'}`);
1933
1951
 
1934
1952
  log('');
1935
1953
 
@@ -2318,7 +2336,7 @@ function cmdHelp() {
2318
2336
  log(` ${C.green}update${C.reset} Pull latest + reinstall`);
2319
2337
  log(` ${C.green}lint${C.reset} Run skill & workflow guards (check length, frontmatter)`);
2320
2338
  log(` ${C.green}doctor${C.reset} Check installation health`);
2321
- log(` ${C.green}rtk setup${C.reset} Auto-install and configure RTK wrapper`);
2339
+ log(` ${C.green}rtk status|setup|off${C.reset} Manage RTK output compression`);
2322
2340
  log(` ${C.green}credentials list${C.reset} List stored API keys`);
2323
2341
  log(` ${C.green}credentials set${C.reset} <k> <v> Set API key (e.g., gemini_api_key, openrouter_api_key)`);
2324
2342
  log(` ${C.green}set-openrouter${C.reset} <key> Shorthand for setting OpenRouter API Key`);
@@ -4112,7 +4130,8 @@ async function checkAutoUpdate() {
4112
4130
  log('');
4113
4131
  }
4114
4132
 
4115
- const currentRtk = depManager.getRtkVersion();
4133
+ const currentRtkMode = rtkRuntime.getRtkMode();
4134
+ const currentRtk = currentRtkMode.mode === 'off' ? null : depManager.getRtkVersion();
4116
4135
  if (updates.latestRtk && currentRtk && isNewerVersion(updates.latestRtk, currentRtk)) {
4117
4136
  log('');
4118
4137
  log(`${C.yellow}${C.bold}🌟 [Thông báo] Có phiên bản mới cho RTK! (v${updates.latestRtk})${C.reset}`);
@@ -4456,35 +4475,12 @@ function cmdGitnexus(args) {
4456
4475
 
4457
4476
  // ─── RTK Integration ──────────────────────────────────────────────────────────
4458
4477
 
4459
- async function cmdRtkSetup() {
4460
- log(`${C.cyan}${C.bold}╔═══════════════════════════════════════════════════════╗${C.reset}`);
4461
- log(`${C.cyan}${C.bold}║ ⚙️ RTK Auto-Setup & Configuration ║${C.reset}`);
4462
- log(`${C.cyan}${C.bold}╚═══════════════════════════════════════════════════════╝${C.reset}`);
4463
-
4464
- const installed = depManager.installRtk();
4465
- if (!installed) return;
4478
+ const RTK_SHELL_MARKER = '# RTK Integration for AI Agents (AWKit)';
4479
+ const RTK_SHELL_END_MARKER = '# End RTK Integration for AI Agents (AWKit)';
4466
4480
 
4467
- const zshrcPath = path.join(HOME, '.zshrc');
4468
- log(`\nConfiguring Shell Aliases in ~/.zshrc...`);
4469
- if (fs.existsSync(zshrcPath)) {
4470
- let zshrc = fs.readFileSync(zshrcPath, 'utf8');
4471
-
4472
- // Clean up old aliases to avoid collision
4473
- const oldAliases = [
4474
- 'alias git="rtk git"',
4475
- 'alias npm="rtk npm"',
4476
- 'alias pnpm="rtk pnpm"',
4477
- 'alias yarn="rtk yarn"',
4478
- 'alias cargo="rtk cargo"'
4479
- ];
4480
- for (const oldAlias of oldAliases) {
4481
- if (zshrc.includes(oldAlias)) {
4482
- zshrc = zshrc.replace(new RegExp(`\\n?${oldAlias}\\n?`, 'g'), '\n');
4483
- }
4484
- }
4485
-
4486
- const functionBlock = `
4487
- # RTK Integration for AI Agents (AWKit)
4481
+ function getRtkShellBlock() {
4482
+ return `
4483
+ ${RTK_SHELL_MARKER}
4488
4484
  unalias npm pnpm yarn cargo git 2>/dev/null
4489
4485
  npm() {
4490
4486
  if [[ "$1" == "login" || "$1" == "adduser" || "$1" == "publish" ]]; then
@@ -4521,19 +4517,130 @@ git() {
4521
4517
  rtk git "$@"
4522
4518
  fi
4523
4519
  }
4520
+ ${RTK_SHELL_END_MARKER}
4524
4521
  `;
4525
- // Clean up old RTK integration block if exists to allow updating
4526
- if (zshrc.includes('# RTK Integration for AI Agents (AWKit)')) {
4527
- const startIdx = zshrc.indexOf('# RTK Integration for AI Agents (AWKit)');
4528
- zshrc = zshrc.substring(0, startIdx);
4522
+ }
4523
+
4524
+ function escapeRegExp(value) {
4525
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
4526
+ }
4527
+
4528
+ function stripRtkShellBlock(content) {
4529
+ const oldAliases = [
4530
+ 'alias git="rtk git"',
4531
+ 'alias npm="rtk npm"',
4532
+ 'alias pnpm="rtk pnpm"',
4533
+ 'alias yarn="rtk yarn"',
4534
+ 'alias cargo="rtk cargo"'
4535
+ ];
4536
+ let updated = content;
4537
+ for (const oldAlias of oldAliases) {
4538
+ updated = updated.replace(new RegExp(`^\\s*${escapeRegExp(oldAlias)}\\s*\\n?`, 'gm'), '');
4539
+ }
4540
+
4541
+ const lines = updated.split('\n');
4542
+ const start = lines.findIndex(line => line.trim() === RTK_SHELL_MARKER);
4543
+ if (start === -1) return { content: updated, removed: updated !== content };
4544
+
4545
+ let end = lines.findIndex((line, index) => index >= start && line.trim() === RTK_SHELL_END_MARKER);
4546
+ if (end === -1) {
4547
+ const gitStart = lines.findIndex((line, index) => index >= start && line.trim() === 'git() {');
4548
+ if (gitStart !== -1) {
4549
+ end = lines.findIndex((line, index) => index > gitStart && line.trim() === '}');
4529
4550
  }
4530
-
4531
- zshrc += functionBlock;
4532
- fs.writeFileSync(zshrcPath, zshrc, 'utf8');
4533
- ok('Shell wrappers successfully added/updated in ~/.zshrc.');
4534
- log(`\n${C.cyan}Please reload your shell (source ~/.zshrc) to apply shifts.${C.reset}`);
4535
- } else {
4536
- warn('~/.zshrc not found. Skipping alias setup.');
4551
+ }
4552
+ if (end === -1) return { content: updated, removed: updated !== content };
4553
+
4554
+ lines.splice(start, end - start + 1);
4555
+ return { content: lines.join('\n').replace(/\n{3,}/g, '\n\n'), removed: true };
4556
+ }
4557
+
4558
+ function hasRtkShellBlock() {
4559
+ const zshrcPath = path.join(HOME, '.zshrc');
4560
+ return fs.existsSync(zshrcPath) && fs.readFileSync(zshrcPath, 'utf8').includes(RTK_SHELL_MARKER);
4561
+ }
4562
+
4563
+ function removeRtkShellBlock({ quiet = false } = {}) {
4564
+ const zshrcPath = path.join(HOME, '.zshrc');
4565
+ if (!fs.existsSync(zshrcPath)) {
4566
+ if (!quiet) warn('~/.zshrc not found. Shell wrappers already absent.');
4567
+ return false;
4568
+ }
4569
+
4570
+ const zshrc = fs.readFileSync(zshrcPath, 'utf8');
4571
+ const stripped = stripRtkShellBlock(zshrc);
4572
+ if (!stripped.removed) {
4573
+ if (!quiet) ok('No AWKit RTK shell wrappers found.');
4574
+ return false;
4575
+ }
4576
+
4577
+ fs.writeFileSync(zshrcPath, stripped.content, 'utf8');
4578
+ if (!quiet) ok('AWKit RTK shell wrappers removed from ~/.zshrc.');
4579
+ return true;
4580
+ }
4581
+
4582
+ function installRtkShellBlock() {
4583
+ if (!depManager.checkRtk()) {
4584
+ err('RTK binary not found. Run `awkit rtk setup` first.');
4585
+ return;
4586
+ }
4587
+
4588
+ const zshrcPath = path.join(HOME, '.zshrc');
4589
+ const zshrc = fs.existsSync(zshrcPath) ? fs.readFileSync(zshrcPath, 'utf8') : '';
4590
+ const stripped = stripRtkShellBlock(zshrc).content.trimEnd();
4591
+ fs.writeFileSync(zshrcPath, `${stripped}\n${getRtkShellBlock()}`, 'utf8');
4592
+ ok('Shell wrappers added to ~/.zshrc.');
4593
+ warn('Reload shell with `source ~/.zshrc` to apply.');
4594
+ }
4595
+
4596
+ function cmdRtkStatus() {
4597
+ const mode = rtkRuntime.getRtkMode();
4598
+ const installed = depManager.checkRtk();
4599
+ const separator = `${C.gray}${'─'.repeat(56)}${C.reset}`;
4600
+
4601
+ log(`${C.cyan}${C.bold}RTK Status${C.reset}`);
4602
+ log(separator);
4603
+ log(` Binary: ${installed ? C.green + 'installed' + C.reset : C.yellow + 'not installed' + C.reset}`);
4604
+ if (installed) log(` Version: ${depManager.getRtkVersion() || 'unknown'}`);
4605
+ log(` Mode: ${C.bold}${mode.mode}${C.reset}`);
4606
+ log(` Mode source: ${mode.source}`);
4607
+ log(` Global config:${rtkRuntime.getRtkConfigPath()}`);
4608
+ log(` Shell wrap: ${hasRtkShellBlock() ? C.yellow + 'enabled in ~/.zshrc' + C.reset : C.green + 'off' + C.reset}`);
4609
+ log('');
4610
+ log(` Modes: off = raw AWKit, safe = low-risk compression, proxy = track raw, aggressive = old broad wrappers`);
4611
+ }
4612
+
4613
+ async function cmdRtkSetup() {
4614
+ log(`${C.cyan}${C.bold}╔═══════════════════════════════════════════════════════╗${C.reset}`);
4615
+ log(`${C.cyan}${C.bold}║ RTK Setup & Safe Configuration ║${C.reset}`);
4616
+ log(`${C.cyan}${C.bold}╚═══════════════════════════════════════════════════════╝${C.reset}`);
4617
+
4618
+ const installed = depManager.checkRtk() || depManager.installRtk();
4619
+ if (!installed) return;
4620
+
4621
+ rtkRuntime.setGlobalRtkMode('safe');
4622
+ ok('RTK mode set to safe.');
4623
+ warn('Shell wrappers are opt-in now. Run `awkit rtk shell-on` only if you want git/npm aliases.');
4624
+ cmdRtkStatus();
4625
+ }
4626
+
4627
+ function cmdRtkOff() {
4628
+ rtkRuntime.setGlobalRtkMode('off');
4629
+ removeRtkShellBlock({ quiet: true });
4630
+ ok('RTK disabled globally for AWKit.');
4631
+ warn('Reload shell with `source ~/.zshrc` if wrappers were active.');
4632
+ }
4633
+
4634
+ function cmdRtkMode(mode) {
4635
+ if (!mode) {
4636
+ err(`Usage: awkit rtk mode <${rtkRuntime.VALID_RTK_MODES.join('|')}>`);
4637
+ return;
4638
+ }
4639
+ try {
4640
+ rtkRuntime.setGlobalRtkMode(mode);
4641
+ ok(`RTK mode set to ${mode}.`);
4642
+ } catch (e) {
4643
+ err(e.message);
4537
4644
  }
4538
4645
  }
4539
4646
 
@@ -4541,9 +4648,23 @@ async function cmdRtk(args) {
4541
4648
  const action = args[0];
4542
4649
  if (action === 'setup') {
4543
4650
  await cmdRtkSetup();
4651
+ } else if (!action || action === 'status') {
4652
+ cmdRtkStatus();
4653
+ } else if (action === 'off') {
4654
+ cmdRtkOff();
4655
+ } else if (action === 'on') {
4656
+ cmdRtkMode('safe');
4657
+ } else if (action === 'mode') {
4658
+ cmdRtkMode(args[1]);
4659
+ } else if (rtkRuntime.VALID_RTK_MODES.includes(action)) {
4660
+ cmdRtkMode(action);
4661
+ } else if (action === 'shell-on') {
4662
+ installRtkShellBlock();
4663
+ } else if (action === 'shell-off') {
4664
+ removeRtkShellBlock();
4544
4665
  } else {
4545
4666
  err(`Unknown rtk command: ${action || ''}`);
4546
- log(` Available: setup`);
4667
+ log(` Available: status, setup, off, on, mode, shell-on, shell-off`);
4547
4668
  }
4548
4669
  }
4549
4670
 
@@ -16,9 +16,36 @@ function generateCodexAgentsMd(sourcePath, destPath) {
16
16
  console.log(`✅ Codex AGENTS.md generated at: ${destPath}`);
17
17
  }
18
18
 
19
+ /**
20
+ * Recursively copies a skill directory preserving structure.
21
+ */
22
+ function copySkillDir(src, dest) {
23
+ if (!fs.existsSync(src)) return 0;
24
+ fs.mkdirSync(dest, { recursive: true });
25
+
26
+ let count = 0;
27
+ const entries = fs.readdirSync(src, { withFileTypes: true });
28
+
29
+ for (const entry of entries) {
30
+ if (entry.name === '.DS_Store') continue;
31
+ if (entry.name === '__pycache__') continue;
32
+
33
+ const srcPath = path.join(src, entry.name);
34
+ const destPath = path.join(dest, entry.name);
35
+
36
+ if (entry.isDirectory()) {
37
+ count += copySkillDir(srcPath, destPath);
38
+ } else {
39
+ fs.copyFileSync(srcPath, destPath);
40
+ count++;
41
+ }
42
+ }
43
+ return count;
44
+ }
45
+
19
46
  /**
20
47
  * Generates Codex skills directory structure.
21
- * Copies SKILL.md and parses it.
48
+ * Copies the entire skill directory and parses/injects frontmatter to SKILL.md.
22
49
  */
23
50
  function generateCodexSkills(srcDir, destDir, selectedSkills = null) {
24
51
  if (!fs.existsSync(srcDir)) return;
@@ -37,11 +64,13 @@ function generateCodexSkills(srcDir, destDir, selectedSkills = null) {
37
64
  const skillFile = path.join(skillDir, 'SKILL.md');
38
65
  if (fs.existsSync(skillFile)) {
39
66
  const destSkillDir = path.join(destDir, skill);
40
- fs.mkdirSync(destSkillDir, { recursive: true });
67
+
68
+ // Copy the entire directory first
69
+ copySkillDir(skillDir, destSkillDir);
41
70
 
42
71
  const destPath = path.join(destSkillDir, 'SKILL.md');
43
72
 
44
- let content = fs.readFileSync(skillFile, 'utf8');
73
+ let content = fs.readFileSync(destPath, 'utf8');
45
74
 
46
75
  if (content.startsWith('---\n')) {
47
76
  if (!content.match(/^name:/m)) {
package/core/GEMINI.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # GEMINI.md — Antigravity v12.6
2
2
 
3
- > Rules only. Updated: 2026-06-15
3
+ > Rules only. Updated: 2026-06-23
4
4
 
5
5
  ---
6
6
 
@@ -62,11 +62,12 @@ symphony-orchestrator → awf-session-restore (gitnexus state) → nm-memory-syn
62
62
  - Build: CHỈ dùng `awkit build`. CẤM gọi native (`xcodebuild`, `./gradlew`, `npm run build`).
63
63
  - `automation.build.enabled: false` → DỪNG, báo user. KHÔNG fallback native.
64
64
  - Thêm params qua `--`: `awkit build -- -destination '...'`. Bypass wrapper = VI PHẠM.
65
+ - **Chạy tác vụ nền (Background Tasks)**: Khi chạy các tác vụ nền hoặc tác vụ dài (>30 giây) như Codex CLI, PHẢI chạy qua wrapper `node scripts/exec-progress.js "<command>"` để hiển thị checklist tiến trình trực quan cho người dùng thay vì để trống màn hình.
65
66
 
66
67
  ### 7-Gate System
67
68
  - Triage: TRIVIAL (→ Gate 4 thẳng) | MODERATE (→ G3+4+5) | COMPLEX (→ all gates).
68
69
  - Gates: G1 brainstorm → G1.5 module-spec (COMPLEX+>3mod) → G2 spec-gate → G2.5 visual (skip nếu backend) → G3 symphony-enforcer → G4 execution → G5 verification.
69
- - **Goal Mode Override:** Khi đang ở goal mode (`/goal`, active Codex goal, hoặc user nói rõ "goal mode") → gates là checklist nội bộ, KHÔNG dừng chờ user approval ở G2/G2.5/G4 checkpoints. AI tự chọn best-effort, tự verify, ghi assumption, rồi tiếp tục tới khi goal complete/bị block thật sự. Safety/destructive/security vẫn phải hỏi.
70
+ - **Goal Mode Override (NO-CONFIRM):** Khi đang ở goal mode (`/goal`, active Codex goal, hoặc user nói rõ "goal mode") → gates là checklist nội bộ, KHÔNG dừng chờ user approval ở bất kỳ bước nào (G2/G2.5/G4 checkpoints, prompt audit, style preview, grid configuration, specs approval, v.v.). AI tự động chọn phương án tối ưu (best-effort/recommended default), tự verify, ghi nhận giả định (assumptions) vào logs/walkthrough, rồi tiếp tục cho đến khi goal hoàn thành hoặc bị block thực sự bởi lỗi kỹ thuật/permission. Chỉ dừng lại hỏi ý kiến khi gặp lệnh thực sự nguy hại (destructive) hoặc nhạy cảm bảo mật quy định tại Safety Guardrails.
70
71
  - **Gate 4 Three-Phase:**
71
72
  - Phase A 🏗️ Infrastructure → B 🎨 UI Shell (mock) → C ⚡ Logic (real data).
72
73
  - COMPLEX+UI: 3 phases bắt buộc. MODERATE+UI: A+C gộp, B optional. TRIVIAL: bypass.
@@ -102,8 +103,11 @@ symphony-orchestrator → awf-session-restore (gitnexus state) → nm-memory-syn
102
103
  - Sau khi dùng tool sửa code → KHÔNG in lại code trong chat. Tóm tắt bằng bullets.
103
104
  - Code block trong chat: tối đa 10 dòng. Show diff → dùng `render_diffs()`.
104
105
 
105
- ### Image Generation Efficiency
106
- - Image gen: grid/spritesheet cho batch variants, không gen từng ảnh rời.
106
+ ### Image Generation & Asset Mandates (BẮT BUỘC)
107
+ - **Cấm tự tạo SVG:** CẤM tự sinh, tự tạo hoặc thiết kế mã SVG cho các UI assets, biểu tượng trang trí, hoặc spritesheet (do chất lượng SVG tự tạo không đảm bảo và không bám sát thiết kế). BẮT BUỘC sử dụng Codex CLI để tạo hình ảnh và spritesheet UI.
108
+ - **Sử dụng Skill bắt buộc:** Tuyệt đối sử dụng các skill `generate-gui-assets` và `hatch-pet` theo tài liệu tương ứng tại `/Users/trungkientn/.agents/skills/generate-gui-assets/SKILL.md` và `/Users/trungkientn/.codex/skills/hatch-pet/SKILL.md`.
109
+ - **Thiết kế dùng Grid để tiết kiệm:** Bắt buộc thiết kế các assets (ngoại trừ background) bằng dạng Grid (spritesheet/atlas) để tối ưu chi phí và tài nguyên.
110
+ - **Quy trình Grid & Tự Động Phê Duyệt:** Luôn ưu tiên tạo và kiểm chứng (verify) theo hướng lưới `8x6` trước. Nếu chất lượng quá xấu, tự động giảm dần số lượng item/kích thước grid xuống các cấu hình nhỏ hơn (ví dụ: 8x5, 6x6, 6x5, v.v.) mà KHÔNG cần hỏi ý kiến hoặc bắt user xác nhận lại (kể cả trong Normal hay Goal Mode).
107
111
 
108
112
  ### Proactive UI Asset Generation (MANDATORY)
109
113
  - **Asset Audit:** Trong Gate 2.5 (Visual Design) và Gate 4 Phase B (UI Shell), BẮT BUỘC rà soát mã nguồn/thiết kế để phát hiện các UI assets bị thiếu (nút bấm, panel, icon, pet, egg...).
@@ -112,12 +116,15 @@ symphony-orchestrator → awf-session-restore (gitnexus state) → nm-memory-syn
112
116
  - **Cấu trúc Lệnh:**
113
117
  - Đối với UI assets: `codex exec "Generate GUI asset: [Prompt/Style/Theme] and save it to [path] using the generate-gui-assets skill rules."`
114
118
  - Đối với Pet/Egg assets: `codex exec "Generate pet companion asset: [Pet Type/State] and save it to [path] using the hatch-pet skill rules and grid configuration [grid]."`
115
- - **Chi tiết & Approval:** Tự động thiết lập prompt chi tiết dựa trên Theme của App, tuân thủ tiêu chuẩn Solid Background và hỏi ý kiến user trước khi thực thi lệnh.
119
+ - **Chi tiết & Approval:** Tự động thiết lập prompt chi tiết dựa trên Theme của App, tuân thủ tiêu chuẩn Solid Background và hỏi ý kiến user trước khi thực thi lệnh (Trừ Goal Mode hoặc trường hợp tự động giảm cấu hình lưới grid: Tự động phê duyệt prompt/cấu hình và thực thi lệnh không cần hỏi).
120
+
116
121
 
117
122
 
118
123
  ### Communication (CAVEMAN ULTRA)
119
124
  - Chat: Tiếng Việt, tối đa 1-2 câu ngắn. Code/Docs: Tiếng Anh.
120
125
  - CẤM giải thích dài, chào hỏi. Chỉ xuất KẾT QUẢ.
126
+ - Caveman chỉ nén prose chat. KHÔNG cắt/mất thông tin kỹ thuật: command output, error, stack trace, diff, JSON/API response, file path, line ref, test evidence.
127
+ - Khi relay output, giữ nguyên dòng quan trọng; chỉ tóm tắt phần nhiễu xung quanh.
121
128
  - Planning artifacts (implementation_plan.md, walkthrough.md) VẪN chi tiết theo format chuẩn.
122
129
  - Tài liệu thảo luận & brainstorm (Brief, Requirements, Brainstorm) PHẢI dùng tiếng Việt (hoặc ngôn ngữ giao tiếp của User), chỉ Code/Architecture mới bắt buộc dùng tiếng Anh.
123
130
 
@@ -145,6 +152,12 @@ symphony-orchestrator → awf-session-restore (gitnexus state) → nm-memory-syn
145
152
  - Commit: CHỈ qua `awkit gate git auto`. CẤM `git commit` trực tiếp qua bash.
146
153
  - Destructive command → double-confirm user. Không chắc → hỏi trước.
147
154
 
155
+ ### GStack Planning & Code Safety
156
+ - **Office Hours & CEO Review**: Chạy `/office-hours` để thử nghiệm ý tưởng dưới góc nhìn startup/YC. Dùng `/plan-ceo-review` để đạt "trải nghiệm sản phẩm 10 sao" và quản lý phạm vi (scope).
157
+ - **Eng Review & Data Safety**: Chốt kiến trúc và thiết kế dữ liệu. Quét an toàn SQL, concurrency/races, và enum completeness trước khi code.
158
+ - **Pass 1 & Pass 2 Review**: Đánh giá code hai lượt (Pass 1: Critical - SQL/data safety, races, LLM boundary, shell injection, enum; Pass 2: Informational - logic/syntax).
159
+ - **Fix-First Heuristic**: Tự động sửa lỗi cơ học (dead code, N+1 queries, stale comments) và hỏi ý kiến user đối với các quyết định rủi ro/kiến trúc.
160
+
148
161
  ### Subagent Orchestration & Protocol
149
162
  - **Định tuyến trước, Tìm kiếm sau:** Tuyệt đối không dùng `grep_search` hoặc `list_dir` diện rộng để định vị subagents (như `critic`). Bắt buộc tra cứu chỉ mục tại `skills/CATALOG.md`, `skills/TRIGGER_INDEX.md` hoặc `skills/review/SKILL.md` trước.
150
163
  - **Tận dụng Subagents Cô lập:** Sử dụng built-in subagents (`research` cho tìm kiếm codebase/log thô, `browser` cho các tác vụ UI) để tránh ô nhiễm context trên luồng chat chính.