further gemini reviews and fixes

This commit is contained in:
trueheads
2025-12-11 09:36:38 -06:00
parent a602b1b519
commit 74efaadb59
9 changed files with 141 additions and 236 deletions

View File

@@ -391,8 +391,7 @@ class AutoModeService {
featureId,
"waiting_approval",
projectPath,
null, // no summary
error.message // pass error message
{ error: error.message }
);
} catch (statusError) {
console.error("[AutoMode] Failed to update feature status after error:", statusError);
@@ -495,8 +494,7 @@ class AutoModeService {
featureId,
"waiting_approval",
projectPath,
null, // no summary
error.message // pass error message
{ error: error.message }
);
} catch (statusError) {
console.error("[AutoMode] Failed to update feature status after error:", statusError);
@@ -662,8 +660,7 @@ class AutoModeService {
featureId,
"waiting_approval",
projectPath,
null, // no summary
error.message // pass error message
{ error: error.message }
);
} catch (statusError) {
console.error("[AutoMode] Failed to update feature status after error:", statusError);
@@ -859,8 +856,7 @@ class AutoModeService {
featureId,
"waiting_approval",
projectPath,
null, // no summary
error.message // pass error message
{ error: error.message }
);
} catch (statusError) {
console.error("[AutoMode] Failed to update feature status after error:", statusError);
@@ -1102,8 +1098,7 @@ class AutoModeService {
featureId,
"waiting_approval",
projectPath,
null, // no summary
error.message // pass error message
{ error: error.message }
);
} catch (statusError) {
console.error("[AutoMode] Failed to update feature status after error:", statusError);

View File

@@ -898,7 +898,7 @@ ipcMain.handle(
featureId,
status,
projectPath,
summary
{ summary }
);
// Notify renderer if window is available
@@ -1170,6 +1170,7 @@ ipcMain.handle("spec-regeneration:status", () => {
isRunning:
specRegenerationExecution !== null &&
specRegenerationExecution.isActive(),
currentPhase: specRegenerationService.getCurrentPhase(),
};
});

View File

