myaidev-method 0.3.3 → 0.3.5

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 (132) hide show
  1. package/.claude-plugin/plugin.json +0 -1
  2. package/.env.example +5 -4
  3. package/CHANGELOG.md +2 -2
  4. package/CONTENT_CREATION_GUIDE.md +489 -3211
  5. package/DEVELOPER_USE_CASES.md +1 -1
  6. package/MODULAR_INSTALLATION.md +2 -2
  7. package/README.md +39 -33
  8. package/TECHNICAL_ARCHITECTURE.md +1 -1
  9. package/USER_GUIDE.md +242 -190
  10. package/agents/content-editor-agent.md +90 -0
  11. package/agents/content-planner-agent.md +97 -0
  12. package/agents/content-research-agent.md +62 -0
  13. package/agents/content-seo-agent.md +101 -0
  14. package/agents/content-writer-agent.md +69 -0
  15. package/agents/infographic-analyzer-agent.md +63 -0
  16. package/agents/infographic-designer-agent.md +72 -0
  17. package/bin/cli.js +777 -535
  18. package/{content-rules.example.md → content-rules-example.md} +2 -2
  19. package/dist/mcp/health-check.js +82 -68
  20. package/dist/mcp/mcp-config.json +8 -0
  21. package/dist/mcp/openstack-server.js +1746 -1262
  22. package/dist/server/.tsbuildinfo +1 -1
  23. package/extension.json +21 -4
  24. package/package.json +181 -184
  25. package/skills/company-config/SKILL.md +133 -0
  26. package/skills/configure/SKILL.md +1 -1
  27. package/skills/myai-configurator/SKILL.md +77 -0
  28. package/skills/myai-configurator/content-creation-configurator/SKILL.md +516 -0
  29. package/skills/myai-configurator/content-maintenance-configurator/SKILL.md +397 -0
  30. package/skills/myai-content-enrichment/SKILL.md +114 -0
  31. package/skills/myai-content-ideation/SKILL.md +288 -0
  32. package/skills/myai-content-ideation/evals/evals.json +182 -0
  33. package/skills/myai-content-production-coordinator/SKILL.md +946 -0
  34. package/skills/{content-rules-setup → myai-content-rules-setup}/SKILL.md +1 -1
  35. package/skills/{content-verifier → myai-content-verifier}/SKILL.md +1 -1
  36. package/skills/myai-content-writer/SKILL.md +333 -0
  37. package/skills/myai-content-writer/agents/editor-agent.md +138 -0
  38. package/skills/myai-content-writer/agents/planner-agent.md +121 -0
  39. package/skills/myai-content-writer/agents/research-agent.md +83 -0
  40. package/skills/myai-content-writer/agents/seo-agent.md +139 -0
  41. package/skills/myai-content-writer/agents/visual-planner-agent.md +110 -0
  42. package/skills/myai-content-writer/agents/writer-agent.md +85 -0
  43. package/skills/{infographic → myai-infographic}/SKILL.md +1 -1
  44. package/skills/myai-proprietary-content-verifier/SKILL.md +175 -0
  45. package/skills/myai-proprietary-content-verifier/evals/evals.json +36 -0
  46. package/skills/myai-skill-builder/SKILL.md +699 -0
  47. package/skills/myai-skill-builder/agents/analyzer-agent.md +137 -0
  48. package/skills/myai-skill-builder/agents/comparator-agent.md +77 -0
  49. package/skills/myai-skill-builder/agents/grader-agent.md +103 -0
  50. package/skills/myai-skill-builder/assets/eval_review.html +131 -0
  51. package/skills/myai-skill-builder/references/schemas.md +211 -0
  52. package/skills/myai-skill-builder/scripts/aggregate_benchmark.py +190 -0
  53. package/skills/myai-skill-builder/scripts/generate_review.py +381 -0
  54. package/skills/myai-skill-builder/scripts/package_skill.py +91 -0
  55. package/skills/myai-skill-builder/scripts/run_eval.py +105 -0
  56. package/skills/myai-skill-builder/scripts/run_loop.py +211 -0
  57. package/skills/myai-skill-builder/scripts/utils.py +123 -0
  58. package/skills/myai-visual-generator/SKILL.md +125 -0
  59. package/skills/myai-visual-generator/evals/evals.json +155 -0
  60. package/skills/myai-visual-generator/references/infographic-pipeline.md +73 -0
  61. package/skills/myai-visual-generator/references/research-visuals.md +57 -0
  62. package/skills/myai-visual-generator/references/services.md +89 -0
  63. package/skills/myai-visual-generator/scripts/visual-generation-utils.js +1272 -0
  64. package/skills/myaidev-analyze/agents/dependency-mapper-agent.md +236 -0
  65. package/skills/myaidev-analyze/agents/pattern-detector-agent.md +240 -0
  66. package/skills/myaidev-analyze/agents/structure-scanner-agent.md +171 -0
  67. package/skills/myaidev-analyze/agents/tech-profiler-agent.md +291 -0
  68. package/skills/myaidev-architect/agents/compliance-checker-agent.md +287 -0
  69. package/skills/myaidev-architect/agents/requirements-analyst-agent.md +194 -0
  70. package/skills/myaidev-architect/agents/system-designer-agent.md +315 -0
  71. package/skills/myaidev-coder/agents/implementer-agent.md +185 -0
  72. package/skills/myaidev-coder/agents/integration-agent.md +168 -0
  73. package/skills/myaidev-coder/agents/pattern-scanner-agent.md +161 -0
  74. package/skills/myaidev-coder/agents/self-reviewer-agent.md +168 -0
  75. package/skills/myaidev-debug/agents/fix-agent-debug.md +317 -0
  76. package/skills/myaidev-debug/agents/hypothesis-agent.md +226 -0
  77. package/skills/myaidev-debug/agents/investigator-agent.md +250 -0
  78. package/skills/myaidev-debug/agents/symptom-collector-agent.md +231 -0
  79. package/skills/myaidev-documenter/agents/code-reader-agent.md +172 -0
  80. package/skills/myaidev-documenter/agents/doc-validator-agent.md +174 -0
  81. package/skills/myaidev-documenter/agents/doc-writer-agent.md +379 -0
  82. package/skills/myaidev-figma/SKILL.md +212 -0
  83. package/skills/myaidev-figma/capture.js +133 -0
  84. package/skills/myaidev-figma/crawl.js +130 -0
  85. package/skills/myaidev-figma-configure/SKILL.md +130 -0
  86. package/skills/myaidev-migrate/agents/migration-planner-agent.md +237 -0
  87. package/skills/myaidev-migrate/agents/migration-writer-agent.md +248 -0
  88. package/skills/myaidev-migrate/agents/schema-analyzer-agent.md +190 -0
  89. package/skills/myaidev-performance/agents/benchmark-agent.md +281 -0
  90. package/skills/myaidev-performance/agents/optimizer-agent.md +277 -0
  91. package/skills/myaidev-performance/agents/profiler-agent.md +252 -0
  92. package/skills/myaidev-refactor/agents/refactor-executor-agent.md +221 -0
  93. package/skills/myaidev-refactor/agents/refactor-planner-agent.md +213 -0
  94. package/skills/myaidev-refactor/agents/regression-guard-agent.md +242 -0
  95. package/skills/myaidev-refactor/agents/smell-detector-agent.md +233 -0
  96. package/skills/myaidev-reviewer/agents/auto-fixer-agent.md +238 -0
  97. package/skills/myaidev-reviewer/agents/code-analyst-agent.md +220 -0
  98. package/skills/myaidev-reviewer/agents/security-scanner-agent.md +262 -0
  99. package/skills/myaidev-tester/agents/coverage-analyst-agent.md +163 -0
  100. package/skills/myaidev-tester/agents/tdd-driver-agent.md +242 -0
  101. package/skills/myaidev-tester/agents/test-runner-agent.md +176 -0
  102. package/skills/myaidev-tester/agents/test-strategist-agent.md +154 -0
  103. package/skills/myaidev-tester/agents/test-writer-agent.md +242 -0
  104. package/skills/myaidev-workflow/agents/analyzer-agent.md +317 -0
  105. package/skills/myaidev-workflow/agents/coordinator-agent.md +253 -0
  106. package/skills/openstack-manager/SKILL.md +1 -1
  107. package/skills/payloadcms-publisher/SKILL.md +141 -77
  108. package/skills/payloadcms-publisher/references/field-mapping.md +142 -0
  109. package/skills/payloadcms-publisher/references/lexical-format.md +97 -0
  110. package/skills/security-auditor/SKILL.md +1 -1
  111. package/src/cli/commands/addon.js +184 -123
  112. package/src/config/workflows.js +172 -228
  113. package/src/lib/ascii-banner.js +197 -182
  114. package/src/lib/{content-coordinator.js → content-production-coordinator.js} +649 -459
  115. package/src/lib/installation-detector.js +93 -59
  116. package/src/lib/payloadcms-utils.js +285 -510
  117. package/src/lib/update-manager.js +120 -61
  118. package/src/lib/workflow-installer.js +55 -0
  119. package/src/mcp/health-check.js +82 -68
  120. package/src/mcp/openstack-server.js +1746 -1262
  121. package/src/scripts/configure-visual-apis.js +224 -173
  122. package/src/scripts/configure-wordpress-mcp.js +96 -66
  123. package/src/scripts/init/install.js +109 -85
  124. package/src/scripts/init-project.js +138 -67
  125. package/src/scripts/utils/write-content.js +67 -52
  126. package/src/scripts/wordpress/publish-to-wordpress.js +128 -128
  127. package/src/templates/claude/CLAUDE.md +131 -0
  128. package/hooks/hooks.json +0 -26
  129. package/skills/content-coordinator/SKILL.md +0 -130
  130. package/skills/content-enrichment/SKILL.md +0 -80
  131. package/skills/content-writer/SKILL.md +0 -285
  132. package/skills/visual-generator/SKILL.md +0 -140
