@leejungkiin/awkit 1.3.8 → 1.4.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.
Files changed (33) hide show
  1. package/bin/awk.js +204 -52
  2. package/core/AGENTS.md +38 -0
  3. package/core/GEMINI.md.bak +126 -199
  4. package/package.json +1 -1
  5. package/skills/awf-session-restore/SKILL.md +12 -2
  6. package/skills/brainstorm-agent/SKILL.md +11 -8
  7. package/skills/gitnexus/gitnexus-cli/SKILL.md +82 -0
  8. package/skills/gitnexus/gitnexus-debugging/SKILL.md +89 -0
  9. package/skills/gitnexus/gitnexus-exploring/SKILL.md +78 -0
  10. package/skills/gitnexus/gitnexus-guide/SKILL.md +64 -0
  11. package/skills/gitnexus/gitnexus-impact-analysis/SKILL.md +97 -0
  12. package/skills/gitnexus/gitnexus-refactoring/SKILL.md +121 -0
  13. package/skills/nm-memory-sync/SKILL.md +14 -1
  14. package/skills/orchestrator/SKILL.md +0 -38
  15. package/skills/ship-to-code/SKILL.md +115 -0
  16. package/skills/single-flow-task-execution/SKILL.md +409 -0
  17. package/skills/single-flow-task-execution/code-quality-reviewer-prompt.md +20 -0
  18. package/skills/single-flow-task-execution/implementer-prompt.md +78 -0
  19. package/skills/single-flow-task-execution/spec-reviewer-prompt.md +61 -0
  20. package/skills/symphony-enforcer/SKILL.md +36 -18
  21. package/skills/trello-sync/SKILL.md +25 -17
  22. package/templates/CODEBASE.md +26 -42
  23. package/templates/configs/trello-config.json +2 -2
  24. package/templates/project-identity/android.json +10 -0
  25. package/templates/project-identity/backend-nestjs.json +10 -0
  26. package/templates/project-identity/expo.json +10 -0
  27. package/templates/project-identity/ios.json +10 -0
  28. package/templates/project-identity/web-nextjs.json +10 -0
  29. package/templates/workflow_dual_mode_template.md +5 -5
  30. package/workflows/_uncategorized/conductor-codex.md +125 -0
  31. package/workflows/_uncategorized/conductor.md +97 -0
  32. package/workflows/_uncategorized/trello-sync.md +52 -0
  33. package/workflows/quality/visual-debug.md +66 -12
package/bin/awk.js CHANGED
@@ -290,35 +290,87 @@ function checkSymphony({ silent = false } = {}) {
290
290
  }
291
291
  }
292
292
 
