prompt refactor

This commit is contained in:
Will Li 2025-07-18 01:47:24 -07:00
parent 775c321e7f
commit 743278c652
4 changed files with 243 additions and 133 deletions

View file

@ -0,0 +1,93 @@
import { describe, it, expect } from "vitest"
import {
generateRulesInstructions,
ruleTypeDefinitions,
RulesGenerationOptions,
RuleInstruction,
} from "../generate-rules"
describe("generateRulesInstructions", () => {
it("should generate instructions with all options enabled", () => {
const ruleInstructions: RuleInstruction[] = [ruleTypeDefinitions.general, ruleTypeDefinitions.code]
const options: RulesGenerationOptions = {
selectedRuleTypes: ["general", "code"],
addToGitignore: true,
alwaysAllowWriteProtected: true,
includeCustomRules: true,
customRulesText: "Always use TypeScript",
}
const result = generateRulesInstructions(ruleInstructions, options)
expect(result).toContain("Analyze this codebase and generate comprehensive rules")
expect(result).toContain("coding-standards.md")
expect(result).toContain("implementation-rules.md")
expect(result).toContain("The directory has already been created for you")
expect(result).toContain("Add the generated files to .gitignore")
expect(result).toContain("Always use TypeScript")
})
it("should generate instructions with minimal options", () => {
const ruleInstructions: RuleInstruction[] = [ruleTypeDefinitions.general]
const options: RulesGenerationOptions = {
selectedRuleTypes: ["general"],
addToGitignore: false,
alwaysAllowWriteProtected: false,
includeCustomRules: false,
customRulesText: "",
}
const result = generateRulesInstructions(ruleInstructions, options)
expect(result).toContain("Analyze this codebase and generate comprehensive rules")
expect(result).toContain("coding-standards.md")
expect(result).toContain("Create the necessary directories if they don't exist")
expect(result).not.toContain("Add the generated files to .gitignore")
expect(result).not.toContain("Additional rules from User")
})
it("should handle all rule types", () => {
const allRuleTypes = Object.keys(ruleTypeDefinitions)
const ruleInstructions: RuleInstruction[] = allRuleTypes.map(
(type) => ruleTypeDefinitions[type as keyof typeof ruleTypeDefinitions],
)
const options: RulesGenerationOptions = {
selectedRuleTypes: allRuleTypes,
addToGitignore: false,
alwaysAllowWriteProtected: false,
includeCustomRules: false,
customRulesText: "",
}
const result = generateRulesInstructions(ruleInstructions, options)
expect(result).toContain("coding-standards.md")
expect(result).toContain("implementation-rules.md")
expect(result).toContain("architecture-rules.md")
expect(result).toContain("debugging-rules.md")
expect(result).toContain("documentation-rules.md")
})
})
describe("ruleTypeDefinitions", () => {
it("should have all expected rule types", () => {
expect(ruleTypeDefinitions).toHaveProperty("general")
expect(ruleTypeDefinitions).toHaveProperty("code")
expect(ruleTypeDefinitions).toHaveProperty("architect")
expect(ruleTypeDefinitions).toHaveProperty("debug")
expect(ruleTypeDefinitions).toHaveProperty("docs-extractor")
})
it("should have proper structure for each rule type", () => {
Object.values(ruleTypeDefinitions).forEach((rule) => {
expect(rule).toHaveProperty("path")
expect(rule).toHaveProperty("focus")
expect(rule).toHaveProperty("analysisSteps")
expect(Array.isArray(rule.analysisSteps)).toBe(true)
expect(rule.analysisSteps.length).toBeGreaterThan(0)
})
})
})

View file

