@leejungkiin/awkit 1.7.7 → 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.
- package/bin/awk.js +169 -69
- package/core/GEMINI.md +8 -0
- package/core/GEMINI.md.bak +18 -5
- package/core/skill-runtime-manifest.json +1 -0
- package/package.json +1 -1
- package/scripts/exec-rtk.js +105 -10
- package/skills/CATALOG.md +1 -1
- package/skills/awf-caveman/SKILL.md +13 -1
- package/skills/code-review/SKILL.md +40 -68
- package/skills/review/SKILL.md +40 -68
- package/workflows/_uncategorized/generate-gui-assets.md +111 -0
- package/workflows/_uncategorized/hatch-pet.md +116 -0
- package/workflows/_uncategorized/office-hours.md +38 -0
- package/workflows/_uncategorized/plan-ceo-review.md +34 -0
- package/workflows/_uncategorized/plan-design-review.md +38 -0
- package/workflows/_uncategorized/plan-eng-review.md +43 -0
- package/workflows/quality/plan-ceo-review.md +34 -0
- package/workflows/quality/plan-design-review.md +38 -0
- package/workflows/quality/plan-eng-review.md +43 -0
- package/workflows/roles/office-hours.md +38 -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 ──────────────────────────────────────────────────
|
|
@@ -488,32 +489,31 @@ function flattenWorkflows(srcBase, destDir) {
|
|
|
488
489
|
}
|
|
489
490
|
|
|
490
491
|
/**
|
|
491
|
-
* Install or update GEMINI.md into
|
|
492
|
+
* Install or update GEMINI.md into Antigravity rule locations.
|
|
492
493
|
*/
|
|
493
494
|
function syncGeminiMd() {
|
|
494
495
|
const srcGemini = path.join(AWK_ROOT, 'core', 'GEMINI.md');
|
|
495
|
-
const
|
|
496
|
+
const primaryDest = TARGETS.geminiMd;
|
|
497
|
+
const legacyDest = path.join(PLATFORMS.antigravity.globalRoot, 'GEMINI.md');
|
|
498
|
+
const destinations = [...new Set([primaryDest, legacyDest])];
|
|
496
499
|
|
|
497
|
-
const
|
|
498
|
-
|
|
500
|
+
for (const destGemini of destinations) {
|
|
501
|
+
const destDir = path.dirname(destGemini);
|
|
502
|
+
if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
|
|
499
503
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
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 });
|
|
504
507
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
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
|
+
}
|
|
508
514
|
|
|
509
|
-
|
|
510
|
-
const backupPath = path.join(backupDir, `GEMINI_${timestamp}.md.bak`);
|
|
511
|
-
fs.copyFileSync(destGemini, backupPath);
|
|
512
|
-
dim(`Backup: ${backupPath}`);
|
|
515
|
+
fs.copyFileSync(srcGemini, destGemini);
|
|
513
516
|
}
|
|
514
|
-
|
|
515
|
-
// Copy new GEMINI.md
|
|
516
|
-
fs.copyFileSync(srcGemini, destGemini);
|
|
517
517
|
ok('GEMINI.md updated');
|
|
518
518
|
}
|
|
519
519
|
|
|
@@ -1030,16 +1030,12 @@ async function cmdDoctor() {
|
|
|
1030
1030
|
warn('schemas/ directory missing'); issues++;
|
|
1031
1031
|
}
|
|
1032
1032
|
|
|
1033
|
-
// 4.5. Check RTK & GitNexus Integration
|
|
1033
|
+
// 4.5. Check optional RTK & GitNexus Integration
|
|
1034
1034
|
if (depManager.checkRtk()) {
|
|
1035
|
-
|
|
1035
|
+
const rtkMode = rtkRuntime.getRtkMode();
|
|
1036
|
+
ok(`RTK (Rust Token Killer) is installed (v${depManager.getRtkVersion() || 'unknown'}, mode: ${rtkMode.mode})`);
|
|
1036
1037
|
} else {
|
|
1037
|
-
warn('RTK (Rust Token Killer) not found.');
|
|
1038
|
-
if (promptYN('Would you like to install RTK automatically now?')) {
|
|
1039
|
-
depManager.installRtk();
|
|
1040
|
-
} else {
|
|
1041
|
-
issues++;
|
|
1042
|
-
}
|
|
1038
|
+
warn('RTK (Rust Token Killer) not found. Optional: run `awkit rtk setup`.');
|
|
1043
1039
|
}
|
|
1044
1040
|
|
|
1045
1041
|
if (depManager.checkGitnexus()) {
|
|
@@ -1073,7 +1069,8 @@ async function cmdDoctor() {
|
|
|
1073
1069
|
ok('AWKit is up-to-date');
|
|
1074
1070
|
}
|
|
1075
1071
|
|
|
1076
|
-
const
|
|
1072
|
+
const currentRtkMode = rtkRuntime.getRtkMode();
|
|
1073
|
+
const currentRtk = currentRtkMode.mode === 'off' ? null : depManager.getRtkVersion();
|
|
1077
1074
|
if (updates.latestRtk && currentRtk && isNewerVersion(updates.latestRtk, currentRtk)) {
|
|
1078
1075
|
warn(`RTK update available: v${updates.latestRtk} (current: v${currentRtk})`);
|
|
1079
1076
|
} else if (currentRtk) {
|
|
@@ -2339,7 +2336,7 @@ function cmdHelp() {
|
|
|
2339
2336
|
log(` ${C.green}update${C.reset} Pull latest + reinstall`);
|
|
2340
2337
|
log(` ${C.green}lint${C.reset} Run skill & workflow guards (check length, frontmatter)`);
|
|
2341
2338
|
log(` ${C.green}doctor${C.reset} Check installation health`);
|
|
2342
|
-
log(` ${C.green}rtk setup${C.reset}
|
|
2339
|
+
log(` ${C.green}rtk status|setup|off${C.reset} Manage RTK output compression`);
|
|
2343
2340
|
log(` ${C.green}credentials list${C.reset} List stored API keys`);
|
|
2344
2341
|
log(` ${C.green}credentials set${C.reset} <k> <v> Set API key (e.g., gemini_api_key, openrouter_api_key)`);
|
|
2345
2342
|
log(` ${C.green}set-openrouter${C.reset} <key> Shorthand for setting OpenRouter API Key`);
|
|
@@ -4133,7 +4130,8 @@ async function checkAutoUpdate() {
|
|
|
4133
4130
|
log('');
|
|
4134
4131
|
}
|
|
4135
4132
|
|
|
4136
|
-
const
|
|
4133
|
+
const currentRtkMode = rtkRuntime.getRtkMode();
|
|
4134
|
+
const currentRtk = currentRtkMode.mode === 'off' ? null : depManager.getRtkVersion();
|
|
4137
4135
|
if (updates.latestRtk && currentRtk && isNewerVersion(updates.latestRtk, currentRtk)) {
|
|
4138
4136
|
log('');
|
|
4139
4137
|
log(`${C.yellow}${C.bold}🌟 [Thông báo] Có phiên bản mới cho RTK! (v${updates.latestRtk})${C.reset}`);
|
|
@@ -4477,35 +4475,12 @@ function cmdGitnexus(args) {
|
|
|
4477
4475
|
|
|
4478
4476
|
// ─── RTK Integration ──────────────────────────────────────────────────────────
|
|
4479
4477
|
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
log(`${C.cyan}${C.bold}║ ⚙️ RTK Auto-Setup & Configuration ║${C.reset}`);
|
|
4483
|
-
log(`${C.cyan}${C.bold}╚═══════════════════════════════════════════════════════╝${C.reset}`);
|
|
4478
|
+
const RTK_SHELL_MARKER = '# RTK Integration for AI Agents (AWKit)';
|
|
4479
|
+
const RTK_SHELL_END_MARKER = '# End RTK Integration for AI Agents (AWKit)';
|
|
4484
4480
|
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
const zshrcPath = path.join(HOME, '.zshrc');
|
|
4489
|
-
log(`\nConfiguring Shell Aliases in ~/.zshrc...`);
|
|
4490
|
-
if (fs.existsSync(zshrcPath)) {
|
|
4491
|
-
let zshrc = fs.readFileSync(zshrcPath, 'utf8');
|
|
4492
|
-
|
|
4493
|
-
// Clean up old aliases to avoid collision
|
|
4494
|
-
const oldAliases = [
|
|
4495
|
-
'alias git="rtk git"',
|
|
4496
|
-
'alias npm="rtk npm"',
|
|
4497
|
-
'alias pnpm="rtk pnpm"',
|
|
4498
|
-
'alias yarn="rtk yarn"',
|
|
4499
|
-
'alias cargo="rtk cargo"'
|
|
4500
|
-
];
|
|
4501
|
-
for (const oldAlias of oldAliases) {
|
|
4502
|
-
if (zshrc.includes(oldAlias)) {
|
|
4503
|
-
zshrc = zshrc.replace(new RegExp(`\\n?${oldAlias}\\n?`, 'g'), '\n');
|
|
4504
|
-
}
|
|
4505
|
-
}
|
|
4506
|
-
|
|
4507
|
-
const functionBlock = `
|
|
4508
|
-
# RTK Integration for AI Agents (AWKit)
|
|
4481
|
+
function getRtkShellBlock() {
|
|
4482
|
+
return `
|
|
4483
|
+
${RTK_SHELL_MARKER}
|
|
4509
4484
|
unalias npm pnpm yarn cargo git 2>/dev/null
|
|
4510
4485
|
npm() {
|
|
4511
4486
|
if [[ "$1" == "login" || "$1" == "adduser" || "$1" == "publish" ]]; then
|
|
@@ -4542,19 +4517,130 @@ git() {
|
|
|
4542
4517
|
rtk git "$@"
|
|
4543
4518
|
fi
|
|
4544
4519
|
}
|
|
4520
|
+
${RTK_SHELL_END_MARKER}
|
|
4545
4521
|
`;
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
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() === '}');
|
|
4550
4550
|
}
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
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);
|
|
4558
4644
|
}
|
|
4559
4645
|
}
|
|
4560
4646
|
|
|
@@ -4562,9 +4648,23 @@ async function cmdRtk(args) {
|
|
|
4562
4648
|
const action = args[0];
|
|
4563
4649
|
if (action === 'setup') {
|
|
4564
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();
|
|
4565
4665
|
} else {
|
|
4566
4666
|
err(`Unknown rtk command: ${action || ''}`);
|
|
4567
|
-
log(` Available: setup`);
|
|
4667
|
+
log(` Available: status, setup, off, on, mode, shell-on, shell-off`);
|
|
4568
4668
|
}
|
|
4569
4669
|
}
|
|
4570
4670
|
|
package/core/GEMINI.md
CHANGED
|
@@ -123,6 +123,8 @@ symphony-orchestrator → awf-session-restore (gitnexus state) → nm-memory-syn
|
|
|
123
123
|
### Communication (CAVEMAN ULTRA)
|
|
124
124
|
- Chat: Tiếng Việt, tối đa 1-2 câu ngắn. Code/Docs: Tiếng Anh.
|
|
125
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.
|
|
126
128
|
- Planning artifacts (implementation_plan.md, walkthrough.md) VẪN chi tiết theo format chuẩn.
|
|
127
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.
|
|
128
130
|
|
|
@@ -150,6 +152,12 @@ symphony-orchestrator → awf-session-restore (gitnexus state) → nm-memory-syn
|
|
|
150
152
|
- Commit: CHỈ qua `awkit gate git auto`. CẤM `git commit` trực tiếp qua bash.
|
|
151
153
|
- Destructive command → double-confirm user. Không chắc → hỏi trước.
|
|
152
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
|
+
|
|
153
161
|
### Subagent Orchestration & Protocol
|
|
154
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.
|
|
155
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.
|
package/core/GEMINI.md.bak
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# GEMINI.md — Antigravity v12.6
|
|
2
2
|
|
|
3
|
-
> Rules only. Updated: 2026-06-
|
|
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
|
|
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
|
|
106
|
-
-
|
|
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.
|
package/package.json
CHANGED
package/scripts/exec-rtk.js
CHANGED
|
@@ -1,6 +1,83 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const os = require('os');
|
|
1
4
|
const { execSync } = require('child_process');
|
|
2
5
|
|
|
3
6
|
let hasRtkCache = null;
|
|
7
|
+
const HOME = os.homedir();
|
|
8
|
+
const CONFIG_DIR = path.join(HOME, '.gemini', 'antigravity');
|
|
9
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'rtk.json');
|
|
10
|
+
const VALID_MODES = new Set(['off', 'proxy', 'safe', 'aggressive']);
|
|
11
|
+
const DEFAULT_MODE = 'safe';
|
|
12
|
+
|
|
13
|
+
function readJsonFile(file) {
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
16
|
+
} catch (_) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function findProjectIdentity(startDir = process.cwd()) {
|
|
22
|
+
let dir = path.resolve(startDir);
|
|
23
|
+
const root = path.parse(dir).root;
|
|
24
|
+
|
|
25
|
+
while (dir !== root) {
|
|
26
|
+
const candidate = path.join(dir, '.project-identity');
|
|
27
|
+
if (fs.existsSync(candidate)) return readJsonFile(candidate);
|
|
28
|
+
dir = path.dirname(dir);
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function normalizeMode(mode) {
|
|
34
|
+
const normalized = String(mode || '').trim().toLowerCase();
|
|
35
|
+
return VALID_MODES.has(normalized) ? normalized : null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function getGlobalRtkConfig() {
|
|
39
|
+
return readJsonFile(CONFIG_FILE) || {};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getProjectRtkMode(startDir = process.cwd()) {
|
|
43
|
+
const identity = findProjectIdentity(startDir);
|
|
44
|
+
const rtkConfig = identity && identity.automation && identity.automation.rtk;
|
|
45
|
+
if (!rtkConfig) return null;
|
|
46
|
+
if (rtkConfig.enabled === false) return 'off';
|
|
47
|
+
return normalizeMode(rtkConfig.mode);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function getRtkMode(startDir = process.cwd()) {
|
|
51
|
+
const envMode = normalizeMode(process.env.AWKIT_RTK_MODE || process.env.RTK_MODE);
|
|
52
|
+
if (envMode) return { mode: envMode, source: 'env' };
|
|
53
|
+
|
|
54
|
+
const globalConfig = getGlobalRtkConfig();
|
|
55
|
+
const globalMode = normalizeMode(globalConfig.mode);
|
|
56
|
+
if (globalMode) return { mode: globalMode, source: CONFIG_FILE };
|
|
57
|
+
|
|
58
|
+
const projectMode = getProjectRtkMode(startDir);
|
|
59
|
+
if (projectMode) return { mode: projectMode, source: '.project-identity' };
|
|
60
|
+
|
|
61
|
+
return { mode: DEFAULT_MODE, source: 'default' };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function setGlobalRtkMode(mode) {
|
|
65
|
+
const normalized = normalizeMode(mode);
|
|
66
|
+
if (!normalized) {
|
|
67
|
+
throw new Error(`Invalid RTK mode: ${mode}. Expected: ${Array.from(VALID_MODES).join(', ')}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
71
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify({
|
|
72
|
+
mode: normalized,
|
|
73
|
+
updatedAt: new Date().toISOString()
|
|
74
|
+
}, null, 2) + '\n');
|
|
75
|
+
return CONFIG_FILE;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function startsWithAny(command, prefixes) {
|
|
79
|
+
return prefixes.some(prefix => command === prefix || command.startsWith(`${prefix} `));
|
|
80
|
+
}
|
|
4
81
|
|
|
5
82
|
/**
|
|
6
83
|
* Check if rtk binary is available in the current environment PATH.
|
|
@@ -26,12 +103,21 @@ function checkRtk() {
|
|
|
26
103
|
function execRtkSync(command, options = {}) {
|
|
27
104
|
const opts = { timeout: 30000, ...options };
|
|
28
105
|
const trimmed = command.trim();
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
|
|
106
|
+
const { mode } = getRtkMode();
|
|
107
|
+
|
|
108
|
+
const safeCommands = ['git status', 'git branch', 'git remote', 'git rev-parse', 'git log'];
|
|
109
|
+
const safePrefixes = ['git add', 'git commit', 'git push'];
|
|
110
|
+
const aggressivePrefixes = [
|
|
111
|
+
'git ', 'npm ', 'cargo ', 'yarn ', 'pnpm ', 'grep ', 'find ', 'awkit trello ',
|
|
112
|
+
'cat ', 'curl ', 'xcodebuild ', './gradlew ', 'swift ', 'flutter ', 'dart ', 'pod ', 'brew '
|
|
113
|
+
];
|
|
114
|
+
const safeEligible = startsWithAny(trimmed, safeCommands) || startsWithAny(trimmed, safePrefixes);
|
|
115
|
+
const aggressiveEligible = aggressivePrefixes.some(prefix => trimmed.startsWith(prefix));
|
|
116
|
+
const isEligible = mode === 'aggressive' ? aggressiveEligible : safeEligible;
|
|
117
|
+
|
|
118
|
+
if (mode === 'off') {
|
|
119
|
+
return execSync(command, opts);
|
|
120
|
+
}
|
|
35
121
|
|
|
36
122
|
if (!checkRtk()) {
|
|
37
123
|
if (isEligible && !opts.stdio) {
|
|
@@ -41,17 +127,26 @@ function execRtkSync(command, options = {}) {
|
|
|
41
127
|
}
|
|
42
128
|
|
|
43
129
|
if (trimmed.startsWith('rtk ')) {
|
|
44
|
-
return execSync(command,
|
|
130
|
+
return execSync(command, opts);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (mode === 'proxy' && aggressiveEligible) {
|
|
134
|
+
return execSync(`rtk proxy ${command}`, opts);
|
|
45
135
|
}
|
|
46
136
|
|
|
47
137
|
if (isEligible) {
|
|
48
|
-
return execSync(`rtk ${command}`,
|
|
138
|
+
return execSync(`rtk ${command}`, opts);
|
|
49
139
|
}
|
|
50
140
|
|
|
51
|
-
return execSync(command,
|
|
141
|
+
return execSync(command, opts);
|
|
52
142
|
}
|
|
53
143
|
|
|
54
144
|
module.exports = {
|
|
55
145
|
execRtkSync,
|
|
56
|
-
checkRtk
|
|
146
|
+
checkRtk,
|
|
147
|
+
getRtkMode,
|
|
148
|
+
getGlobalRtkConfig,
|
|
149
|
+
getRtkConfigPath: () => CONFIG_FILE,
|
|
150
|
+
setGlobalRtkMode,
|
|
151
|
+
VALID_RTK_MODES: Array.from(VALID_MODES)
|
|
57
152
|
};
|
package/skills/CATALOG.md
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
| 5 | `brainstorm-agent` | `manual` | `/brainstorm`, keywords | 5 | 1.0.0 | ✅ Active |
|
|
26
26
|
| 6 | `awf-error-translator` | `auto` | Error detected | 6 | — | ✅ Active |
|
|
27
27
|
| 7 | `awf-adaptive-language` | `auto` | Always | 7 | — | ✅ Active |
|
|
28
|
-
| 8 | `awf-caveman` | `auto` | `.project-identity` check | 7.5 | 1.0.
|
|
28
|
+
| 8 | `awf-caveman` | `auto` | `.project-identity` check | 7.5 | 1.0.1 | ✅ Active |
|
|
29
29
|
| 9 | `ios-engineer` | `manual` | iOS tasks | — | — | ✅ Active |
|
|
30
30
|
| 9 | `smali-to-kotlin` | `manual` | `/reverse-android` | 8 | — | ✅ Active |
|
|
31
31
|
| 10 | `smali-to-swift` | `manual` | `/reverse-ios` | 9 | — | ✅ Active |
|
|
@@ -4,7 +4,7 @@ description: >-
|
|
|
4
4
|
Ultra-compressed communication mode. Cuts token usage ~75% by speaking like caveman.
|
|
5
5
|
Checks `.project-identity` for `communication.cavemanMode.enabled`.
|
|
6
6
|
Supports both Vietnamese and English.
|
|
7
|
-
version: 1.0.
|
|
7
|
+
version: 1.0.1
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# AWF Caveman Mode
|
|
@@ -28,6 +28,17 @@ if config?.communication?.cavemanMode?.enabled == true:
|
|
|
28
28
|
|
|
29
29
|
Áp dụng cho mọi phản hồi của AI (cả Tiếng Việt và Tiếng Anh). Mọi hàm lượng kỹ thuật phải giữ nguyên, CHỈ lược bỏ từ thừa.
|
|
30
30
|
|
|
31
|
+
### Scope Guard
|
|
32
|
+
|
|
33
|
+
Caveman chỉ được nén phần prose/chat. KHÔNG được cắt, viết tắt, tái diễn giải, hoặc gom nhóm các bằng chứng kỹ thuật cần độ chính xác cao:
|
|
34
|
+
- Command output quan trọng.
|
|
35
|
+
- Error message, stack trace, warning.
|
|
36
|
+
- Diff, patch, JSON/API response.
|
|
37
|
+
- File path, symbol name, line number.
|
|
38
|
+
- Test/build evidence.
|
|
39
|
+
|
|
40
|
+
Khi cần tiết kiệm token: tóm tắt phần nhiễu xung quanh, nhưng giữ nguyên các dòng kỹ thuật quyết định.
|
|
41
|
+
|
|
31
42
|
1. **BỎ TỪ ĐỆM**: Bỏ mọi từ thừa, từ lịch sự ("Vâng", "Dạ", "Chắc chắn rồi", "Theo tôi thấy thì...", "Tôi hiểu ý anh...").
|
|
32
43
|
2. **NÓI CỤT LỦN**: Đi thẳng vào vấn đề. Bắt đầu ngay bằng nguyên nhân lỗi hoặc hành động. Dùng câu mảnh (fragments).
|
|
33
44
|
3. **KHÔNG GIẢI THÍCH DÀI DÒNG**: Dùng mũi tên `->` để chỉ nguyên nhân/kết quả.
|
|
@@ -55,6 +66,7 @@ if config?.communication?.cavemanMode?.enabled == true:
|
|
|
55
66
|
Tạm thời ngưng Caveman (trở lại bình thường) khi:
|
|
56
67
|
- Cảnh báo bảo mật quan trọng (Security warnings).
|
|
57
68
|
- Hành động không thể hoàn tác (Xóa DB, git reset --hard).
|
|
69
|
+
- Command output/error/diff là bằng chứng chính của task.
|
|
58
70
|
- Các bước hướng dẫn quá phức tạp dễ gây hiểu nhầm nếu nói tắt.
|
|
59
71
|
- Chữa cháy / Giải thích lỗi quá lắt léo cần rõ nghĩa.
|
|
60
72
|
|