293
- function cmdInstall(platformArg) {
293
+ function cmdInstall(args = []) {
294
294
  log('');
295
295
  log(`${C.cyan}${C.bold}╔══════════════════════════════════════════════════════════╗${C.reset}`);
296
296
  log(`${C.cyan}${C.bold}║ 🚀 AWK v${AWK_VERSION} — Antigravity Workflow Kit ║${C.reset}`);
297
297
  log(`${C.cyan}${C.bold}╚══════════════════════════════════════════════════════════╝${C.reset}`);
298
298
  log('');
299
299
 
300
- // Platform selection
301
- let platform = platformArg || getActivePlatform();
300
+ const isUpdate = args.includes('--update');
301
+ let selectedPlatforms = [];
302
302
 
303
- if (!PLATFORMS[platform]) {
304
- err(`Unknown platform: ${platform}.`);
305
- return;
303
+ if (args.includes('--all') || args.includes('-a') || args.includes('all')) {
304
+ selectedPlatforms = Object.keys(PLATFORMS);
305
+ } else {
306
+ if (args.includes('--gemini') || args.includes('-g') || args.includes('antigravity')) selectedPlatforms.push('antigravity');
307
+ if (args.includes('--claude') || args.includes('-c') || args.includes('cline')) selectedPlatforms.push('cline');
308
+ if (args.includes('--codex') || args.includes('-x')) selectedPlatforms.push('codex');
309
+
310
+ const pIdx = args.indexOf('--platform');
311
+ let legacyArg = null;
312
+ if (pIdx !== -1 && args[pIdx + 1]) {
313
+ legacyArg = args[pIdx + 1];
314
+ } else if (args.length > 0 && !args[0].startsWith('-') && args[0] !== 'all' && args[0] !== '--update') {
315
+ legacyArg = args[0];
316
+ }
317
+
318
+ if (legacyArg && PLATFORMS[legacyArg] && !selectedPlatforms.includes(legacyArg)) {
319
+ selectedPlatforms.push(legacyArg);
320
+ }
321
+ }
322
+
323
+ if (selectedPlatforms.length === 0) {
324
+ if (isUpdate) {
325
+ selectedPlatforms = [getActivePlatform()];
326
+ } else {
327
+ log(`${C.cyan}Select platforms to install (e.g., type "1,2", "all", or "1,2,3"):${C.reset}`);
328
+ log(` 1. Gemini Code Assist (antigravity)`);
329
+ log(` 2. Claude Code (cline - local project)`);
330
+ log(` 3. Codex CLI (codex)`);
331
+ log(` 4. All of the above`);
332
+ const choice = promptChoice('Choice', '4').trim().toLowerCase();
333
+
334
+ if (choice === '4' || choice === 'all' || choice === '') {
335
+ selectedPlatforms = Object.keys(PLATFORMS);
336
+ } else {
337
+ if (choice.includes('1')) selectedPlatforms.push('antigravity');
338
+ if (choice.includes('2')) selectedPlatforms.push('cline');
339
+ if (choice.includes('3')) selectedPlatforms.push('codex');
340
+ }
341
+ }
306
342
  }
307
343
 
308
- activePlatform = platform;
309
- savePlatform(platform);
344
+ if (selectedPlatforms.length === 0) {
345
+ selectedPlatforms = [getActivePlatform()];
346
+ }
310
347
 
311
- const plat = PLATFORMS[platform];
312
- const target = plat.globalRoot;
348
+ log(`${C.cyan}Installing to: ${selectedPlatforms.map(p => PLATFORMS[p].name).join(', ')}${C.reset}`);
313
349
 
314
- info(`Installing for ${C.bold}${plat.name}${C.reset}...`);
315
- log('');
350
+ // Main installation loop
351
+ for (const platform of selectedPlatforms) {
352
+ if (!PLATFORMS[platform]) {
353
+ err(`Unknown platform: ${platform}.`);
354
+ continue;
355
+ }
316
356
 
317
- // 0. Check Symphony dependency
318
- info('Checking dependencies...');
319
- checkSymphony();
357
+ activePlatform = platform;
358
+ if (platform === selectedPlatforms[0]) {
359
+ savePlatform(platform); // Store primary platform
360
+ }
361
+
362
+ const plat = PLATFORMS[platform];
363
+ const target = plat.globalRoot;
364
+
365
+ log('');
366
+ info(`Installing for ${C.bold}${plat.name}${C.reset}...`);
367
+ log('');
368
+
369
+ // 0. Check Symphony dependency
370
+ info('Checking dependencies...');
371
+ checkSymphony({ silent: platform !== selectedPlatforms[0] });
320
372
 
321
- // 1. Ensure target dirs exist
373
+ // 1. Ensure target dirs exist
322
374
  info('Creating directories...');
323
375
  const dirKeys = Object.values(plat.dirs);
324
376
  for (const dir of dirKeys) {
@@ -462,6 +514,7 @@ function cmdInstall(platformArg) {
462
514
  }
463
515
  log(`${C.cyan}👉 Run 'awkit doctor' to verify installation.${C.reset}`);
464
516
  log('');
517
+ } // End of platform loop
465
518
  }
466
519
 
467
520
  /**
@@ -570,7 +623,7 @@ function cmdUpdate() {
570
623
  }
571
624
  log('');
572
625
  info('Applying new workflows, skills & schemas...');
573
- cmdInstall();
626
+ cmdInstall(['--update']);
574
627
  return;
575
628
  }
576
629
 
@@ -579,7 +632,7 @@ function cmdUpdate() {
579
632
  ok(`Already on latest version (v${AWK_VERSION}) — could not verify with npm`);
580
633
  } else {
581
634
  info(`Upgrading from v${installedVersion} → v${AWK_VERSION} (local only, npm unreachable)`);
582
- cmdInstall();
635
+ cmdInstall(['--update']);
583
636
  }
584
637
  }
585
638
 
@@ -1327,6 +1380,46 @@ function cmdSync() {
1327
1380
  log('');
1328
1381
  }
1329
1382
 
1383
+ async function cmdAdmin() {
1384
+ info('Mở Symphony Dashboard...');
1385
+ try {
1386
+ const http = require('http');
1387
+ const isRunning = await new Promise((resolve) => {
1388
+ const req = http.get('http://localhost:3100', (res) => {
1389
+ resolve(true);
1390
+ }).on('error', () => {
1391
+ resolve(false);
1392
+ });
1393
+ req.setTimeout(1000, () => {
1394
+ req.destroy();
1395
+ resolve(false);
1396
+ });
1397
+ });
1398
+
1399
+ if (!isRunning) {
1400
+ info('Symphony service chưa chạy. Đang khởi động ngầm...');
1401
+ const { spawn } = require('child_process');
1402
+ const child = spawn('symphony', ['start'], {
1403
+ detached: true,
1404
+ stdio: 'ignore'
1405
+ });
1406
+ child.unref();
1407
+
1408
+ info('Vui lòng đợi 3 giây để service khởi động...');
1409
+ await new Promise(r => setTimeout(r, 3000));
1410
+ }
1411
+
1412
+ try {
1413
+ execSync('symphony dashboard', { stdio: 'inherit' });
1414
+ } catch (_) {
1415
+ err('Không thể mở Symphony Dashboard.');
1416
+ }
1417
+ } catch (e) {
1418
+ err('Không thể khởi động Symphony Dashboard.');
1419
+ dim('Vui lòng cài đặt: npm install -g @leejungkiin/awkit-symphony');
1420
+ }
1421
+ }
1422
+
1330
1423
  function cmdHelp() {
1331
1424
  const line = `${C.gray}${'─'.repeat(56)}${C.reset}`;
1332
1425
  log('');
@@ -1362,6 +1455,12 @@ function cmdHelp() {
1362
1455
  log(` ${C.green}sync${C.reset} Full sync: harvest + install (one shot)`);
1363
1456
  log('');
1364
1457
 
1458
+ // Symphony
1459
+ log(`${C.bold}🎶 Symphony${C.reset}`);
1460
+ log(line);
1461
+ log(` ${C.green}admin${C.reset} Khởi động Symphony Dashboard`);
1462
+ log('');
1463
+
1365
1464
  // Packs
1366
1465
  log(`${C.bold}📦 Skill Packs${C.reset}`);
1367
1466
  log(line);
@@ -1604,7 +1703,12 @@ function buildProjectIdentity(projectName, projectType, cwd, date) {
1604
1703
  };
1605
1704
 
1606
1705
  return {
1706
+ _comments: {
1707
+ projectId: 'Auto-generated. DO NOT change — used by Symphony for task scoping.',
1708
+ trello: 'Fill in your Trello board/list/card names. Run "awkit trello info" to verify.',
1709
+ },
1607
1710
  projectName,
1711
+ projectId: bundleBase,
1608
1712
  projectType: cfg.projectType,
1609
1713
  ...(cfg.bundleIdentifier && { bundleIdentifier: cfg.bundleIdentifier }),
1610
1714
  ...(cfg.packageName && { packageName: cfg.packageName }),
@@ -1616,6 +1720,11 @@ function buildProjectIdentity(projectName, projectType, cwd, date) {
1616
1720
  features: ['analytics', 'crashlytics', 'remote-config', 'auth'],
1617
1721
  },
1618
1722
  },
1723
+ trello: {
1724
+ board: 'Your Board Name',
1725
+ list: 'Your List Name',
1726
+ card: 'Your Card Name',
1727
+ },
1619
1728
  projectStage: 'development',
1620
1729
  codingStandards: cfg.codingStandards,
1621
1730
  projectGoals: [],
@@ -1784,25 +1893,38 @@ async function cmdInit(forceFlag = false) {
1784
1893
  ok(`${workspaceName} created`);
1785
1894
  }
1786
1895
 
1787
- // ── 3.5. .trello-config.json ───────────────────────────────────────────────
1896
+ // ── 3.5. Trello config (embedded in .project-identity) ──────────────────────
1897
+ // Migration: If .trello-config.json exists but identity has no trello key, merge it in
1788
1898
  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)');
1899
+ if (fs.existsSync(trelloConfigPath)) {
1900
+ try {
1901
+ const oldCfg = JSON.parse(fs.readFileSync(trelloConfigPath, 'utf8'));
1902
+ const currentIdentity = JSON.parse(fs.readFileSync(identityPath, 'utf8'));
1903
+ if (!currentIdentity.trello) {
1904
+ currentIdentity.trello = {
1905
+ board: oldCfg.BOARD_NAME || oldCfg.board || 'Your Board Name',
1906
+ list: oldCfg.LIST_NAME || oldCfg.list || 'Your List',
1907
+ card: oldCfg.CARD_NAME || oldCfg.card || 'Your Card',
1908
+ };
1909
+ fs.writeFileSync(identityPath, JSON.stringify(currentIdentity, null, 2) + '\n');
1910
+ ok('Migrated Trello config from .trello-config.json → .project-identity');
1911
+ dim('You can safely delete .trello-config.json now.');
1912
+ }
1913
+ } catch (_) { /* ignore migration errors */ }
1791
1914
  } 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
- }
1915
+ // Ensure identity has trello placeholder if not already present
1916
+ try {
1917
+ const currentIdentity = JSON.parse(fs.readFileSync(identityPath, 'utf8'));
1918
+ if (!currentIdentity.trello) {
1919
+ currentIdentity.trello = {
1920
+ board: 'Your Board Name',
1921
+ list: 'Your List',
1922
+ card: 'Your Card',
1923
+ };
1924
+ fs.writeFileSync(identityPath, JSON.stringify(currentIdentity, null, 2) + '\n');
1925
+ ok('Added Trello config placeholder to .project-identity');
1926
+ }
1927
+ } catch (_) { /* ignore */ }
1806
1928
  }
