feat: centralize prompts and add customization UI for App Spec, Context, Suggestions, Tasks

- Add 4 new prompt type interfaces (AppSpecPrompts, ContextDescriptionPrompts,
  SuggestionsPrompts, TaskExecutionPrompts) with resolved types
- Add default prompts for all new categories to @automaker/prompts/defaults.ts
- Add merge functions for new prompt categories in merge.ts
- Update settings-helpers.ts getPromptCustomization() to return all 12 categories
- Update server routes (generate-spec, generate-features-from-spec, describe-file,
  describe-image, generate-suggestions) to use centralized prompts
- Add 4 new tabs in prompt customization UI (App Spec, Context, Suggestions, Tasks)
- Fix Ideation tab layout using grid-cols-4 for even distribution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Shirone
2026-01-15 20:13:14 +01:00
parent ca3286a374
commit 285f526e0c
12 changed files with 1507 additions and 66 deletions

View File

@@ -11,6 +11,14 @@ import {
mergeAgentPrompts,
mergeBacklogPlanPrompts,
mergeEnhancementPrompts,
mergeCommitMessagePrompts,
mergeTitleGenerationPrompts,
mergeIssueValidationPrompts,
mergeIdeationPrompts,
mergeAppSpecPrompts,
mergeContextDescriptionPrompts,
mergeSuggestionsPrompts,
mergeTaskExecutionPrompts,
} from '@automaker/prompts';
const logger = createLogger('SettingsHelper');
@@ -218,6 +226,14 @@ export async function getPromptCustomization(
agent: ReturnType<typeof mergeAgentPrompts>;
backlogPlan: ReturnType<typeof mergeBacklogPlanPrompts>;
enhancement: ReturnType<typeof mergeEnhancementPrompts>;
commitMessage: ReturnType<typeof mergeCommitMessagePrompts>;
titleGeneration: ReturnType<typeof mergeTitleGenerationPrompts>;
issueValidation: ReturnType<typeof mergeIssueValidationPrompts>;
ideation: ReturnType<typeof mergeIdeationPrompts>;
appSpec: ReturnType<typeof mergeAppSpecPrompts>;
contextDescription: ReturnType<typeof mergeContextDescriptionPrompts>;
suggestions: ReturnType<typeof mergeSuggestionsPrompts>;
taskExecution: ReturnType<typeof mergeTaskExecutionPrompts>;
}> {
let customization: PromptCustomization = {};
@@ -239,6 +255,14 @@ export async function getPromptCustomization(
agent: mergeAgentPrompts(customization.agent),
backlogPlan: mergeBacklogPlanPrompts(customization.backlogPlan),
enhancement: mergeEnhancementPrompts(customization.enhancement),
commitMessage: mergeCommitMessagePrompts(customization.commitMessage),
titleGeneration: mergeTitleGenerationPrompts(customization.titleGeneration),
issueValidation: mergeIssueValidationPrompts(customization.issueValidation),
ideation: mergeIdeationPrompts(customization.ideation),
appSpec: mergeAppSpecPrompts(customization.appSpec),
contextDescription: mergeContextDescriptionPrompts(customization.contextDescription),
suggestions: mergeSuggestionsPrompts(customization.suggestions),
taskExecution: mergeTaskExecutionPrompts(customization.taskExecution),
};
}

View File

