edsger 0.36.2 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/.claude/settings.local.json +23 -3
  2. package/.env.local +12 -0
  3. package/dist/api/features/__tests__/regression-prevention.test.d.ts +5 -0
  4. package/dist/api/features/__tests__/regression-prevention.test.js +338 -0
  5. package/dist/api/features/__tests__/status-updater.integration.test.d.ts +5 -0
  6. package/dist/api/features/__tests__/status-updater.integration.test.js +497 -0
  7. package/dist/api/growth.d.ts +23 -1
  8. package/dist/api/growth.js +25 -0
  9. package/dist/commands/app-store/index.js +2 -6
  10. package/dist/commands/code-review/index.js +3 -3
  11. package/dist/commands/growth-analysis/index.js +2 -0
  12. package/dist/commands/init/index.js +3 -3
  13. package/dist/commands/workflow/pipeline-runner.d.ts +17 -0
  14. package/dist/commands/workflow/pipeline-runner.js +393 -0
  15. package/dist/commands/workflow/runner.d.ts +26 -0
  16. package/dist/commands/workflow/runner.js +119 -0
  17. package/dist/commands/workflow/workflow-runner.d.ts +26 -0
  18. package/dist/commands/workflow/workflow-runner.js +119 -0
  19. package/dist/index.js +4 -0
  20. package/dist/phases/app-store-generation/__tests__/screenshot-composer.test.js +452 -32
  21. package/dist/phases/app-store-generation/assets/inter-latin-ext.woff2 +0 -0
  22. package/dist/phases/app-store-generation/assets/inter-latin.woff2 +0 -0
  23. package/dist/phases/app-store-generation/inter-font.d.ts +20 -0
  24. package/dist/phases/app-store-generation/inter-font.js +49 -0
  25. package/dist/phases/app-store-generation/screenshot-composer.js +183 -19
  26. package/dist/phases/code-implementation/analyzer-helpers.d.ts +28 -0
  27. package/dist/phases/code-implementation/analyzer-helpers.js +177 -0
  28. package/dist/phases/code-implementation/analyzer.d.ts +32 -0
  29. package/dist/phases/code-implementation/analyzer.js +629 -0
  30. package/dist/phases/code-implementation/context-fetcher.d.ts +17 -0
  31. package/dist/phases/code-implementation/context-fetcher.js +86 -0
  32. package/dist/phases/code-implementation/mcp-server.d.ts +1 -0
  33. package/dist/phases/code-implementation/mcp-server.js +93 -0
  34. package/dist/phases/code-implementation/prompts-improvement.d.ts +5 -0
  35. package/dist/phases/code-implementation/prompts-improvement.js +108 -0
  36. package/dist/phases/code-implementation-verification/verifier.d.ts +31 -0
  37. package/dist/phases/code-implementation-verification/verifier.js +196 -0
  38. package/dist/phases/code-refine/analyzer.d.ts +41 -0
  39. package/dist/phases/code-refine/analyzer.js +561 -0
  40. package/dist/phases/code-refine/context-fetcher.d.ts +94 -0
  41. package/dist/phases/code-refine/context-fetcher.js +423 -0
  42. package/dist/phases/code-refine-verification/analysis/llm-analyzer.d.ts +22 -0
  43. package/dist/phases/code-refine-verification/analysis/llm-analyzer.js +134 -0
  44. package/dist/phases/code-refine-verification/verifier.d.ts +47 -0
  45. package/dist/phases/code-refine-verification/verifier.js +597 -0
  46. package/dist/phases/code-review/analyzer.d.ts +29 -0
  47. package/dist/phases/code-review/analyzer.js +363 -0
  48. package/dist/phases/code-review/context-fetcher.d.ts +92 -0
  49. package/dist/phases/code-review/context-fetcher.js +296 -0
  50. package/dist/phases/feature-analysis/analyzer-helpers.d.ts +10 -0
  51. package/dist/phases/feature-analysis/analyzer-helpers.js +47 -0
  52. package/dist/phases/feature-analysis/analyzer.d.ts +11 -0
  53. package/dist/phases/feature-analysis/analyzer.js +208 -0
  54. package/dist/phases/feature-analysis/context-fetcher.d.ts +26 -0
  55. package/dist/phases/feature-analysis/context-fetcher.js +134 -0
  56. package/dist/phases/feature-analysis/http-fallback.d.ts +20 -0
  57. package/dist/phases/feature-analysis/http-fallback.js +95 -0
  58. package/dist/phases/feature-analysis/mcp-server.d.ts +1 -0
  59. package/dist/phases/feature-analysis/mcp-server.js +144 -0
  60. package/dist/phases/feature-analysis/prompts-improvement.d.ts +8 -0
  61. package/dist/phases/feature-analysis/prompts-improvement.js +109 -0
  62. package/dist/phases/feature-analysis-verification/verifier.d.ts +37 -0
  63. package/dist/phases/feature-analysis-verification/verifier.js +147 -0
  64. package/dist/phases/growth-analysis/context.d.ts +2 -2
  65. package/dist/phases/growth-analysis/context.js +18 -4
  66. package/dist/phases/growth-analysis/index.d.ts +2 -0
  67. package/dist/phases/growth-analysis/index.js +21 -13
  68. package/dist/phases/technical-design/analyzer-helpers.d.ts +25 -0
  69. package/dist/phases/technical-design/analyzer-helpers.js +39 -0
  70. package/dist/phases/technical-design/analyzer.d.ts +21 -0
  71. package/dist/phases/technical-design/analyzer.js +461 -0
  72. package/dist/phases/technical-design/context-fetcher.d.ts +12 -0
  73. package/dist/phases/technical-design/context-fetcher.js +39 -0
  74. package/dist/phases/technical-design/http-fallback.d.ts +17 -0
  75. package/dist/phases/technical-design/http-fallback.js +151 -0
  76. package/dist/phases/technical-design/mcp-server.d.ts +1 -0
  77. package/dist/phases/technical-design/mcp-server.js +157 -0
  78. package/dist/phases/technical-design/prompts-improvement.d.ts +5 -0
  79. package/dist/phases/technical-design/prompts-improvement.js +93 -0
  80. package/dist/phases/technical-design-verification/verifier.d.ts +53 -0
  81. package/dist/phases/technical-design-verification/verifier.js +170 -0
  82. package/dist/services/feature-branches.d.ts +77 -0
  83. package/dist/services/feature-branches.js +205 -0
  84. package/dist/services/video/device-frames.d.ts +1 -1
  85. package/dist/services/video/device-frames.js +81 -3
  86. package/dist/services/video/index.d.ts +1 -1
  87. package/dist/services/video/index.js +12 -6
  88. package/dist/services/video/screenshot-generator.js +5 -8
  89. package/dist/services/video/video-assembler.js +2 -6
  90. package/dist/types/index.d.ts +2 -0
  91. package/dist/utils/validation.d.ts +11 -2
  92. package/dist/utils/validation.js +93 -6
  93. package/dist/workflow-runner/config/phase-configs.d.ts +5 -0
  94. package/dist/workflow-runner/config/phase-configs.js +120 -0
  95. package/dist/workflow-runner/core/feature-filter.d.ts +16 -0
  96. package/dist/workflow-runner/core/feature-filter.js +46 -0
  97. package/dist/workflow-runner/core/index.d.ts +8 -0
  98. package/dist/workflow-runner/core/index.js +12 -0
  99. package/dist/workflow-runner/core/pipeline-evaluator.d.ts +24 -0
  100. package/dist/workflow-runner/core/pipeline-evaluator.js +32 -0
  101. package/dist/workflow-runner/core/state-manager.d.ts +24 -0
  102. package/dist/workflow-runner/core/state-manager.js +42 -0
  103. package/dist/workflow-runner/core/workflow-logger.d.ts +20 -0
  104. package/dist/workflow-runner/core/workflow-logger.js +65 -0
  105. package/dist/workflow-runner/executors/phase-executor.d.ts +8 -0
  106. package/dist/workflow-runner/executors/phase-executor.js +248 -0
  107. package/dist/workflow-runner/feature-workflow-runner.d.ts +26 -0
  108. package/dist/workflow-runner/feature-workflow-runner.js +119 -0
  109. package/dist/workflow-runner/index.d.ts +2 -0
  110. package/dist/workflow-runner/index.js +2 -0
  111. package/dist/workflow-runner/pipeline-runner.d.ts +17 -0
  112. package/dist/workflow-runner/pipeline-runner.js +393 -0
  113. package/dist/workflow-runner/workflow-processor.d.ts +54 -0
  114. package/dist/workflow-runner/workflow-processor.js +170 -0
  115. package/package.json +2 -2
  116. package/dist/services/lifecycle-agent/__tests__/phase-criteria.test.d.ts +0 -4
  117. package/dist/services/lifecycle-agent/__tests__/phase-criteria.test.js +0 -133
  118. package/dist/services/lifecycle-agent/__tests__/transition-rules.test.d.ts +0 -4
  119. package/dist/services/lifecycle-agent/__tests__/transition-rules.test.js +0 -336
  120. package/dist/services/lifecycle-agent/index.d.ts +0 -24
  121. package/dist/services/lifecycle-agent/index.js +0 -25
  122. package/dist/services/lifecycle-agent/phase-criteria.d.ts +0 -57
  123. package/dist/services/lifecycle-agent/phase-criteria.js +0 -335
  124. package/dist/services/lifecycle-agent/transition-rules.d.ts +0 -60
  125. package/dist/services/lifecycle-agent/transition-rules.js +0 -184
  126. package/dist/services/lifecycle-agent/types.d.ts +0 -190
  127. package/dist/services/lifecycle-agent/types.js +0 -12
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Checklist verification agent for feature analysis
3
+ * This agent independently reviews checklist compliance to ensure objectivity
4
+ */
5
+ import { query } from '@anthropic-ai/claude-code';
6
+ import { logInfo, logError } from '../../utils/logger.js';
7
+ import { createChecklistVerificationPrompt, createChecklistVerificationSystemPrompt, } from './prompts.js';
8
+ function userMessage(content) {
9
+ return {
10
+ type: 'user',
11
+ message: { role: 'user', content: content },
12
+ };
13
+ }
14
+ async function* prompt(verificationPrompt) {
15
+ yield userMessage(verificationPrompt);
16
+ }
17
+ /**
18
+ * Verify checklist compliance using an independent AI agent
19
+ * This agent acts as a "challenger" to validate the claims made by the analysis agent
20
+ */
21
+ export async function verifyChecklistCompliance(options, config) {
22
+ const { checklistContext, analysisContext, createdUserStories, createdTestCases, verbose, } = options;
23
+ const totalChecklistItems = checklistContext.checklists.reduce((sum, checklist) => sum + checklist.items.length, 0);
24
+ if (verbose) {
25
+ logInfo('🔍 Starting checklist verification...');
26
+ logInfo(` Verifying ${totalChecklistItems} checklist items`);
27
+ }
28
+ try {
29
+ const systemPrompt = createChecklistVerificationSystemPrompt(config);
30
+ const verificationPrompt = createChecklistVerificationPrompt({
31
+ checklistContext,
32
+ analysisContext,
33
+ createdUserStories,
34
+ createdTestCases,
35
+ });
36
+ let lastAssistantResponse = '';
37
+ let verificationResult = null;
38
+ if (verbose) {
39
+ logInfo('🤖 Starting verification agent query...');
40
+ }
41
+ // Use Claude Code SDK for verification
42
+ for await (const message of query({
43
+ prompt: prompt(verificationPrompt),
44
+ options: {
45
+ appendSystemPrompt: systemPrompt,
46
+ model: config.claude.model || 'sonnet',
47
+ maxTurns: 100,
48
+ permissionMode: 'bypassPermissions',
49
+ },
50
+ })) {
51
+ if (verbose) {
52
+ logInfo(` Received message type: ${message.type}`);
53
+ }
54
+ // Capture assistant responses
55
+ if (message.type === 'assistant' && message.message?.content) {
56
+ for (const content of message.message.content) {
57
+ if (content.type === 'text') {
58
+ lastAssistantResponse += content.text + '\n';
59
+ if (verbose) {
60
+ console.log(`\n🔍 ${content.text}`);
61
+ }
62
+ }
63
+ }
64
+ }
65
+ if (message.type === 'result') {
66
+ if (message.subtype === 'success') {
67
+ logInfo('\n✅ Verification completed, parsing results...');
68
+ try {
69
+ const responseText = message.result || lastAssistantResponse;
70
+ // Try to extract JSON from markdown code block
71
+ const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
72
+ let jsonResult = null;
73
+ if (jsonBlockMatch) {
74
+ jsonResult = JSON.parse(jsonBlockMatch[1]);
75
+ }
76
+ else {
77
+ jsonResult = JSON.parse(responseText);
78
+ }
79
+ if (jsonResult && jsonResult.verification) {
80
+ verificationResult = jsonResult.verification;
81
+ }
82
+ else {
83
+ throw new Error('Invalid verification JSON structure');
84
+ }
85
+ }
86
+ catch (error) {
87
+ logError(`Failed to parse verification result: ${error}`);
88
+ // Return default "uncertain" result
89
+ verificationResult = createUncertainVerificationResult(checklistContext, 'Failed to parse verification response');
90
+ }
91
+ }
92
+ else {
93
+ logError(`\n⚠️ Verification incomplete: ${message.subtype}`);
94
+ verificationResult = createUncertainVerificationResult(checklistContext, `Verification incomplete: ${message.subtype}`);
95
+ }
96
+ }
97
+ }
98
+ if (!verificationResult) {
99
+ verificationResult = createUncertainVerificationResult(checklistContext, 'No verification result received');
100
+ }
101
+ if (verbose) {
102
+ logInfo('\n📊 Verification Summary:');
103
+ logInfo(` Total items: ${verificationResult.total_items}`);
104
+ logInfo(` ✅ Confirmed: ${verificationResult.confirmed_count}`);
105
+ logInfo(` ❌ Rejected: ${verificationResult.rejected_count}`);
106
+ logInfo(` ⚠️ Uncertain: ${verificationResult.uncertain_count}`);
107
+ logInfo(` Summary: ${verificationResult.summary}`);
108
+ if (verificationResult.rejected_count > 0) {
109
+ logInfo('\n❌ Rejected items:');
110
+ verificationResult.item_verifications
111
+ .filter((v) => v.verification_status === 'rejected')
112
+ .forEach((v) => {
113
+ logInfo(` - ${v.checklist_item_id}`);
114
+ logInfo(` Reason: ${v.verification_reason}`);
115
+ });
116
+ }
117
+ }
118
+ return verificationResult;
119
+ }
120
+ catch (error) {
121
+ logError(`Checklist verification failed: ${error instanceof Error ? error.message : String(error)}`);
122
+ return createUncertainVerificationResult(checklistContext, `Verification error: ${error instanceof Error ? error.message : String(error)}`);
123
+ }
124
+ }
125
+ /**
126
+ * Create a default "uncertain" verification result when verification fails
127
+ */
128
+ function createUncertainVerificationResult(checklistContext, reason) {
129
+ // Get all checklist items
130
+ const allItems = checklistContext.checklists.flatMap((checklist) => checklist.items.map((item) => ({
131
+ checklist_item_id: item.id,
132
+ })));
133
+ return {
134
+ all_verified: false,
135
+ total_items: allItems.length,
136
+ confirmed_count: 0,
137
+ rejected_count: 0,
138
+ uncertain_count: allItems.length,
139
+ item_verifications: allItems.map((item) => ({
140
+ checklist_item_id: item.checklist_item_id,
141
+ is_satisfied: false,
142
+ verification_status: 'uncertain',
143
+ verification_reason: reason,
144
+ })),
145
+ summary: `Verification could not be completed: ${reason}`,
146
+ };
147
+ }
@@ -11,11 +11,11 @@ export declare function fetchGrowthAnalysisContext(productId: string, verbose?:
11
11
  /**
12
12
  * Format context into a prompt string for the AI
13
13
  */
14
- export declare function formatContextForPrompt(context: GrowthAnalysisContext): string;
14
+ export declare function formatContextForPrompt(context: GrowthAnalysisContext, guidance?: string): string;
15
15
  /**
16
16
  * Prepare the full analysis prompt with all context
17
17
  */
18
- export declare function prepareGrowthAnalysisContext(productId: string, verbose?: boolean, hasCodebase?: boolean): Promise<{
18
+ export declare function prepareGrowthAnalysisContext(productId: string, verbose?: boolean, hasCodebase?: boolean, guidance?: string): Promise<{
19
19
  context: GrowthAnalysisContext;
20
20
  analysisPrompt: string;
21
21
  }>;
@@ -30,7 +30,7 @@ export async function fetchGrowthAnalysisContext(productId, verbose) {
30
30
  /**
31
31
  * Format context into a prompt string for the AI
32
32
  */
33
- export function formatContextForPrompt(context) {
33
+ export function formatContextForPrompt(context, guidance) {
34
34
  const { product, previousCampaigns } = context;
35
35
  const campaignsList = previousCampaigns.length > 0
36
36
  ? previousCampaigns
@@ -45,6 +45,16 @@ export function formatContextForPrompt(context) {
45
45
  .map((f) => `- **${f.name}**: ${f.description || 'No description'} (Status: ${f.status || 'unknown'})`)
46
46
  .join('\n')
47
47
  : 'No features listed.';
48
+ const guidanceSection = guidance
49
+ ? `
50
+
51
+ ## Human Growth Guidance
52
+ The product owner has provided the following direction for this growth analysis. **You MUST follow this guidance closely** — it takes priority over your own judgement for content direction, themes, audience, and channel selection.
53
+
54
+ ${guidance}
55
+
56
+ ---`
57
+ : '';
48
58
  return `# Growth Analysis Context
49
59
 
50
60
  ## Product Information
@@ -54,23 +64,27 @@ export function formatContextForPrompt(context) {
54
64
 
55
65
  ## Product Features (${product.features?.length || 0})
56
66
  ${featuresList}
67
+ ${guidanceSection}
57
68
 
58
69
  ## Previous Growth Campaigns (${previousCampaigns.length})
59
70
  ${campaignsList}
60
71
 
61
72
  ---
62
73
 
63
- **Important**: Analyze the product above and create a growth strategy. Each content suggestion must be DIFFERENT from all previous campaigns listed above. Use the product name, description, and features to write specific, concrete content — never use placeholder text.`;
74
+ **Important**: Analyze the product above and create a growth strategy.${guidance ? ' Follow the human growth guidance provided above for direction, themes, and tone.' : ''} Each content suggestion must be DIFFERENT from all previous campaigns listed above. Use the product name, description, and features to write specific, concrete content — never use placeholder text.`;
64
75
  }
65
76
  /**
66
77
  * Prepare the full analysis prompt with all context
67
78
  */
68
- export async function prepareGrowthAnalysisContext(productId, verbose, hasCodebase = false) {
79
+ export async function prepareGrowthAnalysisContext(productId, verbose, hasCodebase = false, guidance) {
69
80
  if (verbose) {
70
81
  logInfo('Fetching growth analysis context via MCP endpoints...');
82
+ if (guidance) {
83
+ logInfo(`Human guidance provided: "${guidance.substring(0, 80)}${guidance.length > 80 ? '...' : ''}"`);
84
+ }
71
85
  }
72
86
  const context = await fetchGrowthAnalysisContext(productId, verbose);
73
- const contextInfo = formatContextForPrompt(context);
87
+ const contextInfo = formatContextForPrompt(context, guidance);
74
88
  const analysisPrompt = createGrowthAnalysisPromptWithContext(productId, contextInfo, hasCodebase);
75
89
  return { context, analysisPrompt };
76
90
  }
@@ -3,6 +3,8 @@ import { type EdsgerConfig } from '../../types/index.js';
3
3
  export interface GrowthAnalysisOptions {
4
4
  productId: string;
5
5
  verbose?: boolean;
6
+ guidance?: string;
7
+ analysisId?: string;
6
8
  }
7
9
  export interface GrowthAnalysisResult {
8
10
  productId: string;
@@ -1,5 +1,5 @@
1
1
  import { getGitHubConfigByProduct } from '../../api/github.js';
2
- import { saveGrowthAnalysis } from '../../api/growth.js';
2
+ import { saveGrowthAnalysis, updateGrowthAnalysis } from '../../api/growth.js';
3
3
  import { generateGrowthVideo, } from '../../services/video/index.js';
4
4
  import { logError, logInfo, logSuccess, logWarning, } from '../../utils/logger.js';
5
5
  import { cloneFeatureRepo, ensureWorkspaceDir, } from '../../workspace/workspace-manager.js';
@@ -52,7 +52,7 @@ contentSuggestions) {
52
52
  export const analyseGrowth = async (options, config
53
53
  // eslint-disable-next-line complexity -- orchestration function with context assembly, agent execution, and result processing
54
54
  ) => {
55
- const { productId, verbose } = options;
55
+ const { productId, verbose, guidance, analysisId } = options;
56
56
  if (verbose) {
57
57
  logInfo(`Starting growth analysis for product ID: ${productId}`);
58
58
  }
@@ -78,7 +78,7 @@ export const analyseGrowth = async (options, config
78
78
  logInfo(`Could not clone repo (continuing without codebase): ${error instanceof Error ? error.message : String(error)}`);
79
79
  }
80
80
  const hasCodebase = !!repoCwd;
81
- const { context: _context, analysisPrompt } = await prepareGrowthAnalysisContext(productId, verbose, hasCodebase);
81
+ const { context: _context, analysisPrompt } = await prepareGrowthAnalysisContext(productId, verbose, hasCodebase, guidance);
82
82
  const systemPrompt = createGrowthAnalysisSystemPrompt(hasCodebase);
83
83
  if (verbose) {
84
84
  logInfo('Starting AI query for growth analysis...');
@@ -95,21 +95,29 @@ export const analyseGrowth = async (options, config
95
95
  const targetChannels = (analysisResult.target_channels || []);
96
96
  const contentSuggestions = (analysisResult.content_suggestions || []);
97
97
  const searchContext = analysisResult.search_context || null;
98
- const savedAnalysis = await saveGrowthAnalysis({
99
- product_id: productId,
100
- analysis_content: analysisContent,
101
- target_channels: targetChannels,
102
- content_suggestions: contentSuggestions,
103
- search_context: searchContext,
104
- status: 'completed',
105
- }, verbose);
98
+ const savedAnalysis = analysisId
99
+ ? await updateGrowthAnalysis(analysisId, {
100
+ analysis_content: analysisContent,
101
+ target_channels: targetChannels,
102
+ content_suggestions: contentSuggestions,
103
+ search_context: searchContext,
104
+ status: 'completed',
105
+ }, verbose)
106
+ : await saveGrowthAnalysis({
107
+ product_id: productId,
108
+ analysis_content: analysisContent,
109
+ target_channels: targetChannels,
110
+ content_suggestions: contentSuggestions,
111
+ search_context: searchContext,
112
+ growth_guidance: guidance ?? null,
113
+ status: 'completed',
114
+ }, verbose);
106
115
  logInfo(`Growth analysis completed: ${targetChannels.length} channels, ${contentSuggestions.length} suggestions`);
107
116
  // Process video generation for applicable content suggestions
108
117
  const videoPlans = extractVideoPlans(contentSuggestions);
109
118
  const videoResults = new Map();
110
119
  if (videoPlans.length > 0) {
111
120
  logInfo(`\nFound ${videoPlans.length} content suggestion(s) with video plans`);
112
- const analysisId = savedAnalysis?.id || productId;
113
121
  // Log all planned videos
114
122
  for (const { index, plan } of videoPlans) {
115
123
  const suggestion = contentSuggestions[index];
@@ -122,7 +130,7 @@ export const analyseGrowth = async (options, config
122
130
  logInfo(`\nGenerating ${videoPlans.length} video(s) (max ${MAX_CONCURRENT_VIDEOS} concurrent)...`);
123
131
  const settled = await runWithConcurrencyLimit(videoPlans.map(({ index, plan }) => () => generateGrowthVideo(plan, {
124
132
  productId,
125
- analysisId,
133
+ analysisId: analysisId ?? '',
126
134
  verbose,
127
135
  }).then((result) => ({ index, result }))), MAX_CONCURRENT_VIDEOS);
128
136
  for (const outcome of settled) {
@@ -0,0 +1,25 @@
1
+ import { type ChecklistVerificationResult } from '../technical-design-verification/agent.js';
2
+ export interface TechnicalDesignResult {
3
+ featureId: string;
4
+ technicalDesign: string | null;
5
+ status: 'success' | 'error';
6
+ summary: string;
7
+ verificationResult?: ChecklistVerificationResult;
8
+ iterations?: number;
9
+ data?: {
10
+ checklist_item_results?: any[];
11
+ [key: string]: any;
12
+ };
13
+ }
14
+ /**
15
+ * Build successful design result
16
+ */
17
+ export declare function buildDesignResult(featureId: string, technicalDesign: string, summary: string, iterations: number, checklistItemResults?: any[]): TechnicalDesignResult;
18
+ /**
19
+ * Build verification failure result
20
+ */
21
+ export declare function buildVerificationFailureResult(featureId: string, technicalDesign: string, verificationResult: ChecklistVerificationResult, iterations: number): TechnicalDesignResult;
22
+ /**
23
+ * Build error result when no design was generated
24
+ */
25
+ export declare function buildNoResultsError(featureId: string): TechnicalDesignResult;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Build successful design result
3
+ */
4
+ export function buildDesignResult(featureId, technicalDesign, summary, iterations, checklistItemResults) {
5
+ return {
6
+ featureId,
7
+ technicalDesign,
8
+ status: 'success',
9
+ summary,
10
+ iterations,
11
+ data: checklistItemResults
12
+ ? { checklist_item_results: checklistItemResults }
13
+ : undefined,
14
+ };
15
+ }
16
+ /**
17
+ * Build verification failure result
18
+ */
19
+ export function buildVerificationFailureResult(featureId, technicalDesign, verificationResult, iterations) {
20
+ return {
21
+ featureId,
22
+ technicalDesign,
23
+ status: 'error',
24
+ summary: `Checklist verification failed after ${iterations} iterations: ${verificationResult.summary}`,
25
+ verificationResult,
26
+ iterations,
27
+ };
28
+ }
29
+ /**
30
+ * Build error result when no design was generated
31
+ */
32
+ export function buildNoResultsError(featureId) {
33
+ return {
34
+ featureId,
35
+ technicalDesign: null,
36
+ status: 'error',
37
+ summary: 'Failed to generate technical design - no valid result received',
38
+ };
39
+ }
@@ -0,0 +1,21 @@
1
+ import { EdsgerConfig } from '../../types/index.js';
2
+ import { ChecklistPhaseContext } from '../../services/checklist.js';
3
+ export interface TechnicalDesignOptions {
4
+ featureId: string;
5
+ verbose?: boolean;
6
+ maxVerificationIterations?: number;
7
+ }
8
+ export interface TechnicalDesignResult {
9
+ featureId: string;
10
+ technicalDesign: string | null;
11
+ status: 'success' | 'error';
12
+ summary: string;
13
+ verificationResult?: any;
14
+ iterations?: number;
15
+ savedViaHttp?: boolean;
16
+ data?: {
17
+ checklist_item_results?: any[];
18
+ [key: string]: any;
19
+ };
20
+ }
21
+ export declare const generateTechnicalDesign: (options: TechnicalDesignOptions, config: EdsgerConfig, checklistContext?: ChecklistPhaseContext | null) => Promise<TechnicalDesignResult>;