Overhaul updates for appspec & feature generation. Added detail back to kanban feature creation

This commit is contained in:
trueheads
2025-12-11 03:40:16 -06:00
parent c198c10244
commit 8d6f825c5c
4 changed files with 115 additions and 42 deletions

View File

@@ -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}"` : ""
}`
);

View File

@@ -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}`);

View File

@@ -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:**

View File

@@ -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;