@@ -14,7 +14,7 @@ import { streamingQuery } from '../../providers/simple-query-service.js';
import { parseAndCreateFeatures } from './parse-and-create-features.js';
import { getAppSpecPath } from '@automaker/platform';
import type { SettingsService } from '../../services/settings-service.js';
import { getAutoLoadClaudeMdSetting } from '../../lib/settings-helpers.js';
import { getAutoLoadClaudeMdSetting, getPromptCustomization } from '../../lib/settings-helpers.js';
const logger = createLogger('SpecRegeneration');
@@ -53,38 +53,16 @@ export async function generateFeaturesFromSpec(
return;
}
// Get customized prompts from settings
const prompts = await getPromptCustomization(settingsService, '[FeatureGeneration]');
const prompt = `Based on this project specification:
${spec}
Generate a prioritized list of implementable features. For each feature provide:
${prompts.appSpec.generateFeaturesFromSpecPrompt}
1. **id**: A unique lowercase-hyphenated identifier
2. **category**: Functional category (e.g., "Core", "UI", "API", "Authentication", "Database")
3. **title**: Short descriptive title
4. **description**: What this feature does (2-3 sentences)
5. **priority**: 1 (high), 2 (medium), or 3 (low)
6. **complexity**: "simple", "moderate", or "complex"
7. **dependencies**: Array of feature IDs this depends on (can be empty)
Format as JSON:
{
"features": [
{
"id": "feature-id",
"category": "Feature Category",
"title": "Feature Title",
"description": "What it does",
"priority": 1,
"complexity": "moderate",
"dependencies": []
}
]
}
Generate ${featureCount} features that build on each other logically.
IMPORTANT: Do not ask for clarification. The specification is provided above. Generate the JSON immediately.`;
Generate ${featureCount} features that build on each other logically.`;
logger.info('========== PROMPT BEING SENT ==========');
logger.info(`Prompt length: ${prompt.length} chars`);

View File

@@ -7,12 +7,7 @@
import * as secureFs from '../../lib/secure-fs.js';
import type { EventEmitter } from '../../lib/events.js';
import {
specOutputSchema,
specToXml,
getStructuredSpecPromptInstruction,
type SpecOutput,
} from '../../lib/app-spec-format.js';
import { specOutputSchema, specToXml, type SpecOutput } from '../../lib/app-spec-format.js';
import { createLogger } from '@automaker/utils';
import { DEFAULT_PHASE_MODELS, isCursorModel } from '@automaker/types';
import { resolvePhaseModel } from '@automaker/model-resolver';
@@ -21,7 +16,7 @@ import { streamingQuery } from '../../providers/simple-query-service.js';
import { generateFeaturesFromSpec } from './generate-features-from-spec.js';
import { ensureAutomakerDir, getAppSpecPath } from '@automaker/platform';
import type { SettingsService } from '../../services/settings-service.js';
import { getAutoLoadClaudeMdSetting } from '../../lib/settings-helpers.js';
import { getAutoLoadClaudeMdSetting, getPromptCustomization } from '../../lib/settings-helpers.js';
const logger = createLogger('SpecRegeneration');
@@ -43,6 +38,9 @@ export async function generateSpec(
logger.info('analyzeProject:', analyzeProject);
logger.info('maxFeatures:', maxFeatures);
// Get customized prompts from settings
const prompts = await getPromptCustomization(settingsService, '[SpecRegeneration]');
// Build the prompt based on whether we should analyze the project
let analysisInstructions = '';
let techStackDefaults = '';
@@ -66,9 +64,7 @@ export async function generateSpec(
Use these technologies as the foundation for the specification.`;
}
const prompt = `You are helping to define a software project specification.
IMPORTANT: Never ask for clarification or additional information. Use the information provided and make reasonable assumptions to create the best possible specification. If details are missing, infer them based on common patterns and best practices.
const prompt = `${prompts.appSpec.generateSpecSystemPrompt}
Project Overview:
${projectOverview}
@@ -77,7 +73,7 @@ ${techStackDefaults}
${analysisInstructions}
${getStructuredSpecPromptInstruction()}`;
${prompts.appSpec.structuredSpecInstructions}`;
logger.info('========== PROMPT BEING SENT ==========');
logger.info(`Prompt length: ${prompt.length} chars`);

View File

