mirror of
https://github.com/supabase/agent-skills.git
synced 2026-01-26 19:09:51 +08:00
automatically reorder sections on agents.md by priority
This commit is contained in:
@@ -18,6 +18,10 @@ function parseSections(): Section[] {
|
||||
const content = readFileSync(sectionsFile, "utf-8");
|
||||
const sections: Section[] = [];
|
||||
|
||||
// Match format: Impact and Description on separate lines
|
||||
// ## 1. Query Performance (query)
|
||||
// **Impact:** CRITICAL
|
||||
// **Description:** Description text
|
||||
const sectionMatches = content.matchAll(
|
||||
/##\s+(\d+)\.\s+([^\n(]+)\s*\((\w+)\)\s*\n\*\*Impact:\*\*\s*(\w+(?:-\w+)?)\s*\n\*\*Description:\*\*\s*([^\n]+)/g,
|
||||
);
|
||||
@@ -56,25 +60,25 @@ function getDefaultSections(): Section[] {
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
title: "Security & RLS",
|
||||
prefix: "security",
|
||||
impact: "CRITICAL",
|
||||
description: "Row-Level Security, privileges, auth patterns",
|
||||
},
|
||||
{
|
||||
number: 4,
|
||||
title: "Schema Design",
|
||||
prefix: "schema",
|
||||
impact: "HIGH",
|
||||
description: "Table design, indexes, partitioning, data types",
|
||||
},
|
||||
{
|
||||
number: 4,
|
||||
number: 5,
|
||||
title: "Concurrency & Locking",
|
||||
prefix: "lock",
|
||||
impact: "MEDIUM-HIGH",
|
||||
description: "Transactions, isolation, deadlocks",
|
||||
},
|
||||
{
|
||||
number: 5,
|
||||
title: "Security & RLS",
|
||||
prefix: "security",
|
||||
impact: "MEDIUM-HIGH",
|
||||
description: "Row-Level Security, privileges, auth patterns",
|
||||
},
|
||||
{
|
||||
number: 6,
|
||||
title: "Data Access Patterns",
|
||||
@@ -129,6 +133,19 @@ function toAnchor(text: string): string {
|
||||
.replace(/\s+/g, "-");
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate SECTION_MAP from parsed sections
|
||||
*/
|
||||
export function generateSectionMap(
|
||||
sections: Section[],
|
||||
): Record<string, number> {
|
||||
const map: Record<string, number> = {};
|
||||
for (const section of sections) {
|
||||
map[section.prefix] = section.number;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build AGENTS.md from all rule files
|
||||
*/
|
||||
@@ -138,6 +155,7 @@ function buildAgents(): void {
|
||||
// Load metadata and sections
|
||||
const metadata = loadMetadata();
|
||||
const sections = parseSections();
|
||||
const sectionMap = generateSectionMap(sections);
|
||||
|
||||
// Get all rule files
|
||||
const ruleFiles = readdirSync(RULES_DIR)
|
||||
@@ -152,7 +170,7 @@ function buildAgents(): void {
|
||||
const rules: Rule[] = [];
|
||||
|
||||
for (const file of ruleFiles) {
|
||||
const validation = validateRuleFile(file);
|
||||
const validation = validateRuleFile(file, sectionMap);
|
||||
if (!validation.valid) {
|
||||
console.error(`Skipping invalid file ${basename(file)}:`);
|
||||
for (const e of validation.errors) {
|
||||
@@ -161,7 +179,7 @@ function buildAgents(): void {
|
||||
continue;
|
||||
}
|
||||
|
||||
const result = parseRuleFile(file);
|
||||
const result = parseRuleFile(file, sectionMap);
|
||||
if (result.success && result.rule) {
|
||||
rules.push(result.rule);
|
||||
}
|
||||
@@ -303,4 +321,4 @@ if (isMainModule) {
|
||||
buildAgents();
|
||||
}
|
||||
|
||||
export { buildAgents };
|
||||
export { buildAgents, parseSections };
|
||||
|
||||
@@ -20,14 +20,17 @@ export const RULES_DIR = join(SKILL_DIR, "rules");
|
||||
export const AGENTS_OUTPUT = join(SKILL_DIR, "AGENTS.md");
|
||||
export const METADATA_FILE = join(SKILL_DIR, "metadata.json");
|
||||
|
||||
// Section prefix to number mapping
|
||||
// Section prefix to number mapping (DEPRECATED)
|
||||
// This is kept as a fallback, but the build system now generates
|
||||
// the section map dynamically from _sections.md.
|
||||
// To reorder sections, simply change the order in _sections.md.
|
||||
export const SECTION_MAP: Record<string, number> = {
|
||||
query: 1,
|
||||
conn: 2,
|
||||
connection: 2,
|
||||
schema: 3,
|
||||
lock: 4,
|
||||
security: 5,
|
||||
security: 3,
|
||||
schema: 4,
|
||||
lock: 5,
|
||||
data: 6,
|
||||
monitor: 7,
|
||||
advanced: 8,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { basename } from "node:path";
|
||||
import { IMPACT_LEVELS, SECTION_MAP } from "./config.js";
|
||||
import { IMPACT_LEVELS } from "./config.js";
|
||||
import type { CodeExample, ImpactLevel, ParseResult, Rule } from "./types.js";
|
||||
|
||||
/**
|
||||
@@ -48,10 +48,13 @@ function parseFrontmatter(content: string): {
|
||||
/**
|
||||
* Extract section number from filename prefix
|
||||
*/
|
||||
function getSectionFromFilename(filename: string): number | null {
|
||||
function getSectionFromFilename(
|
||||
filename: string,
|
||||
sectionMap: Record<string, number>,
|
||||
): number | null {
|
||||
const base = basename(filename, ".md");
|
||||
const prefix = base.split("-")[0];
|
||||
return SECTION_MAP[prefix] ?? null;
|
||||
return sectionMap[prefix] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,7 +210,10 @@ function extractReferences(body: string): string[] {
|
||||
/**
|
||||
* Parse a rule file and return structured data
|
||||
*/
|
||||
export function parseRuleFile(filePath: string): ParseResult {
|
||||
export function parseRuleFile(
|
||||
filePath: string,
|
||||
sectionMap: Record<string, number>,
|
||||
): ParseResult {
|
||||
const errors: string[] = [];
|
||||
const warnings: string[] = [];
|
||||
|
||||
@@ -216,7 +222,7 @@ export function parseRuleFile(filePath: string): ParseResult {
|
||||
const { frontmatter, body } = parseFrontmatter(content);
|
||||
|
||||
// Extract section from filename
|
||||
const section = getSectionFromFilename(filePath);
|
||||
const section = getSectionFromFilename(filePath, sectionMap);
|
||||
if (section === null) {
|
||||
errors.push(
|
||||
`Could not determine section from filename: ${basename(filePath)}`,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { readdirSync } from "node:fs";
|
||||
import { basename, join } from "node:path";
|
||||
import { generateSectionMap, parseSections } from "./build.js";
|
||||
import { IMPACT_LEVELS, RULES_DIR } from "./config.js";
|
||||
import { parseRuleFile } from "./parser.js";
|
||||
import type { ValidationResult } from "./types.js";
|
||||
@@ -34,11 +35,20 @@ function isGoodExample(label: string): boolean {
|
||||
/**
|
||||
* Validate a single rule file
|
||||
*/
|
||||
export function validateRuleFile(filePath: string): ValidationResult {
|
||||
export function validateRuleFile(
|
||||
filePath: string,
|
||||
sectionMap?: Record<string, number>,
|
||||
): ValidationResult {
|
||||
const errors: string[] = [];
|
||||
const warnings: string[] = [];
|
||||
|
||||
const result = parseRuleFile(filePath);
|
||||
// Generate section map if not provided
|
||||
if (!sectionMap) {
|
||||
const sections = parseSections();
|
||||
sectionMap = generateSectionMap(sections);
|
||||
}
|
||||
|
||||
const result = parseRuleFile(filePath, sectionMap);
|
||||
|
||||
// Add parser errors and warnings
|
||||
errors.push(...result.errors);
|
||||
|
||||
Reference in New Issue
Block a user