fix(skills): address QA round 4

QA4-1: Split Game Development into separate Unity and Godot packs to
avoid cross-contamination between engines.

QA4-2: Add requirements.txt to Python base pack matchFiles so Python
Advanced doesn't trigger without the base pack.

QA4-3: Add Prisma to fullstack-js greenfield stack to differentiate
it from react-web.

QA4-4: Remove Spring Boot from Android greenfield stack — server-side
Java framework is irrelevant for Android development.

QA4-5: Extract FastAPI into its own pack (consistent with Django being
separate) instead of bundling in Python Advanced.

QA4-6: Add airflow.cfg to PROJECT_FILES and Data Engineering matchFiles
so Airflow-only projects also trigger data engineering skills.

QA4-7: Add Tailwind CSS to react-web, fullstack-js, nextjs, and
svelte greenfield stacks.

QA4-8: Add Unity and Godot as separate greenfield stack options.

QA4-9: Fix Vue.js detection for non-Nuxt projects by adding .vue
file extension scanning (scans src/ for *.vue files), vue.config.*
to PROJECT_FILES, and *.vue synthetic marker to Vue.js pack matchFiles.

QA4-10: Add app/build.gradle and app/build.gradle.kts to LANGUAGE_MAP
for Android project language detection.
This commit is contained in:
Derek Pearson 2026-03-22 07:21:04 -04:00
parent 0067ada24e
commit 90b13021f8
2 changed files with 60 additions and 15 deletions

View file