1807
1929
 
1808
1930
  const trelloCred = trelloLoadCredentials();
@@ -1894,7 +2016,7 @@ async function cmdInit(forceFlag = false) {
1894
2016
  log('');
1895
2017
  dim(`Type: ${projectType}`);
1896
2018
  dim(`Firebase: analytics, crashlytics, remote-config, auth`);
1897
- dim(`Files: .project-identity, ${workspaceName}, CODEBASE.md, .trello-config.json`);
2019
+ dim(`Files: .project-identity, ${workspaceName}, CODEBASE.md`);
1898
2020
  dim(`Symphony: task tracking ready)`);
1899
2021
  log('');
1900
2022
  log(`${C.cyan}👉 Open ${workspaceName} in VS Code to get started.${C.reset}`);
@@ -2111,10 +2233,28 @@ function trelloLoadCredentials() {
2111
2233
  }
2112
2234
 
2113
2235
  /**
2114
- * Load Trello project config from .trello-config.json in CWD.
2236
+ * Load Trello project config from .project-identity (preferred) or .trello-config.json (fallback).
2115
2237
  * Returns { board, list, card } or null.
2116
2238
  */
2117
2239
  function trelloLoadProjectConfig() {
2240
+ // 1. Try .project-identity → trello key
2241
+ const identityPath = path.join(process.cwd(), '.project-identity');
2242
+ if (fs.existsSync(identityPath)) {
2243
+ try {
2244
+ const identity = JSON.parse(fs.readFileSync(identityPath, 'utf8'));
2245
+ if (identity.trello) {
2246
+ const t = identity.trello;
2247
+ const board = t.board || t.BOARD_NAME;
2248
+ const list = t.list || t.LIST_NAME;
2249
+ const card = t.card || t.CARD_NAME;
2250
+ if (board && list && card) {
2251
+ return { board, list, card };
2252
+ }
2253
+ }
2254
+ } catch (_) { /* ignore parse error */ }
2255
+ }
2256
+
2257
+ // 2. Fallback: .trello-config.json
2118
2258
  const configPath = path.join(process.cwd(), '.trello-config.json');
2119
2259
  if (!fs.existsSync(configPath)) return null;
2120
2260
  try {
@@ -2141,8 +2281,8 @@ function trelloExec(cliArgs, retries = 3) {
2141
2281
  return false;
2142
2282
  }
2143
2283
  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.`);
2284
+ err('Trello config not found. Add "trello" key to .project-identity or create .trello-config.json.');
2285
+ log(` Run ${C.cyan}awkit init${C.reset} to set up, or add manually to .project-identity.`);
2146
2286
  return false;
2147
2287
  }
2148
2288
 
@@ -2191,9 +2331,12 @@ function trelloHelp() {
2191
2331
  log(` ${C.green}awkit trello complete${C.reset} <name> Mark checklist item ✅ complete`);
2192
2332
  log(` ${C.green}awkit trello block${C.reset} <reason> Label card Blocked + comment`);
2193
2333
  log(` ${C.green}awkit trello checklist${C.reset} <name> Create a new checklist on card`);
2334
+ log(` ${C.green}awkit trello info${C.reset} Show card details`);
2335
+ log(` ${C.green}awkit trello checklists${C.reset} List checklists on card`);
2336
+ log(` ${C.green}awkit trello comments${C.reset} List comments on card`);
2194
2337
  log('');
2195
2338
  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}`);
2339
+ log(` ${C.gray}Project config: "trello" key in .project-identity (fallback: .trello-config.json)${C.reset}`);
2197
2340
  log('');
2198
2341
  }
2199
2342
 
@@ -2206,12 +2349,28 @@ function cmdTrello(args) {
2206
2349
  return;
2207
2350
  }
2208
2351
 
2209
- if (!text) {
2352
+ const noTextCmds = ['info', 'checklists', 'comments'];
2353
+ if (!text && !noTextCmds.includes(subCmd)) {
2210
2354
  err(`Missing argument for 'trello ${subCmd}'. Usage: awkit trello ${subCmd} <text>`);
2211
2355
  return;
2212
2356
  }
2213
2357
 
2214
2358
  switch (subCmd) {
2359
+ case 'info':
2360
+ info(`Fetching card details...`);
2361
+ trelloExec(['card:show']);
2362
+ break;
2363
+
2364
+ case 'checklists':
2365
+ info(`Fetching card checklists...`);
2366
+ trelloExec(['card:checklists']);
2367
+ break;
2368
+
2369
+ case 'comments':
2370
+ info(`Fetching card comments...`);
2371
+ trelloExec(['card:comments']);
2372
+ break;
2373
+
2215
2374
  case 'desc':
2216
2375
  info(`Updating card description...`);
2217
2376
  trelloExec(['card:update', '--description', text]);
@@ -2344,17 +2503,7 @@ const [, , command, ...args] = process.argv;
2344
2503
  await cmdInit(args.includes('--force'));
2345
2504
  break;
2346
2505
  case 'install':
2347
- // Parse platform from either first arg or --platform flag
2348
- {
2349
- const pIdx = args.indexOf('--platform');
2350
- let platformArg = null;
2351
- if (pIdx !== -1 && args[pIdx + 1]) {
2352
- platformArg = args[pIdx + 1];
2353
- } else if (args[0] && !args[0].startsWith('-')) {
2354
- platformArg = args[0];
2355
- }
2356
- cmdInstall(platformArg);
2357
- }
2506
+ cmdInstall(args);
2358
2507
  break;
2359
2508
  case 'uninstall':
2360
2509
  cmdUninstall();
@@ -2398,6 +2547,9 @@ const [, , command, ...args] = process.argv;
2398
2547
  case 'telegram':
2399
2548
  cmdTelegram(args);
2400
2549
  break;
2550
+ case 'admin':
2551
+ cmdAdmin();
2552
+ break;
2401
2553
  case 'help':
2402
2554
  case '--help':
2403
2555
  case '-h':
package/core/AGENTS.md ADDED
@@ -0,0 +1,38 @@
1
+ # Agent Instructions
2
+
3
+ This project uses **Symphony** for task management and issue tracking.
4
+
5
+ ## Quick Reference
6
+
7
+ ```bash
8
+ symphony_available_tasks # Find available work
9
+ symphony_claim_task <id> # Claim a task
10
+ symphony_report_progress <id> # Report progress
11
+ symphony_complete_task <id> # Complete work
12
+ symphony_status # Check system status
13
+ ```
14
+
15
+ ## Landing the Plane (Session Completion)
16
+
17
+ **When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
18
+
19
+ **MANDATORY WORKFLOW:**
20
+
21
+ 1. **File issues for remaining work** — Create tasks for anything that needs follow-up
22
+ 2. **Run quality gates** (if code changed) — Tests, linters, builds
23
+ 3. **Update task status** — Complete finished work, update in-progress items
24
+ 4. **PUSH TO REMOTE** — This is MANDATORY:
25
+ ```bash
26
+ git pull --rebase
27
+ git push
28
+ git status # MUST show "up to date with origin"
29
+ ```
30
+ 5. **Clean up** — Clear stashes, prune remote branches
31
+ 6. **Verify** — All changes committed AND pushed
32
+ 7. **Hand off** — Provide context for next session
33
+
34
+ **CRITICAL RULES:**
35
+ - Work is NOT complete until `git push` succeeds
36
+ - NEVER stop before pushing — that leaves work stranded locally
37
+ - NEVER say "ready to push when you are" — YOU must push
38
+ - If push fails, resolve and retry until it succeeds