@@ -17,7 +17,7 @@ import inquirer from 'inquirer';
17
17
  import fs from 'fs-extra';
18
18
  import path from 'path';
19
19
  import os from 'os';
20
- import { execSync } from 'child_process';
20
+
21
21
  import matter from 'gray-matter';
22
22
  import { isAuthenticated, getAuthToken, getAuthData, authFetch } from '../../lib/auth-helper.js';
23
23
  import { validateSkill, generateSlug } from '../../lib/skill-validator.js';
@@ -215,11 +215,12 @@ async function installSkill(name, options) {
215
215
  const { location } = await inquirer.prompt([{
216
216
  type: 'list',
217
217
  name: 'location',
218
- message: 'Install location:',
218
+ message: 'Where do you want to install this skill?',
219
219
  choices: [
220
- { name: `Project ${chalk.gray('.claude/skills/')}`, value: 'project' },
221
- { name: `Global ${chalk.gray('~/.claude/skills/')}`, value: 'global' },
220
+ { name: `Project ${chalk.gray('.claude/skills/ (this project only)')}`, value: 'project' },
221
+ { name: `Global ${chalk.gray('~/.claude/skills/ (available everywhere)')}`, value: 'global' },
222
222
  ],
223
+ default: 'project',
223
224
  }]);
224
225
  targetDir = location === 'project' ? projectSkillsDir() : globalSkillsDir();
225
226
  }