@@ -19,7 +19,10 @@ import { simpleQuery } from '../../../providers/simple-query-service.js';
import * as secureFs from '../../../lib/secure-fs.js';
import * as path from 'path';
import type { SettingsService } from '../../../services/settings-service.js';
import { getAutoLoadClaudeMdSetting } from '../../../lib/settings-helpers.js';
import {
getAutoLoadClaudeMdSetting,
getPromptCustomization,
} from '../../../lib/settings-helpers.js';
const logger = createLogger('DescribeFile');
@@ -130,11 +133,12 @@ export function createDescribeFileHandler(
// Get the filename for context
const fileName = path.basename(resolvedPath);
// Get customized prompts from settings
const prompts = await getPromptCustomization(settingsService, '[DescribeFile]');
// Build prompt with file content passed as structured data
// The file content is included directly, not via tool invocation
const prompt = `Analyze the following file and provide a 1-2 sentence description suitable for use as context in an AI coding assistant. Focus on what the file contains, its purpose, and why an AI agent might want to use this context in the future (e.g., "API documentation for the authentication endpoints", "Configuration file for database connections", "Coding style guidelines for the project").
Respond with ONLY the description text, no additional formatting, preamble, or explanation.
const prompt = `${prompts.contextDescription.describeFilePrompt}
File: ${fileName}${truncated ? ' (truncated)' : ''}

View File

@@ -19,7 +19,10 @@ import { simpleQuery } from '../../../providers/simple-query-service.js';
import * as secureFs from '../../../lib/secure-fs.js';
import * as path from 'path';
import type { SettingsService } from '../../../services/settings-service.js';
import { getAutoLoadClaudeMdSetting } from '../../../lib/settings-helpers.js';
import {
getAutoLoadClaudeMdSetting,
getPromptCustomization,
} from '../../../lib/settings-helpers.js';
const logger = createLogger('DescribeImage');
@@ -278,12 +281,11 @@ export function createDescribeImageHandler(
logger.info(`[${requestId}] Using model: ${model}`);
// Build the instruction text
const instructionText =
`Describe this image in 1-2 sentences suitable for use as context in an AI coding assistant. ` +
`Focus on what the image shows and its purpose (e.g., "UI mockup showing login form with email/password fields", ` +
`"Architecture diagram of microservices", "Screenshot of error message in terminal").\n\n` +
`Respond with ONLY the description text, no additional formatting, preamble, or explanation.`;
// Get customized prompts from settings
const prompts = await getPromptCustomization(settingsService, '[DescribeImage]');
// Build the instruction text from centralized prompts
const instructionText = prompts.contextDescription.describeImagePrompt;
// Build prompt based on provider capability
// Some providers (like Cursor) may not support image content blocks

View File

@@ -15,7 +15,7 @@ import { FeatureLoader } from '../../services/feature-loader.js';
import { getAppSpecPath } from '@automaker/platform';
import * as secureFs from '../../lib/secure-fs.js';
import type { SettingsService } from '../../services/settings-service.js';
import { getAutoLoadClaudeMdSetting } from '../../lib/settings-helpers.js';
import { getAutoLoadClaudeMdSetting, getPromptCustomization } from '../../lib/settings-helpers.js';
const logger = createLogger('Suggestions');
@@ -137,11 +137,15 @@ export async function generateSuggestions(
modelOverride?: string,
thinkingLevelOverride?: ThinkingLevel
): Promise<void> {
// Get customized prompts from settings
const prompts = await getPromptCustomization(settingsService, '[Suggestions]');
// Map suggestion types to their prompts
const typePrompts: Record<string, string> = {
features: 'Analyze this project and suggest new features that would add value.',
refactoring: 'Analyze this project and identify refactoring opportunities.',
security: 'Analyze this project for security vulnerabilities and suggest fixes.',
performance: 'Analyze this project for performance issues and suggest optimizations.',
features: prompts.suggestions.featuresPrompt,
refactoring: prompts.suggestions.refactoringPrompt,
security: prompts.suggestions.securityPrompt,
performance: prompts.suggestions.performancePrompt,
};
// Load existing context to avoid duplicates
@@ -151,15 +155,7 @@ export async function generateSuggestions(
${existingContext}
${existingContext ? '\nIMPORTANT: Do NOT suggest features that are already implemented or already in the backlog above. Focus on NEW ideas that complement what already exists.\n' : ''}
Look at the codebase and provide 3-5 concrete suggestions.
For each suggestion, provide:
1. A category (e.g., "User Experience", "Security", "Performance")
2. A clear description of what to implement
3. Priority (1=high, 2=medium, 3=low)
4. Brief reasoning for why this would help
The response will be automatically formatted as structured JSON.`;
${prompts.suggestions.baseTemplate}`;
// Don't send initial message - let the agent output speak for itself
// The first agent message will be captured as an info entry

View File

@@ -13,6 +13,13 @@ import {
Info,
AlertTriangle,
GitCommitHorizontal,
Type,
CheckCircle,
Lightbulb,
FileCode,
FileText,
Wand2,
Cog,
} from 'lucide-react';
import { cn } from '@/lib/utils';
import type { PromptCustomization, CustomPrompt } from '@automaker/types';
@@ -22,6 +29,13 @@ import {
DEFAULT_BACKLOG_PLAN_PROMPTS,
DEFAULT_ENHANCEMENT_PROMPTS,
DEFAULT_COMMIT_MESSAGE_PROMPTS,
DEFAULT_TITLE_GENERATION_PROMPTS,
DEFAULT_ISSUE_VALIDATION_PROMPTS,
DEFAULT_IDEATION_PROMPTS,
DEFAULT_APP_SPEC_PROMPTS,
DEFAULT_CONTEXT_DESCRIPTION_PROMPTS,
DEFAULT_SUGGESTIONS_PROMPTS,
DEFAULT_TASK_EXECUTION_PROMPTS,
} from '@automaker/prompts';
interface PromptCustomizationSectionProps {
@@ -221,7 +235,7 @@ export function PromptCustomizationSection({
{/* Tabs */}
<div className="p-6">
<Tabs value={activeTab} onValueChange={setActiveTab}>
<TabsList className="grid grid-cols-5 w-full">
<TabsList className="grid grid-cols-4 gap-1 h-auto w-full bg-transparent p-0">
<TabsTrigger value="auto-mode" className="gap-2">
<Bot className="w-4 h-4" />
Auto Mode
@@ -232,7 +246,7 @@ export function PromptCustomizationSection({
</TabsTrigger>
<TabsTrigger value="backlog-plan" className="gap-2">
<KanbanSquare className="w-4 h-4" />
Backlog Plan
Backlog
</TabsTrigger>
<TabsTrigger value="enhancement" className="gap-2">
<Sparkles className="w-4 h-4" />
@@ -242,6 +256,34 @@ export function PromptCustomizationSection({
<GitCommitHorizontal className="w-4 h-4" />
Commit
</TabsTrigger>
<TabsTrigger value="title-generation" className="gap-2">
<Type className="w-4 h-4" />
Title
</TabsTrigger>
<TabsTrigger value="issue-validation" className="gap-2">
<CheckCircle className="w-4 h-4" />
Issues
</TabsTrigger>
<TabsTrigger value="ideation" className="gap-2">
<Lightbulb className="w-4 h-4" />
Ideation
</TabsTrigger>
<TabsTrigger value="app-spec" className="gap-2">
<FileCode className="w-4 h-4" />
App Spec
</TabsTrigger>
<TabsTrigger value="context-description" className="gap-2">
<FileText className="w-4 h-4" />
Context
</TabsTrigger>
<TabsTrigger value="suggestions" className="gap-2">
<Wand2 className="w-4 h-4" />
Suggestions
</TabsTrigger>
<TabsTrigger value="task-execution" className="gap-2">
<Cog className="w-4 h-4" />
Tasks
</TabsTrigger>
</TabsList>
{/* Auto Mode Tab */}
@@ -313,6 +355,71 @@ export function PromptCustomizationSection({
critical={true}
/>
</div>
{/* Template Prompts Section */}
<div className="pt-4 border-t border-border/50">
<h4 className="text-sm font-medium text-muted-foreground mb-4">Template Prompts</h4>
{/* Info Banner for Templates */}
<div className="flex items-start gap-3 p-4 rounded-xl bg-blue-500/10 border border-blue-500/20 mb-4">
<Info className="w-5 h-5 text-blue-500 mt-0.5 flex-shrink-0" />
<div className="space-y-1">
<p className="text-sm text-foreground font-medium">Template Variables</p>
<p className="text-xs text-muted-foreground/80 leading-relaxed">
Template prompts use Handlebars syntax for variable substitution. Available
variables include{' '}
<code className="px-1 py-0.5 rounded bg-muted text-xs">{'{{featureId}}'}</code>,{' '}
<code className="px-1 py-0.5 rounded bg-muted text-xs">{'{{title}}'}</code>,{' '}
<code className="px-1 py-0.5 rounded bg-muted text-xs">
{'{{description}}'}
</code>
, etc.
</p>
</div>
</div>
<div className="space-y-4">
<PromptField
label="Feature Prompt Template"
description="Template for building feature implementation prompts. Variables: featureId, title, description, spec, imagePaths, dependencies, verificationInstructions"
defaultValue={DEFAULT_AUTO_MODE_PROMPTS.featurePromptTemplate}
customValue={promptCustomization?.autoMode?.featurePromptTemplate}
onCustomValueChange={(value) =>
updatePrompt('autoMode', 'featurePromptTemplate', value)
}
/>
<PromptField
label="Follow-up Prompt Template"
description="Template for follow-up prompts when resuming work. Variables: featurePrompt, previousContext, followUpInstructions"
defaultValue={DEFAULT_AUTO_MODE_PROMPTS.followUpPromptTemplate}
customValue={promptCustomization?.autoMode?.followUpPromptTemplate}
onCustomValueChange={(value) =>
updatePrompt('autoMode', 'followUpPromptTemplate', value)
}
/>
<PromptField
label="Continuation Prompt Template"
description="Template for continuation prompts. Variables: featurePrompt, previousContext"
defaultValue={DEFAULT_AUTO_MODE_PROMPTS.continuationPromptTemplate}
customValue={promptCustomization?.autoMode?.continuationPromptTemplate}
onCustomValueChange={(value) =>
updatePrompt('autoMode', 'continuationPromptTemplate', value)
}
/>
<PromptField
label="Pipeline Step Prompt Template"
description="Template for pipeline step execution prompts. Variables: stepName, featurePrompt, previousContext, stepInstructions"
defaultValue={DEFAULT_AUTO_MODE_PROMPTS.pipelineStepPromptTemplate}
customValue={promptCustomization?.autoMode?.pipelineStepPromptTemplate}
onCustomValueChange={(value) =>
updatePrompt('autoMode', 'pipelineStepPromptTemplate', value)
}
/>
</div>
</div>
</TabsContent>
{/* Agent Tab */}
@@ -379,6 +486,17 @@ export function PromptCustomizationSection({
onCustomValueChange={(value) => updatePrompt('backlogPlan', 'systemPrompt', value)}
critical={true}
/>
<PromptField
label="User Prompt Template"
description="Template for the user prompt sent to the AI. Variables: currentFeatures, userRequest"
defaultValue={DEFAULT_BACKLOG_PLAN_PROMPTS.userPromptTemplate}
customValue={promptCustomization?.backlogPlan?.userPromptTemplate}
onCustomValueChange={(value) =>
updatePrompt('backlogPlan', 'userPromptTemplate', value)
}
critical={true}
/>
</div>
</TabsContent>
@@ -477,6 +595,402 @@ export function PromptCustomizationSection({
/>
</div>
</TabsContent>
{/* Title Generation Tab */}
<TabsContent value="title-generation" className="space-y-6 mt-6">
<div className="flex items-center justify-between mb-4">
<h3 className="text-sm font-medium text-foreground">Title Generation Prompts</h3>
<Button
variant="ghost"
size="sm"
onClick={() => resetToDefaults('titleGeneration')}
className="gap-2"
>
<RotateCcw className="w-3 h-3" />
Reset Section
</Button>
</div>
<div className="space-y-4">
<PromptField
label="System Prompt"
description="Instructions for generating concise, descriptive feature titles from descriptions. Used when auto-generating titles for new features."
defaultValue={DEFAULT_TITLE_GENERATION_PROMPTS.systemPrompt}
customValue={promptCustomization?.titleGeneration?.systemPrompt}
onCustomValueChange={(value) =>
updatePrompt('titleGeneration', 'systemPrompt', value)
}
/>
</div>
</TabsContent>
{/* Issue Validation Tab */}
<TabsContent value="issue-validation" className="space-y-6 mt-6">
<div className="flex items-center justify-between mb-4">
<h3 className="text-sm font-medium text-foreground">Issue Validation Prompts</h3>
<Button
variant="ghost"
size="sm"
onClick={() => resetToDefaults('issueValidation')}
className="gap-2"
>
<RotateCcw className="w-3 h-3" />
Reset Section
</Button>
</div>
{/* Critical Warning for Issue Validation */}
<div className="flex items-start gap-3 p-4 rounded-xl bg-amber-500/10 border border-amber-500/20">
<AlertTriangle className="w-5 h-5 text-amber-500 mt-0.5 flex-shrink-0" />
<div className="space-y-1">
<p className="text-sm text-foreground font-medium">Warning: Critical Prompt</p>
<p className="text-xs text-muted-foreground/80 leading-relaxed">
The issue validation prompt guides the AI through a structured validation process
and expects specific output format. Modifying this prompt incorrectly may affect
validation accuracy.
</p>
</div>
</div>
<div className="space-y-4">
<PromptField
label="System Prompt"
description="Instructions for validating GitHub issues against the codebase. Guides the AI to determine if issues are valid, invalid, or need clarification."
defaultValue={DEFAULT_ISSUE_VALIDATION_PROMPTS.systemPrompt}
customValue={promptCustomization?.issueValidation?.systemPrompt}
onCustomValueChange={(value) =>
updatePrompt('issueValidation', 'systemPrompt', value)
}
critical={true}
/>
</div>
</TabsContent>
{/* Ideation Tab */}
<TabsContent value="ideation" className="space-y-6 mt-6">
<div className="flex items-center justify-between mb-4">
<h3 className="text-sm font-medium text-foreground">Ideation Prompts</h3>
<Button
variant="ghost"
size="sm"
onClick={() => resetToDefaults('ideation')}
className="gap-2"
>
<RotateCcw className="w-3 h-3" />
Reset Section
</Button>
</div>
<div className="space-y-4">
<PromptField
label="Ideation Chat System Prompt"
description="System prompt for AI-powered ideation chat conversations. Guides the AI to brainstorm and suggest feature ideas."
defaultValue={DEFAULT_IDEATION_PROMPTS.ideationSystemPrompt}
customValue={promptCustomization?.ideation?.ideationSystemPrompt}
onCustomValueChange={(value) =>
updatePrompt('ideation', 'ideationSystemPrompt', value)
}
/>
<PromptField
label="Suggestions System Prompt"
description="System prompt for generating structured feature suggestions. Used when generating batch suggestions from prompts."
defaultValue={DEFAULT_IDEATION_PROMPTS.suggestionsSystemPrompt}
customValue={promptCustomization?.ideation?.suggestionsSystemPrompt}
onCustomValueChange={(value) =>
updatePrompt('ideation', 'suggestionsSystemPrompt', value)
}
critical={true}
/>
</div>
</TabsContent>
{/* App Spec Tab */}
<TabsContent value="app-spec" className="space-y-6 mt-6">
<div className="flex items-center justify-between mb-4">
<h3 className="text-sm font-medium text-foreground">App Specification Prompts</h3>
<Button
variant="ghost"
size="sm"
onClick={() => resetToDefaults('appSpec')}
className="gap-2"
>
<RotateCcw className="w-3 h-3" />
Reset Section
</Button>
</div>
<div className="space-y-4">
<PromptField
label="Generate Spec System Prompt"
description="System prompt for generating project specifications from overview"
defaultValue={DEFAULT_APP_SPEC_PROMPTS.generateSpecSystemPrompt}
customValue={promptCustomization?.appSpec?.generateSpecSystemPrompt}
onCustomValueChange={(value) =>
updatePrompt('appSpec', 'generateSpecSystemPrompt', value)
}
/>
<PromptField
label="Structured Spec Instructions"
description="Instructions for structured specification output format"
defaultValue={DEFAULT_APP_SPEC_PROMPTS.structuredSpecInstructions}
customValue={promptCustomization?.appSpec?.structuredSpecInstructions}
onCustomValueChange={(value) =>
updatePrompt('appSpec', 'structuredSpecInstructions', value)
}
critical={true}
/>
<PromptField
label="Generate Features from Spec"
description="Prompt for generating features from a project specification"
defaultValue={DEFAULT_APP_SPEC_PROMPTS.generateFeaturesFromSpecPrompt}
customValue={promptCustomization?.appSpec?.generateFeaturesFromSpecPrompt}
onCustomValueChange={(value) =>
updatePrompt('appSpec', 'generateFeaturesFromSpecPrompt', value)
}
critical={true}
/>
</div>
</TabsContent>
{/* Context Description Tab */}
<TabsContent value="context-description" className="space-y-6 mt-6">
<div className="flex items-center justify-between mb-4">
<h3 className="text-sm font-medium text-foreground">Context Description Prompts</h3>
<Button
variant="ghost"
size="sm"
onClick={() => resetToDefaults('contextDescription')}
className="gap-2"
>
<RotateCcw className="w-3 h-3" />
Reset Section
</Button>
</div>
<div className="space-y-4">
<PromptField
label="Describe File Prompt"
description="Prompt for generating descriptions of text files added as context"
defaultValue={DEFAULT_CONTEXT_DESCRIPTION_PROMPTS.describeFilePrompt}
customValue={promptCustomization?.contextDescription?.describeFilePrompt}
onCustomValueChange={(value) =>
updatePrompt('contextDescription', 'describeFilePrompt', value)
}
/>
<PromptField
label="Describe Image Prompt"
description="Prompt for generating descriptions of images added as context"
defaultValue={DEFAULT_CONTEXT_DESCRIPTION_PROMPTS.describeImagePrompt}
customValue={promptCustomization?.contextDescription?.describeImagePrompt}
onCustomValueChange={(value) =>
updatePrompt('contextDescription', 'describeImagePrompt', value)
}
/>
</div>
</TabsContent>
{/* Suggestions Tab */}
<TabsContent value="suggestions" className="space-y-6 mt-6">
<div className="flex items-center justify-between mb-4">
<h3 className="text-sm font-medium text-foreground">Suggestions Prompts</h3>
<Button
variant="ghost"
size="sm"
onClick={() => resetToDefaults('suggestions')}
className="gap-2"
>
<RotateCcw className="w-3 h-3" />
Reset Section
</Button>
</div>
<div className="space-y-4">
<PromptField
label="Features Suggestion Prompt"
description="Prompt for analyzing the project and suggesting new features"
defaultValue={DEFAULT_SUGGESTIONS_PROMPTS.featuresPrompt}
customValue={promptCustomization?.suggestions?.featuresPrompt}
onCustomValueChange={(value) =>
updatePrompt('suggestions', 'featuresPrompt', value)
}
/>
<PromptField
label="Refactoring Suggestion Prompt"
description="Prompt for identifying refactoring opportunities"
defaultValue={DEFAULT_SUGGESTIONS_PROMPTS.refactoringPrompt}
customValue={promptCustomization?.suggestions?.refactoringPrompt}
onCustomValueChange={(value) =>
updatePrompt('suggestions', 'refactoringPrompt', value)
}
/>
<PromptField
label="Security Suggestion Prompt"
description="Prompt for analyzing security vulnerabilities"
defaultValue={DEFAULT_SUGGESTIONS_PROMPTS.securityPrompt}
customValue={promptCustomization?.suggestions?.securityPrompt}
onCustomValueChange={(value) =>
updatePrompt('suggestions', 'securityPrompt', value)
}
/>
<PromptField
label="Performance Suggestion Prompt"
description="Prompt for identifying performance issues"
defaultValue={DEFAULT_SUGGESTIONS_PROMPTS.performancePrompt}
customValue={promptCustomization?.suggestions?.performancePrompt}
onCustomValueChange={(value) =>
updatePrompt('suggestions', 'performancePrompt', value)
}
/>
<PromptField
label="Base Template"
description="Base template applied to all suggestion types"
defaultValue={DEFAULT_SUGGESTIONS_PROMPTS.baseTemplate}
customValue={promptCustomization?.suggestions?.baseTemplate}
onCustomValueChange={(value) => updatePrompt('suggestions', 'baseTemplate', value)}
/>
</div>
</TabsContent>
{/* Task Execution Tab */}
<TabsContent value="task-execution" className="space-y-6 mt-6">
<div className="flex items-center justify-between mb-4">
<h3 className="text-sm font-medium text-foreground">Task Execution Prompts</h3>
<Button
variant="ghost"
size="sm"
onClick={() => resetToDefaults('taskExecution')}
className="gap-2"
>
<RotateCcw className="w-3 h-3" />
Reset Section
</Button>
</div>
{/* Info Banner for Task Execution */}
<div className="flex items-start gap-3 p-4 rounded-xl bg-blue-500/10 border border-blue-500/20">
<Info className="w-5 h-5 text-blue-500 mt-0.5 flex-shrink-0" />
<div className="space-y-1">
<p className="text-sm text-foreground font-medium">Template Variables</p>
<p className="text-xs text-muted-foreground/80 leading-relaxed">
Task execution prompts use Handlebars syntax for variable substitution. Variables
include{' '}
<code className="px-1 py-0.5 rounded bg-muted text-xs">{'{{taskId}}'}</code>,{' '}
<code className="px-1 py-0.5 rounded bg-muted text-xs">
{'{{taskDescription}}'}
</code>
,{' '}
<code className="px-1 py-0.5 rounded bg-muted text-xs">
{'{{completedTasks}}'}
</code>
, etc.
</p>
</div>
</div>
<div className="space-y-4">
<PromptField
label="Task Prompt Template"
description="Template for building individual task execution prompts"
defaultValue={DEFAULT_TASK_EXECUTION_PROMPTS.taskPromptTemplate}
customValue={promptCustomization?.taskExecution?.taskPromptTemplate}
onCustomValueChange={(value) =>
updatePrompt('taskExecution', 'taskPromptTemplate', value)
}
/>
<PromptField
label="Implementation Instructions"
description="Instructions appended to feature implementation prompts"
defaultValue={DEFAULT_TASK_EXECUTION_PROMPTS.implementationInstructions}
customValue={promptCustomization?.taskExecution?.implementationInstructions}
onCustomValueChange={(value) =>
updatePrompt('taskExecution', 'implementationInstructions', value)
}
/>
<PromptField
label="Playwright Verification Instructions"
description="Instructions for automated Playwright verification (when enabled)"
defaultValue={DEFAULT_TASK_EXECUTION_PROMPTS.playwrightVerificationInstructions}
customValue={promptCustomization?.taskExecution?.playwrightVerificationInstructions}
onCustomValueChange={(value) =>
updatePrompt('taskExecution', 'playwrightVerificationInstructions', value)
}
/>
<PromptField
label="Learning Extraction System Prompt"
description="System prompt for extracting learnings/ADRs from implementation output"
defaultValue={DEFAULT_TASK_EXECUTION_PROMPTS.learningExtractionSystemPrompt}
customValue={promptCustomization?.taskExecution?.learningExtractionSystemPrompt}
onCustomValueChange={(value) =>
updatePrompt('taskExecution', 'learningExtractionSystemPrompt', value)
}
critical={true}
/>
<PromptField
label="Learning Extraction User Template"
description="User prompt template for learning extraction. Variables: featureTitle, implementationLog"
defaultValue={DEFAULT_TASK_EXECUTION_PROMPTS.learningExtractionUserPromptTemplate}
customValue={
promptCustomization?.taskExecution?.learningExtractionUserPromptTemplate
}
onCustomValueChange={(value) =>
updatePrompt('taskExecution', 'learningExtractionUserPromptTemplate', value)
}
critical={true}
/>
<PromptField
label="Plan Revision Template"
description="Template for prompting plan revisions. Variables: planVersion, previousPlan, userFeedback"
defaultValue={DEFAULT_TASK_EXECUTION_PROMPTS.planRevisionTemplate}
customValue={promptCustomization?.taskExecution?.planRevisionTemplate}
onCustomValueChange={(value) =>
updatePrompt('taskExecution', 'planRevisionTemplate', value)
}
/>
<PromptField
label="Continuation After Approval Template"
description="Template for continuation after plan approval. Variables: userFeedback, approvedPlan"
defaultValue={DEFAULT_TASK_EXECUTION_PROMPTS.continuationAfterApprovalTemplate}
customValue={promptCustomization?.taskExecution?.continuationAfterApprovalTemplate}
onCustomValueChange={(value) =>
updatePrompt('taskExecution', 'continuationAfterApprovalTemplate', value)
}
/>
<PromptField
label="Resume Feature Template"
description="Template for resuming interrupted features. Variables: featurePrompt, previousContext"
defaultValue={DEFAULT_TASK_EXECUTION_PROMPTS.resumeFeatureTemplate}
customValue={promptCustomization?.taskExecution?.resumeFeatureTemplate}
onCustomValueChange={(value) =>
updatePrompt('taskExecution', 'resumeFeatureTemplate', value)
}
/>
<PromptField
label="Project Analysis Prompt"
description="Prompt for AI-powered project analysis"
defaultValue={DEFAULT_TASK_EXECUTION_PROMPTS.projectAnalysisPrompt}
customValue={promptCustomization?.taskExecution?.projectAnalysisPrompt}
onCustomValueChange={(value) =>
updatePrompt('taskExecution', 'projectAnalysisPrompt', value)
}
/>
</div>
</TabsContent>
</Tabs>
</div>
</div>