@ -0,0 +1,127 @@
export interface RuleInstruction {
path: string
focus: string
analysisSteps: string[]
}
export interface RulesGenerationOptions {
selectedRuleTypes: string[]
addToGitignore: boolean
alwaysAllowWriteProtected: boolean
includeCustomRules: boolean
customRulesText: string
}
export function generateRulesInstructions(
ruleInstructions: RuleInstruction[],
options: RulesGenerationOptions,
): string {
const { addToGitignore, alwaysAllowWriteProtected, includeCustomRules, customRulesText } = options
return `Analyze this codebase and generate comprehensive rules for AI agents working in this repository.
Your task is to:
1. **Analyze the project structure** by:
${ruleInstructions.map((rule) => ` - For ${rule.path.split("/").pop()}: ${rule.analysisSteps.join("; ")}`).join("\n")}
2. **Look for existing rule files** that might provide guidance:
- Check for CLAUDE.md, .cursorrules, .cursor/rules, or .github/copilot-instructions.md
- If found, incorporate and improve upon their content
3. **Generate and save the following rule files**:
${ruleInstructions
.map(
(rule, index) => `
${index + 1}. **${rule.path}**
- Focus: ${rule.focus}${alwaysAllowWriteProtected ? "\n - The directory has already been created for you" : "\n - Create the necessary directories if they don't exist"}
- Always overwrite the existing file if it exists
- Use the \`write_to_file\` tool to save the content${alwaysAllowWriteProtected ? "\n - Note: Auto-approval for protected file writes is enabled, so you can write to .roo directories without manual approval" : "\n - Note: You will need to approve the creation of protected directories and files"}`,
)
.join("\n")}
4. **Make the rules actionable and specific** by including:
- Build/lint/test commands (especially for running single tests)
- Code style guidelines including imports, formatting, types, naming conventions
- Error handling patterns specific to this project
- Project-specific conventions and best practices
- File organization patterns
5. **Keep rules concise** - aim for 20 lines per file, focusing on the most important guidelines
6. **Open the generated files** in the editor for review after creation
${
addToGitignore
? `7. **Add the generated files to .gitignore**:
- After generating all rule files, add entries to .gitignore to prevent them from being committed
- Add each generated file path to .gitignore (e.g., .roo/rules/coding-standards.md)
- If .gitignore doesn't exist, create it
- If the entries already exist in .gitignore, don't duplicate them`
: ""
}
${
includeCustomRules && customRulesText
? `\n**Additional rules from User to add to the rules file:**\n${customRulesText}`
: ""
}`
}
export const ruleTypeDefinitions = {
general: {
path: ".roo/rules/coding-standards.md",
focus: "General coding standards that apply to all modes, including naming conventions, file organization, and general best practices",
analysisSteps: [
"Examine the project structure and file organization patterns",
"Identify naming conventions for files, functions, variables, and classes",
"Look for general coding patterns and conventions used throughout the codebase",
"Check for any existing documentation or README files that describe project standards",
],
},
code: {
path: ".roo/rules-code/implementation-rules.md",
focus: "Specific rules for code implementation, focusing on syntax patterns, code structure, error handling, testing approaches, and detailed implementation guidelines",
analysisSteps: [
"Analyze package.json or equivalent files to identify dependencies and build tools",
"Check for linting and formatting tools (ESLint, Prettier, etc.) and their configurations",
"Examine test files to understand testing patterns and frameworks used",
"Look for error handling patterns and logging strategies",
"Identify code style preferences and import/export patterns",
"Check for TypeScript usage and type definition patterns if applicable",
],
},
architect: {
path: ".roo/rules-architect/architecture-rules.md",
focus: "High-level system design rules, focusing on file layout, module organization, architectural patterns, and system-wide design principles",
analysisSteps: [
"Analyze the overall directory structure and module organization",
"Identify architectural patterns (MVC, microservices, monorepo, etc.)",
"Look for separation of concerns and layering patterns",
"Check for API design patterns and service boundaries",
"Examine how different parts of the system communicate",
],
},
debug: {
path: ".roo/rules-debug/debugging-rules.md",
focus: "Debugging workflow rules, including error investigation approaches, logging strategies, troubleshooting patterns, and debugging best practices",
analysisSteps: [
"Identify logging frameworks and patterns used in the codebase",
"Look for error handling and exception patterns",
"Check for debugging tools or scripts in the project",
"Analyze test structure for debugging approaches",
"Look for monitoring or observability patterns",
],
},
"docs-extractor": {
path: ".roo/rules-docs-extractor/documentation-rules.md",
focus: "Documentation extraction and formatting rules, including documentation style guides, API documentation patterns, and content organization",
analysisSteps: [
"Check for existing documentation files and their formats",
"Analyze code comments and documentation patterns",
"Look for API documentation tools or generators",
"Identify documentation structure and organization patterns",
"Check for examples or tutorials in the codebase",
],
},
}

View file

@ -1,5 +1,11 @@
import * as fs from "fs/promises"
import * as path from "path"
import {
generateRulesInstructions,
ruleTypeDefinitions,
RulesGenerationOptions,
RuleInstruction,
} from "../../core/prompts/instructions/generate-rules"
/**
* Creates a comprehensive task message for rules generation that can be used with initClineWithTask
@ -32,132 +38,20 @@ export async function createRulesGenerationTaskMessage(
}
// Create rule-specific instructions based on selected types
interface RuleInstruction {
path: string
focus: string
analysisSteps: string[]
}
const ruleInstructions: RuleInstruction[] = selectedRuleTypes
.map((type) => {
switch (type) {
case "general":
return {
path: ".roo/rules/coding-standards.md",
focus: "General coding standards that apply to all modes, including naming conventions, file organization, and general best practices",
analysisSteps: [
"Examine the project structure and file organization patterns",
"Identify naming conventions for files, functions, variables, and classes",
"Look for general coding patterns and conventions used throughout the codebase",
"Check for any existing documentation or README files that describe project standards",
],
}
case "code":
return {
path: ".roo/rules-code/implementation-rules.md",
focus: "Specific rules for code implementation, focusing on syntax patterns, code structure, error handling, testing approaches, and detailed implementation guidelines",
analysisSteps: [
"Analyze package.json or equivalent files to identify dependencies and build tools",
"Check for linting and formatting tools (ESLint, Prettier, etc.) and their configurations",
"Examine test files to understand testing patterns and frameworks used",
"Look for error handling patterns and logging strategies",
"Identify code style preferences and import/export patterns",
"Check for TypeScript usage and type definition patterns if applicable",
],
}
case "architect":
return {
path: ".roo/rules-architect/architecture-rules.md",
focus: "High-level system design rules, focusing on file layout, module organization, architectural patterns, and system-wide design principles",
analysisSteps: [
"Analyze the overall directory structure and module organization",
"Identify architectural patterns (MVC, microservices, monorepo, etc.)",
"Look for separation of concerns and layering patterns",
"Check for API design patterns and service boundaries",
"Examine how different parts of the system communicate",
],
}
case "debug":
return {
path: ".roo/rules-debug/debugging-rules.md",
focus: "Debugging workflow rules, including error investigation approaches, logging strategies, troubleshooting patterns, and debugging best practices",
analysisSteps: [
"Identify logging frameworks and patterns used in the codebase",
"Look for error handling and exception patterns",
"Check for debugging tools or scripts in the project",
"Analyze test structure for debugging approaches",
"Look for monitoring or observability patterns",
],
}
case "docs-extractor":
return {
path: ".roo/rules-docs-extractor/documentation-rules.md",
focus: "Documentation extraction and formatting rules, including documentation style guides, API documentation patterns, and content organization",
analysisSteps: [
"Check for existing documentation files and their formats",
"Analyze code comments and documentation patterns",
"Look for API documentation tools or generators",
"Identify documentation structure and organization patterns",
"Check for examples or tutorials in the codebase",
],
}
default:
return null
}
const definition = ruleTypeDefinitions[type as keyof typeof ruleTypeDefinitions]
return definition || null
})
.filter((rule): rule is RuleInstruction => rule !== null)
// Create a comprehensive message for the rules generation task
const taskMessage = `Analyze this codebase and generate comprehensive rules for AI agents working in this repository.
const options: RulesGenerationOptions = {
selectedRuleTypes,
addToGitignore,
alwaysAllowWriteProtected,
includeCustomRules,
customRulesText,
}
Your task is to:
1. **Analyze the project structure** by:
${ruleInstructions.map((rule) => ` - For ${rule.path.split("/").pop()}: ${rule.analysisSteps.join("; ")}`).join("\n")}
2. **Look for existing rule files** that might provide guidance:
- Check for CLAUDE.md, .cursorrules, .cursor/rules, or .github/copilot-instructions.md
- If found, incorporate and improve upon their content
3. **Generate and save the following rule files**:
${ruleInstructions
.map(
(rule, index) => `
${index + 1}. **${rule.path}**
- Focus: ${rule.focus}${alwaysAllowWriteProtected ? "\n - The directory has already been created for you" : "\n - Create the necessary directories if they don't exist"}
- Always overwrite the existing file if it exists
- Use the \`write_to_file\` tool to save the content${alwaysAllowWriteProtected ? "\n - Note: Auto-approval for protected file writes is enabled, so you can write to .roo directories without manual approval" : "\n - Note: You will need to approve the creation of protected directories and files"}`,
)
.join("\n")}
4. **Make the rules actionable and specific** by including:
- Build/lint/test commands (especially for running single tests)
- Code style guidelines including imports, formatting, types, naming conventions
- Error handling patterns specific to this project
- Project-specific conventions and best practices
- File organization patterns
5. **Keep rules concise** - aim for 20 lines per file, focusing on the most important guidelines
6. **Open the generated files** in the editor for review after creation
Use the \`safeWriteJson\` utility from \`src/utils/safeWriteJson.ts\` for any JSON file operations to ensure atomic writes.
${
addToGitignore
? `7. **Add the generated files to .gitignore**:
- After generating all rule files, add entries to .gitignore to prevent them from being committed
- Add each generated file path to .gitignore (e.g., .roo/rules/coding-standards.md)
- If .gitignore doesn't exist, create it
- If the entries already exist in .gitignore, don't duplicate them`
: ""
}
${
includeCustomRules && customRulesText
? `\n**Additional rules from User to add to the rules file:**\n${customRulesText}`
: ""
}`
return taskMessage
return generateRulesInstructions(ruleInstructions, options)
}

View file

@ -178,7 +178,7 @@ export const RulesSettings = ({ className, hasUnsavedChanges, ...props }: RulesS
<Section>
<div className="space-y-6">
{/* Magic Rules Generation subsection */}
<div className="flex flex-col gap-3">
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-1">
<div className="flex items-center gap-2 font-bold">
<Sparkles className="w-4 h-4" />
@ -188,9 +188,9 @@ export const RulesSettings = ({ className, hasUnsavedChanges, ...props }: RulesS
{t("settings:rules.magicGeneration.description")}
</div>
</div>
<div className="flex flex-col gap-4 pl-3 border-l-2 border-vscode-button-background">
<div className="flex flex-col gap-3 pl-3 border-l-2 border-vscode-button-background">
{/* Recommendation box */}
<div className="flex items-start gap-2 p-3 bg-vscode-inputValidation-infoBackground border border-vscode-inputValidation-infoBorder rounded-md">
<div className="flex items-start gap-2 p-2 bg-vscode-inputValidation-infoBackground border border-vscode-inputValidation-infoBorder rounded-md">
<Info className="w-4 h-4 text-vscode-inputValidation-infoForeground mt-0.5 flex-shrink-0" />
<div className="text-sm text-vscode-inputValidation-infoForeground">
{t("settings:rules.autoApproveRecommendation")}
@ -233,7 +233,7 @@ export const RulesSettings = ({ className, hasUnsavedChanges, ...props }: RulesS
{/* Small repository warning */}
{sourceFileCount !== null && sourceFileCount > 0 && sourceFileCount < 20 && (
<div className="flex items-start gap-2 p-3 bg-vscode-inputValidation-warningBackground border border-vscode-inputValidation-warningBorder rounded-md">
<div className="flex items-start gap-2 p-2 bg-vscode-inputValidation-warningBackground border border-vscode-inputValidation-warningBorder rounded-md">
<AlertTriangle className="w-4 h-4 text-vscode-inputValidation-warningForeground mt-0.5 flex-shrink-0" />
<div className="text-sm text-vscode-inputValidation-warningForeground">
{t("settings:rules.smallRepoWarning", { count: sourceFileCount })}
@ -241,7 +241,7 @@ export const RulesSettings = ({ className, hasUnsavedChanges, ...props }: RulesS
</div>
)}
{hasExistingFiles && (
<div className="flex items-start gap-2 p-3 bg-vscode-inputValidation-warningBackground border border-vscode-inputValidation-warningBorder rounded-md">
<div className="flex items-start gap-2 p-2 bg-vscode-inputValidation-warningBackground border border-vscode-inputValidation-warningBorder rounded-md">
<AlertTriangle className="w-4 h-4 text-vscode-inputValidation-warningForeground mt-0.5 flex-shrink-0" />
<div className="text-sm text-vscode-inputValidation-warningForeground">
<div>{t("settings:rules.overwriteWarning")}</div>
@ -254,7 +254,7 @@ export const RulesSettings = ({ className, hasUnsavedChanges, ...props }: RulesS
</div>
)}
<div className="border-t border-vscode-panel-border pt-2">
<div className="border-t border-vscode-panel-border pt-2 space-y-2">
<label className="flex items-center gap-2 cursor-pointer hover:opacity-80">
<input
type="checkbox"
@ -268,9 +268,7 @@ export const RulesSettings = ({ className, hasUnsavedChanges, ...props }: RulesS
</div>
</div>
</label>
</div>
<div className="border-t border-vscode-panel-border pt-2">
<label className="flex items-center gap-2 cursor-pointer hover:opacity-80">
<input
type="checkbox"
@ -292,9 +290,7 @@ export const RulesSettings = ({ className, hasUnsavedChanges, ...props }: RulesS
</div>
</div>
</label>
</div>
<div className="border-t border-vscode-panel-border pt-4">
<label className="flex items-center gap-2 cursor-pointer hover:opacity-80">
<input
type="checkbox"
@ -333,7 +329,7 @@ export const RulesSettings = ({ className, hasUnsavedChanges, ...props }: RulesS
)}
</div>
<div className="flex flex-col gap-3">
<div className="flex flex-col gap-2 mt-3">
<Select value={selectedApiConfig} onValueChange={setSelectedApiConfig}>
<SelectTrigger className="w-fit min-w-[5rem] max-w-[8rem]">
<SelectValue placeholder={t("settings:rules.selectApiConfig")} />