@@ -382,13 +382,15 @@ class FeatureLoader {
* @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
* @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
* @param {Object} options - Options object for optional parameters
* @param {string} [options.summary] - Optional summary of what was done
* @param {string} [options.error] - Optional error message if feature errored
* @param {string} [options.description] - Optional detailed description
* @param {string} [options.category] - Optional category/phase
* @param {string[]} [options.steps] - Optional array of implementation steps
*/
async updateFeatureStatus(featureId, status, projectPath, summary, error, description, category, steps) {
async updateFeatureStatus(featureId, status, projectPath, options = {}) {
const { summary, error, description, category, steps } = options;
// Check if feature exists
const existingFeature = await this.get(projectPath, featureId);

View File

@@ -53,16 +53,17 @@ class McpServerFactory {
finalStatus = "waiting_approval";
}
// Call the provided callback to update feature status with all parameters
// Call the provided callback to update feature status
await updateFeatureStatusCallback(
args.featureId,
finalStatus,
projectPath,
args.summary,
undefined, // error
args.description,
args.category,
args.steps
{
summary: args.summary,
description: args.description,
category: args.category,
steps: args.steps,
}
);
const statusMessage = finalStatus !== args.status

View File

@@ -215,7 +215,7 @@ async function handleToolsCall(params, id) {
// Call the update callback via IPC or direct call
// Since we're in a separate process, we need to use IPC to communicate back
// For now, we'll call the feature loader directly since it has the update method
await featureLoader.updateFeatureStatus(featureId, finalStatus, projectPath, summary);
await featureLoader.updateFeatureStatus(featureId, finalStatus, projectPath, { summary });
const statusMessage = finalStatus !== status
? `Successfully updated feature ${featureId} to status "${finalStatus}" (converted from "${status}" because skipTests=true)${summary ? ` with summary: "${summary}"` : ''}`

View File

@@ -86,6 +86,15 @@ const APP_SPEC_XML_TEMPLATE = `<project_specification>
class SpecRegenerationService {
constructor() {
this.runningRegeneration = null;
this.currentPhase = ""; // Tracks current phase for status queries
}
/**
* Get the current phase of the regeneration process
* @returns {string} Current phase or empty string if not running
*/
getCurrentPhase() {
return this.currentPhase;
}
/**
@@ -107,14 +116,14 @@ class SpecRegenerationService {
const abortController = new AbortController();
execution.abortController = abortController;
// Phase tracking
let currentPhase = "initialization";
// Phase tracking - use instance property for status queries
this.currentPhase = "initialization";
sendToRenderer({
type: "spec_regeneration_progress",
content: `[Phase: ${currentPhase}] Initializing spec generation process...\n`,
content: `[Phase: ${this.currentPhase}] Initializing spec generation process...\n`,
});
console.log(`[SpecRegeneration] Phase: ${currentPhase}`);
console.log(`[SpecRegeneration] Phase: ${this.currentPhase}`);
// Create custom MCP server with UpdateFeatureStatus tool if generating features
if (generateFeatures) {
@@ -135,12 +144,12 @@ class SpecRegenerationService {
}
}
currentPhase = "setup";
this.currentPhase = "setup";
sendToRenderer({
type: "spec_regeneration_progress",
content: `[Phase: ${currentPhase}] Configuring AI agent and tools...\n`,
content: `[Phase: ${this.currentPhase}] Configuring AI agent and tools...\n`,
});
console.log(`[SpecRegeneration] Phase: ${currentPhase}`);
console.log(`[SpecRegeneration] Phase: ${this.currentPhase}`);
// Phase 1: Generate spec WITHOUT UpdateFeatureStatus tool
// This prevents features from being created before the spec is complete
@@ -160,17 +169,17 @@ class SpecRegenerationService {
const prompt = this.buildInitialCreationPrompt(projectOverview); // No feature generation during spec creation
currentPhase = "analysis";
this.currentPhase = "analysis";
sendToRenderer({
type: "spec_regeneration_progress",
content: `[Phase: ${currentPhase}] Starting project analysis and spec creation...\n`,
content: `[Phase: ${this.currentPhase}] Starting project analysis and spec creation...\n`,
});
console.log(`[SpecRegeneration] Phase: ${currentPhase} - Starting AI agent query`);
console.log(`[SpecRegeneration] Phase: ${this.currentPhase} - Starting AI agent query`);
if (generateFeatures) {
sendToRenderer({
type: "spec_regeneration_progress",
content: `[Phase: ${currentPhase}] Feature generation is enabled - features will be created after spec is complete.\n`,
content: `[Phase: ${this.currentPhase}] Feature generation is enabled - features will be created after spec is complete.\n`,
});
console.log("[SpecRegeneration] Feature generation enabled - will create features after spec");
}
@@ -253,11 +262,11 @@ class SpecRegenerationService {
execution.abortController = null;
const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(1);
currentPhase = "spec_complete";
console.log(`[SpecRegeneration] Phase: ${currentPhase} - Spec creation completed in ${elapsedTime}s`);
this.currentPhase = "spec_complete";
console.log(`[SpecRegeneration] Phase: ${this.currentPhase} - Spec creation completed in ${elapsedTime}s`);
sendToRenderer({
type: "spec_regeneration_progress",
content: `\n[Phase: ${currentPhase}] ✓ App specification created successfully! (${elapsedTime}s)\n`,
content: `\n[Phase: ${this.currentPhase}] ✓ App specification created successfully! (${elapsedTime}s)\n`,
});
if (generateFeatures) {
@@ -282,10 +291,10 @@ class SpecRegenerationService {
});
}
} else {
currentPhase = "complete";
this.currentPhase = "complete";
sendToRenderer({
type: "spec_regeneration_progress",
content: `[Phase: ${currentPhase}] All tasks completed!\n`,
content: `[Phase: ${this.currentPhase}] All tasks completed!\n`,
});
// Send final completion event
@@ -344,16 +353,16 @@ class SpecRegenerationService {
*/
async generateFeaturesFromSpec(projectPath, sendToRenderer, execution, startTime) {
const featureStartTime = Date.now();
let currentPhase = "feature_generation";
this.currentPhase = "feature_generation";
console.log(`[SpecRegeneration] ===== Starting Phase 2: Feature Generation =====`);
console.log(`[SpecRegeneration] Project path: ${projectPath}`);
sendToRenderer({
type: "spec_regeneration_progress",
content: `\n[Phase: ${currentPhase}] Starting feature creation from implementation roadmap...\n`,
content: `\n[Phase: ${this.currentPhase}] Starting feature creation from implementation roadmap...\n`,
});
console.log(`[SpecRegeneration] Phase: ${currentPhase} - Starting feature generation query`);
console.log(`[SpecRegeneration] Phase: ${this.currentPhase} - Starting feature generation query`);
try {
// Create feature tools server
@@ -492,12 +501,12 @@ Use the UpdateFeatureStatus tool to create features with ALL the fields above.`,
execution.query = null;
execution.abortController = null;
currentPhase = "complete";
this.currentPhase = "complete";
const featureElapsedTime = ((Date.now() - featureStartTime) / 1000).toFixed(1);
const totalElapsedTime = ((Date.now() - startTime) / 1000).toFixed(1);
sendToRenderer({
type: "spec_regeneration_progress",
content: `\n[Phase: ${currentPhase}] ✓ All tasks completed! (${totalElapsedTime}s total, ${featureElapsedTime}s for features)\n`,
content: `\n[Phase: ${this.currentPhase}] ✓ All tasks completed! (${totalElapsedTime}s total, ${featureElapsedTime}s for features)\n`,
});
sendToRenderer({
type: "spec_regeneration_complete",
@@ -653,22 +662,22 @@ Begin by exploring the project structure.`;
console.log(`[SpecRegeneration] Project definition length: ${projectDefinition.length} characters`);
try {
let currentPhase = "initialization";
this.currentPhase = "initialization";
sendToRenderer({
type: "spec_regeneration_progress",
content: `[Phase: ${currentPhase}] Initializing spec regeneration process...\n`,
content: `[Phase: ${this.currentPhase}] Initializing spec regeneration process...\n`,
});
console.log(`[SpecRegeneration] Phase: ${currentPhase}`);
console.log(`[SpecRegeneration] Phase: ${this.currentPhase}`);
const abortController = new AbortController();
execution.abortController = abortController;
currentPhase = "setup";
this.currentPhase = "setup";
sendToRenderer({
type: "spec_regeneration_progress",
content: `[Phase: ${currentPhase}] Configuring AI agent and tools...\n`,
content: `[Phase: ${this.currentPhase}] Configuring AI agent and tools...\n`,
});
console.log(`[SpecRegeneration] Phase: ${currentPhase}`);
console.log(`[SpecRegeneration] Phase: ${this.currentPhase}`);
const options = {
model: "claude-sonnet-4-20250514",
@@ -686,12 +695,12 @@ Begin by exploring the project structure.`;
const prompt = this.buildRegenerationPrompt(projectDefinition);
currentPhase = "regeneration";
this.currentPhase = "regeneration";
sendToRenderer({
type: "spec_regeneration_progress",
content: `[Phase: ${currentPhase}] Starting spec regeneration...\n`,
content: `[Phase: ${this.currentPhase}] Starting spec regeneration...\n`,
});
console.log(`[SpecRegeneration] Phase: ${currentPhase} - Starting AI agent query`);
console.log(`[SpecRegeneration] Phase: ${this.currentPhase} - Starting AI agent query`);
const currentQuery = query({ prompt, options });
execution.query = currentQuery;
@@ -725,21 +734,10 @@ Begin by exploring the project structure.`;
console.log(`[SpecRegeneration] Tool call #${toolCallCount}: ${toolName}`);
console.log(`[SpecRegeneration] Tool input: ${JSON.stringify(toolInput).substring(0, 200)}...`);
// Special handling for UpdateFeatureStatus to show feature creation
if (toolName === "mcp__automaker-tools__UpdateFeatureStatus" || toolName === "UpdateFeatureStatus") {
const featureId = toolInput?.featureId || "unknown";
const status = toolInput?.status || "unknown";
const summary = toolInput?.summary || "";
sendToRenderer({
type: "spec_regeneration_progress",
content: `\n[Feature Creation] Creating feature "${featureId}" with status "${status}"${summary ? `\n Summary: ${summary}` : ""}\n`,
});
} else {
sendToRenderer({
type: "spec_regeneration_progress",
content: `\n[Tool] Using ${toolName}...\n`,
});
}
sendToRenderer({
type: "spec_regeneration_progress",
content: `\n[Tool] Using ${toolName}...\n`,
});
sendToRenderer({
type: "spec_regeneration_tool",
@@ -755,18 +753,10 @@ Begin by exploring the project structure.`;
const resultPreview = result.substring(0, 200).replace(/\n/g, " ");
console.log(`[SpecRegeneration] Tool result (${toolName}): ${resultPreview}...`);
// Special handling for UpdateFeatureStatus results
if (toolName === "mcp__automaker-tools__UpdateFeatureStatus" || toolName === "UpdateFeatureStatus") {
sendToRenderer({
type: "spec_regeneration_progress",
content: `[Feature Creation] ${result}\n`,
});
} else {
sendToRenderer({
type: "spec_regeneration_progress",
content: `[Tool Result] ${toolName} completed successfully\n`,
});
}
sendToRenderer({
type: "spec_regeneration_progress",
content: `[Tool Result] ${toolName} completed successfully\n`,
});
} else if (msg.type === "error") {
const errorMsg = msg.error?.message || JSON.stringify(msg.error);
console.error(`[SpecRegeneration] ERROR in query stream: ${errorMsg}`);
@@ -791,11 +781,11 @@ Begin by exploring the project structure.`;
execution.abortController = null;
const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(1);
currentPhase = "complete";
console.log(`[SpecRegeneration] Phase: ${currentPhase} - Spec regeneration completed in ${elapsedTime}s`);
this.currentPhase = "complete";
console.log(`[SpecRegeneration] Phase: ${this.currentPhase} - Spec regeneration completed in ${elapsedTime}s`);
sendToRenderer({
type: "spec_regeneration_progress",
content: `\n[Phase: ${currentPhase}] ✓ Spec regeneration complete! (${elapsedTime}s)\n`,
content: `\n[Phase: ${this.currentPhase}] ✓ Spec regeneration complete! (${elapsedTime}s)\n`,
});
sendToRenderer({
@@ -867,9 +857,8 @@ When analyzing, look at:
- Database configurations and schemas
- API structures and patterns
**Feature Storage:**
Features are stored in .automaker/features/{id}/feature.json - each feature has its own folder.
Do NOT manually create feature files. Use the UpdateFeatureStatus tool to manage features.
**Note:** Feature files are stored separately in .automaker/features/{id}/feature.json.
Your task is ONLY to update the app_spec.txt file - feature files will be managed separately.
You CAN and SHOULD modify:
- .automaker/app_spec.txt (this is your primary target)
@@ -1042,6 +1031,7 @@ Begin by exploring the project structure.`;
this.runningRegeneration.abortController.abort();
}
this.runningRegeneration = null;
this.currentPhase = "";
}
}

View File

@@ -105,93 +105,38 @@ export function SpecView() {
console.log("[SpecView] Status check on mount:", status);
if (status.success && status.isRunning) {
// Something is running - restore state
console.log("[SpecView] Spec generation is running - restoring state");
// Something is running - restore state using backend's authoritative phase
console.log("[SpecView] Spec generation is running - restoring state", { phase: status.currentPhase });
// Only restore state if we haven't already done so for this project
// This prevents resetting state when switching tabs
if (!stateRestoredRef.current) {
setIsCreating(true);
setIsRegenerating(true);
stateRestoredRef.current = true;
}
// Try to extract the current phase from existing logs
let detectedPhase = "";
if (logsRef.current) {
// Look for the most recent phase in the logs
const phaseMatches = logsRef.current.matchAll(/\[Phase:\s*([^\]]+)\]/g);
const phases = Array.from(phaseMatches);
if (phases.length > 0) {
// Get the last phase mentioned in the logs
detectedPhase = phases[phases.length - 1][1];
console.log(`[SpecView] Detected phase from logs: ${detectedPhase}`);
}
// Also check for feature generation indicators in logs
const hasFeatureGeneration = logsRef.current.includes("Feature Generation") ||
logsRef.current.includes("Feature Creation") ||
logsRef.current.includes("Creating feature") ||
logsRef.current.includes("feature_generation");
if (hasFeatureGeneration && !detectedPhase) {
detectedPhase = "feature_generation";
console.log("[SpecView] Detected feature generation from logs");
}
}
// Update phase from logs if we found one and don't have a specific phase set
// This allows the phase to update as new events come in
if (detectedPhase) {
setCurrentPhase((prevPhase) => {
// Only update if we don't have a phase or if the detected phase is more recent
if (!prevPhase || prevPhase === "unknown" || prevPhase === "in progress") {
return detectedPhase;
}
return prevPhase;
});
} else if (!currentPhase) {
// Use a more descriptive default instead of "unknown"
// Use the backend's currentPhase directly - single source of truth
if (status.currentPhase) {
setCurrentPhase(status.currentPhase);
} else {
setCurrentPhase("in progress");
}
// Don't clear logs - they may have been persisted
// Add resume message to logs if needed
if (!logsRef.current) {
const resumeMessage = "[Status] Resumed monitoring existing spec generation process...\n";
logsRef.current = resumeMessage;
setLogs(resumeMessage);
} else if (!logsRef.current.includes("Resumed monitoring")) {
// Add a resume message to existing logs only if not already present
const resumeMessage = "\n[Status] Resumed monitoring existing spec generation process...\n";
logsRef.current = logsRef.current + resumeMessage;
setLogs(logsRef.current);
}
} else if (status.success && !status.isRunning) {
// Check if we might still be in feature generation phase based on logs
const mightBeGeneratingFeatures = logsRef.current && (
logsRef.current.includes("Feature Generation") ||
logsRef.current.includes("Feature Creation") ||
logsRef.current.includes("Creating feature") ||
logsRef.current.includes("feature_generation") ||
currentPhase === "feature_generation"
);
if (mightBeGeneratingFeatures && specExists) {
// Spec exists and we might still be generating features - keep state active
console.log("[SpecView] Detected potential feature generation - keeping state active");
if (!isCreating && !isRegenerating) {
setIsCreating(true);
}
if (currentPhase !== "feature_generation") {
setCurrentPhase("feature_generation");
}
} else {
// Not running - clear running state
setIsCreating(false);
setIsRegenerating(false);
setCurrentPhase("");
stateRestoredRef.current = false;
}
// Not running - clear all state
setIsCreating(false);
setIsRegenerating(false);
setCurrentPhase("");
stateRestoredRef.current = false;
}
} catch (error) {
console.error("[SpecView] Failed to check status:", error);
@@ -209,7 +154,7 @@ export function SpecView() {
useEffect(() => {
const handleVisibilityChange = async () => {
if (!document.hidden && currentProject && (isCreating || isRegenerating || isGeneratingFeatures)) {
// Tab became visible and we think we're still generating - verify status
// Tab became visible and we think we're still generating - verify status from backend
try {
const api = getElectronAPI();
if (!api.specRegeneration) return;
@@ -218,45 +163,17 @@ export function SpecView() {
console.log("[SpecView] Visibility change - status check:", status);
if (!status.isRunning) {
// Not running but we think we are - check if we're truly done
// Look for recent activity in logs (within last 30 seconds worth of content)
const recentLogs = logsRef.current.slice(-5000); // Last ~5000 chars
const hasRecentFeatureActivity = recentLogs.includes("Feature Creation") ||
recentLogs.includes("Creating feature") ||
recentLogs.match(/\[Feature Creation\].*$/m);
// Check if we have a completion message or complete phase
const hasCompletion = logsRef.current.includes("All tasks completed") ||
logsRef.current.includes("[Complete] All tasks completed") ||
logsRef.current.includes("[Phase: complete]");
if (hasCompletion || (!hasRecentFeatureActivity && currentPhase !== "feature_generation")) {
// No recent activity and not running - we're done
console.log("[SpecView] Visibility change: Generation appears complete - clearing state");
setIsCreating(false);
setIsRegenerating(false);
setIsGeneratingFeatures(false);
setCurrentPhase("");
stateRestoredRef.current = false;
loadSpec();
} else if (currentPhase === "feature_generation" && !hasRecentFeatureActivity) {
// We were in feature generation but no recent activity - might be done
// Wait a moment and check again
setTimeout(async () => {
if (api.specRegeneration) {
const recheckStatus = await api.specRegeneration.status();
if (!recheckStatus.isRunning) {
console.log("[SpecView] Re-check after visibility: Still not running - clearing state");
setIsCreating(false);
setIsRegenerating(false);
setIsGeneratingFeatures(false);
setCurrentPhase("");
stateRestoredRef.current = false;
loadSpec();
}
}
}, STATUS_CHECK_INTERVAL_MS);
}
// Backend says not running - clear state
console.log("[SpecView] Visibility change: Backend indicates generation complete - clearing state");
setIsCreating(false);
setIsRegenerating(false);
setIsGeneratingFeatures(false);
setCurrentPhase("");
stateRestoredRef.current = false;
loadSpec();
} else if (status.currentPhase) {
// Still running - update phase from backend
setCurrentPhase(status.currentPhase);
}
} catch (error) {
console.error("[SpecView] Failed to check status on visibility change:", error);
@@ -268,7 +185,7 @@ export function SpecView() {
return () => {
document.removeEventListener("visibilitychange", handleVisibilityChange);
};
}, [currentProject, isCreating, isRegenerating, isGeneratingFeatures, currentPhase, loadSpec]);
}, [currentProject, isCreating, isRegenerating, isGeneratingFeatures, loadSpec]);
// Periodic status check to ensure state stays in sync (only when we think we're running)
useEffect(() => {
@@ -281,40 +198,22 @@ export function SpecView() {
const status = await api.specRegeneration.status();
// If not running but we think we are, verify we're truly done
if (!status.isRunning && (isCreating || isRegenerating || isGeneratingFeatures)) {
// Check logs for completion indicators
const hasCompletion = logsRef.current.includes("All tasks completed") ||
logsRef.current.includes("[Complete] All tasks completed") ||
logsRef.current.includes("[Phase: complete]") ||
currentPhase === "complete";
// Also check if we haven't seen feature activity recently
const recentLogs = logsRef.current.slice(-3000); // Last 3000 chars (more context)
const hasRecentFeatureActivity = recentLogs.includes("Feature Creation") ||
recentLogs.includes("Creating feature") ||
recentLogs.includes("UpdateFeatureStatus") ||
recentLogs.includes("[Tool]") && recentLogs.includes("UpdateFeatureStatus");
// If we're in feature_generation phase and not running, we're likely done
// (features are created via tool calls, so when stream ends, they're done)
const isFeatureGenComplete = currentPhase === "feature_generation" &&
!hasRecentFeatureActivity;
if (hasCompletion || isFeatureGenComplete) {
console.log("[SpecView] Periodic check: Generation complete - clearing state", {
hasCompletion,
hasRecentFeatureActivity,
currentPhase,
isFeatureGenComplete
});
setIsCreating(false);
setIsRegenerating(false);
setIsGeneratingFeatures(false);
setCurrentPhase("");
stateRestoredRef.current = false;
loadSpec();
}
if (!status.isRunning) {
// Backend says not running - clear state
console.log("[SpecView] Periodic check: Backend indicates generation complete - clearing state");
setIsCreating(false);
setIsRegenerating(false);
setIsGeneratingFeatures(false);
setCurrentPhase("");
stateRestoredRef.current = false;
loadSpec();
} else if (status.currentPhase && status.currentPhase !== currentPhase) {
// Still running but phase changed - update from backend
console.log("[SpecView] Periodic check: Phase updated from backend", {
old: currentPhase,
new: status.currentPhase
});
setCurrentPhase(status.currentPhase);
}
} catch (error) {
console.error("[SpecView] Periodic status check error:", error);

View File

@@ -1800,6 +1800,7 @@ async function simulateSuggestionsGeneration(
// Mock Spec Regeneration state and implementation
let mockSpecRegenerationRunning = false;
let mockSpecRegenerationPhase = "";
let mockSpecRegenerationCallbacks: ((event: SpecRegenerationEvent) => void)[] =
[];
let mockSpecRegenerationTimeout: NodeJS.Timeout | null = null;
@@ -1862,6 +1863,7 @@ function createMockSpecRegenerationAPI(): SpecRegenerationAPI {
stop: async () => {
mockSpecRegenerationRunning = false;
mockSpecRegenerationPhase = "";
if (mockSpecRegenerationTimeout) {
clearTimeout(mockSpecRegenerationTimeout);
mockSpecRegenerationTimeout = null;
@@ -1873,6 +1875,7 @@ function createMockSpecRegenerationAPI(): SpecRegenerationAPI {
return {
success: true,
isRunning: mockSpecRegenerationRunning,
currentPhase: mockSpecRegenerationPhase,
};
},
@@ -1896,9 +1899,10 @@ async function simulateSpecCreation(
projectOverview: string,
generateFeatures = true
) {
mockSpecRegenerationPhase = "initialization";
emitSpecRegenerationEvent({
type: "spec_regeneration_progress",
content: "Starting project analysis...\n",
content: "[Phase: initialization] Starting project analysis...\n",
});
await new Promise((resolve) => {
@@ -1906,6 +1910,7 @@ async function simulateSpecCreation(
});
if (!mockSpecRegenerationRunning) return;
mockSpecRegenerationPhase = "setup";
emitSpecRegenerationEvent({
type: "spec_regeneration_tool",
tool: "Glob",
@@ -1917,9 +1922,10 @@ async function simulateSpecCreation(
});
if (!mockSpecRegenerationRunning) return;
mockSpecRegenerationPhase = "analysis";
emitSpecRegenerationEvent({
type: "spec_regeneration_progress",
content: "Detecting tech stack...\n",
content: "[Phase: analysis] Detecting tech stack...\n",
});
await new Promise((resolve) => {
@@ -1959,12 +1965,14 @@ async function simulateSpecCreation(
// The generateFeatures parameter is kept for API compatibility but features
// should be created through the features API
mockSpecRegenerationPhase = "complete";
emitSpecRegenerationEvent({
type: "spec_regeneration_complete",
message: "Initial spec creation complete!",
message: "All tasks completed!",
});
mockSpecRegenerationRunning = false;
mockSpecRegenerationPhase = "";
mockSpecRegenerationTimeout = null;
}
@@ -1972,9 +1980,10 @@ async function simulateSpecRegeneration(
projectPath: string,
projectDefinition: string
) {
mockSpecRegenerationPhase = "initialization";
emitSpecRegenerationEvent({
type: "spec_regeneration_progress",
content: "Starting spec regeneration...\n",
content: "[Phase: initialization] Starting spec regeneration...\n",
});
await new Promise((resolve) => {
@@ -1982,9 +1991,10 @@ async function simulateSpecRegeneration(
});
if (!mockSpecRegenerationRunning) return;
mockSpecRegenerationPhase = "analysis";
emitSpecRegenerationEvent({
type: "spec_regeneration_progress",
content: "Analyzing codebase...\n",
content: "[Phase: analysis] Analyzing codebase...\n",
});
await new Promise((resolve) => {
@@ -2015,16 +2025,19 @@ async function simulateSpecRegeneration(
</core_capabilities>
</project_specification>`;
mockSpecRegenerationPhase = "complete";
emitSpecRegenerationEvent({
type: "spec_regeneration_complete",
message: "Spec regeneration complete!",
message: "All tasks completed!",
});
mockSpecRegenerationRunning = false;
mockSpecRegenerationPhase = "";
mockSpecRegenerationTimeout = null;
}
async function simulateFeatureGeneration(projectPath: string) {
mockSpecRegenerationPhase = "initialization";
emitSpecRegenerationEvent({
type: "spec_regeneration_progress",
content: "[Phase: initialization] Starting feature generation from existing app_spec.txt...\n",
@@ -2045,9 +2058,10 @@ async function simulateFeatureGeneration(projectPath: string) {
});
if (!mockSpecRegenerationRunning) return;
mockSpecRegenerationPhase = "feature_generation";
emitSpecRegenerationEvent({
type: "spec_regeneration_progress",
content: "[Feature Creation] Creating features from roadmap...\n",
content: "[Phase: feature_generation] Creating features from roadmap...\n",
});
await new Promise((resolve) => {
@@ -2055,6 +2069,7 @@ async function simulateFeatureGeneration(projectPath: string) {
});
if (!mockSpecRegenerationRunning) return;
mockSpecRegenerationPhase = "complete";
emitSpecRegenerationEvent({
type: "spec_regeneration_progress",
content: "[Phase: complete] All tasks completed!\n",
@@ -2066,6 +2081,7 @@ async function simulateFeatureGeneration(projectPath: string) {
});
mockSpecRegenerationRunning = false;
mockSpecRegenerationPhase = "";
mockSpecRegenerationTimeout = null;
}

View File

@@ -270,6 +270,7 @@ export interface SpecRegenerationAPI {
status: () => Promise<{
success: boolean;
isRunning?: boolean;
currentPhase?: string;
error?: string;
}>;