mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-31 06:42:03 +00:00
Overhaul updates for appspec & feature generation. Added detail back to kanban feature creation
This commit is contained in:
@@ -384,20 +384,30 @@ class FeatureLoader {
|
||||
* @param {string} projectPath - Path to the project
|
||||
* @param {string} [summary] - Optional summary of what was done
|
||||
* @param {string} [error] - Optional error message if feature errored
|
||||
* @param {string} [description] - Optional detailed description
|
||||
* @param {string} [category] - Optional category/phase
|
||||
* @param {string[]} [steps] - Optional array of implementation steps
|
||||
*/
|
||||
async updateFeatureStatus(featureId, status, projectPath, summary, error) {
|
||||
async updateFeatureStatus(featureId, status, projectPath, summary, error, description, category, steps) {
|
||||
// Check if feature exists
|
||||
const existingFeature = await this.get(projectPath, featureId);
|
||||
|
||||
if (!existingFeature) {
|
||||
// Feature doesn't exist - create it
|
||||
// Feature doesn't exist - create it with all required fields
|
||||
console.log(`[FeatureLoader] Feature ${featureId} not found - creating new feature`);
|
||||
const newFeature = {
|
||||
id: featureId,
|
||||
title: featureId.split('-').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' '),
|
||||
description: summary || '', // Use summary as description for display
|
||||
description: description || summary || '', // Use provided description, fall back to summary
|
||||
category: category || "Uncategorized",
|
||||
steps: steps || [],
|
||||
status: status,
|
||||
summary: summary || '',
|
||||
images: [],
|
||||
imagePaths: [],
|
||||
skipTests: true,
|
||||
model: "sonnet",
|
||||
thinkingLevel: "none",
|
||||
summary: summary || description || '',
|
||||
createdAt: new Date().toISOString(),
|
||||
};
|
||||
if (error !== undefined) {
|
||||
@@ -405,7 +415,7 @@ class FeatureLoader {
|
||||
}
|
||||
await this.create(projectPath, newFeature);
|
||||
console.log(
|
||||
`[FeatureLoader] Created feature ${featureId}: status=${status}${
|
||||
`[FeatureLoader] Created feature ${featureId}: status=${status}, category=${category || "Uncategorized"}, steps=${steps?.length || 0}${
|
||||
summary ? `, summary="${summary}"` : ""
|
||||
}`
|
||||
);
|
||||
@@ -421,6 +431,15 @@ class FeatureLoader {
|
||||
updates.description = summary;
|
||||
}
|
||||
}
|
||||
if (description !== undefined) {
|
||||
updates.description = description;
|
||||
}
|
||||
if (category !== undefined) {
|
||||
updates.category = category;
|
||||
}
|
||||
if (steps !== undefined && Array.isArray(steps)) {
|
||||
updates.steps = steps;
|
||||
}
|
||||
if (error !== undefined) {
|
||||
updates.error = error;
|
||||
} else {
|
||||
@@ -429,10 +448,21 @@ class FeatureLoader {
|
||||
updates.error = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure required fields exist (for features created before this fix)
|
||||
if (!existingFeature.category && !updates.category) updates.category = "Uncategorized";
|
||||
if (!existingFeature.steps && !updates.steps) updates.steps = [];
|
||||
if (!existingFeature.images) updates.images = [];
|
||||
if (!existingFeature.imagePaths) updates.imagePaths = [];
|
||||
if (existingFeature.skipTests === undefined) updates.skipTests = true;
|
||||
if (!existingFeature.model) updates.model = "sonnet";
|
||||
if (!existingFeature.thinkingLevel) updates.thinkingLevel = "none";
|
||||
|
||||
await this.update(projectPath, featureId, updates);
|
||||
console.log(
|
||||
`[FeatureLoader] Updated feature ${featureId}: status=${status}${
|
||||
category ? `, category="${category}"` : ""
|
||||
}${steps ? `, steps=${steps.length}` : ""}${
|
||||
summary ? `, summary="${summary}"` : ""
|
||||
}`
|
||||
);
|
||||
|
||||
@@ -19,15 +19,18 @@ class McpServerFactory {
|
||||
tools: [
|
||||
tool(
|
||||
"UpdateFeatureStatus",
|
||||
"Update the status of a feature. Use this tool instead of directly modifying feature files to safely update feature status. IMPORTANT: If the feature has skipTests=true, you should NOT mark it as verified - instead it will automatically go to waiting_approval status for manual review. Always include a summary of what was done.",
|
||||
"Create or update a feature. Use this tool to create new features with detailed information or update existing feature status. When creating features, provide comprehensive description, category, and implementation steps.",
|
||||
{
|
||||
featureId: z.string().describe("The ID of the feature to update"),
|
||||
status: z.enum(["backlog", "in_progress", "verified"]).describe("The new status for the feature. Note: If skipTests=true, verified will be converted to waiting_approval automatically."),
|
||||
summary: z.string().optional().describe("A brief summary of what was implemented/changed. This will be displayed on the Kanban card. Example: 'Added dark mode toggle. Modified: settings.tsx, theme-provider.tsx'")
|
||||
featureId: z.string().describe("The ID of the feature (lowercase, hyphens for spaces). Example: 'user-authentication', 'budget-tracking'"),
|
||||
status: z.enum(["backlog", "todo", "in_progress", "verified"]).describe("The status for the feature. Use 'backlog' or 'todo' for new features."),
|
||||
summary: z.string().optional().describe("A brief summary of what was implemented/changed or what the feature does."),
|
||||
description: z.string().optional().describe("A detailed description of the feature. Be comprehensive - explain what the feature does, its purpose, and key functionality."),
|
||||
category: z.string().optional().describe("The category/phase for this feature. Example: 'Phase 1: Foundation', 'Phase 2: Core Logic', 'Phase 3: Polish', 'Authentication', 'UI/UX'"),
|
||||
steps: z.array(z.string()).optional().describe("Array of implementation steps. Each step should be a clear, actionable task. Example: ['Set up database schema', 'Create API endpoints', 'Build UI components', 'Add validation']")
|
||||
},
|
||||
async (args) => {
|
||||
try {
|
||||
console.log(`[McpServerFactory] UpdateFeatureStatus tool called: featureId=${args.featureId}, status=${args.status}, summary=${args.summary || "(none)"}`);
|
||||
console.log(`[McpServerFactory] UpdateFeatureStatus tool called: featureId=${args.featureId}, status=${args.status}, summary=${args.summary || "(none)"}, category=${args.category || "(none)"}, steps=${args.steps?.length || 0}`);
|
||||
console.log(`[Feature Creation] Creating/updating feature "${args.featureId}" with status "${args.status}"`);
|
||||
|
||||
// Load the feature to check skipTests flag
|
||||
@@ -41,17 +44,30 @@ class McpServerFactory {
|
||||
|
||||
// If agent tries to mark as verified but feature has skipTests=true, convert to waiting_approval
|
||||
let finalStatus = args.status;
|
||||
// Convert 'todo' to 'backlog' for consistency
|
||||
if (finalStatus === "todo") {
|
||||
finalStatus = "backlog";
|
||||
}
|
||||
if (feature && args.status === "verified" && feature.skipTests === true) {
|
||||
console.log(`[McpServerFactory] Feature ${args.featureId} has skipTests=true, converting verified -> waiting_approval`);
|
||||
finalStatus = "waiting_approval";
|
||||
}
|
||||
|
||||
// Call the provided callback to update feature status with summary
|
||||
await updateFeatureStatusCallback(args.featureId, finalStatus, projectPath, args.summary);
|
||||
// Call the provided callback to update feature status with all parameters
|
||||
await updateFeatureStatusCallback(
|
||||
args.featureId,
|
||||
finalStatus,
|
||||
projectPath,
|
||||
args.summary,
|
||||
undefined, // error
|
||||
args.description,
|
||||
args.category,
|
||||
args.steps
|
||||
);
|
||||
|
||||
const statusMessage = finalStatus !== args.status
|
||||
? `Successfully updated feature ${args.featureId} to status "${finalStatus}" (converted from "${args.status}" because skipTests=true)${args.summary ? ` with summary: "${args.summary}"` : ""}`
|
||||
: `Successfully updated feature ${args.featureId} to status "${finalStatus}"${args.summary ? ` with summary: "${args.summary}"` : ""}`;
|
||||
? `Successfully created/updated feature ${args.featureId} to status "${finalStatus}" (converted from "${args.status}")${args.summary ? ` - ${args.summary}` : ""}`
|
||||
: `Successfully created/updated feature ${args.featureId} to status "${finalStatus}"${args.summary ? ` - ${args.summary}` : ""}`;
|
||||
|
||||
console.log(`[Feature Creation] ✓ ${statusMessage}`);
|
||||
|
||||
|
||||
@@ -52,11 +52,11 @@ ${memoryContent}
|
||||
**Current Feature to Implement:**
|
||||
|
||||
ID: ${feature.id}
|
||||
Category: ${feature.category}
|
||||
Description: ${feature.description}
|
||||
Category: ${feature.category || "Uncategorized"}
|
||||
Description: ${feature.description || feature.summary || feature.title || "No description provided"}
|
||||
${skipTestsNote}${imagesNote}${contextFilesPreview}
|
||||
**Steps to Complete:**
|
||||
${feature.steps.map((step, i) => `${i + 1}. ${step}`).join("\n")}
|
||||
${(feature.steps || []).map((step, i) => `${i + 1}. ${step}`).join("\n") || "No specific steps provided - implement based on description"}
|
||||
|
||||
**Your Task:**
|
||||
|
||||
@@ -195,12 +195,12 @@ ${memoryContent}
|
||||
**Feature to Implement/Verify:**
|
||||
|
||||
ID: ${feature.id}
|
||||
Category: ${feature.category}
|
||||
Description: ${feature.description}
|
||||
Category: ${feature.category || "Uncategorized"}
|
||||
Description: ${feature.description || feature.summary || feature.title || "No description provided"}
|
||||
Current Status: ${feature.status}
|
||||
${skipTestsNote}${imagesNote}${contextFilesPreview}
|
||||
**Steps that should be implemented:**
|
||||
${feature.steps.map((step, i) => `${i + 1}. ${step}`).join("\n")}
|
||||
${(feature.steps || []).map((step, i) => `${i + 1}. ${step}`).join("\n") || "No specific steps provided - implement based on description"}
|
||||
|
||||
**Your Task:**
|
||||
|
||||
@@ -335,11 +335,11 @@ ${memoryContent}
|
||||
**Current Feature:**
|
||||
|
||||
ID: ${feature.id}
|
||||
Category: ${feature.category}
|
||||
Description: ${feature.description}
|
||||
Category: ${feature.category || "Uncategorized"}
|
||||
Description: ${feature.description || feature.summary || feature.title || "No description provided"}
|
||||
${skipTestsNote}${imagesNote}${contextFilesPreview}
|
||||
**Steps to Complete:**
|
||||
${feature.steps.map((step, i) => `${i + 1}. ${step}`).join("\n")}
|
||||
${(feature.steps || []).map((step, i) => `${i + 1}. ${step}`).join("\n") || "No specific steps provided - implement based on description"}
|
||||
|
||||
**Previous Work Context:**
|
||||
|
||||
|
||||
@@ -368,24 +368,42 @@ class SpecRegenerationService {
|
||||
|
||||
const options = {
|
||||
model: "claude-sonnet-4-20250514",
|
||||
systemPrompt: `You are a feature management assistant. Your job is to read the app_spec.txt file and create feature entries based on the implementation_roadmap section.
|
||||
systemPrompt: `You are a feature management assistant. Your job is to read the app_spec.txt file and create DETAILED, COMPREHENSIVE feature entries based on the implementation_roadmap section.
|
||||
|
||||
**Your Task:**
|
||||
1. Read the .automaker/app_spec.txt file
|
||||
1. Read the .automaker/app_spec.txt file thoroughly
|
||||
2. Parse the implementation_roadmap section (it contains phases with features listed)
|
||||
3. For each feature listed in the roadmap, use the UpdateFeatureStatus tool to create a feature entry
|
||||
4. Set the initial status to "todo" for all features
|
||||
5. Extract a meaningful summary/description for each feature from the roadmap
|
||||
3. For EACH feature in the roadmap, use the UpdateFeatureStatus tool to create a detailed feature entry
|
||||
4. Set the initial status to "backlog" for all features
|
||||
|
||||
**IMPORTANT - For each feature you MUST provide:**
|
||||
- **featureId**: A descriptive ID (lowercase, hyphens for spaces). Example: "user-authentication", "budget-tracking"
|
||||
- **status**: "backlog" for all new features
|
||||
- **description**: A DETAILED description (2-4 sentences) explaining what the feature does, its purpose, and key functionality
|
||||
- **category**: The phase from the roadmap (e.g., "Phase 1: Foundation", "Phase 2: Core Logic", "Phase 3: Polish")
|
||||
- **steps**: An array of 4-8 clear, actionable implementation steps. Each step should be specific and completable.
|
||||
- **summary**: A brief one-line summary of the feature
|
||||
|
||||
**Example of a well-defined feature:**
|
||||
{
|
||||
"featureId": "user-authentication",
|
||||
"status": "backlog",
|
||||
"description": "Implement secure user authentication system with email/password login, OAuth integration for Google and Facebook, password reset functionality, and session management. This forms the foundation for all user-specific features.",
|
||||
"category": "Phase 1: Foundation",
|
||||
"steps": [
|
||||
"Set up authentication provider (NextAuth.js or similar)",
|
||||
"Configure email/password authentication",
|
||||
"Implement social login (Google, Facebook OAuth)",
|
||||
"Create login and registration UI components",
|
||||
"Add password reset flow with email verification",
|
||||
"Implement session management and token refresh"
|
||||
],
|
||||
"summary": "Secure authentication with email/password and social login"
|
||||
}
|
||||
|
||||
**Feature Storage:**
|
||||
Features are stored in .automaker/features/{id}/feature.json - each feature has its own folder.
|
||||
Use the UpdateFeatureStatus tool to create features. The tool will handle creating the directory structure and feature.json file.
|
||||
|
||||
**Important:**
|
||||
- Create features ONLY from the implementation_roadmap section
|
||||
- Use the UpdateFeatureStatus tool for each feature
|
||||
- Set status to "todo" initially
|
||||
- Use a descriptive featureId based on the feature name (lowercase, hyphens for spaces)`,
|
||||
Use the UpdateFeatureStatus tool to create features with ALL the fields above.`,
|
||||
maxTurns: 50,
|
||||
cwd: projectPath,
|
||||
mcpServers: {
|
||||
@@ -400,15 +418,24 @@ Use the UpdateFeatureStatus tool to create features. The tool will handle creati
|
||||
abortController: abortController,
|
||||
};
|
||||
|
||||
const prompt = `Please read the .automaker/app_spec.txt file and create feature entries for all features listed in the implementation_roadmap section.
|
||||
const prompt = `Please read the .automaker/app_spec.txt file and create DETAILED feature entries for ALL features listed in the implementation_roadmap section.
|
||||
|
||||
For each feature in the roadmap:
|
||||
1. Use the UpdateFeatureStatus tool to create the feature
|
||||
2. Set status to "todo"
|
||||
3. Provide a clear summary/description based on what's in the roadmap
|
||||
4. Use a featureId that's descriptive and follows the pattern: lowercase with hyphens (e.g., "user-authentication", "payment-processing")
|
||||
**Your workflow:**
|
||||
1. Read the app_spec.txt file completely
|
||||
2. Identify ALL features from the implementation_roadmap section
|
||||
3. For EACH feature, call UpdateFeatureStatus with ALL required fields:
|
||||
|
||||
Start by reading the app_spec.txt file to see the implementation roadmap.`;
|
||||
**Required for each UpdateFeatureStatus call:**
|
||||
- featureId: Descriptive ID (lowercase, hyphens). Example: "user-authentication"
|
||||
- status: "backlog"
|
||||
- description: 2-4 sentences explaining the feature in detail
|
||||
- category: The phase name (e.g., "Phase 1: Foundation", "Phase 2: Core Logic")
|
||||
- steps: Array of 4-8 specific implementation steps
|
||||
- summary: One-line summary
|
||||
|
||||
**Do NOT create features with just a summary - each feature needs description, category, AND steps.**
|
||||
|
||||
Start by reading the app_spec.txt file, then create each feature with full detail.`;
|
||||
|
||||
const currentQuery = query({ prompt, options });
|
||||
execution.query = currentQuery;
|
||||
|
||||
Reference in New Issue
Block a user