@@ -227,17 +228,21 @@ async function installSkill(name, options) {
227
228
  const slug = skill.slug || skill.name.toLowerCase().replace(/\s+/g, '-');
228
229
  const installPath = path.join(targetDir, slug);
229
230
 
230
- // Download
231
+ // Download (request JSON to get supporting files if available)
231
232
  const dlSpinner = ora(`Downloading ${chalk.cyan(skill.name)}...`).start();
232
- const dlRes = await fetchWithTimeout(`${API_BASE}/${skill.id}/download`);
233
+ const dlRes = await fetchWithTimeout(`${API_BASE}/${skill.id}/download`, {
234
+ headers: { 'Accept': 'application/json' },
235
+ });
233
236
  if (!dlRes.ok) throw new Error(`Download failed: ${dlRes.status}`);
234
237
 
235
238
  // Handle both JSON and raw markdown responses
236
239
  const contentType = dlRes.headers.get('content-type') || '';
237
240
  let content;
241
+ let supportingFiles = null;
238
242
  if (contentType.includes('application/json')) {
239
243
  const dlBody = await dlRes.json();
240
244
  content = dlBody.content;
245
+ supportingFiles = dlBody.supportingFiles || null;
241
246
  } else {
242
247
  content = await dlRes.text();
243
248
  }
@@ -247,10 +252,41 @@ async function installSkill(name, options) {
247
252
  await fs.ensureDir(installPath);
248
253
  await fs.writeFile(path.join(installPath, 'SKILL.md'), content, 'utf8');
249
254
 
255
+ // Install supporting files (agents, scripts, references, assets)
256
+ let extraFileCount = 0;
257
+ if (supportingFiles && typeof supportingFiles === 'object') {
258
+ for (const [relPath, fileContent] of Object.entries(supportingFiles)) {
259
+ const filePath = path.join(installPath, relPath);
260
+ await fs.ensureDir(path.dirname(filePath));
261
+ await fs.writeFile(filePath, fileContent, 'utf8');
262
+ extraFileCount++;
263
+ }
264
+ }
265
+
250
266
  dlSpinner.succeed(chalk.green(`Installed ${chalk.bold(skill.name)}`));
251
267
 
268
+ // Track installation (non-blocking, best-effort)
269
+ try {
270
+ const token = await getAuthToken();
271
+ if (token) {
272
+ fetchWithTimeout(`${API_BASE}/${skill.id}/install`, {
273
+ method: 'POST',
274
+ headers: {
275
+ 'Authorization': `Bearer ${token}`,
276
+ 'Content-Type': 'application/json',
277
+ },
278
+ body: JSON.stringify({ source: 'cli' }),
279
+ }).catch(() => {}); // Fire-and-forget
280
+ }
281
+ } catch {
282
+ // Silently ignore tracking failures
283
+ }
284
+
252
285
  const rel = path.relative(process.cwd(), installPath);
253
286
  console.log(chalk.gray(` → ${rel}/SKILL.md`));
287
+ if (extraFileCount > 0) {
288
+ console.log(chalk.gray(` → ${extraFileCount} supporting file(s) (agents, scripts, etc.)`));
289
+ }
254
290
  console.log(chalk.cyan('\n Restart Claude Code to load the new skill.\n'));
255
291
  } catch (err) {
256
292
  if (err.name === 'AbortError') {
@@ -696,26 +732,10 @@ async function scaffoldSkill() {
696
732
  return targetDir;
697
733
  }
698
734
 
699
- function ghAvailable() {
700
- try {
701
- execSync('gh auth status', { stdio: 'pipe' });
702
- return true;
703
- } catch {
704
- return false;
705
- }
706
- }
707
-
708
735
  async function submitSkill(opts) {
709
- // Step 1: Auth checks
736
+ // Step 1: Auth check
710
737
  if (!(await requireAuth())) return;
711
738
 
712
- if (!ghAvailable()) {
713
- console.log(chalk.red('\n✗ GitHub CLI (gh) is required for submissions.'));
714
- console.log(chalk.gray(' Install: https://cli.github.com'));
715
- console.log(chalk.gray(' Then: gh auth login\n'));
716
- return;
717
- }
718
-
719
739
  // Step 2: Detect or scaffold SKILL.md
720
740
  let targetPath = opts.dir ? path.resolve(opts.dir) : process.cwd();
721
741
  let skillDir = targetPath;
@@ -747,14 +767,13 @@ async function submitSkill(opts) {
747
767
 
748
768
  const scaffoldedDir = await scaffoldSkill();
749
769
  if (!scaffoldedDir) return;
750
- // User needs to edit the scaffold first
751
770
  return;
752
771
  }
753
772
 
754
- // Step 3: Validate
773
+ // Step 3: Local validation
755
774
  const spinner = ora('Validating skill...').start();
756
775
  const result = await validateSkill(skillDir, {
757
- checkDuplicates: true,
776
+ checkDuplicates: false,
758
777
  apiBase: API_BASE,
759
778
  });
760
779
  spinner.stop();
@@ -777,11 +796,11 @@ async function submitSkill(opts) {
777
796
  }
778
797
 
779
798
  // Step 4: Show summary and confirm
780
- const slug = result.info.slug;
781
799
  console.log(chalk.cyan('\n📤 Submit to MyAIDev Marketplace\n'));
782
800
  console.log(` ${chalk.gray('Name:')} ${chalk.white.bold(result.info.name)}`);
783
- console.log(` ${chalk.gray('Slug:')} ${chalk.white(slug)}`);
801
+ console.log(` ${chalk.gray('Slug:')} ${chalk.white(result.info.slug)}`);
784
802
  console.log(` ${chalk.gray('Description:')} ${chalk.white(truncate(result.info.description, 60))}`);
803
+ console.log(` ${chalk.gray('Category:')} ${result.info.category || 'general'}`);
785
804
  console.log(` ${chalk.gray('Sections:')} ${result.info.sectionCount}`);
786
805
  console.log('');
787
806
 
@@ -798,116 +817,138 @@ async function submitSkill(opts) {
798
817
  }
799
818
  }
800
819
 
801
- // Step 5: Fork, branch, commit, PR
802
- const prSpinner = ora('Creating pull request...').start();
803
- const tmpDir = path.join(os.tmpdir(), `myaidev-submit-${Date.now()}`);
820
+ // Step 5: Detect supporting files (agents, scripts, references, assets)
821
+ const supportingDirs = ['agents', 'scripts', 'references', 'assets', 'evals'];
822
+ const bundledFiles = {};
823
+ let hasSupportingFiles = false;
824
+
825
+ for (const dir of supportingDirs) {
826
+ const dirPath = path.join(skillDir, dir);
827
+ if (await fs.pathExists(dirPath)) {
828
+ const files = await collectFiles(dirPath, dir);
829
+ if (files.length > 0) {
830
+ hasSupportingFiles = true;
831
+ for (const f of files) {
832
+ bundledFiles[f.relativePath] = f.content;
833
+ }
834
+ }
835
+ }
836
+ }
837
+
838
+ if (hasSupportingFiles) {
839
+ const fileCount = Object.keys(bundledFiles).length;
840
+ console.log(chalk.gray(` Bundling ${fileCount} supporting file(s) (agents, scripts, etc.)\n`));
841
+ }
842
+
843
+ // Step 6: Submit via API
844
+ const submitSpinner = ora('Submitting skill for review...').start();
804
845
 
805
846
  try {
806
- // Fork and clone
807
- try {
808
- execSync(`gh repo fork ${MARKETPLACE_REPO} --clone=false`, { stdio: 'pipe' });
809
- } catch {
810
- // Fork may already exist, that's fine
811
- }
812
-
813
- // Get the user's GitHub username
814
- const ghUser = execSync('gh api user --jq .login', { encoding: 'utf8' }).trim();
815
-
816
- // Clone the user's fork
817
- execSync(`gh repo clone ${ghUser}/myaidev-marketplace "${tmpDir}" -- --depth 1`, { stdio: 'pipe' });
818
-
819
- // Create branch
820
- const branch = `skill/${slug}`;
821
- execSync(`git -C "${tmpDir}" checkout -b ${branch}`, { stdio: 'pipe' });
822
-
823
- // Copy skill files
824
- const destDir = path.join(tmpDir, 'skills', slug);
825
- await fs.ensureDir(destDir);
826
- await fs.copy(skillDir, destDir, {
827
- filter: (src) => {
828
- const ext = path.extname(src).toLowerCase();
829
- const base = path.basename(src);
830
- // Copy directories and allowed file types
831
- if (fs.statSync(src).isDirectory()) return true;
832
- return ['.md', '.json', '.yaml', '.yml', '.sh', '.js', '.ts', '.py', '.txt'].includes(ext) || base === '.gitkeep';
833
- },
847
+ const content = await fs.readFile(skillFile, 'utf8');
848
+
849
+ const payload = {
850
+ content,
851
+ category: result.info.category || undefined,
852
+ };
853
+
854
+ // Include supporting files if present
855
+ if (hasSupportingFiles) {
856
+ payload.supportingFiles = bundledFiles;
857
+ }
858
+
859
+ const res = await authFetch(`${API_BASE}/submissions`, {
860
+ method: 'POST',
861
+ body: JSON.stringify(payload),
834
862
  });
835
863
 
836
- // Commit
837
- execSync(`git -C "${tmpDir}" add skills/${slug}`, { stdio: 'pipe' });
838
- execSync(`git -C "${tmpDir}" commit -m "feat: add skill ${result.info.name}"`, { stdio: 'pipe' });
839
-
840
- // Push
841
- execSync(`git -C "${tmpDir}" push -u origin ${branch}`, { stdio: 'pipe' });
842
-
843
- // Create PR
844
- const prBody = [
845
- `## Skill Submission: ${result.info.name}`,
846
- '',
847
- `**Description**: ${result.info.description || 'N/A'}`,
848
- `**Category**: ${result.info.category || 'general'}`,
849
- '',
850
- '### Checklist',
851
- '- [x] SKILL.md has valid YAML frontmatter',
852
- '- [x] Passes local validation',
853
- '- [ ] Tested locally with Claude Code',
854
- ].join('\n');
855
-
856
- const prOutput = execSync(
857
- `gh pr create --repo ${MARKETPLACE_REPO} --head ${ghUser}:${branch} --title "feat: add skill ${result.info.name}" --body "${prBody.replace(/"/g, '\\"')}"`,
858
- { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }
859
- ).trim();
860
-
861
- prSpinner.succeed(chalk.green('Pull request created!'));
862
-
863
- // Extract PR URL from output
864
- const prUrl = prOutput.match(/https:\/\/github\.com\S+/)?.[0] || prOutput;
865
- console.log(chalk.gray(` PR: ${prUrl}`));
866
-
867
- // Step 6: Record submission
868
- try {
869
- await authFetch(`${API_BASE}/submissions`, {
870
- method: 'POST',
871
- body: JSON.stringify({
872
- skillName: result.info.name,
873
- slug,
874
- description: result.info.description || '',
875
- prUrl,
876
- }),
877
- });
878
- } catch {
879
- // Non-fatal: submission tracking is optional
864
+ if (!res.ok) {
865
+ const body = await res.json().catch(() => ({}));
866
+ if (body.validation?.errors?.length) {
867
+ submitSpinner.fail(chalk.red('Server validation failed:'));
868
+ for (const err of body.validation.errors) {
869
+ console.log(chalk.red(` ${err}`));
870
+ }
871
+ return;
872
+ }
873
+ throw new Error(body.error || `API error: ${res.status}`);
880
874
  }
881
875
 
882
- console.log(chalk.cyan('\n Status: awaiting review'));
883
- console.log(chalk.gray(' Check: myaidev-method addon status\n'));
876
+ const body = await res.json();
877
+ const submission = body.submission;
878
+
879
+ submitSpinner.succeed(chalk.green('Skill submitted for review!'));
880
+
881
+ console.log('');
882
+ console.log(` ${chalk.gray('Submission ID:')} ${chalk.white(submission.id)}`);
883
+ console.log(` ${chalk.gray('Status:')} ${chalk.yellow(submission.status)}`);
884
+ if (hasSupportingFiles) {
885
+ console.log(` ${chalk.gray('Files:')} ${chalk.white(`SKILL.md + ${Object.keys(bundledFiles).length} supporting files`)}`);
886
+ }
887
+ console.log('');
888
+ console.log(chalk.gray(' AI analysis will run automatically.'));
889
+ console.log(chalk.gray(' An admin will review and approve your skill.'));
890
+ console.log(chalk.gray(` Check status: ${chalk.white('myaidev-method addon status')}\n`));
884
891
  } catch (err) {
885
- prSpinner.fail(chalk.red(`Submission failed: ${err.message}`));
892
+ submitSpinner.fail(chalk.red(`Submission failed: ${err.message}`));
886
893
  process.exit(1);
887
- } finally {
888
- // Clean up temp directory
889
- await fs.remove(tmpDir).catch(() => {});
890
894
  }
891
895
  }
892
896
 
897
+ /**
898
+ * Recursively collect files from a directory for bundling.
899
+ * Skips __pycache__, .pyc, and other artifacts.
900
+ */
901
+ async function collectFiles(dirPath, prefix) {
902
+ const results = [];
903
+ const SKIP_PATTERNS = ['__pycache__', '.pyc', '.DS_Store', 'node_modules'];
904
+
905
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
906
+ for (const entry of entries) {
907
+ if (SKIP_PATTERNS.some(p => entry.name.includes(p))) continue;
908
+
909
+ const fullPath = path.join(dirPath, entry.name);
910
+ const relativePath = path.join(prefix, entry.name);
911
+
912
+ if (entry.isDirectory()) {
913
+ const subFiles = await collectFiles(fullPath, relativePath);
914
+ results.push(...subFiles);
915
+ } else if (entry.isFile()) {
916
+ try {
917
+ const content = await fs.readFile(fullPath, 'utf8');
918
+ results.push({ relativePath, content });
919
+ } catch {
920
+ // Skip binary files
921
+ }
922
+ }
923
+ }
924
+ return results;
925
+ }
926
+
893
927
  // ── Status Command ─────────────────────────────────────────────────────
894
928
 
895
- async function checkStatus(name) {
929
+ async function checkStatus(nameOrId) {
896
930
  if (!(await requireAuth())) return;
897
931
 
898
932
  const spinner = ora('Fetching submission status...').start();
899
933
 
900
934
  try {
901
- const params = name ? `?name=${encodeURIComponent(name)}` : '';
902
- const res = await authFetch(`${API_BASE}/submissions${params}`);
903
-
904
- if (!res.ok) {
905
- throw new Error(`API error: ${res.status}`);
935
+ // If it looks like a UUID, fetch by ID
936
+ const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(nameOrId || '');
937
+
938
+ let submissions;
939
+ if (isUuid) {
940
+ const res = await authFetch(`${API_BASE}/submissions/${nameOrId}`);
941
+ if (!res.ok) throw new Error(`API error: ${res.status}`);
942
+ const body = await res.json();
943
+ submissions = body.submission ? [body.submission] : [];
944
+ } else {
945
+ const params = nameOrId ? `?name=${encodeURIComponent(nameOrId)}` : '';
946
+ const res = await authFetch(`${API_BASE}/submissions${params}`);
947
+ if (!res.ok) throw new Error(`API error: ${res.status}`);
948
+ const body = await res.json();
949
+ submissions = body.submissions || [];
906
950
  }
907
951
 
908
- const body = await res.json();
909
- const submissions = body.submissions || [];
910
-
911
952
  spinner.stop();
912
953
 
913
954
  if (submissions.length === 0) {
@@ -921,16 +962,36 @@ async function checkStatus(name) {
921
962
  for (const sub of submissions) {
922
963
  const statusColor = {
923
964
  pending_review: chalk.yellow,
965
+ ai_analyzing: chalk.magenta,
966
+ ready_for_review: chalk.blue,
924
967
  approved: chalk.green,
925
- merged: chalk.green.bold,
926
968
  rejected: chalk.red,
927
969
  changes_requested: chalk.yellow,
928
970
  }[sub.status] || chalk.gray;
929
971
 
930
- console.log(` ${chalk.white.bold(sub.skillName)} ${statusColor(`[${sub.status}]`)}`);
931
- if (sub.prUrl) console.log(chalk.gray(` PR: ${sub.prUrl}`));
932
- if (sub.reviewNotes) console.log(chalk.gray(` Notes: ${sub.reviewNotes}`));
933
- console.log(chalk.gray(` Submitted: ${new Date(sub.createdAt).toLocaleDateString()}`));
972
+ const statusLabel = {
973
+ pending_review: 'pending review',
974
+ ai_analyzing: 'AI analyzing...',
975
+ ready_for_review: 'ready for review',
976
+ approved: 'approved',
977
+ rejected: 'rejected',
978
+ changes_requested: 'changes requested',
979
+ }[sub.status] || sub.status;
980
+
981
+ console.log(` ${chalk.white.bold(sub.skillName)} ${statusColor(`[${statusLabel}]`)}`);
982
+
983
+ // Show AI score if available
984
+ if (sub.aiAnalysis?.overallScore != null) {
985
+ const score = sub.aiAnalysis.overallScore;
986
+ const scoreColor = score >= 75 ? chalk.green : score >= 50 ? chalk.yellow : chalk.red;
987
+ console.log(` ${chalk.gray('AI Score:')} ${scoreColor(`${score}/100`)} ${chalk.gray(`(${sub.aiAnalysis.recommendation})`)}`);
988
+ } else if (sub.aiAnalysisStatus === 'running') {
989
+ console.log(` ${chalk.gray('AI Score:')} ${chalk.magenta('analyzing...')}`);
990
+ }
991
+
992
+ if (sub.reviewNotes) console.log(` ${chalk.gray('Review:')} ${sub.reviewNotes}`);
993
+ console.log(` ${chalk.gray('Submitted:')} ${new Date(sub.createdAt).toLocaleDateString()}`);
994
+ if (sub.reviewedAt) console.log(` ${chalk.gray('Reviewed:')} ${new Date(sub.reviewedAt).toLocaleDateString()}`);
934
995
  console.log('');
935
996
  }
936
997
  } catch (err) {