@leejungkiin/awkit 1.2.0 → 1.3.7
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/awf.js +0 -1
- package/bin/awk.js +316 -68
- package/core/GEMINI.md +19 -5
- package/package.json +2 -3
- package/skills/CATALOG.md +4 -0
- package/skills/GEMINI.md +158 -0
- package/skills/brainstorm-agent/SKILL.md +44 -11
- package/skills/ios-engineer/SKILL.md +4 -0
- package/skills/module-spec-writer/SKILL.md +459 -0
- package/skills/module-spec-writer/module-spec-writer/SKILL.md +414 -0
- package/skills/orchestrator/SKILL.md +178 -19
- package/skills/spec-gate/SKILL.md +39 -10
- package/skills/symphony-enforcer/SKILL.md +40 -22
- package/skills/trello-sync/SKILL.md +225 -0
- package/skills/verification-gate/SKILL.md +2 -0
- package/skills/visual-design-gate/SKILL.md +177 -0
- package/templates/configs/trello-config.json +5 -0
- package/VERSION +0 -1
package/bin/awf.js
CHANGED
|
@@ -275,7 +275,6 @@ function cmdInstall() {
|
|
|
275
275
|
dim(`Templates: ${path.join(target, 'templates')}`);
|
|
276
276
|
dim(`GEMINI.md: ${TARGETS.geminiMd}`);
|
|
277
277
|
log('');
|
|
278
|
-
log(`${C.cyan}👉 Type '/plan' in your AI chat to get started.${C.reset}`);
|
|
279
278
|
log(`${C.cyan}👉 Run 'awf doctor' to verify installation.${C.reset}`);
|
|
280
279
|
log('');
|
|
281
280
|
}
|
package/bin/awk.js
CHANGED
|
@@ -27,8 +27,10 @@ const fs = require('fs');
|
|
|
27
27
|
const path = require('path');
|
|
28
28
|
const https = require('https');
|
|
29
29
|
const { execSync, spawnSync } = require('child_process');
|
|
30
|
+
const os = require('os');
|
|
30
31
|
|
|
31
|
-
const
|
|
32
|
+
const packageJson = require(path.join(__dirname, '..', 'package.json'));
|
|
33
|
+
const AWK_VERSION = packageJson.version;
|
|
32
34
|
const AWK_ROOT = path.join(__dirname, '..');
|
|
33
35
|
const HOME = process.env.HOME || process.env.USERPROFILE;
|
|
34
36
|
|
|
@@ -454,10 +456,7 @@ function cmdInstall(platformArg) {
|
|
|
454
456
|
log('');
|
|
455
457
|
|
|
456
458
|
if (platform === 'antigravity') {
|
|
457
|
-
log(`${C.cyan}👉 Type '/plan' in your AI chat to get started.${C.reset}`);
|
|
458
459
|
log(`${C.cyan}👉 Run 'awkit init' in any project to initialize it.${C.reset}`);
|
|
459
|
-
} else if (platform === 'cline') {
|
|
460
|
-
log(`${C.cyan}👉 Type '/plan' in Cline chat to get started.${C.reset}`);
|
|
461
460
|
} else if (platform === 'codex') {
|
|
462
461
|
log(`${C.cyan}👉 Type '$skill' in Codex to invoke skills.${C.reset}`);
|
|
463
462
|
}
|
|
@@ -1371,6 +1370,18 @@ function cmdHelp() {
|
|
|
1371
1370
|
log(` ${C.green}disable-pack${C.reset} <name> Uninstall a skill pack (backed up)`);
|
|
1372
1371
|
log('');
|
|
1373
1372
|
|
|
1373
|
+
// Trello
|
|
1374
|
+
log(`${C.bold}📋 Trello${C.reset}`);
|
|
1375
|
+
log(line);
|
|
1376
|
+
log(` ${C.green}trello desc${C.reset} <text> Update card description`);
|
|
1377
|
+
log(` ${C.green}trello comment${C.reset} <text> Add milestone comment`);
|
|
1378
|
+
log(` ${C.green}trello item${C.reset} <name> Add checklist item`);
|
|
1379
|
+
log(` ${C.green}trello complete${C.reset} <name> Mark checklist item ✅`);
|
|
1380
|
+
log(` ${C.green}trello block${C.reset} <reason> Label card Blocked + comment`);
|
|
1381
|
+
log(` ${C.green}trello checklist${C.reset} <name> Create new checklist`);
|
|
1382
|
+
log(` ${C.gray} Auto-loads .trello-config.json + global credentials${C.reset}`);
|
|
1383
|
+
log('');
|
|
1384
|
+
|
|
1374
1385
|
// Telegram
|
|
1375
1386
|
log(`${C.bold}📨 Telegram${C.reset}`);
|
|
1376
1387
|
log(line);
|
|
@@ -1719,7 +1730,7 @@ function buildCodebaseMd(projectName, projectType, identity) {
|
|
|
1719
1730
|
* CODEBASE.md
|
|
1720
1731
|
* .symphony/ (via Symphony)
|
|
1721
1732
|
*/
|
|
1722
|
-
function cmdInit(forceFlag = false) {
|
|
1733
|
+
async function cmdInit(forceFlag = false) {
|
|
1723
1734
|
const cwd = process.cwd();
|
|
1724
1735
|
const dirName = path.basename(cwd);
|
|
1725
1736
|
// Convert dir name to PascalCase project name: my-app → MyApp, fitbite → Fitbite
|
|
@@ -1773,6 +1784,81 @@ function cmdInit(forceFlag = false) {
|
|
|
1773
1784
|
ok(`${workspaceName} created`);
|
|
1774
1785
|
}
|
|
1775
1786
|
|
|
1787
|
+
// ── 3.5. .trello-config.json ───────────────────────────────────────────────
|
|
1788
|
+
const trelloConfigPath = path.join(cwd, '.trello-config.json');
|
|
1789
|
+
if (fs.existsSync(trelloConfigPath) && !forceFlag) {
|
|
1790
|
+
warn('.trello-config.json already exists — skipping (use --force to overwrite)');
|
|
1791
|
+
} else {
|
|
1792
|
+
info('Creating .trello-config.json...');
|
|
1793
|
+
const templatePath = path.join(TARGETS.antigravity, 'templates', 'configs', 'trello-config.json');
|
|
1794
|
+
if (fs.existsSync(templatePath)) {
|
|
1795
|
+
fs.copyFileSync(templatePath, trelloConfigPath);
|
|
1796
|
+
ok('.trello-config.json created from template');
|
|
1797
|
+
} else {
|
|
1798
|
+
const defaultTrelloConfig = {
|
|
1799
|
+
"BOARD_NAME": "Your Board Name",
|
|
1800
|
+
"LIST_NAME": "Your Backlog List",
|
|
1801
|
+
"CARD_NAME": "Project Card Name or ID"
|
|
1802
|
+
};
|
|
1803
|
+
fs.writeFileSync(trelloConfigPath, JSON.stringify(defaultTrelloConfig, null, 2) + '\n');
|
|
1804
|
+
ok('.trello-config.json created with default values');
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
const trelloCred = trelloLoadCredentials();
|
|
1809
|
+
if (!trelloCred) {
|
|
1810
|
+
log('');
|
|
1811
|
+
warn('Trello API Key & Token are not set.');
|
|
1812
|
+
log(` 👉 To setup Trello integration, please get your credentials at: https://trello.com/app-key`);
|
|
1813
|
+
|
|
1814
|
+
const readline = require('readline');
|
|
1815
|
+
const rl = readline.createInterface({
|
|
1816
|
+
input: process.stdin,
|
|
1817
|
+
output: process.stdout
|
|
1818
|
+
});
|
|
1819
|
+
|
|
1820
|
+
const question = (query) => new Promise(resolve => rl.question(query, resolve));
|
|
1821
|
+
// Sanitize: strip ALL whitespace (spaces, tabs, newlines) from pasted input
|
|
1822
|
+
const sanitize = (s) => s.replace(/\s+/g, '');
|
|
1823
|
+
|
|
1824
|
+
try {
|
|
1825
|
+
const apiKey = sanitize(await question(` ${C.yellow}Enter Trello API Key: ${C.reset}`));
|
|
1826
|
+
|
|
1827
|
+
if (apiKey) {
|
|
1828
|
+
const tokenUrl = `https://trello.com/1/authorize?expiration=never&scope=read,write&response_type=token&key=${apiKey}&name=AWKit`;
|
|
1829
|
+
log('');
|
|
1830
|
+
log(` ${C.cyan}👉 Open this link to generate your Token:${C.reset}`);
|
|
1831
|
+
log(` ${C.green}${tokenUrl}${C.reset}`);
|
|
1832
|
+
log('');
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
const apiToken = sanitize(await question(` ${C.yellow}Enter Trello API Token: ${C.reset}`));
|
|
1836
|
+
|
|
1837
|
+
if (apiKey && apiToken) {
|
|
1838
|
+
let profilePath = path.join(os.homedir(), '.zshrc');
|
|
1839
|
+
if (!fs.existsSync(profilePath) && fs.existsSync(path.join(os.homedir(), '.bashrc'))) {
|
|
1840
|
+
profilePath = path.join(os.homedir(), '.bashrc');
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
const exportLines = `\n# Trello API Credentials for AWKit\nexport TRELLO_KEY="${apiKey}"\nexport TRELLO_TOKEN="${apiToken}"\n`;
|
|
1844
|
+
fs.appendFileSync(profilePath, exportLines);
|
|
1845
|
+
|
|
1846
|
+
// Also inject into current process so immediate awkit trello calls work
|
|
1847
|
+
process.env.TRELLO_KEY = apiKey;
|
|
1848
|
+
process.env.TRELLO_TOKEN = apiToken;
|
|
1849
|
+
|
|
1850
|
+
ok(`Credentials saved to ${path.basename(profilePath)} ✅`);
|
|
1851
|
+
log(` ${C.green}👉 Trello is ready! Credentials are active for this session and all future terminals.${C.reset}`);
|
|
1852
|
+
} else {
|
|
1853
|
+
warn('Setup skipped. Automated Trello sync will be disabled.');
|
|
1854
|
+
}
|
|
1855
|
+
} catch (e) {
|
|
1856
|
+
warn(`Failed to setup Trello: ${e.message}`);
|
|
1857
|
+
} finally {
|
|
1858
|
+
rl.close();
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1776
1862
|
// ── 4. CODEBASE.md ────────────────────────────────────────────────────────
|
|
1777
1863
|
const codebasePath = path.join(cwd, 'CODEBASE.md');
|
|
1778
1864
|
if (fs.existsSync(codebasePath) && !forceFlag) {
|
|
@@ -1808,7 +1894,7 @@ function cmdInit(forceFlag = false) {
|
|
|
1808
1894
|
log('');
|
|
1809
1895
|
dim(`Type: ${projectType}`);
|
|
1810
1896
|
dim(`Firebase: analytics, crashlytics, remote-config, auth`);
|
|
1811
|
-
dim(`Files: .project-identity, ${workspaceName}, CODEBASE.md`);
|
|
1897
|
+
dim(`Files: .project-identity, ${workspaceName}, CODEBASE.md, .trello-config.json`);
|
|
1812
1898
|
dim(`Symphony: task tracking ready)`);
|
|
1813
1899
|
log('');
|
|
1814
1900
|
log(`${C.cyan}👉 Open ${workspaceName} in VS Code to get started.${C.reset}`);
|
|
@@ -2011,6 +2097,163 @@ function cmdTelegram(args) {
|
|
|
2011
2097
|
}
|
|
2012
2098
|
}
|
|
2013
2099
|
|
|
2100
|
+
// ─── Trello Integration ───────────────────────────────────────────────────────
|
|
2101
|
+
|
|
2102
|
+
/**
|
|
2103
|
+
* Load Trello credentials from environment variables.
|
|
2104
|
+
* Returns { api_key, api_token } or null.
|
|
2105
|
+
*/
|
|
2106
|
+
function trelloLoadCredentials() {
|
|
2107
|
+
if (process.env.TRELLO_KEY && process.env.TRELLO_TOKEN) {
|
|
2108
|
+
return { api_key: process.env.TRELLO_KEY, api_token: process.env.TRELLO_TOKEN };
|
|
2109
|
+
}
|
|
2110
|
+
return null;
|
|
2111
|
+
}
|
|
2112
|
+
|
|
2113
|
+
/**
|
|
2114
|
+
* Load Trello project config from .trello-config.json in CWD.
|
|
2115
|
+
* Returns { board, list, card } or null.
|
|
2116
|
+
*/
|
|
2117
|
+
function trelloLoadProjectConfig() {
|
|
2118
|
+
const configPath = path.join(process.cwd(), '.trello-config.json');
|
|
2119
|
+
if (!fs.existsSync(configPath)) return null;
|
|
2120
|
+
try {
|
|
2121
|
+
const cfg = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
2122
|
+
return {
|
|
2123
|
+
board: cfg.BOARD_NAME || cfg.board,
|
|
2124
|
+
list: cfg.LIST_NAME || cfg.list,
|
|
2125
|
+
card: cfg.CARD_NAME || cfg.card,
|
|
2126
|
+
};
|
|
2127
|
+
} catch (_) {
|
|
2128
|
+
return null;
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
/**
|
|
2133
|
+
* Execute a trello-cli command with auto-injected credentials and rate-limit retries.
|
|
2134
|
+
*/
|
|
2135
|
+
function trelloExec(cliArgs, retries = 3) {
|
|
2136
|
+
const cred = trelloLoadCredentials();
|
|
2137
|
+
const cfg = trelloLoadProjectConfig();
|
|
2138
|
+
if (!cred) {
|
|
2139
|
+
err('Trello credentials not found.');
|
|
2140
|
+
log(` Please export ${C.cyan}TRELLO_KEY${C.reset} and ${C.cyan}TRELLO_TOKEN${C.reset} in your ~/.zshrc`);
|
|
2141
|
+
return false;
|
|
2142
|
+
}
|
|
2143
|
+
if (!cfg) {
|
|
2144
|
+
err('.trello-config.json not found in current directory.');
|
|
2145
|
+
log(` Run ${C.cyan}awkit init${C.reset} to generate one, or create it manually.`);
|
|
2146
|
+
return false;
|
|
2147
|
+
}
|
|
2148
|
+
|
|
2149
|
+
const env = { ...process.env, TRELLO_KEY: cred.api_key, TRELLO_TOKEN: cred.api_token };
|
|
2150
|
+
const fullArgs = [...cliArgs, '--board', cfg.board, '--list', cfg.list, '--card', cfg.card];
|
|
2151
|
+
|
|
2152
|
+
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
2153
|
+
const result = spawnSync('npx', ['--yes', 'trello-cli', ...fullArgs], {
|
|
2154
|
+
env,
|
|
2155
|
+
encoding: 'utf-8',
|
|
2156
|
+
timeout: 30000,
|
|
2157
|
+
});
|
|
2158
|
+
|
|
2159
|
+
const stdoutStr = result.stdout || '';
|
|
2160
|
+
const stderrStr = result.stderr || '';
|
|
2161
|
+
const combinedOut = stdoutStr + stderrStr;
|
|
2162
|
+
|
|
2163
|
+
if (stdoutStr) process.stdout.write(stdoutStr);
|
|
2164
|
+
if (stderrStr) process.stderr.write(stderrStr);
|
|
2165
|
+
|
|
2166
|
+
if (result.status === 0) {
|
|
2167
|
+
return true;
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
if (combinedOut.includes('429') || combinedOut.includes('Rate limit exceeded') || combinedOut.includes('Too Many Requests') || combinedOut.includes('API_TOKEN_LIMIT_EXCEEDED') || combinedOut.includes('API_KEY_LIMIT_EXCEEDED')) {
|
|
2171
|
+
warn(`[Trello API] Rate limit hit (429). Waiting 10s before retry ${attempt}/${retries}...`);
|
|
2172
|
+
// Sleep for 10 seconds to satisfy the 100 requests / 10s window boundary
|
|
2173
|
+
spawnSync('sleep', ['10']);
|
|
2174
|
+
continue;
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
warn(`Trello CLI returned non-zero exit code (${result.status}). Command: awkit trello ${cliArgs.join(' ')}`);
|
|
2178
|
+
return false;
|
|
2179
|
+
}
|
|
2180
|
+
err('Trello CLI failed after multiple retries due to rate limits.');
|
|
2181
|
+
return false;
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2184
|
+
function trelloHelp() {
|
|
2185
|
+
log('');
|
|
2186
|
+
log(`${C.cyan}${C.bold}📋 Trello Commands${C.reset}`);
|
|
2187
|
+
log('');
|
|
2188
|
+
log(` ${C.green}awkit trello desc${C.reset} <text> Update card description`);
|
|
2189
|
+
log(` ${C.green}awkit trello comment${C.reset} <text> Add milestone comment to card`);
|
|
2190
|
+
log(` ${C.green}awkit trello item${C.reset} <name> Add checklist item (incomplete)`);
|
|
2191
|
+
log(` ${C.green}awkit trello complete${C.reset} <name> Mark checklist item ✅ complete`);
|
|
2192
|
+
log(` ${C.green}awkit trello block${C.reset} <reason> Label card Blocked + comment`);
|
|
2193
|
+
log(` ${C.green}awkit trello checklist${C.reset} <name> Create a new checklist on card`);
|
|
2194
|
+
log('');
|
|
2195
|
+
log(` ${C.gray}Credentials: env vars TRELLO_KEY and TRELLO_TOKEN${C.reset}`);
|
|
2196
|
+
log(` ${C.gray}Project config: .trello-config.json in CWD${C.reset}`);
|
|
2197
|
+
log('');
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2200
|
+
function cmdTrello(args) {
|
|
2201
|
+
const subCmd = args[0];
|
|
2202
|
+
const text = args.slice(1).join(' ');
|
|
2203
|
+
|
|
2204
|
+
if (!subCmd || subCmd === 'help') {
|
|
2205
|
+
trelloHelp();
|
|
2206
|
+
return;
|
|
2207
|
+
}
|
|
2208
|
+
|
|
2209
|
+
if (!text && subCmd !== 'help') {
|
|
2210
|
+
err(`Missing argument for 'trello ${subCmd}'. Usage: awkit trello ${subCmd} <text>`);
|
|
2211
|
+
return;
|
|
2212
|
+
}
|
|
2213
|
+
|
|
2214
|
+
switch (subCmd) {
|
|
2215
|
+
case 'desc':
|
|
2216
|
+
info(`Updating card description...`);
|
|
2217
|
+
trelloExec(['card:update', '--description', text]);
|
|
2218
|
+
break;
|
|
2219
|
+
|
|
2220
|
+
case 'comment':
|
|
2221
|
+
info(`Adding comment to card...`);
|
|
2222
|
+
trelloExec(['card:comment', '--text', text]);
|
|
2223
|
+
break;
|
|
2224
|
+
|
|
2225
|
+
case 'item':
|
|
2226
|
+
// trello-cli doesn't support adding checklist items natively.
|
|
2227
|
+
// We fall back to marking an item incomplete (which implicitly creates it in some versions)
|
|
2228
|
+
// or inform the user to use the REST API.
|
|
2229
|
+
info(`Adding checklist item: ${text}`);
|
|
2230
|
+
warn('Note: trello-cli may not support adding items. Use REST API if this fails.');
|
|
2231
|
+
trelloExec(['card:check-item', '--item', text, '--state', 'incomplete']);
|
|
2232
|
+
break;
|
|
2233
|
+
|
|
2234
|
+
case 'complete':
|
|
2235
|
+
info(`Marking item complete: ${text}`);
|
|
2236
|
+
trelloExec(['card:check-item', '--item', text, '--state', 'complete']);
|
|
2237
|
+
break;
|
|
2238
|
+
|
|
2239
|
+
case 'block':
|
|
2240
|
+
info(`Blocking card with reason...`);
|
|
2241
|
+
trelloExec(['card:label', '--label', 'Blocked']);
|
|
2242
|
+
trelloExec(['card:comment', '--text', `⚠️ BLOCKED: ${text}`]);
|
|
2243
|
+
break;
|
|
2244
|
+
|
|
2245
|
+
case 'checklist':
|
|
2246
|
+
info(`Creating checklist: ${text}`);
|
|
2247
|
+
trelloExec(['card:checklist', '-n', text]);
|
|
2248
|
+
break;
|
|
2249
|
+
|
|
2250
|
+
default:
|
|
2251
|
+
err(`Unknown trello subcommand: ${subCmd}`);
|
|
2252
|
+
trelloHelp();
|
|
2253
|
+
break;
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2014
2257
|
// ─── Auto-Update Checker ──────────────────────────────────────────────────────
|
|
2015
2258
|
|
|
2016
2259
|
function checkAutoUpdate() {
|
|
@@ -2056,66 +2299,71 @@ checkAutoUpdate();
|
|
|
2056
2299
|
|
|
2057
2300
|
const [, , command, ...args] = process.argv;
|
|
2058
2301
|
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2302
|
+
(async () => {
|
|
2303
|
+
switch (command) {
|
|
2304
|
+
case 'init':
|
|
2305
|
+
await cmdInit(args.includes('--force'));
|
|
2306
|
+
break;
|
|
2307
|
+
case 'install':
|
|
2308
|
+
// Parse platform from either first arg or --platform flag
|
|
2309
|
+
{
|
|
2310
|
+
const pIdx = args.indexOf('--platform');
|
|
2311
|
+
let platformArg = null;
|
|
2312
|
+
if (pIdx !== -1 && args[pIdx + 1]) {
|
|
2313
|
+
platformArg = args[pIdx + 1];
|
|
2314
|
+
} else if (args[0] && !args[0].startsWith('-')) {
|
|
2315
|
+
platformArg = args[0];
|
|
2316
|
+
}
|
|
2317
|
+
cmdInstall(platformArg);
|
|
2072
2318
|
}
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2319
|
+
break;
|
|
2320
|
+
case 'uninstall':
|
|
2321
|
+
cmdUninstall();
|
|
2322
|
+
break;
|
|
2323
|
+
case 'update':
|
|
2324
|
+
cmdUpdate();
|
|
2325
|
+
break;
|
|
2326
|
+
case 'sync':
|
|
2327
|
+
cmdSync();
|
|
2328
|
+
break;
|
|
2329
|
+
case 'status':
|
|
2330
|
+
cmdStatus();
|
|
2331
|
+
break;
|
|
2332
|
+
case 'harvest':
|
|
2333
|
+
cmdHarvest(args.includes('--dry-run'));
|
|
2334
|
+
break;
|
|
2335
|
+
case 'doctor':
|
|
2336
|
+
cmdDoctor();
|
|
2337
|
+
break;
|
|
2338
|
+
case 'enable-pack':
|
|
2339
|
+
cmdEnablePack(args[0]);
|
|
2340
|
+
break;
|
|
2341
|
+
case 'disable-pack':
|
|
2342
|
+
cmdDisablePack(args[0]);
|
|
2343
|
+
break;
|
|
2344
|
+
case 'list-packs':
|
|
2345
|
+
cmdListPacks();
|
|
2346
|
+
break;
|
|
2347
|
+
case 'version':
|
|
2348
|
+
case '--version':
|
|
2349
|
+
case '-v':
|
|
2350
|
+
cmdVersion();
|
|
2351
|
+
break;
|
|
2352
|
+
case 'lint':
|
|
2353
|
+
cmdLint();
|
|
2354
|
+
break;
|
|
2355
|
+
case 'trello':
|
|
2356
|
+
cmdTrello(args);
|
|
2357
|
+
break;
|
|
2358
|
+
case 'tg':
|
|
2359
|
+
case 'telegram':
|
|
2360
|
+
cmdTelegram(args);
|
|
2361
|
+
break;
|
|
2362
|
+
case 'help':
|
|
2363
|
+
case '--help':
|
|
2364
|
+
case '-h':
|
|
2365
|
+
default:
|
|
2366
|
+
cmdHelp();
|
|
2367
|
+
break;
|
|
2368
|
+
}
|
|
2369
|
+
})();
|
package/core/GEMINI.md
CHANGED
|
@@ -50,19 +50,22 @@ Mỗi skill tự xử lý gate logic riêng — xem SKILL.md của từng skill.
|
|
|
50
50
|
- AI models: Gemini 2.5+ only.
|
|
51
51
|
- Firebase: Firebase AI Logic SDK.
|
|
52
52
|
|
|
53
|
-
###
|
|
53
|
+
### 6-Gate Autonomous System (v12.1)
|
|
54
54
|
- orchestrator PHẢI triage complexity (TRIVIAL/MODERATE/COMPLEX) trước mọi task.
|
|
55
|
-
- COMPLEX tasks PHẢI qua
|
|
55
|
+
- COMPLEX tasks PHẢI qua 6 Gates tuần tự:
|
|
56
56
|
- Gate 1 (Spec): `brainstorm-agent` → BRIEF.md / spec document
|
|
57
|
+
- Gate 1.5 (Module Spec): `module-spec-writer` → per-module product specs (screens, flows, rules)
|
|
57
58
|
- Gate 2 (Architecture): `spec-gate` → design doc + user approve
|
|
58
59
|
- Gate 3 (Tasks): `symphony-enforcer` → tạo Symphony tickets
|
|
59
60
|
- Gate 4 (Execution): code theo ticket, đối chiếu design doc
|
|
60
61
|
- Gate 5 (Verification): `verification-gate` + `code-review`
|
|
62
|
+
- Gate 1.5 MANDATORY khi: COMPLEX + >3 modules hoặc port/migration projects.
|
|
63
|
+
- Gate 1.5 SKIP khi: TRIVIAL/MODERATE hoặc single-module projects.
|
|
61
64
|
- TRIVIAL tasks bypass → thẳng Gate 4.
|
|
62
65
|
- MODERATE tasks → Gate 3 + 4 + 5.
|
|
63
66
|
- AI tự detect gate state — user KHÔNG CẦN gọi workflow bằng tay.
|
|
64
67
|
- Trong lúc code, nếu cần sửa schema khác approved design → ⛔ DỪNG, quay Gate 2.
|
|
65
|
-
- Chi tiết: xem `orchestrator/SKILL.md` (triage) + `spec-gate/SKILL.md` (Gate 2).
|
|
68
|
+
- Chi tiết: xem `orchestrator/SKILL.md` (triage) + `module-spec-writer/SKILL.md` (Gate 1.5) + `spec-gate/SKILL.md` (Gate 2).
|
|
66
69
|
|
|
67
70
|
### NeuralMemory
|
|
68
71
|
- Brain = projectId. Switch trước mọi nmem call.
|
|
@@ -109,6 +112,16 @@ Khi AI cần tự quyết định mà không hỏi user:
|
|
|
109
112
|
- KHÔNG hỏi user về project structure.
|
|
110
113
|
- CODEBASE.md outdated → ghi chú "⚠️ dùng /codebase-sync".
|
|
111
114
|
|
|
115
|
+
### GitNexus (Code Intelligence)
|
|
116
|
+
- Project đã index (`.gitnexus/` tồn tại) → PHẢI dùng GitNexus tools.
|
|
117
|
+
- Trước khi edit symbol → `gitnexus_impact` check blast radius.
|
|
118
|
+
- Trước khi commit → `gitnexus_detect_changes()` verify scope.
|
|
119
|
+
- Risk HIGH/CRITICAL → PHẢI cảnh báo user trước khi sửa.
|
|
120
|
+
- Explore code lạ → ưu tiên `gitnexus_query` thay vì grep thủ công.
|
|
121
|
+
- Rename symbol → PHẢI dùng `gitnexus_rename` (dry_run trước).
|
|
122
|
+
- Index stale → cảnh báo "⚠️ chạy `npx gitnexus analyze`".
|
|
123
|
+
- Chi tiết: xem `gitnexus-intelligence/SKILL.md`.
|
|
124
|
+
|
|
112
125
|
### Two-Agent Flow (Conductor)
|
|
113
126
|
- Antigravity CHỦ ĐỘNG gọi `gemini -p "..." --approval-mode plan` khi cần tầm nhìn rộng.
|
|
114
127
|
- CLI dùng **quota pool riêng** → không ảnh hưởng Antigravity quota.
|
|
@@ -123,9 +136,10 @@ Khi AI cần tự quyết định mà không hỏi user:
|
|
|
123
136
|
## Routing
|
|
124
137
|
|
|
125
138
|
- **Execution order:** `symphony-orchestrator` → `awf-session-restore` → `nm-memory-sync` → `symphony-enforcer` → `orchestrator` (triage + gate-check) → action
|
|
126
|
-
- **Gate skills:** `orchestrator` (triage) → `brainstorm-agent` (G1) → `spec-gate` (G2) → `symphony-enforcer` (G3) → `verification-gate` (G5)
|
|
139
|
+
- **Gate skills:** `orchestrator` (triage) → `brainstorm-agent` (G1) → `module-spec-writer` (G1.5) → `spec-gate` (G2) → `symphony-enforcer` (G3) → `verification-gate` (G5)
|
|
140
|
+
- **Code intelligence:** `gitnexus-intelligence` (impact analysis, blast radius, safe refactoring)
|
|
127
141
|
- **Skill catalog:** xem `orchestrator/SKILL.md`
|
|
128
|
-
- **Workflows:** 75+ (`/xxx`). Core: `/init` `/code` `/debug` `/recap` `/next` `/todo`
|
|
142
|
+
- **Workflows:** 75+ (`/xxx`). Core: `/init` `/code` `/debug` `/recap` `/next` `/todo` `/gitnexus`
|
|
129
143
|
- **Shortcuts:** `/todo` `/done` `/next`
|
|
130
144
|
|
|
131
145
|
---
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leejungkiin/awkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.7",
|
|
4
4
|
"description": "Antigravity Workflow Kit. Unified AI agent orchestration system.",
|
|
5
5
|
"main": "bin/awk.js",
|
|
6
6
|
"bin": {
|
|
@@ -34,8 +34,7 @@
|
|
|
34
34
|
"templates/",
|
|
35
35
|
"docs/",
|
|
36
36
|
"README.md",
|
|
37
|
-
"CHANGELOG.md"
|
|
38
|
-
"VERSION"
|
|
37
|
+
"CHANGELOG.md"
|
|
39
38
|
],
|
|
40
39
|
"dependencies": {
|
|
41
40
|
"@leejungkiin/awkit-symphony": "^0.1.0",
|
package/skills/CATALOG.md
CHANGED
|
@@ -31,6 +31,10 @@
|
|
|
31
31
|
| 11 | `awf-context-help` | `auto` | `/help`, stuck | — | — | ✅ Active |
|
|
32
32
|
| 12 | `auto-save` | `auto` | Session end | — | — | ✅ Background |
|
|
33
33
|
| 13 | `awf-version-tracker` | `auto` | Skill changes | — | — | ✅ Background |
|
|
34
|
+
| 14 | `module-spec-writer` | `auto` | Gate 1.5 check fail | 1.5 | 1.0.0 | ✅ Active |
|
|
35
|
+
| 15 | `spec-gate` | `auto` | Gate 2 check fail | 2 | 1.0.0 | ✅ Active |
|
|
36
|
+
| 16 | `visual-design-gate` | `auto` | Gate 2.5 check fail | 2.5 | 1.0.0 | ✅ Active |
|
|
37
|
+
| 17 | `trello-sync` | `auto` | Always | 2 | 3.0.0 | ✅ Active |
|
|
34
38
|
|
|
35
39
|
---
|
|
36
40
|
|