mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-03 08:53:36 +00:00
Merge branch 'main' of github.com:webdevcody/automaker
This commit is contained in:
@@ -32,7 +32,7 @@ class AutoModeService {
|
||||
query: null,
|
||||
projectPath: null,
|
||||
sendToRenderer: null,
|
||||
isActive: () => this.runningFeatures.has(featureId)
|
||||
isActive: () => this.runningFeatures.has(featureId),
|
||||
};
|
||||
return context;
|
||||
}
|
||||
@@ -126,7 +126,11 @@ class AutoModeService {
|
||||
console.log(`[AutoMode] Running feature: ${feature.description}`);
|
||||
|
||||
// Update feature status to in_progress
|
||||
await featureLoader.updateFeatureStatus(featureId, "in_progress", projectPath);
|
||||
await featureLoader.updateFeatureStatus(
|
||||
featureId,
|
||||
"in_progress",
|
||||
projectPath
|
||||
);
|
||||
|
||||
sendToRenderer({
|
||||
type: "auto_mode_feature_start",
|
||||
@@ -135,13 +139,28 @@ class AutoModeService {
|
||||
});
|
||||
|
||||
// Implement the feature
|
||||
const result = await featureExecutor.implementFeature(feature, projectPath, sendToRenderer, execution);
|
||||
const result = await featureExecutor.implementFeature(
|
||||
feature,
|
||||
projectPath,
|
||||
sendToRenderer,
|
||||
execution
|
||||
);
|
||||
|
||||
// Update feature status based on result
|
||||
const newStatus = result.passes ? "verified" : "backlog";
|
||||
await featureLoader.updateFeatureStatus(feature.id, newStatus, projectPath);
|
||||
// For skipTests features, go to waiting_approval on success instead of verified
|
||||
let newStatus;
|
||||
if (result.passes) {
|
||||
newStatus = feature.skipTests ? "waiting_approval" : "verified";
|
||||
} else {
|
||||
newStatus = "backlog";
|
||||
}
|
||||
await featureLoader.updateFeatureStatus(
|
||||
feature.id,
|
||||
newStatus,
|
||||
projectPath
|
||||
);
|
||||
|
||||
// Delete context file if verified
|
||||
// Delete context file only if verified (not for waiting_approval)
|
||||
if (newStatus === "verified") {
|
||||
await contextManager.deleteContextFile(projectPath, feature.id);
|
||||
}
|
||||
@@ -208,11 +227,20 @@ class AutoModeService {
|
||||
});
|
||||
|
||||
// Verify the feature by running tests
|
||||
const result = await featureVerifier.verifyFeatureTests(feature, projectPath, sendToRenderer, execution);
|
||||
const result = await featureVerifier.verifyFeatureTests(
|
||||
feature,
|
||||
projectPath,
|
||||
sendToRenderer,
|
||||
execution
|
||||
);
|
||||
|
||||
// Update feature status based on result
|
||||
const newStatus = result.passes ? "verified" : "in_progress";
|
||||
await featureLoader.updateFeatureStatus(featureId, newStatus, projectPath);
|
||||
await featureLoader.updateFeatureStatus(
|
||||
featureId,
|
||||
newStatus,
|
||||
projectPath
|
||||
);
|
||||
|
||||
// Delete context file if verified
|
||||
if (newStatus === "verified") {
|
||||
@@ -281,10 +309,19 @@ class AutoModeService {
|
||||
});
|
||||
|
||||
// Read existing context
|
||||
const previousContext = await contextManager.readContextFile(projectPath, featureId);
|
||||
const previousContext = await contextManager.readContextFile(
|
||||
projectPath,
|
||||
featureId
|
||||
);
|
||||
|
||||
// Resume implementation with context
|
||||
const result = await featureExecutor.resumeFeatureWithContext(feature, projectPath, sendToRenderer, previousContext, execution);
|
||||
const result = await featureExecutor.resumeFeatureWithContext(
|
||||
feature,
|
||||
projectPath,
|
||||
sendToRenderer,
|
||||
previousContext,
|
||||
execution
|
||||
);
|
||||
|
||||
// If the agent ends early without finishing, automatically re-run
|
||||
let attempts = 0;
|
||||
@@ -298,11 +335,16 @@ class AutoModeService {
|
||||
|
||||
if (updatedFeature && updatedFeature.status === "in_progress") {
|
||||
attempts++;
|
||||
console.log(`[AutoMode] Feature ended early, auto-retrying (attempt ${attempts}/${maxAttempts})...`);
|
||||
console.log(
|
||||
`[AutoMode] Feature ended early, auto-retrying (attempt ${attempts}/${maxAttempts})...`
|
||||
);
|
||||
|
||||
// Update context file with retry message
|
||||
await contextManager.writeToContextFile(projectPath, featureId,
|
||||
`\n\n🔄 Auto-retry #${attempts} - Continuing implementation...\n\n`);
|
||||
await contextManager.writeToContextFile(
|
||||
projectPath,
|
||||
featureId,
|
||||
`\n\n🔄 Auto-retry #${attempts} - Continuing implementation...\n\n`
|
||||
);
|
||||
|
||||
sendToRenderer({
|
||||
type: "auto_mode_progress",
|
||||
@@ -311,20 +353,39 @@ class AutoModeService {
|
||||
});
|
||||
|
||||
// Read updated context
|
||||
const retryContext = await contextManager.readContextFile(projectPath, featureId);
|
||||
const retryContext = await contextManager.readContextFile(
|
||||
projectPath,
|
||||
featureId
|
||||
);
|
||||
|
||||
// Resume again with full context
|
||||
finalResult = await featureExecutor.resumeFeatureWithContext(feature, projectPath, sendToRenderer, retryContext, execution);
|
||||
finalResult = await featureExecutor.resumeFeatureWithContext(
|
||||
feature,
|
||||
projectPath,
|
||||
sendToRenderer,
|
||||
retryContext,
|
||||
execution
|
||||
);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update feature status based on final result
|
||||
const newStatus = finalResult.passes ? "verified" : "in_progress";
|
||||
await featureLoader.updateFeatureStatus(featureId, newStatus, projectPath);
|
||||
// For skipTests features, go to waiting_approval on success instead of verified
|
||||
let newStatus;
|
||||
if (finalResult.passes) {
|
||||
newStatus = feature.skipTests ? "waiting_approval" : "verified";
|
||||
} else {
|
||||
newStatus = "in_progress";
|
||||
}
|
||||
await featureLoader.updateFeatureStatus(
|
||||
featureId,
|
||||
newStatus,
|
||||
projectPath
|
||||
);
|
||||
|
||||
// Delete context file if verified
|
||||
// Delete context file only if verified (not for waiting_approval)
|
||||
if (newStatus === "verified") {
|
||||
await contextManager.deleteContextFile(projectPath, featureId);
|
||||
}
|
||||
@@ -377,7 +438,9 @@ class AutoModeService {
|
||||
|
||||
// Skip if this feature is already running (via manual trigger)
|
||||
if (this.runningFeatures.has(currentFeatureId)) {
|
||||
console.log(`[AutoMode] Skipping ${currentFeatureId} - already running`);
|
||||
console.log(
|
||||
`[AutoMode] Skipping ${currentFeatureId} - already running`
|
||||
);
|
||||
await this.sleep(3000);
|
||||
continue;
|
||||
}
|
||||
@@ -397,13 +460,28 @@ class AutoModeService {
|
||||
this.runningFeatures.set(currentFeatureId, execution);
|
||||
|
||||
// Implement the feature
|
||||
const result = await featureExecutor.implementFeature(nextFeature, projectPath, sendToRenderer, execution);
|
||||
const result = await featureExecutor.implementFeature(
|
||||
nextFeature,
|
||||
projectPath,
|
||||
sendToRenderer,
|
||||
execution
|
||||
);
|
||||
|
||||
// Update feature status based on result
|
||||
const newStatus = result.passes ? "verified" : "backlog";
|
||||
await featureLoader.updateFeatureStatus(nextFeature.id, newStatus, projectPath);
|
||||
// For skipTests features, go to waiting_approval on success instead of verified
|
||||
let newStatus;
|
||||
if (result.passes) {
|
||||
newStatus = nextFeature.skipTests ? "waiting_approval" : "verified";
|
||||
} else {
|
||||
newStatus = "backlog";
|
||||
}
|
||||
await featureLoader.updateFeatureStatus(
|
||||
nextFeature.id,
|
||||
newStatus,
|
||||
projectPath
|
||||
);
|
||||
|
||||
// Delete context file if verified
|
||||
// Delete context file only if verified (not for waiting_approval)
|
||||
if (newStatus === "verified") {
|
||||
await contextManager.deleteContextFile(projectPath, nextFeature.id);
|
||||
}
|
||||
@@ -477,7 +555,12 @@ class AutoModeService {
|
||||
});
|
||||
|
||||
// Perform the analysis
|
||||
const result = await projectAnalyzer.runProjectAnalysis(projectPath, analysisId, sendToRenderer, execution);
|
||||
const result = await projectAnalyzer.runProjectAnalysis(
|
||||
projectPath,
|
||||
analysisId,
|
||||
sendToRenderer,
|
||||
execution
|
||||
);
|
||||
|
||||
sendToRenderer({
|
||||
type: "auto_mode_feature_complete",
|
||||
@@ -500,6 +583,239 @@ class AutoModeService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a specific feature by ID
|
||||
*/
|
||||
async stopFeature({ featureId }) {
|
||||
if (!this.runningFeatures.has(featureId)) {
|
||||
return { success: false, error: `Feature ${featureId} is not running` };
|
||||
}
|
||||
|
||||
console.log(`[AutoMode] Stopping feature: ${featureId}`);
|
||||
|
||||
const execution = this.runningFeatures.get(featureId);
|
||||
if (execution && execution.abortController) {
|
||||
execution.abortController.abort();
|
||||
}
|
||||
|
||||
// Clean up
|
||||
this.runningFeatures.delete(featureId);
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
/**
|
||||
* Follow-up on a feature with additional prompt
|
||||
* This continues work on a feature that's in waiting_approval status
|
||||
*/
|
||||
async followUpFeature({
|
||||
projectPath,
|
||||
featureId,
|
||||
prompt,
|
||||
imagePaths,
|
||||
sendToRenderer,
|
||||
}) {
|
||||
// Check if this feature is already running
|
||||
if (this.runningFeatures.has(featureId)) {
|
||||
throw new Error(`Feature ${featureId} is already running`);
|
||||
}
|
||||
|
||||
console.log(
|
||||
`[AutoMode] Follow-up on feature: ${featureId} with prompt: ${prompt}`
|
||||
);
|
||||
|
||||
// Register this feature as running
|
||||
const execution = this.createExecutionContext(featureId);
|
||||
execution.projectPath = projectPath;
|
||||
execution.sendToRenderer = sendToRenderer;
|
||||
this.runningFeatures.set(featureId, execution);
|
||||
|
||||
// Start the async work in the background (don't await)
|
||||
// This allows the API to return immediately so the modal can close
|
||||
this.runFollowUpWork({
|
||||
projectPath,
|
||||
featureId,
|
||||
prompt,
|
||||
imagePaths,
|
||||
sendToRenderer,
|
||||
execution,
|
||||
}).catch((error) => {
|
||||
console.error("[AutoMode] Follow-up work error:", error);
|
||||
this.runningFeatures.delete(featureId);
|
||||
});
|
||||
|
||||
// Return immediately so the frontend can close the modal
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to run follow-up work asynchronously
|
||||
*/
|
||||
async runFollowUpWork({
|
||||
projectPath,
|
||||
featureId,
|
||||
prompt,
|
||||
imagePaths,
|
||||
sendToRenderer,
|
||||
execution,
|
||||
}) {
|
||||
try {
|
||||
// Load features
|
||||
const features = await featureLoader.loadFeatures(projectPath);
|
||||
const feature = features.find((f) => f.id === featureId);
|
||||
|
||||
if (!feature) {
|
||||
throw new Error(`Feature ${featureId} not found`);
|
||||
}
|
||||
|
||||
console.log(`[AutoMode] Following up on feature: ${feature.description}`);
|
||||
|
||||
// Update status to in_progress
|
||||
await featureLoader.updateFeatureStatus(
|
||||
featureId,
|
||||
"in_progress",
|
||||
projectPath
|
||||
);
|
||||
|
||||
sendToRenderer({
|
||||
type: "auto_mode_feature_start",
|
||||
featureId: feature.id,
|
||||
feature: feature,
|
||||
});
|
||||
|
||||
// Read existing context and append follow-up prompt
|
||||
const previousContext = await contextManager.readContextFile(
|
||||
projectPath,
|
||||
featureId
|
||||
);
|
||||
|
||||
// Append follow-up prompt to context
|
||||
const followUpContext = `${previousContext}\n\n## Follow-up Instructions\n\n${prompt}`;
|
||||
await contextManager.writeToContextFile(
|
||||
projectPath,
|
||||
featureId,
|
||||
`\n\n## Follow-up Instructions\n\n${prompt}`
|
||||
);
|
||||
|
||||
// Resume implementation with follow-up context and optional images
|
||||
const result = await featureExecutor.resumeFeatureWithContext(
|
||||
{ ...feature, followUpPrompt: prompt, followUpImages: imagePaths },
|
||||
projectPath,
|
||||
sendToRenderer,
|
||||
followUpContext,
|
||||
execution
|
||||
);
|
||||
|
||||
// For skipTests features, go to waiting_approval on success instead of verified
|
||||
const newStatus = result.passes
|
||||
? feature.skipTests
|
||||
? "waiting_approval"
|
||||
: "verified"
|
||||
: "in_progress";
|
||||
|
||||
await featureLoader.updateFeatureStatus(
|
||||
feature.id,
|
||||
newStatus,
|
||||
projectPath
|
||||
);
|
||||
|
||||
// Delete context file if verified (only for non-skipTests)
|
||||
if (newStatus === "verified") {
|
||||
await contextManager.deleteContextFile(projectPath, feature.id);
|
||||
}
|
||||
|
||||
sendToRenderer({
|
||||
type: "auto_mode_feature_complete",
|
||||
featureId: feature.id,
|
||||
passes: result.passes,
|
||||
message: result.message,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("[AutoMode] Error in follow-up:", error);
|
||||
sendToRenderer({
|
||||
type: "auto_mode_error",
|
||||
error: error.message,
|
||||
featureId: featureId,
|
||||
});
|
||||
} finally {
|
||||
this.runningFeatures.delete(featureId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit changes for a feature without doing additional work
|
||||
* This marks the feature as verified and commits the changes
|
||||
*/
|
||||
async commitFeature({ projectPath, featureId, sendToRenderer }) {
|
||||
console.log(`[AutoMode] Committing feature: ${featureId}`);
|
||||
|
||||
// Register briefly as running for the commit operation
|
||||
const execution = this.createExecutionContext(featureId);
|
||||
execution.projectPath = projectPath;
|
||||
execution.sendToRenderer = sendToRenderer;
|
||||
this.runningFeatures.set(featureId, execution);
|
||||
|
||||
try {
|
||||
// Load feature to get description for commit message
|
||||
const features = await featureLoader.loadFeatures(projectPath);
|
||||
const feature = features.find((f) => f.id === featureId);
|
||||
|
||||
if (!feature) {
|
||||
throw new Error(`Feature ${featureId} not found`);
|
||||
}
|
||||
|
||||
sendToRenderer({
|
||||
type: "auto_mode_feature_start",
|
||||
featureId: feature.id,
|
||||
feature: { ...feature, description: "Committing changes..." },
|
||||
});
|
||||
|
||||
sendToRenderer({
|
||||
type: "auto_mode_phase",
|
||||
featureId,
|
||||
phase: "action",
|
||||
message: "Committing changes to git...",
|
||||
});
|
||||
|
||||
// Run git commit via the agent
|
||||
const commitResult = await featureExecutor.commitChangesOnly(
|
||||
feature,
|
||||
projectPath,
|
||||
sendToRenderer,
|
||||
execution
|
||||
);
|
||||
|
||||
// Update status to verified
|
||||
await featureLoader.updateFeatureStatus(
|
||||
featureId,
|
||||
"verified",
|
||||
projectPath
|
||||
);
|
||||
|
||||
// Delete context file
|
||||
await contextManager.deleteContextFile(projectPath, featureId);
|
||||
|
||||
sendToRenderer({
|
||||
type: "auto_mode_feature_complete",
|
||||
featureId: feature.id,
|
||||
passes: true,
|
||||
message: "Changes committed successfully",
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error("[AutoMode] Error committing feature:", error);
|
||||
sendToRenderer({
|
||||
type: "auto_mode_error",
|
||||
error: error.message,
|
||||
featureId: featureId,
|
||||
});
|
||||
throw error;
|
||||
} finally {
|
||||
this.runningFeatures.delete(featureId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep helper
|
||||
*/
|
||||
|
||||
@@ -500,3 +500,54 @@ ipcMain.handle("auto-mode:analyze-project", async (_, { projectPath }) => {
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Stop a specific feature
|
||||
*/
|
||||
ipcMain.handle("auto-mode:stop-feature", async (_, { featureId }) => {
|
||||
console.log("[IPC] auto-mode:stop-feature called with:", { featureId });
|
||||
try {
|
||||
return await autoModeService.stopFeature({ featureId });
|
||||
} catch (error) {
|
||||
console.error("[IPC] auto-mode:stop-feature error:", error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Follow-up on a feature with additional prompt
|
||||
*/
|
||||
ipcMain.handle("auto-mode:follow-up-feature", async (_, { projectPath, featureId, prompt, imagePaths }) => {
|
||||
console.log("[IPC] auto-mode:follow-up-feature called with:", { projectPath, featureId, prompt, imagePaths });
|
||||
try {
|
||||
const sendToRenderer = (data) => {
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
mainWindow.webContents.send("auto-mode:event", data);
|
||||
}
|
||||
};
|
||||
|
||||
return await autoModeService.followUpFeature({ projectPath, featureId, prompt, imagePaths, sendToRenderer });
|
||||
} catch (error) {
|
||||
console.error("[IPC] auto-mode:follow-up-feature error:", error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Commit changes for a feature (no further work, just commit)
|
||||
*/
|
||||
ipcMain.handle("auto-mode:commit-feature", async (_, { projectPath, featureId }) => {
|
||||
console.log("[IPC] auto-mode:commit-feature called with:", { projectPath, featureId });
|
||||
try {
|
||||
const sendToRenderer = (data) => {
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
mainWindow.webContents.send("auto-mode:event", data);
|
||||
}
|
||||
};
|
||||
|
||||
return await autoModeService.commitFeature({ projectPath, featureId, sendToRenderer });
|
||||
} catch (error) {
|
||||
console.error("[IPC] auto-mode:commit-feature error:", error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
});
|
||||
|
||||
@@ -115,6 +115,18 @@ contextBridge.exposeInMainWorld("electronAPI", {
|
||||
analyzeProject: (projectPath) =>
|
||||
ipcRenderer.invoke("auto-mode:analyze-project", { projectPath }),
|
||||
|
||||
// Stop a specific feature
|
||||
stopFeature: (featureId) =>
|
||||
ipcRenderer.invoke("auto-mode:stop-feature", { featureId }),
|
||||
|
||||
// Follow-up on a feature with additional prompt
|
||||
followUpFeature: (projectPath, featureId, prompt, imagePaths) =>
|
||||
ipcRenderer.invoke("auto-mode:follow-up-feature", { projectPath, featureId, prompt, imagePaths }),
|
||||
|
||||
// Commit changes for a feature
|
||||
commitFeature: (projectPath, featureId) =>
|
||||
ipcRenderer.invoke("auto-mode:commit-feature", { projectPath, featureId }),
|
||||
|
||||
// Listen for auto mode events
|
||||
onEvent: (callback) => {
|
||||
const subscription = (_, data) => callback(data);
|
||||
|
||||
@@ -182,10 +182,12 @@ class FeatureExecutor {
|
||||
content: checkingMsg,
|
||||
});
|
||||
|
||||
// Re-load features to check if it was marked as verified
|
||||
// Re-load features to check if it was marked as verified or waiting_approval (for skipTests)
|
||||
const updatedFeatures = await featureLoader.loadFeatures(projectPath);
|
||||
const updatedFeature = updatedFeatures.find((f) => f.id === feature.id);
|
||||
const passes = updatedFeature?.status === "verified";
|
||||
// For skipTests features, waiting_approval is also considered a success
|
||||
const passes = updatedFeature?.status === "verified" ||
|
||||
(updatedFeature?.skipTests && updatedFeature?.status === "waiting_approval");
|
||||
|
||||
// Send verification result
|
||||
const resultMsg = passes
|
||||
@@ -312,10 +314,12 @@ class FeatureExecutor {
|
||||
execution.query = null;
|
||||
execution.abortController = null;
|
||||
|
||||
// Check if feature was marked as verified
|
||||
// Check if feature was marked as verified or waiting_approval (for skipTests)
|
||||
const updatedFeatures = await featureLoader.loadFeatures(projectPath);
|
||||
const updatedFeature = updatedFeatures.find((f) => f.id === feature.id);
|
||||
const passes = updatedFeature?.status === "verified";
|
||||
// For skipTests features, waiting_approval is also considered a success
|
||||
const passes = updatedFeature?.status === "verified" ||
|
||||
(updatedFeature?.skipTests && updatedFeature?.status === "waiting_approval");
|
||||
|
||||
const finalMsg = passes
|
||||
? "✓ Feature successfully verified and completed\n"
|
||||
@@ -354,6 +358,171 @@ class FeatureExecutor {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit changes for a feature without doing additional work
|
||||
* Analyzes changes and creates a proper conventional commit message
|
||||
*/
|
||||
async commitChangesOnly(feature, projectPath, sendToRenderer, execution) {
|
||||
console.log(`[FeatureExecutor] Committing changes for: ${feature.description}`);
|
||||
|
||||
try {
|
||||
const commitMessage = `\n📝 Committing changes for: ${feature.description}\n`;
|
||||
await contextManager.writeToContextFile(projectPath, feature.id, commitMessage);
|
||||
|
||||
sendToRenderer({
|
||||
type: "auto_mode_progress",
|
||||
featureId: feature.id,
|
||||
content: "Analyzing changes and creating commit...",
|
||||
});
|
||||
|
||||
const abortController = new AbortController();
|
||||
execution.abortController = abortController;
|
||||
|
||||
// Create custom MCP server with UpdateFeatureStatus tool
|
||||
const featureToolsServer = mcpServerFactory.createFeatureToolsServer(
|
||||
featureLoader.updateFeatureStatus.bind(featureLoader),
|
||||
projectPath
|
||||
);
|
||||
|
||||
const options = {
|
||||
model: "claude-sonnet-4-20250514", // Use sonnet for commit task
|
||||
systemPrompt: `You are a git commit assistant that creates professional conventional commit messages.
|
||||
|
||||
IMPORTANT RULES:
|
||||
- DO NOT modify any code
|
||||
- DO NOT write tests
|
||||
- DO NOT do anything except analyzing changes and committing them
|
||||
- Use the git command line tools via Bash
|
||||
- Create proper conventional commit messages based on what was actually changed`,
|
||||
maxTurns: 15, // Allow some turns to analyze and commit
|
||||
cwd: projectPath,
|
||||
mcpServers: {
|
||||
"automaker-tools": featureToolsServer
|
||||
},
|
||||
allowedTools: ["Bash", "mcp__automaker-tools__UpdateFeatureStatus"],
|
||||
permissionMode: "acceptEdits",
|
||||
sandbox: {
|
||||
enabled: false, // Need to run git commands
|
||||
},
|
||||
abortController: abortController,
|
||||
};
|
||||
|
||||
// Prompt that guides the agent to create a proper conventional commit
|
||||
const prompt = `Please commit the current changes with a proper conventional commit message.
|
||||
|
||||
**Feature Context:**
|
||||
Category: ${feature.category}
|
||||
Description: ${feature.description}
|
||||
|
||||
**Your Task:**
|
||||
|
||||
1. First, run \`git status\` to see all untracked and modified files
|
||||
2. Run \`git diff\` to see the actual changes (both staged and unstaged)
|
||||
3. Run \`git log --oneline -5\` to see recent commit message styles in this repo
|
||||
4. Analyze all the changes and draft a proper conventional commit message:
|
||||
- Use conventional commit format: \`type(scope): description\`
|
||||
- Types: feat, fix, refactor, style, docs, test, chore
|
||||
- The description should be concise (under 72 chars) and focus on "what" was done
|
||||
- Summarize the nature of the changes (new feature, enhancement, bug fix, etc.)
|
||||
- Make sure the commit message accurately reflects the actual code changes
|
||||
5. Run \`git add .\` to stage all changes
|
||||
6. Create the commit with a message ending with:
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
|
||||
Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
|
||||
|
||||
Use a HEREDOC for the commit message to ensure proper formatting:
|
||||
\`\`\`bash
|
||||
git commit -m "$(cat <<'EOF'
|
||||
type(scope): Short description here
|
||||
|
||||
Optional longer description if needed.
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
|
||||
Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
|
||||
EOF
|
||||
)"
|
||||
\`\`\`
|
||||
|
||||
**IMPORTANT:**
|
||||
- DO NOT use the feature description verbatim as the commit message
|
||||
- Analyze the actual code changes to determine the appropriate commit message
|
||||
- The commit message should be professional and follow conventional commit standards
|
||||
- DO NOT modify any code or run tests - ONLY commit the existing changes`;
|
||||
|
||||
const currentQuery = query({ prompt, options });
|
||||
execution.query = currentQuery;
|
||||
|
||||
let responseText = "";
|
||||
for await (const msg of currentQuery) {
|
||||
if (!execution.isActive()) break;
|
||||
|
||||
if (msg.type === "assistant" && msg.message?.content) {
|
||||
for (const block of msg.message.content) {
|
||||
if (block.type === "text") {
|
||||
responseText += block.text;
|
||||
|
||||
await contextManager.writeToContextFile(projectPath, feature.id, block.text);
|
||||
|
||||
sendToRenderer({
|
||||
type: "auto_mode_progress",
|
||||
featureId: feature.id,
|
||||
content: block.text,
|
||||
});
|
||||
} else if (block.type === "tool_use") {
|
||||
const toolMsg = `\n🔧 Tool: ${block.name}\n`;
|
||||
await contextManager.writeToContextFile(projectPath, feature.id, toolMsg);
|
||||
|
||||
sendToRenderer({
|
||||
type: "auto_mode_tool",
|
||||
featureId: feature.id,
|
||||
tool: block.name,
|
||||
input: block.input,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
execution.query = null;
|
||||
execution.abortController = null;
|
||||
|
||||
const finalMsg = "✓ Changes committed successfully\n";
|
||||
await contextManager.writeToContextFile(projectPath, feature.id, finalMsg);
|
||||
|
||||
sendToRenderer({
|
||||
type: "auto_mode_progress",
|
||||
featureId: feature.id,
|
||||
content: finalMsg,
|
||||
});
|
||||
|
||||
return {
|
||||
passes: true,
|
||||
message: responseText.substring(0, 500),
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof AbortError || error?.name === "AbortError") {
|
||||
console.log("[FeatureExecutor] Commit aborted");
|
||||
if (execution) {
|
||||
execution.abortController = null;
|
||||
execution.query = null;
|
||||
}
|
||||
return {
|
||||
passes: false,
|
||||
message: "Commit aborted",
|
||||
};
|
||||
}
|
||||
|
||||
console.error("[FeatureExecutor] Error committing feature:", error);
|
||||
if (execution) {
|
||||
execution.abortController = null;
|
||||
execution.query = null;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new FeatureExecutor();
|
||||
|
||||
@@ -32,8 +32,12 @@ class FeatureLoader {
|
||||
|
||||
/**
|
||||
* Update feature status in .automaker/feature_list.json
|
||||
* @param {string} featureId - The ID of the feature to update
|
||||
* @param {string} status - The new status
|
||||
* @param {string} projectPath - Path to the project
|
||||
* @param {string} [summary] - Optional summary of what was done
|
||||
*/
|
||||
async updateFeatureStatus(featureId, status, projectPath) {
|
||||
async updateFeatureStatus(featureId, status, projectPath, summary) {
|
||||
const features = await this.loadFeatures(projectPath);
|
||||
const feature = features.find((f) => f.id === featureId);
|
||||
|
||||
@@ -45,31 +49,56 @@ class FeatureLoader {
|
||||
// Update the status field
|
||||
feature.status = status;
|
||||
|
||||
// Update the summary field if provided
|
||||
if (summary) {
|
||||
feature.summary = summary;
|
||||
}
|
||||
|
||||
// Save back to file
|
||||
const featuresPath = path.join(
|
||||
projectPath,
|
||||
".automaker",
|
||||
"feature_list.json"
|
||||
);
|
||||
const toSave = features.map((f) => ({
|
||||
id: f.id,
|
||||
category: f.category,
|
||||
description: f.description,
|
||||
steps: f.steps,
|
||||
status: f.status,
|
||||
}));
|
||||
const toSave = features.map((f) => {
|
||||
const featureData = {
|
||||
id: f.id,
|
||||
category: f.category,
|
||||
description: f.description,
|
||||
steps: f.steps,
|
||||
status: f.status,
|
||||
};
|
||||
// Preserve optional fields if they exist
|
||||
if (f.skipTests !== undefined) {
|
||||
featureData.skipTests = f.skipTests;
|
||||
}
|
||||
if (f.images !== undefined) {
|
||||
featureData.images = f.images;
|
||||
}
|
||||
if (f.imagePaths !== undefined) {
|
||||
featureData.imagePaths = f.imagePaths;
|
||||
}
|
||||
if (f.startedAt !== undefined) {
|
||||
featureData.startedAt = f.startedAt;
|
||||
}
|
||||
if (f.summary !== undefined) {
|
||||
featureData.summary = f.summary;
|
||||
}
|
||||
return featureData;
|
||||
});
|
||||
|
||||
await fs.writeFile(featuresPath, JSON.stringify(toSave, null, 2), "utf-8");
|
||||
console.log(`[FeatureLoader] Updated feature ${featureId}: status=${status}`);
|
||||
console.log(`[FeatureLoader] Updated feature ${featureId}: status=${status}${summary ? `, summary="${summary}"` : ""}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the next feature to implement
|
||||
* Prioritizes: earlier features in the list that are not verified
|
||||
* Prioritizes: earlier features in the list that are not verified or waiting_approval
|
||||
*/
|
||||
selectNextFeature(features) {
|
||||
// Find first feature that is in backlog or in_progress status
|
||||
return features.find((f) => f.status !== "verified");
|
||||
// Skip verified and waiting_approval (which needs user input)
|
||||
return features.find((f) => f.status !== "verified" && f.status !== "waiting_approval");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,10 +101,12 @@ class FeatureVerifier {
|
||||
execution.query = null;
|
||||
execution.abortController = null;
|
||||
|
||||
// Re-load features to check if it was marked as verified
|
||||
// Re-load features to check if it was marked as verified or waiting_approval (for skipTests)
|
||||
const updatedFeatures = await featureLoader.loadFeatures(projectPath);
|
||||
const updatedFeature = updatedFeatures.find((f) => f.id === feature.id);
|
||||
const passes = updatedFeature?.status === "verified";
|
||||
// For skipTests features, waiting_approval is also considered a success
|
||||
const passes = updatedFeature?.status === "verified" ||
|
||||
(updatedFeature?.skipTests && updatedFeature?.status === "waiting_approval");
|
||||
|
||||
const finalMsg = passes
|
||||
? "✓ Verification successful: All tests passed\n"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const { createSdkMcpServer, tool } = require("@anthropic-ai/claude-agent-sdk");
|
||||
const { z } = require("zod");
|
||||
const featureLoader = require("./feature-loader");
|
||||
|
||||
/**
|
||||
* MCP Server Factory - Creates custom MCP servers with tools
|
||||
@@ -18,22 +19,42 @@ class McpServerFactory {
|
||||
tools: [
|
||||
tool(
|
||||
"UpdateFeatureStatus",
|
||||
"Update the status of a feature in the feature list. Use this tool instead of directly modifying feature_list.json to safely update feature status.",
|
||||
"Update the status of a feature in the feature list. Use this tool instead of directly modifying feature_list.json 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.",
|
||||
{
|
||||
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")
|
||||
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'")
|
||||
},
|
||||
async (args) => {
|
||||
try {
|
||||
console.log(`[McpServerFactory] UpdateFeatureStatus tool called: featureId=${args.featureId}, status=${args.status}`);
|
||||
console.log(`[McpServerFactory] UpdateFeatureStatus tool called: featureId=${args.featureId}, status=${args.status}, summary=${args.summary || "(none)"}`);
|
||||
|
||||
// Call the provided callback to update feature status
|
||||
await updateFeatureStatusCallback(args.featureId, args.status, projectPath);
|
||||
// Load the feature to check skipTests flag
|
||||
const features = await featureLoader.loadFeatures(projectPath);
|
||||
const feature = features.find((f) => f.id === args.featureId);
|
||||
|
||||
if (!feature) {
|
||||
throw new Error(`Feature ${args.featureId} not found`);
|
||||
}
|
||||
|
||||
// If agent tries to mark as verified but feature has skipTests=true, convert to waiting_approval
|
||||
let finalStatus = args.status;
|
||||
if (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);
|
||||
|
||||
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}"` : ""}`;
|
||||
|
||||
return {
|
||||
content: [{
|
||||
type: "text",
|
||||
text: `Successfully updated feature ${args.featureId} to status "${args.status}"`
|
||||
text: statusMessage
|
||||
}]
|
||||
};
|
||||
} catch (error) {
|
||||
|
||||
@@ -6,6 +6,10 @@ class PromptBuilder {
|
||||
* Build the prompt for implementing a specific feature
|
||||
*/
|
||||
buildFeaturePrompt(feature) {
|
||||
const skipTestsNote = feature.skipTests
|
||||
? `\n**⚠️ IMPORTANT - Manual Testing Mode:**\nThis feature has skipTests=true, which means:\n- DO NOT commit changes automatically\n- DO NOT mark as verified - it will automatically go to "waiting_approval" status\n- The user will manually review and commit the changes\n- Just implement the feature and mark it as verified (it will be converted to waiting_approval)\n`
|
||||
: "";
|
||||
|
||||
return `You are working on a feature implementation task.
|
||||
|
||||
**Current Feature to Implement:**
|
||||
@@ -13,7 +17,7 @@ class PromptBuilder {
|
||||
ID: ${feature.id}
|
||||
Category: ${feature.category}
|
||||
Description: ${feature.description}
|
||||
|
||||
${skipTestsNote}
|
||||
**Steps to Complete:**
|
||||
${feature.steps.map((step, i) => `${i + 1}. ${step}`).join("\n")}
|
||||
|
||||
@@ -21,30 +25,64 @@ ${feature.steps.map((step, i) => `${i + 1}. ${step}`).join("\n")}
|
||||
|
||||
1. Read the project files to understand the current codebase structure
|
||||
2. Implement the feature according to the description and steps
|
||||
3. Write Playwright tests to verify the feature works correctly
|
||||
4. Run the tests and ensure they pass
|
||||
5. **DELETE the test file(s) you created** - tests are only for immediate verification
|
||||
6. **CRITICAL: Use the UpdateFeatureStatus tool to mark this feature as verified** - DO NOT manually edit .automaker/feature_list.json
|
||||
7. Commit your changes with git
|
||||
${
|
||||
feature.skipTests
|
||||
? "3. Test the implementation manually (no automated tests needed for skipTests features)"
|
||||
: "3. Write Playwright tests to verify the feature works correctly\n4. Run the tests and ensure they pass\n5. **DELETE the test file(s) you created** - tests are only for immediate verification"
|
||||
}
|
||||
${
|
||||
feature.skipTests ? "4" : "6"
|
||||
}. **CRITICAL: Use the UpdateFeatureStatus tool to mark this feature as verified** - DO NOT manually edit .automaker/feature_list.json
|
||||
${
|
||||
feature.skipTests
|
||||
? "5. **DO NOT commit changes** - the user will review and commit manually"
|
||||
: "7. Commit your changes with git"
|
||||
}
|
||||
|
||||
**IMPORTANT - Updating Feature Status:**
|
||||
|
||||
When you have completed the feature and all tests pass, you MUST use the \`mcp__automaker-tools__UpdateFeatureStatus\` tool to update the feature status:
|
||||
When you have completed the feature${
|
||||
feature.skipTests ? "" : " and all tests pass"
|
||||
}, you MUST use the \`mcp__automaker-tools__UpdateFeatureStatus\` tool to update the feature status:
|
||||
- Call the tool with: featureId="${feature.id}" and status="verified"
|
||||
- **You can also include a summary parameter** to describe what was done: summary="Brief summary of changes"
|
||||
- **DO NOT manually edit the .automaker/feature_list.json file** - this can cause race conditions
|
||||
- The UpdateFeatureStatus tool safely updates the feature status without risk of corrupting other data
|
||||
- **If skipTests=true, the tool will automatically convert "verified" to "waiting_approval"** - this is correct behavior
|
||||
|
||||
**IMPORTANT - Feature Summary (REQUIRED):**
|
||||
|
||||
When calling UpdateFeatureStatus, you MUST include a summary parameter that describes:
|
||||
- What files were modified/created
|
||||
- What functionality was added or changed
|
||||
- Any notable implementation decisions
|
||||
|
||||
Example:
|
||||
\`\`\`
|
||||
UpdateFeatureStatus(featureId="${
|
||||
feature.id
|
||||
}", status="verified", summary="Added dark mode toggle to settings. Modified: settings.tsx, theme-provider.tsx. Created new useTheme hook.")
|
||||
\`\`\`
|
||||
|
||||
The summary will be displayed on the Kanban card so the user can see what was done without checking the code.
|
||||
|
||||
**Important Guidelines:**
|
||||
|
||||
- Focus ONLY on implementing this specific feature
|
||||
- Write clean, production-quality code
|
||||
- Add proper error handling
|
||||
- Write comprehensive Playwright tests
|
||||
- Ensure all existing tests still pass
|
||||
- Mark the feature as passing only when all tests are green
|
||||
- **CRITICAL: Delete test files after verification** - tests accumulate and become brittle
|
||||
${
|
||||
feature.skipTests
|
||||
? "- Skip automated testing (skipTests=true) - user will manually verify"
|
||||
: "- Write comprehensive Playwright tests\n- Ensure all existing tests still pass\n- Mark the feature as passing only when all tests are green\n- **CRITICAL: Delete test files after verification** - tests accumulate and become brittle"
|
||||
}
|
||||
- **CRITICAL: Use UpdateFeatureStatus tool instead of editing feature_list.json directly**
|
||||
- Make a git commit when complete
|
||||
- **CRITICAL: Always include a summary when marking feature as verified**
|
||||
${
|
||||
feature.skipTests
|
||||
? "- **DO NOT commit changes** - user will review and commit manually"
|
||||
: "- Make a git commit when complete"
|
||||
}
|
||||
|
||||
**Testing Utilities (CRITICAL):**
|
||||
|
||||
@@ -75,6 +113,10 @@ Begin by reading the project structure and then implementing the feature.`;
|
||||
* Build the prompt for verifying a specific feature
|
||||
*/
|
||||
buildVerificationPrompt(feature) {
|
||||
const skipTestsNote = feature.skipTests
|
||||
? `\n**⚠️ IMPORTANT - Manual Testing Mode:**\nThis feature has skipTests=true, which means:\n- DO NOT commit changes automatically\n- DO NOT mark as verified - it will automatically go to "waiting_approval" status\n- The user will manually review and commit the changes\n- Just implement the feature and mark it as verified (it will be converted to waiting_approval)\n`
|
||||
: "";
|
||||
|
||||
return `You are implementing and verifying a feature until it is complete and working correctly.
|
||||
|
||||
**Feature to Implement/Verify:**
|
||||
@@ -83,7 +125,7 @@ ID: ${feature.id}
|
||||
Category: ${feature.category}
|
||||
Description: ${feature.description}
|
||||
Current Status: ${feature.status}
|
||||
|
||||
${skipTestsNote}
|
||||
**Steps that should be implemented:**
|
||||
${feature.steps.map((step, i) => `${i + 1}. ${step}`).join("\n")}
|
||||
|
||||
@@ -91,7 +133,10 @@ ${feature.steps.map((step, i) => `${i + 1}. ${step}`).join("\n")}
|
||||
|
||||
1. Read the project files to understand the current implementation
|
||||
2. If the feature is not fully implemented, continue implementing it
|
||||
3. Write or update Playwright tests to verify the feature works correctly
|
||||
${
|
||||
feature.skipTests
|
||||
? "3. Test the implementation manually (no automated tests needed for skipTests features)"
|
||||
: `3. Write or update Playwright tests to verify the feature works correctly
|
||||
4. Run the Playwright tests: npx playwright test tests/[feature-name].spec.ts
|
||||
5. Check if all tests pass
|
||||
6. **If ANY tests fail:**
|
||||
@@ -101,17 +146,43 @@ ${feature.steps.map((step, i) => `${i + 1}. ${step}`).join("\n")}
|
||||
- Re-run the tests to verify the fixes
|
||||
- **REPEAT this process until ALL tests pass**
|
||||
7. **If ALL tests pass:**
|
||||
- **DELETE the test file(s) for this feature** - tests are only for immediate verification
|
||||
- **CRITICAL: Use the UpdateFeatureStatus tool to mark this feature as verified** - DO NOT manually edit .automaker/feature_list.json
|
||||
- Explain what was implemented/fixed and that all tests passed
|
||||
- Commit your changes with git
|
||||
- **DELETE the test file(s) for this feature** - tests are only for immediate verification`
|
||||
}
|
||||
${
|
||||
feature.skipTests ? "4" : "8"
|
||||
}. **CRITICAL: Use the UpdateFeatureStatus tool to mark this feature as verified** - DO NOT manually edit .automaker/feature_list.json
|
||||
${
|
||||
feature.skipTests
|
||||
? "5. **DO NOT commit changes** - the user will review and commit manually"
|
||||
: "9. Explain what was implemented/fixed and that all tests passed\n10. Commit your changes with git"
|
||||
}
|
||||
|
||||
**IMPORTANT - Updating Feature Status:**
|
||||
|
||||
When all tests pass, you MUST use the \`mcp__automaker-tools__UpdateFeatureStatus\` tool to update the feature status:
|
||||
When you have completed the feature${
|
||||
feature.skipTests ? "" : " and all tests pass"
|
||||
}, you MUST use the \`mcp__automaker-tools__UpdateFeatureStatus\` tool to update the feature status:
|
||||
- Call the tool with: featureId="${feature.id}" and status="verified"
|
||||
- **You can also include a summary parameter** to describe what was done: summary="Brief summary of changes"
|
||||
- **DO NOT manually edit the .automaker/feature_list.json file** - this can cause race conditions
|
||||
- The UpdateFeatureStatus tool safely updates the feature status without risk of corrupting other data
|
||||
- **If skipTests=true, the tool will automatically convert "verified" to "waiting_approval"** - this is correct behavior
|
||||
|
||||
**IMPORTANT - Feature Summary (REQUIRED):**
|
||||
|
||||
When calling UpdateFeatureStatus, you MUST include a summary parameter that describes:
|
||||
- What files were modified/created
|
||||
- What functionality was added or changed
|
||||
- Any notable implementation decisions
|
||||
|
||||
Example:
|
||||
\`\`\`
|
||||
UpdateFeatureStatus(featureId="${
|
||||
feature.id
|
||||
}", status="verified", summary="Added dark mode toggle to settings. Modified: settings.tsx, theme-provider.tsx. Created new useTheme hook.")
|
||||
\`\`\`
|
||||
|
||||
The summary will be displayed on the Kanban card so the user can see what was done without checking the code.
|
||||
|
||||
**Testing Utilities:**
|
||||
- Check if tests/utils.ts exists and is being used
|
||||
@@ -126,13 +197,13 @@ rm tests/[feature-name].spec.ts
|
||||
\`\`\`
|
||||
|
||||
**Important:**
|
||||
- **CONTINUE IMPLEMENTING until all tests pass** - don't stop at the first failure
|
||||
- Only mark as "verified" if Playwright tests pass
|
||||
- **CRITICAL: Delete test files after they pass** - tests should not accumulate
|
||||
${
|
||||
feature.skipTests
|
||||
? "- Skip automated testing (skipTests=true) - user will manually verify\n- **DO NOT commit changes** - user will review and commit manually"
|
||||
: "- **CONTINUE IMPLEMENTING until all tests pass** - don't stop at the first failure\n- Only mark as verified if Playwright tests pass\n- **CRITICAL: Delete test files after they pass** - tests should not accumulate\n- Update test utilities if functionality changed\n- Make a git commit when the feature is complete\n- Be thorough and persistent in fixing issues"
|
||||
}
|
||||
- **CRITICAL: Use UpdateFeatureStatus tool instead of editing feature_list.json directly**
|
||||
- Update test utilities if functionality changed
|
||||
- Make a git commit when the feature is complete
|
||||
- Be thorough and persistent in fixing issues
|
||||
- **CRITICAL: Always include a summary when marking feature as verified**
|
||||
|
||||
Begin by reading the project structure and understanding what needs to be implemented or fixed.`;
|
||||
}
|
||||
@@ -141,6 +212,10 @@ Begin by reading the project structure and understanding what needs to be implem
|
||||
* Build prompt for resuming feature with previous context
|
||||
*/
|
||||
buildResumePrompt(feature, previousContext) {
|
||||
const skipTestsNote = feature.skipTests
|
||||
? `\n**⚠️ IMPORTANT - Manual Testing Mode:**\nThis feature has skipTests=true, which means:\n- DO NOT commit changes automatically\n- DO NOT mark as verified - it will automatically go to "waiting_approval" status\n- The user will manually review and commit the changes\n- Just implement the feature and mark it as verified (it will be converted to waiting_approval)\n`
|
||||
: "";
|
||||
|
||||
return `You are resuming work on a feature implementation that was previously started.
|
||||
|
||||
**Current Feature:**
|
||||
@@ -148,7 +223,7 @@ Begin by reading the project structure and understanding what needs to be implem
|
||||
ID: ${feature.id}
|
||||
Category: ${feature.category}
|
||||
Description: ${feature.description}
|
||||
|
||||
${skipTestsNote}
|
||||
**Steps to Complete:**
|
||||
${feature.steps.map((step, i) => `${i + 1}. ${step}`).join("\n")}
|
||||
|
||||
@@ -162,29 +237,64 @@ Continue where you left off and complete the feature implementation:
|
||||
|
||||
1. Review the previous work context above to understand what has been done
|
||||
2. Continue implementing the feature according to the description and steps
|
||||
3. Write Playwright tests to verify the feature works correctly (if not already done)
|
||||
4. Run the tests and ensure they pass
|
||||
5. **DELETE the test file(s) you created** - tests are only for immediate verification
|
||||
6. **CRITICAL: Use the UpdateFeatureStatus tool to mark this feature as verified** - DO NOT manually edit .automaker/feature_list.json
|
||||
7. Commit your changes with git
|
||||
${
|
||||
feature.skipTests
|
||||
? "3. Test the implementation manually (no automated tests needed for skipTests features)"
|
||||
: "3. Write Playwright tests to verify the feature works correctly (if not already done)\n4. Run the tests and ensure they pass\n5. **DELETE the test file(s) you created** - tests are only for immediate verification"
|
||||
}
|
||||
${
|
||||
feature.skipTests ? "4" : "6"
|
||||
}. **CRITICAL: Use the UpdateFeatureStatus tool to mark this feature as verified** - DO NOT manually edit .automaker/feature_list.json
|
||||
${
|
||||
feature.skipTests
|
||||
? "5. **DO NOT commit changes** - the user will review and commit manually"
|
||||
: "7. Commit your changes with git"
|
||||
}
|
||||
|
||||
**IMPORTANT - Updating Feature Status:**
|
||||
|
||||
When all tests pass, you MUST use the \`mcp__automaker-tools__UpdateFeatureStatus\` tool to update the feature status:
|
||||
When you have completed the feature${
|
||||
feature.skipTests ? "" : " and all tests pass"
|
||||
}, you MUST use the \`mcp__automaker-tools__UpdateFeatureStatus\` tool to update the feature status:
|
||||
- Call the tool with: featureId="${feature.id}" and status="verified"
|
||||
- **You can also include a summary parameter** to describe what was done: summary="Brief summary of changes"
|
||||
- **DO NOT manually edit the .automaker/feature_list.json file** - this can cause race conditions
|
||||
- The UpdateFeatureStatus tool safely updates the feature status without risk of corrupting other data
|
||||
- **If skipTests=true, the tool will automatically convert "verified" to "waiting_approval"** - this is correct behavior
|
||||
|
||||
**IMPORTANT - Feature Summary (REQUIRED):**
|
||||
|
||||
When calling UpdateFeatureStatus, you MUST include a summary parameter that describes:
|
||||
- What files were modified/created
|
||||
- What functionality was added or changed
|
||||
- Any notable implementation decisions
|
||||
|
||||
Example:
|
||||
\`\`\`
|
||||
UpdateFeatureStatus(featureId="${
|
||||
feature.id
|
||||
}", status="verified", summary="Added dark mode toggle to settings. Modified: settings.tsx, theme-provider.tsx. Created new useTheme hook.")
|
||||
\`\`\`
|
||||
|
||||
The summary will be displayed on the Kanban card so the user can see what was done without checking the code.
|
||||
|
||||
**Important Guidelines:**
|
||||
|
||||
- Review what was already done in the previous context
|
||||
- Don't redo work that's already complete - continue from where it left off
|
||||
- Focus on completing any remaining tasks
|
||||
- Write comprehensive Playwright tests if not already done
|
||||
- Ensure all tests pass before marking as verified
|
||||
- **CRITICAL: Delete test files after verification**
|
||||
${
|
||||
feature.skipTests
|
||||
? "- Skip automated testing (skipTests=true) - user will manually verify"
|
||||
: "- Write comprehensive Playwright tests if not already done\n- Ensure all tests pass before marking as verified\n- **CRITICAL: Delete test files after verification**"
|
||||
}
|
||||
- **CRITICAL: Use UpdateFeatureStatus tool instead of editing feature_list.json directly**
|
||||
- Make a git commit when complete
|
||||
- **CRITICAL: Always include a summary when marking feature as verified**
|
||||
${
|
||||
feature.skipTests
|
||||
? "- **DO NOT commit changes** - user will review and commit manually"
|
||||
: "- Make a git commit when complete"
|
||||
}
|
||||
|
||||
Begin by assessing what's been done and what remains to be completed.`;
|
||||
}
|
||||
@@ -278,18 +388,38 @@ Begin by exploring the project structure.`;
|
||||
Your role is to:
|
||||
- Implement features exactly as specified
|
||||
- Write production-quality code
|
||||
- Create comprehensive Playwright tests using testing utilities
|
||||
- Ensure all tests pass before marking features complete
|
||||
- **DELETE test files after successful verification** - tests are only for immediate feature verification
|
||||
- Check if feature.skipTests is true - if so, skip automated testing and don't commit
|
||||
- Create comprehensive Playwright tests using testing utilities (only if skipTests is false)
|
||||
- Ensure all tests pass before marking features complete (only if skipTests is false)
|
||||
- **DELETE test files after successful verification** - tests are only for immediate feature verification (only if skipTests is false)
|
||||
- **Use the UpdateFeatureStatus tool to mark features as verified** - NEVER manually edit feature_list.json
|
||||
- Commit working code to git
|
||||
- **Always include a summary parameter when calling UpdateFeatureStatus** - describe what was done
|
||||
- Commit working code to git (only if skipTests is false - skipTests features require manual review)
|
||||
- Be thorough and detail-oriented
|
||||
|
||||
**IMPORTANT - Manual Testing Mode (skipTests=true):**
|
||||
If a feature has skipTests=true:
|
||||
- DO NOT write automated tests
|
||||
- DO NOT commit changes - the user will review and commit manually
|
||||
- Still mark the feature as verified using UpdateFeatureStatus - it will automatically convert to "waiting_approval" for manual review
|
||||
- The user will manually verify and commit the changes
|
||||
|
||||
**IMPORTANT - UpdateFeatureStatus Tool:**
|
||||
You have access to the \`mcp__automaker-tools__UpdateFeatureStatus\` tool. When all tests pass, use this tool to update the feature status:
|
||||
- Call with featureId and status="verified"
|
||||
You have access to the \`mcp__automaker-tools__UpdateFeatureStatus\` tool. When the feature is complete (and all tests pass if skipTests is false), use this tool to update the feature status:
|
||||
- Call with featureId, status="verified", and summary="Description of what was done"
|
||||
- **DO NOT manually edit .automaker/feature_list.json** - this can cause race conditions and restore old state
|
||||
- The tool safely updates the status without corrupting other feature data
|
||||
- **If skipTests=true, the tool will automatically convert "verified" to "waiting_approval"** - this is correct
|
||||
|
||||
**IMPORTANT - Feature Summary (REQUIRED):**
|
||||
When calling UpdateFeatureStatus, you MUST include a summary parameter that describes:
|
||||
- What files were modified/created
|
||||
- What functionality was added or changed
|
||||
- Any notable implementation decisions
|
||||
|
||||
Example: summary="Added dark mode toggle. Modified: settings.tsx, theme-provider.tsx. Created useTheme hook."
|
||||
|
||||
The summary will be displayed on the Kanban card so the user can quickly see what was done.
|
||||
|
||||
**Testing Utilities (CRITICAL):**
|
||||
- **Create and maintain tests/utils.ts** with helper functions for finding elements and common operations
|
||||
@@ -327,21 +457,41 @@ Focus on one feature at a time and complete it fully before finishing. Always de
|
||||
|
||||
Your role is to:
|
||||
- **Continue implementing features until they are complete** - don't stop at the first failure
|
||||
- Write or update code to fix failing tests
|
||||
- Run Playwright tests to verify feature implementations
|
||||
- If tests fail, analyze errors and fix the implementation
|
||||
- If other tests fail, verify if those tests are still accurate or should be updated or deleted
|
||||
- Continue rerunning tests and fixing issues until ALL tests pass
|
||||
- **DELETE test files after successful verification** - tests are only for immediate feature verification
|
||||
- Check if feature.skipTests is true - if so, skip automated testing and don't commit
|
||||
- Write or update code to fix failing tests (only if skipTests is false)
|
||||
- Run Playwright tests to verify feature implementations (only if skipTests is false)
|
||||
- If tests fail, analyze errors and fix the implementation (only if skipTests is false)
|
||||
- If other tests fail, verify if those tests are still accurate or should be updated or deleted (only if skipTests is false)
|
||||
- Continue rerunning tests and fixing issues until ALL tests pass (only if skipTests is false)
|
||||
- **DELETE test files after successful verification** - tests are only for immediate feature verification (only if skipTests is false)
|
||||
- **Use the UpdateFeatureStatus tool to mark features as verified** - NEVER manually edit feature_list.json
|
||||
- **Update test utilities (tests/utils.ts) if functionality changed** - keep helpers in sync with code
|
||||
- Commit working code to git
|
||||
- **Always include a summary parameter when calling UpdateFeatureStatus** - describe what was done
|
||||
- **Update test utilities (tests/utils.ts) if functionality changed** - keep helpers in sync with code (only if skipTests is false)
|
||||
- Commit working code to git (only if skipTests is false - skipTests features require manual review)
|
||||
|
||||
**IMPORTANT - Manual Testing Mode (skipTests=true):**
|
||||
If a feature has skipTests=true:
|
||||
- DO NOT write automated tests
|
||||
- DO NOT commit changes - the user will review and commit manually
|
||||
- Still mark the feature as verified using UpdateFeatureStatus - it will automatically convert to "waiting_approval" for manual review
|
||||
- The user will manually verify and commit the changes
|
||||
|
||||
**IMPORTANT - UpdateFeatureStatus Tool:**
|
||||
You have access to the \`mcp__automaker-tools__UpdateFeatureStatus\` tool. When all tests pass, use this tool to update the feature status:
|
||||
- Call with featureId and status="verified"
|
||||
You have access to the \`mcp__automaker-tools__UpdateFeatureStatus\` tool. When the feature is complete (and all tests pass if skipTests is false), use this tool to update the feature status:
|
||||
- Call with featureId, status="verified", and summary="Description of what was done"
|
||||
- **DO NOT manually edit .automaker/feature_list.json** - this can cause race conditions and restore old state
|
||||
- The tool safely updates the status without corrupting other feature data
|
||||
- **If skipTests=true, the tool will automatically convert "verified" to "waiting_approval"** - this is correct
|
||||
|
||||
**IMPORTANT - Feature Summary (REQUIRED):**
|
||||
When calling UpdateFeatureStatus, you MUST include a summary parameter that describes:
|
||||
- What files were modified/created
|
||||
- What functionality was added or changed
|
||||
- Any notable implementation decisions
|
||||
|
||||
Example: summary="Fixed login validation. Modified: auth.ts, login-form.tsx. Added password strength check."
|
||||
|
||||
The summary will be displayed on the Kanban card so the user can quickly see what was done.
|
||||
|
||||
**Testing Utilities:**
|
||||
- Check if tests/utils.ts needs updates based on code changes
|
||||
@@ -365,7 +515,7 @@ You have access to:
|
||||
- Make git commits
|
||||
- **UpdateFeatureStatus tool** (mcp__automaker-tools__UpdateFeatureStatus) - Use this to update feature status
|
||||
|
||||
**CRITICAL:** Be persistent and thorough - keep iterating on the implementation until all tests pass. Don't give up after the first failure. Always delete tests after they pass, use the UpdateFeatureStatus tool, and commit your work.`;
|
||||
**CRITICAL:** Be persistent and thorough - keep iterating on the implementation until all tests pass. Don't give up after the first failure. Always delete tests after they pass, use the UpdateFeatureStatus tool with a summary, and commit your work.`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user