feat(skills): add SQLite/SQL detection, SQL optimization pack, and Redis pack

- Scan project root for *.sqlite/*.sqlite3/*.db files → synthetic *.sqlite marker
- Scan for *.sql files (migrations, schemas, seeds) → synthetic *.sql marker
- Add SQL Optimization & Review pack (github/awesome-copilot): sql-optimization
  (7.8K installs) and sql-code-review (7.6K installs) — covers SQL injection
  prevention, parameterized queries, index strategy, anti-patterns. Triggers on
  *.sql, *.sqlite, or any database ORM config (Prisma, Supabase, Drizzle).
- Add Redis pack (redis/agent-skills): redis-development. Triggers on redis.conf.
- Add redis.conf to PROJECT_FILES.
- 4 new detection tests for SQLite/SQL file scanning.
This commit is contained in:
Derek Pearson 2026-03-22 06:40:53 -04:00
parent e48538b70d
commit a30b125020
3 changed files with 88 additions and 0 deletions

View file

@ -104,12 +104,19 @@ export const PROJECT_FILES = [
"supabase/config.toml",
"drizzle.config.ts",
"drizzle.config.js",
"redis.conf",
// React Native markers
"metro.config.js",
"metro.config.ts",
"react-native.config.js",
] as const;
/** File extensions that indicate SQLite databases in the project. */
const SQLITE_EXTENSIONS = [".sqlite", ".sqlite3", ".db"] as const;
/** File extensions that indicate SQL usage (migrations, schemas, seeds). */
const SQL_EXTENSIONS = [".sql"] as const;
const LANGUAGE_MAP: Record<string, string> = {
"package.json": "javascript/typescript",
"Cargo.toml": "rust",
@ -282,6 +289,21 @@ export function detectProjectSignals(basePath: string): ProjectSignals {
}
}
// SQLite / SQL file detection — scan root entries for database file extensions.
// Adds synthetic markers (e.g. "*.sqlite", "*.sql") to detectedFiles so
// skill catalog matchFiles can reference them.
try {
const rootEntries = readdirSync(basePath);
if (rootEntries.some((e) => SQLITE_EXTENSIONS.some((ext) => e.endsWith(ext)))) {
detectedFiles.push("*.sqlite");
}
if (rootEntries.some((e) => SQL_EXTENSIONS.some((ext) => e.endsWith(ext)))) {
detectedFiles.push("*.sql");
}
} catch {
// unreadable root — skip extension scan
}
// Git repo detection
const isGitRepo = existsSync(join(basePath, ".git"));

View file

@ -248,6 +248,27 @@ export const SKILL_CATALOG: SkillPack[] = [
skills: ["supabase-postgres-best-practices"],
matchFiles: ["supabase/config.toml"],
},
{
label: "SQL Optimization & Review",
description: "Universal SQL performance optimization, security (injection prevention), and code review",
repo: "github/awesome-copilot",
skills: ["sql-optimization", "sql-code-review"],
matchFiles: [
"*.sql",
"*.sqlite",
"prisma/schema.prisma",
"supabase/config.toml",
"drizzle.config.ts",
"drizzle.config.js",
],
},
{
label: "Redis",
description: "Redis development patterns and best practices",
repo: "redis/agent-skills",
skills: ["redis-development"],
matchFiles: ["redis.conf"],
},
// ── Cloud Platforms ────────────────────────────────────────────────────────
{
label: "Firebase",

View file

@ -396,3 +396,48 @@ test("detectProjectSignals: Makefile with test target", () => {
cleanup(dir);
}
});
test("detectProjectSignals: SQLite file detection via extensions", () => {
const dir = makeTempDir("signals-sqlite");
try {
writeFileSync(join(dir, "app.sqlite3"), "", "utf-8");
const signals = detectProjectSignals(dir);
assert.ok(signals.detectedFiles.includes("*.sqlite"), "should add synthetic *.sqlite marker");
} finally {
cleanup(dir);
}
});
test("detectProjectSignals: SQL file detection", () => {
const dir = makeTempDir("signals-sql");
try {
writeFileSync(join(dir, "migrations.sql"), "", "utf-8");
const signals = detectProjectSignals(dir);
assert.ok(signals.detectedFiles.includes("*.sql"), "should add synthetic *.sql marker");
} finally {
cleanup(dir);
}
});
test("detectProjectSignals: .db file triggers SQLite detection", () => {
const dir = makeTempDir("signals-db");
try {
writeFileSync(join(dir, "data.db"), "", "utf-8");
const signals = detectProjectSignals(dir);
assert.ok(signals.detectedFiles.includes("*.sqlite"), "should add synthetic *.sqlite marker for .db files");
} finally {
cleanup(dir);
}
});
test("detectProjectSignals: no SQLite markers without matching files", () => {
const dir = makeTempDir("signals-no-sqlite");
try {
writeFileSync(join(dir, "package.json"), "{}", "utf-8");
const signals = detectProjectSignals(dir);
assert.ok(!signals.detectedFiles.includes("*.sqlite"), "should not have *.sqlite marker");
assert.ok(!signals.detectedFiles.includes("*.sql"), "should not have *.sql marker");
} finally {
cleanup(dir);
}
});