@leejungkiin/awkit 1.0.0
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/CHANGELOG.md +27 -0
- package/README.md +146 -0
- package/VERSION +1 -0
- package/bin/awf.js +549 -0
- package/bin/awk.js +1759 -0
- package/core/AGENTS.md +39 -0
- package/core/GEMINI.md +202 -0
- package/core/GEMINI.md.bak +244 -0
- package/core/orchestrator.md +58 -0
- package/package.json +46 -0
- package/schemas/brain.schema.json +342 -0
- package/schemas/preferences.schema.json +95 -0
- package/schemas/session.schema.json +112 -0
- package/skill-packs/neural-memory/README.md +111 -0
- package/skill-packs/neural-memory/pack.json +35 -0
- package/skill-packs/neural-memory/schemas/brain-snapshot.json +167 -0
- package/skill-packs/neural-memory/skills/nm-memory-audit/SKILL.md +157 -0
- package/skill-packs/neural-memory/skills/nm-memory-evolution/SKILL.md +202 -0
- package/skill-packs/neural-memory/skills/nm-memory-intake/SKILL.md +135 -0
- package/skill-packs/neural-memory/skills/nm-memory-sync/SKILL.md +184 -0
- package/skill-packs/neural-memory/workflows/nm-import.md +73 -0
- package/skill-packs/neural-memory/workflows/nm-recall.md +67 -0
- package/skill-packs/neural-memory/workflows/nm-snapshot.md +69 -0
- package/skills/adaptive-language/SKILL.md +189 -0
- package/skills/ambient-brain/SKILL.md +314 -0
- package/skills/ambient-brain/brain-router.md +185 -0
- package/skills/ambient-brain/brain-templates.md +201 -0
- package/skills/auto-save/SKILL.md +223 -0
- package/skills/awf-adaptive-language/SKILL.md +189 -0
- package/skills/awf-context-help/SKILL.md +180 -0
- package/skills/awf-error-translator/SKILL.md +153 -0
- package/skills/awf-session-restore/SKILL.md +270 -0
- package/skills/awf-version-tracker/SKILL.md +32 -0
- package/skills/awf-version-tracker/scripts/snapshot.sh +22 -0
- package/skills/beads-manager/SKILL.md +323 -0
- package/skills/brainstorm-agent/SKILL.md +295 -0
- package/skills/context-help/SKILL.md +180 -0
- package/skills/error-translator/SKILL.md +153 -0
- package/skills/ios-engineer/SKILL.md +101 -0
- package/skills/memory-sync/SKILL.md +378 -0
- package/skills/memory-sync/memory-router.md +185 -0
- package/skills/memory-sync/memory-templates.md +201 -0
- package/skills/orchestrator/SKILL.md +193 -0
- package/skills/session-restore/SKILL.md +240 -0
- package/templates/CODEBASE.md +80 -0
- package/templates/brain.example.json +321 -0
- package/templates/preferences.example.json +21 -0
- package/templates/project-identity/android.json +28 -0
- package/templates/project-identity/backend-nestjs.json +24 -0
- package/templates/project-identity/expo.json +27 -0
- package/templates/project-identity/ios.json +27 -0
- package/templates/project-identity/web-nextjs.json +24 -0
- package/templates/session.example.json +53 -0
- package/templates/specs/design-template.md +166 -0
- package/templates/specs/requirements-template.md +65 -0
- package/templates/specs/tasks-template.md +132 -0
- package/templates/structures/android.txt +10 -0
- package/templates/structures/backend-nestjs.txt +6 -0
- package/templates/structures/expo.txt +9 -0
- package/templates/structures/ios.txt +9 -0
- package/templates/structures/web-nextjs.txt +6 -0
- package/templates/workflow_dual_mode_template.md +87 -0
- package/workflows/_uncategorized/README.md +339 -0
- package/workflows/_uncategorized/ads-creative.md +357 -0
- package/workflows/_uncategorized/ads-full-optimization.md +308 -0
- package/workflows/_uncategorized/ads-plan.md +247 -0
- package/workflows/_uncategorized/ads-user-analysis.md +337 -0
- package/workflows/_uncategorized/skill-health.md +35 -0
- package/workflows/_uncategorized/skill-rollback.md +35 -0
- package/workflows/ads/admob.md +62 -0
- package/workflows/ads/ads-analyst.md +201 -0
- package/workflows/ads/ads-audit.md +106 -0
- package/workflows/ads/ads-optimize.md +97 -0
- package/workflows/ads/ads-targeting.md +241 -0
- package/workflows/ads/adsExpert.md +160 -0
- package/workflows/ads/smali-ads-config.md +400 -0
- package/workflows/ads/smali-ads-flow.md +331 -0
- package/workflows/ads/smali-ads-interstitial.md +377 -0
- package/workflows/ads/smali-ads-native.md +382 -0
- package/workflows/context/auto-execution-workflow.md +291 -0
- package/workflows/context/auto-implement.md +211 -0
- package/workflows/context/codebase-sync.md +163 -0
- package/workflows/context/logic-reasoning-workflow.md +260 -0
- package/workflows/context/next.md +195 -0
- package/workflows/context/recap.md +212 -0
- package/workflows/context/save-brain.md +285 -0
- package/workflows/context/user-intent-analysis-workflow.md +206 -0
- package/workflows/expert/codeExpert.md +126 -0
- package/workflows/expert/debugExpert.md +136 -0
- package/workflows/expert/planExpert.md +112 -0
- package/workflows/git/cloudflare-tunnel.md +135 -0
- package/workflows/git/git-commit-workflow.md +75 -0
- package/workflows/git/hotfix.md +357 -0
- package/workflows/git/release-notes.md +160 -0
- package/workflows/git/rollback.md +52 -0
- package/workflows/git/smart-git-ops.md +103 -0
- package/workflows/lifecycle/brainstorm.md +377 -0
- package/workflows/lifecycle/code.md +663 -0
- package/workflows/lifecycle/debug.md +116 -0
- package/workflows/lifecycle/deploy.md +95 -0
- package/workflows/lifecycle/init.md +152 -0
- package/workflows/lifecycle/master-code-workflow.md +300 -0
- package/workflows/lifecycle/migration.md +196 -0
- package/workflows/lifecycle/plan.md +91 -0
- package/workflows/lifecycle/refactor.md +165 -0
- package/workflows/lifecycle/run.md +52 -0
- package/workflows/lifecycle/test.md +91 -0
- package/workflows/meta/customize.md +346 -0
- package/workflows/meta/file-protection-rules.md +129 -0
- package/workflows/meta/help.html +350 -0
- package/workflows/meta/project-identity-enforcement.md +180 -0
- package/workflows/mobile/app-analysis.md +64 -0
- package/workflows/mobile/maestro-qa-workflow.md +470 -0
- package/workflows/mobile/maestro-test-workflow.md +84 -0
- package/workflows/mobile/structure-clean-architect.md +271 -0
- package/workflows/mobile/turbo-mobile-build.md +190 -0
- package/workflows/quality/accessibility-audit.md +311 -0
- package/workflows/quality/audit.md +217 -0
- package/workflows/quality/bug-hunter.md +243 -0
- package/workflows/quality/code-janitor.md +209 -0
- package/workflows/quality/code-quality-rules.md +132 -0
- package/workflows/quality/performance-audit.md +343 -0
- package/workflows/quality/project-audit.md +61 -0
- package/workflows/quality/self-healing-test.md +192 -0
- package/workflows/quality/ui-review.md +130 -0
- package/workflows/quality/ux-audit.md +213 -0
- package/workflows/quality/visual-debug.md +34 -0
- package/workflows/roles/oracle.md +267 -0
- package/workflows/roles/product-manager-workflow.md +52 -0
- package/workflows/roles/qa-engineer-workflow.md +41 -0
- package/workflows/roles/tech-lead-workflow.md +45 -0
- package/workflows/roles/ui-ux-designer-workflow.md +42 -0
- package/workflows/roles/vibe-coding-master-workflow.md +52 -0
- package/workflows/ui/app-screen-analyzer.md +152 -0
- package/workflows/ui/create-feature.md +332 -0
- package/workflows/ui/create-spec-architect.md +184 -0
- package/workflows/ui/design-to-ui.md +308 -0
- package/workflows/ui/ui-first-methodology.md +279 -0
- package/workflows/ui/visualize.md +298 -0
package/bin/awf.js
ADDED
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AWF v6.0 CLI — Antigravity Workflow Framework
|
|
5
|
+
* Unified installer, updater, and manager for AI agent workflows.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* awf install Install AWF into ~/.gemini/antigravity/
|
|
9
|
+
* awf uninstall Remove AWF from system
|
|
10
|
+
* awf update Update to latest version
|
|
11
|
+
* awf doctor Check installation health
|
|
12
|
+
* awf enable-pack Enable a skill pack
|
|
13
|
+
* awf disable-pack Disable a skill pack
|
|
14
|
+
* awf list-packs List available skill packs
|
|
15
|
+
* awf version Show current version
|
|
16
|
+
*
|
|
17
|
+
* Created by Kien AI
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const fs = require('fs');
|
|
21
|
+
const path = require('path');
|
|
22
|
+
const { execSync } = require('child_process');
|
|
23
|
+
|
|
24
|
+
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
const AWF_VERSION = fs.readFileSync(path.join(__dirname, '..', 'VERSION'), 'utf8').trim();
|
|
27
|
+
const AWF_ROOT = path.join(__dirname, '..');
|
|
28
|
+
const HOME = process.env.HOME || process.env.USERPROFILE;
|
|
29
|
+
|
|
30
|
+
const TARGETS = {
|
|
31
|
+
antigravity: path.join(HOME, '.gemini', 'antigravity'),
|
|
32
|
+
geminiMd: path.join(HOME, '.gemini', 'GEMINI.md'),
|
|
33
|
+
versionFile: path.join(HOME, '.gemini', 'awf_version'),
|
|
34
|
+
agentsDir: null, // Set per-project
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Mapping: source dir in package → target dir in antigravity
|
|
38
|
+
const SYNC_MAP = {
|
|
39
|
+
'core/GEMINI.md': 'GEMINI.md',
|
|
40
|
+
'core/AGENTS.md': 'global_workflows/AGENTS.md',
|
|
41
|
+
'core/orchestrator.md': 'skills/orchestrator/SKILL.md',
|
|
42
|
+
'workflows': 'global_workflows',
|
|
43
|
+
'skills': 'skills',
|
|
44
|
+
'schemas': 'schemas',
|
|
45
|
+
'templates': 'templates',
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// ─── Colors ──────────────────────────────────────────────────────────────────
|
|
49
|
+
|
|
50
|
+
const C = {
|
|
51
|
+
reset: '\x1b[0m',
|
|
52
|
+
red: '\x1b[31m',
|
|
53
|
+
green: '\x1b[32m',
|
|
54
|
+
yellow: '\x1b[33m',
|
|
55
|
+
cyan: '\x1b[36m',
|
|
56
|
+
gray: '\x1b[90m',
|
|
57
|
+
bold: '\x1b[1m',
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
function log(msg) { console.log(msg); }
|
|
61
|
+
function ok(msg) { log(`${C.green}✅ ${msg}${C.reset}`); }
|
|
62
|
+
function warn(msg) { log(`${C.yellow}⚠️ ${msg}${C.reset}`); }
|
|
63
|
+
function err(msg) { log(`${C.red}❌ ${msg}${C.reset}`); }
|
|
64
|
+
function info(msg) { log(`${C.cyan}ℹ️ ${msg}${C.reset}`); }
|
|
65
|
+
function dim(msg) { log(`${C.gray} ${msg}${C.reset}`); }
|
|
66
|
+
|
|
67
|
+
// ─── Utility Functions ──────────────────────────────────────────────────────
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Recursively copy directory, preserving structure.
|
|
71
|
+
* Does NOT overwrite files prefixed with `.` (user configs).
|
|
72
|
+
*/
|
|
73
|
+
function copyDirRecursive(src, dest, options = {}) {
|
|
74
|
+
const { flatten = false, dryRun = false, overwrite = true } = options;
|
|
75
|
+
let count = 0;
|
|
76
|
+
|
|
77
|
+
if (!fs.existsSync(src)) return count;
|
|
78
|
+
if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
|
|
79
|
+
|
|
80
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
81
|
+
|
|
82
|
+
for (const entry of entries) {
|
|
83
|
+
if (entry.name === '.DS_Store') continue;
|
|
84
|
+
|
|
85
|
+
const srcPath = path.join(src, entry.name);
|
|
86
|
+
|
|
87
|
+
if (entry.isDirectory()) {
|
|
88
|
+
if (flatten) {
|
|
89
|
+
// Flatten: copy workflow files from subcategories into single dir
|
|
90
|
+
count += copyDirRecursive(srcPath, dest, options);
|
|
91
|
+
} else {
|
|
92
|
+
const destPath = path.join(dest, entry.name);
|
|
93
|
+
count += copyDirRecursive(srcPath, destPath, options);
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
const destPath = path.join(dest, entry.name);
|
|
97
|
+
|
|
98
|
+
// Skip user config files if they already exist and overwrite is off
|
|
99
|
+
if (!overwrite && fs.existsSync(destPath)) {
|
|
100
|
+
dim(`Skip (exists): ${entry.name}`);
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!dryRun) {
|
|
105
|
+
fs.copyFileSync(srcPath, destPath);
|
|
106
|
+
}
|
|
107
|
+
count++;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return count;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Flatten workflow category dirs into single global_workflows dir.
|
|
116
|
+
* workflows/lifecycle/code.md → global_workflows/code.md
|
|
117
|
+
* workflows/context/recap.md → global_workflows/recap.md
|
|
118
|
+
*/
|
|
119
|
+
function flattenWorkflows(srcBase, destDir) {
|
|
120
|
+
let count = 0;
|
|
121
|
+
|
|
122
|
+
if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
|
|
123
|
+
|
|
124
|
+
const categories = fs.readdirSync(srcBase, { withFileTypes: true });
|
|
125
|
+
|
|
126
|
+
for (const cat of categories) {
|
|
127
|
+
if (!cat.isDirectory()) continue;
|
|
128
|
+
|
|
129
|
+
const catPath = path.join(srcBase, cat.name);
|
|
130
|
+
const files = fs.readdirSync(catPath, { withFileTypes: true });
|
|
131
|
+
|
|
132
|
+
for (const file of files) {
|
|
133
|
+
if (file.name === '.DS_Store') continue;
|
|
134
|
+
|
|
135
|
+
if (file.isFile() && file.name.endsWith('.md')) {
|
|
136
|
+
const srcFile = path.join(catPath, file.name);
|
|
137
|
+
const destFile = path.join(destDir, file.name);
|
|
138
|
+
fs.copyFileSync(srcFile, destFile);
|
|
139
|
+
count++;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return count;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Install or update GEMINI.md into ~/.gemini/
|
|
149
|
+
*/
|
|
150
|
+
function syncGeminiMd() {
|
|
151
|
+
const srcGemini = path.join(AWF_ROOT, 'core', 'GEMINI.md');
|
|
152
|
+
const destGemini = TARGETS.geminiMd;
|
|
153
|
+
|
|
154
|
+
const destDir = path.dirname(destGemini);
|
|
155
|
+
if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
|
|
156
|
+
|
|
157
|
+
// Read existing GEMINI.md if present
|
|
158
|
+
let existingContent = '';
|
|
159
|
+
if (fs.existsSync(destGemini)) {
|
|
160
|
+
existingContent = fs.readFileSync(destGemini, 'utf8');
|
|
161
|
+
|
|
162
|
+
// Backup existing
|
|
163
|
+
const backupDir = path.join(destDir, 'antigravity', 'backup');
|
|
164
|
+
if (!fs.existsSync(backupDir)) fs.mkdirSync(backupDir, { recursive: true });
|
|
165
|
+
|
|
166
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
167
|
+
const backupPath = path.join(backupDir, `GEMINI_${timestamp}.md.bak`);
|
|
168
|
+
fs.copyFileSync(destGemini, backupPath);
|
|
169
|
+
dim(`Backup: ${backupPath}`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Copy new GEMINI.md
|
|
173
|
+
fs.copyFileSync(srcGemini, destGemini);
|
|
174
|
+
ok('GEMINI.md updated');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ─── Commands ────────────────────────────────────────────────────────────────
|
|
178
|
+
|
|
179
|
+
function cmdInstall() {
|
|
180
|
+
log('');
|
|
181
|
+
log(`${C.cyan}${C.bold}╔══════════════════════════════════════════════════════════╗${C.reset}`);
|
|
182
|
+
log(`${C.cyan}${C.bold}║ 🚀 AWF v${AWF_VERSION} — Antigravity Workflow Framework ║${C.reset}`);
|
|
183
|
+
log(`${C.cyan}${C.bold}╚══════════════════════════════════════════════════════════╝${C.reset}`);
|
|
184
|
+
log('');
|
|
185
|
+
|
|
186
|
+
const target = TARGETS.antigravity;
|
|
187
|
+
|
|
188
|
+
// 1. Ensure target dirs exist
|
|
189
|
+
info('Creating directories...');
|
|
190
|
+
const dirs = ['global_workflows', 'skills', 'schemas', 'templates'];
|
|
191
|
+
for (const dir of dirs) {
|
|
192
|
+
const fullPath = path.join(target, dir);
|
|
193
|
+
if (!fs.existsSync(fullPath)) {
|
|
194
|
+
fs.mkdirSync(fullPath, { recursive: true });
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
ok('Directories ready');
|
|
198
|
+
|
|
199
|
+
// 2. Sync GEMINI.md
|
|
200
|
+
info('Syncing GEMINI.md...');
|
|
201
|
+
syncGeminiMd();
|
|
202
|
+
|
|
203
|
+
// 3. Backup and flatten workflows
|
|
204
|
+
info('Installing workflows...');
|
|
205
|
+
const wfSrc = path.join(AWF_ROOT, 'workflows');
|
|
206
|
+
const wfDest = path.join(target, 'global_workflows');
|
|
207
|
+
|
|
208
|
+
// Backup existing global_workflows to a zip file
|
|
209
|
+
if (fs.existsSync(wfDest)) {
|
|
210
|
+
const backupDir = path.join(target, 'backup');
|
|
211
|
+
if (!fs.existsSync(backupDir)) fs.mkdirSync(backupDir, { recursive: true });
|
|
212
|
+
|
|
213
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
214
|
+
const zipFile = path.join(backupDir, `global_workflows_${timestamp}.bak.zip`);
|
|
215
|
+
try {
|
|
216
|
+
info('Creating zip backup of global_workflows...');
|
|
217
|
+
execSync(`zip -r "${zipFile}" .`, { cwd: wfDest, stdio: 'ignore' });
|
|
218
|
+
ok(`Backup created: ${zipFile}`);
|
|
219
|
+
} catch (e) {
|
|
220
|
+
warn(`Failed to create backup zip: ${e.message}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const wfCount = flattenWorkflows(wfSrc, wfDest);
|
|
225
|
+
ok(`${wfCount} workflows installed`);
|
|
226
|
+
|
|
227
|
+
// 4. Copy AGENTS.md
|
|
228
|
+
const agentsSrc = path.join(AWF_ROOT, 'core', 'AGENTS.md');
|
|
229
|
+
const agentsDest = path.join(target, 'global_workflows', 'AGENTS.md');
|
|
230
|
+
if (fs.existsSync(agentsSrc)) {
|
|
231
|
+
fs.copyFileSync(agentsSrc, agentsDest);
|
|
232
|
+
ok('AGENTS.md installed');
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// 5. Copy skills
|
|
236
|
+
info('Installing skills...');
|
|
237
|
+
const skillsSrc = path.join(AWF_ROOT, 'skills');
|
|
238
|
+
const skillsDest = path.join(target, 'skills');
|
|
239
|
+
const skillCount = copyDirRecursive(skillsSrc, skillsDest);
|
|
240
|
+
ok(`${skillCount} skill files installed`);
|
|
241
|
+
|
|
242
|
+
// 6. Copy orchestrator
|
|
243
|
+
const orchSrc = path.join(AWF_ROOT, 'core', 'orchestrator.md');
|
|
244
|
+
const orchDestDir = path.join(target, 'skills', 'orchestrator');
|
|
245
|
+
if (!fs.existsSync(orchDestDir)) fs.mkdirSync(orchDestDir, { recursive: true });
|
|
246
|
+
fs.copyFileSync(orchSrc, path.join(orchDestDir, 'SKILL.md'));
|
|
247
|
+
ok('Orchestrator skill installed');
|
|
248
|
+
|
|
249
|
+
// 7. Copy schemas (always overwrite)
|
|
250
|
+
info('Installing schemas...');
|
|
251
|
+
const schemaSrc = path.join(AWF_ROOT, 'schemas');
|
|
252
|
+
const schemaDest = path.join(target, 'schemas');
|
|
253
|
+
const schemaCount = copyDirRecursive(schemaSrc, schemaDest);
|
|
254
|
+
ok(`${schemaCount} schemas installed`);
|
|
255
|
+
|
|
256
|
+
// 8. Copy templates (don't overwrite existing)
|
|
257
|
+
info('Installing templates...');
|
|
258
|
+
const tmplSrc = path.join(AWF_ROOT, 'templates');
|
|
259
|
+
const tmplDest = path.join(target, 'templates');
|
|
260
|
+
const tmplCount = copyDirRecursive(tmplSrc, tmplDest, { overwrite: false });
|
|
261
|
+
ok(`${tmplCount} templates installed`);
|
|
262
|
+
|
|
263
|
+
// 9. Save version
|
|
264
|
+
fs.writeFileSync(TARGETS.versionFile, AWF_VERSION);
|
|
265
|
+
ok(`Version ${AWF_VERSION} saved`);
|
|
266
|
+
|
|
267
|
+
// 10. Summary
|
|
268
|
+
log('');
|
|
269
|
+
log(`${C.gray}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}`);
|
|
270
|
+
log(`${C.yellow}${C.bold}🎉 AWF v${AWF_VERSION} installed successfully!${C.reset}`);
|
|
271
|
+
log('');
|
|
272
|
+
dim(`Workflows: ${path.join(target, 'global_workflows')}`);
|
|
273
|
+
dim(`Skills: ${path.join(target, 'skills')}`);
|
|
274
|
+
dim(`Schemas: ${path.join(target, 'schemas')}`);
|
|
275
|
+
dim(`Templates: ${path.join(target, 'templates')}`);
|
|
276
|
+
dim(`GEMINI.md: ${TARGETS.geminiMd}`);
|
|
277
|
+
log('');
|
|
278
|
+
log(`${C.cyan}👉 Type '/plan' in your AI chat to get started.${C.reset}`);
|
|
279
|
+
log(`${C.cyan}👉 Run 'awf doctor' to verify installation.${C.reset}`);
|
|
280
|
+
log('');
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function cmdUninstall() {
|
|
284
|
+
warn('Uninstalling AWF...');
|
|
285
|
+
|
|
286
|
+
// Remove version file
|
|
287
|
+
if (fs.existsSync(TARGETS.versionFile)) {
|
|
288
|
+
fs.unlinkSync(TARGETS.versionFile);
|
|
289
|
+
ok('Version file removed');
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Don't remove workflows/skills — user may have custom ones
|
|
293
|
+
warn('Workflow and skill files were NOT removed (may contain custom content).');
|
|
294
|
+
warn('To fully remove, manually delete:');
|
|
295
|
+
dim(TARGETS.antigravity);
|
|
296
|
+
|
|
297
|
+
ok('AWF uninstalled. Custom files preserved.');
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function cmdUpdate() {
|
|
301
|
+
info(`Updating to AWF v${AWF_VERSION}...`);
|
|
302
|
+
|
|
303
|
+
// Check current version
|
|
304
|
+
let currentVersion = '0.0.0';
|
|
305
|
+
if (fs.existsSync(TARGETS.versionFile)) {
|
|
306
|
+
currentVersion = fs.readFileSync(TARGETS.versionFile, 'utf8').trim();
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (currentVersion === AWF_VERSION) {
|
|
310
|
+
ok(`Already on latest version (${AWF_VERSION})`);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
info(`Upgrading from ${currentVersion} → ${AWF_VERSION}`);
|
|
315
|
+
cmdInstall();
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function cmdDoctor() {
|
|
319
|
+
log('');
|
|
320
|
+
log(`${C.cyan}${C.bold}🏥 AWF Health Check${C.reset}`);
|
|
321
|
+
log('');
|
|
322
|
+
|
|
323
|
+
let issues = 0;
|
|
324
|
+
|
|
325
|
+
// 1. Check GEMINI.md
|
|
326
|
+
if (fs.existsSync(TARGETS.geminiMd)) {
|
|
327
|
+
ok('GEMINI.md exists');
|
|
328
|
+
} else {
|
|
329
|
+
err('GEMINI.md missing'); issues++;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// 2. Check global_workflows
|
|
333
|
+
const wfDir = path.join(TARGETS.antigravity, 'global_workflows');
|
|
334
|
+
if (fs.existsSync(wfDir)) {
|
|
335
|
+
const wfFiles = fs.readdirSync(wfDir).filter(f => f.endsWith('.md'));
|
|
336
|
+
ok(`${wfFiles.length} workflows found`);
|
|
337
|
+
|
|
338
|
+
// Check essential workflows
|
|
339
|
+
const essential = ['code.md', 'plan.md', 'debug.md', 'save-brain.md', 'recap.md', 'init.md'];
|
|
340
|
+
for (const wf of essential) {
|
|
341
|
+
if (!wfFiles.includes(wf)) {
|
|
342
|
+
warn(`Essential workflow missing: ${wf}`); issues++;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
} else {
|
|
346
|
+
err('global_workflows/ directory missing'); issues++;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// 3. Check skills
|
|
350
|
+
const skillsDir = path.join(TARGETS.antigravity, 'skills');
|
|
351
|
+
if (fs.existsSync(skillsDir)) {
|
|
352
|
+
const skills = fs.readdirSync(skillsDir, { withFileTypes: true })
|
|
353
|
+
.filter(d => d.isDirectory())
|
|
354
|
+
.map(d => d.name);
|
|
355
|
+
ok(`${skills.length} skills found`);
|
|
356
|
+
|
|
357
|
+
// Check essential skills
|
|
358
|
+
const essentialSkills = ['orchestrator', 'beads-manager', 'session-restore'];
|
|
359
|
+
for (const s of essentialSkills) {
|
|
360
|
+
if (!skills.includes(s)) {
|
|
361
|
+
warn(`Essential skill missing: ${s}`); issues++;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
} else {
|
|
365
|
+
err('skills/ directory missing'); issues++;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// 4. Check schemas
|
|
369
|
+
const schemasDir = path.join(TARGETS.antigravity, 'schemas');
|
|
370
|
+
if (fs.existsSync(schemasDir)) {
|
|
371
|
+
const schemas = fs.readdirSync(schemasDir).filter(f => f.endsWith('.json'));
|
|
372
|
+
ok(`${schemas.length} schemas found`);
|
|
373
|
+
} else {
|
|
374
|
+
warn('schemas/ directory missing'); issues++;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// 5. Check version
|
|
378
|
+
if (fs.existsSync(TARGETS.versionFile)) {
|
|
379
|
+
const v = fs.readFileSync(TARGETS.versionFile, 'utf8').trim();
|
|
380
|
+
ok(`AWF version: ${v}`);
|
|
381
|
+
if (v !== AWF_VERSION) {
|
|
382
|
+
warn(`Package version (${AWF_VERSION}) differs from installed (${v}). Run 'awf update'.`);
|
|
383
|
+
}
|
|
384
|
+
} else {
|
|
385
|
+
warn('Version file missing. Run "awf install" first.'); issues++;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Summary
|
|
389
|
+
log('');
|
|
390
|
+
if (issues === 0) {
|
|
391
|
+
log(`${C.green}${C.bold}✅ All checks passed! AWF is healthy.${C.reset}`);
|
|
392
|
+
} else {
|
|
393
|
+
log(`${C.yellow}${C.bold}⚠️ ${issues} issue(s) found. Run 'awf install' to fix.${C.reset}`);
|
|
394
|
+
}
|
|
395
|
+
log('');
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function cmdEnablePack(packName) {
|
|
399
|
+
if (!packName) {
|
|
400
|
+
err('Usage: awf enable-pack <pack-name>');
|
|
401
|
+
log('');
|
|
402
|
+
cmdListPacks();
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const packSrc = path.join(AWF_ROOT, 'skill-packs', packName);
|
|
407
|
+
|
|
408
|
+
if (!fs.existsSync(packSrc)) {
|
|
409
|
+
err(`Skill pack "${packName}" not found.`);
|
|
410
|
+
cmdListPacks();
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const target = path.join(TARGETS.antigravity, 'skills');
|
|
415
|
+
info(`Enabling skill pack: ${packName}`);
|
|
416
|
+
|
|
417
|
+
// Copy all skills from pack into skills/
|
|
418
|
+
const count = copyDirRecursive(packSrc, target);
|
|
419
|
+
ok(`${count} files from "${packName}" pack installed`);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function cmdDisablePack(packName) {
|
|
423
|
+
if (!packName) {
|
|
424
|
+
err('Usage: awf disable-pack <pack-name>');
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const packSrc = path.join(AWF_ROOT, 'skill-packs', packName);
|
|
429
|
+
|
|
430
|
+
if (!fs.existsSync(packSrc)) {
|
|
431
|
+
err(`Skill pack "${packName}" not found.`);
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// Get list of skill dirs in this pack
|
|
436
|
+
const skillDirs = fs.readdirSync(packSrc, { withFileTypes: true })
|
|
437
|
+
.filter(d => d.isDirectory())
|
|
438
|
+
.map(d => d.name);
|
|
439
|
+
|
|
440
|
+
const target = path.join(TARGETS.antigravity, 'skills');
|
|
441
|
+
|
|
442
|
+
for (const skillDir of skillDirs) {
|
|
443
|
+
const destPath = path.join(target, skillDir);
|
|
444
|
+
if (fs.existsSync(destPath)) {
|
|
445
|
+
// Move to backup instead of deleting
|
|
446
|
+
const backupDir = path.join(TARGETS.antigravity, 'backup', 'skills');
|
|
447
|
+
if (!fs.existsSync(backupDir)) fs.mkdirSync(backupDir, { recursive: true });
|
|
448
|
+
fs.renameSync(destPath, path.join(backupDir, skillDir));
|
|
449
|
+
dim(`Moved to backup: ${skillDir}`);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
ok(`Skill pack "${packName}" disabled (backed up)`);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function cmdListPacks() {
|
|
457
|
+
const packsDir = path.join(AWF_ROOT, 'skill-packs');
|
|
458
|
+
|
|
459
|
+
log('');
|
|
460
|
+
log(`${C.cyan}${C.bold}📦 Available Skill Packs${C.reset}`);
|
|
461
|
+
log('');
|
|
462
|
+
|
|
463
|
+
if (!fs.existsSync(packsDir)) {
|
|
464
|
+
warn('No skill packs directory found.');
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const packs = fs.readdirSync(packsDir, { withFileTypes: true })
|
|
469
|
+
.filter(d => d.isDirectory());
|
|
470
|
+
|
|
471
|
+
if (packs.length === 0) {
|
|
472
|
+
info('No skill packs available yet.');
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
for (const pack of packs) {
|
|
477
|
+
const readmePath = path.join(packsDir, pack.name, 'README.md');
|
|
478
|
+
let desc = '';
|
|
479
|
+
if (fs.existsSync(readmePath)) {
|
|
480
|
+
const content = fs.readFileSync(readmePath, 'utf8');
|
|
481
|
+
desc = content.split('\n').find(l => l.trim() && !l.startsWith('#')) || '';
|
|
482
|
+
}
|
|
483
|
+
log(` ${C.green}${pack.name}${C.reset} ${C.gray}${desc}${C.reset}`);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
log('');
|
|
487
|
+
log(`${C.cyan}Usage: awf enable-pack <name>${C.reset}`);
|
|
488
|
+
log('');
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
function cmdVersion() {
|
|
492
|
+
log(`AWF v${AWF_VERSION}`);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
function cmdHelp() {
|
|
496
|
+
log('');
|
|
497
|
+
log(`${C.cyan}${C.bold}AWF v${AWF_VERSION} — Antigravity Workflow Framework${C.reset}`);
|
|
498
|
+
log('');
|
|
499
|
+
log('Commands:');
|
|
500
|
+
log(` ${C.green}install${C.reset} Install AWF into ~/.gemini/antigravity/`);
|
|
501
|
+
log(` ${C.green}uninstall${C.reset} Remove AWF (preserves custom files)`);
|
|
502
|
+
log(` ${C.green}update${C.reset} Update to latest version`);
|
|
503
|
+
log(` ${C.green}doctor${C.reset} Check installation health`);
|
|
504
|
+
log(` ${C.green}enable-pack${C.reset} Enable a skill pack`);
|
|
505
|
+
log(` ${C.green}disable-pack${C.reset} Disable a skill pack`);
|
|
506
|
+
log(` ${C.green}list-packs${C.reset} List available skill packs`);
|
|
507
|
+
log(` ${C.green}version${C.reset} Show version`);
|
|
508
|
+
log(` ${C.green}help${C.reset} Show this help`);
|
|
509
|
+
log('');
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// ─── Main ────────────────────────────────────────────────────────────────────
|
|
513
|
+
|
|
514
|
+
const [, , command, ...args] = process.argv;
|
|
515
|
+
|
|
516
|
+
switch (command) {
|
|
517
|
+
case 'install':
|
|
518
|
+
cmdInstall();
|
|
519
|
+
break;
|
|
520
|
+
case 'uninstall':
|
|
521
|
+
cmdUninstall();
|
|
522
|
+
break;
|
|
523
|
+
case 'update':
|
|
524
|
+
cmdUpdate();
|
|
525
|
+
break;
|
|
526
|
+
case 'doctor':
|
|
527
|
+
cmdDoctor();
|
|
528
|
+
break;
|
|
529
|
+
case 'enable-pack':
|
|
530
|
+
cmdEnablePack(args[0]);
|
|
531
|
+
break;
|
|
532
|
+
case 'disable-pack':
|
|
533
|
+
cmdDisablePack(args[0]);
|
|
534
|
+
break;
|
|
535
|
+
case 'list-packs':
|
|
536
|
+
cmdListPacks();
|
|
537
|
+
break;
|
|
538
|
+
case 'version':
|
|
539
|
+
case '--version':
|
|
540
|
+
case '-v':
|
|
541
|
+
cmdVersion();
|
|
542
|
+
break;
|
|
543
|
+
case 'help':
|
|
544
|
+
case '--help':
|
|
545
|
+
case '-h':
|
|
546
|
+
default:
|
|
547
|
+
cmdHelp();
|
|
548
|
+
break;
|
|
549
|
+
}
|