@ -118,6 +118,9 @@ export const PROJECT_FILES = [
"nuxt.config.js",
"svelte.config.js",
"svelte.config.ts",
// Vue CLI config files
"vue.config.js",
"vue.config.ts",
// Frontend tooling
"tailwind.config.js",
"tailwind.config.ts",
@ -143,6 +146,7 @@ export const PROJECT_FILES = [
"foundry.toml",
// Data engineering markers
"dbt_project.yml",
"airflow.cfg",
// Game engine markers
"ProjectSettings/ProjectVersion.txt",
"project.godot",
@ -160,6 +164,9 @@ const SQL_EXTENSIONS = [".sql"] as const;
/** File extensions that indicate .NET / C# projects. */
const DOTNET_EXTENSIONS = [".csproj", ".sln", ".fsproj"] as const;
/** File extensions that indicate Vue.js single-file components. */
const VUE_EXTENSIONS = [".vue"] as const;
const LANGUAGE_MAP: Record<string, string> = {
"package.json": "javascript/typescript",
"Cargo.toml": "rust",
@ -170,6 +177,8 @@ const LANGUAGE_MAP: Record<string, string> = {
"pom.xml": "java",
"build.gradle": "java/kotlin",
"build.gradle.kts": "kotlin",
"app/build.gradle": "java/kotlin",
"app/build.gradle.kts": "kotlin",
"CMakeLists.txt": "c/c++",
"composer.json": "php",
"pubspec.yaml": "dart/flutter",
@ -349,6 +358,15 @@ export function detectProjectSignals(basePath: string): ProjectSignals {
detectedFiles.push("*.csproj");
if (!primaryLanguage) primaryLanguage = "csharp";
}
// Vue.js: scan src/ dir for .vue files (Vite-based Vue projects have no vue.config.*)
try {
const srcEntries = readdirSync(join(basePath, "src"));
if (srcEntries.some((e) => VUE_EXTENSIONS.some((ext) => e.endsWith(ext)))) {
detectedFiles.push("*.vue");
}
} catch {
// no src/ directory — skip Vue scan
}
} catch {
// unreadable root — skip extension scan
}

View file

@ -275,7 +275,7 @@ export const SKILL_CATALOG: SkillPack[] = [
"vue-router-best-practices",
"vue-testing-best-practices",
],
matchFiles: ["nuxt.config.ts", "nuxt.config.js"],
matchFiles: ["nuxt.config.ts", "nuxt.config.js", "vue.config.js", "vue.config.ts", "*.vue"],
},
// ── Svelte / SvelteKit ────────────────────────────────────────────────────
{
@ -380,22 +380,29 @@ export const SKILL_CATALOG: SkillPack[] = [
repo: "anthropics/skills",
skills: ["python-best-practices"],
matchLanguages: ["python"],
matchFiles: ["pyproject.toml", "setup.py"],
matchFiles: ["pyproject.toml", "setup.py", "requirements.txt"],
},
{
label: "Python Advanced",
description: "Python performance, testing, async patterns, uv package manager, and FastAPI",
description: "Python performance, testing, async patterns, and uv package manager",
repo: "wshobson/agents",
skills: [
"python-performance-optimization",
"python-testing-patterns",
"async-python-patterns",
"uv-package-manager",
"fastapi-templates",
],
matchLanguages: ["python"],
matchFiles: ["pyproject.toml", "setup.py", "requirements.txt"],
},
{
label: "FastAPI",
description: "Production-ready FastAPI projects with async patterns and error handling",
repo: "wshobson/agents",
skills: ["fastapi-templates"],
matchLanguages: ["python"],
matchFiles: ["pyproject.toml", "setup.py", "requirements.txt"],
},
// ── Go ────────────────────────────────────────────────────────────────────
{
label: "Go",
@ -562,15 +569,23 @@ export const SKILL_CATALOG: SkillPack[] = [
"spark-optimization",
"data-quality-frameworks",
],
matchFiles: ["dbt_project.yml"],
matchFiles: ["dbt_project.yml", "airflow.cfg"],
},
// ── Game Development (wshobson/agents — 2 skills) ──────────────────────────
// ── Game Development — Unity (wshobson/agents) ─────────────────────────────
{
label: "Game Development",
description: "Unity ECS patterns and Godot GDScript best practices",
label: "Unity",
description: "Unity ECS patterns for high-performance game systems",
repo: "wshobson/agents",
skills: ["unity-ecs-patterns", "godot-gdscript-patterns"],
matchFiles: ["ProjectSettings/ProjectVersion.txt", "project.godot"],
skills: ["unity-ecs-patterns"],
matchFiles: ["ProjectSettings/ProjectVersion.txt"],
},
// ── Game Development — Godot (wshobson/agents) ─────────────────────────────
{
label: "Godot",
description: "Godot GDScript best practices and scene composition",
repo: "wshobson/agents",
skills: ["godot-gdscript-patterns"],
matchFiles: ["project.godot"],
},
// ── Essential (all projects) ────────────────────────────────────────────
{
@ -661,7 +676,7 @@ export const GREENFIELD_STACKS: Array<{
id: "react-web",
label: "React Web",
description: "React, Next.js, shadcn/ui, web frontend",
packs: ["React & Web Frontend", "TypeScript & JS Development", "React State & Patterns", "shadcn/ui", "Frontend Design & UX"],
packs: ["React & Web Frontend", "TypeScript & JS Development", "React State & Patterns", "Tailwind CSS", "shadcn/ui", "Frontend Design & UX"],
},
{
id: "react-native",
@ -673,7 +688,7 @@ export const GREENFIELD_STACKS: Array<{
id: "fullstack-js",
label: "Full-Stack JavaScript/TypeScript",
description: "Node.js backend + React frontend",
packs: ["React & Web Frontend", "TypeScript & JS Development", "React State & Patterns", "shadcn/ui", "Frontend Design & UX"],
packs: ["React & Web Frontend", "TypeScript & JS Development", "React State & Patterns", "Tailwind CSS", "shadcn/ui", "Frontend Design & UX", "Prisma"],
},
{
id: "rust",
@ -727,13 +742,13 @@ export const GREENFIELD_STACKS: Array<{
id: "svelte",
label: "Svelte / SvelteKit",
description: "Svelte 5 and SvelteKit patterns",
packs: ["Svelte", "Frontend Design & UX"],
packs: ["Svelte", "Tailwind CSS", "Frontend Design & UX"],
},
{
id: "nextjs",
label: "Next.js",
description: "Next.js app router, React, and Vercel deployment",
packs: ["Next.js", "Next.js App Router Patterns", "React & Web Frontend", "TypeScript & JS Development", "shadcn/ui"],
packs: ["Next.js", "Next.js App Router Patterns", "React & Web Frontend", "TypeScript & JS Development", "Tailwind CSS", "shadcn/ui"],
},
{
id: "flutter",
@ -769,7 +784,7 @@ export const GREENFIELD_STACKS: Array<{
id: "android",
label: "Android / Kotlin",
description: "Android app development with Material Design 3",
packs: ["Android", "Java & Spring Boot"],
packs: ["Android"],
},
{
id: "kubernetes",
@ -789,6 +804,18 @@ export const GREENFIELD_STACKS: Array<{
description: "dbt, Airflow, Spark, and data quality",
packs: ["Data Engineering", "Python", "Python Advanced"],
},
{
id: "unity",
label: "Unity",
description: "Unity game development with ECS patterns",
packs: ["Unity"],
},
{
id: "godot",
label: "Godot",
description: "Godot game development with GDScript",
packs: ["Godot"],
},
{
id: "other",
label: "Other / Skip",