edsger 0.28.4 → 0.29.1
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.
- package/.claude/settings.local.json +28 -0
- package/.env.local +12 -0
- package/dist/api/features/__tests__/regression-prevention.test.d.ts +5 -0
- package/dist/api/features/__tests__/regression-prevention.test.js +338 -0
- package/dist/api/features/__tests__/status-updater.integration.test.d.ts +5 -0
- package/dist/api/features/__tests__/status-updater.integration.test.js +497 -0
- package/dist/api/tasks.d.ts +26 -0
- package/dist/api/tasks.js +44 -0
- package/dist/commands/task-worker/index.d.ts +8 -0
- package/dist/commands/task-worker/index.js +34 -0
- package/dist/commands/task-worker/processor.d.ts +23 -0
- package/dist/commands/task-worker/processor.js +81 -0
- package/dist/commands/workflow/pipeline-runner.d.ts +17 -0
- package/dist/commands/workflow/pipeline-runner.js +393 -0
- package/dist/commands/workflow/runner.d.ts +26 -0
- package/dist/commands/workflow/runner.js +119 -0
- package/dist/commands/workflow/workflow-runner.d.ts +26 -0
- package/dist/commands/workflow/workflow-runner.js +119 -0
- package/dist/index.js +7 -0
- package/dist/phases/chat-processor/context.d.ts +1 -0
- package/dist/phases/chat-processor/context.js +1 -0
- package/dist/phases/chat-processor/index.js +2 -0
- package/dist/phases/chat-processor/prompts.d.ts +1 -1
- package/dist/phases/chat-processor/prompts.js +35 -0
- package/dist/phases/chat-processor/tools.js +46 -0
- package/dist/phases/code-implementation/analyzer-helpers.d.ts +28 -0
- package/dist/phases/code-implementation/analyzer-helpers.js +177 -0
- package/dist/phases/code-implementation/analyzer.d.ts +32 -0
- package/dist/phases/code-implementation/analyzer.js +629 -0
- package/dist/phases/code-implementation/context-fetcher.d.ts +17 -0
- package/dist/phases/code-implementation/context-fetcher.js +86 -0
- package/dist/phases/code-implementation/mcp-server.d.ts +1 -0
- package/dist/phases/code-implementation/mcp-server.js +93 -0
- package/dist/phases/code-implementation/prompts-improvement.d.ts +5 -0
- package/dist/phases/code-implementation/prompts-improvement.js +108 -0
- package/dist/phases/code-implementation-verification/verifier.d.ts +31 -0
- package/dist/phases/code-implementation-verification/verifier.js +196 -0
- package/dist/phases/code-refine/analyzer.d.ts +41 -0
- package/dist/phases/code-refine/analyzer.js +561 -0
- package/dist/phases/code-refine/context-fetcher.d.ts +94 -0
- package/dist/phases/code-refine/context-fetcher.js +423 -0
- package/dist/phases/code-refine-verification/analysis/llm-analyzer.d.ts +22 -0
- package/dist/phases/code-refine-verification/analysis/llm-analyzer.js +134 -0
- package/dist/phases/code-refine-verification/verifier.d.ts +47 -0
- package/dist/phases/code-refine-verification/verifier.js +597 -0
- package/dist/phases/code-review/analyzer.d.ts +29 -0
- package/dist/phases/code-review/analyzer.js +363 -0
- package/dist/phases/code-review/context-fetcher.d.ts +92 -0
- package/dist/phases/code-review/context-fetcher.js +296 -0
- package/dist/phases/feature-analysis/analyzer-helpers.d.ts +10 -0
- package/dist/phases/feature-analysis/analyzer-helpers.js +47 -0
- package/dist/phases/feature-analysis/analyzer.d.ts +11 -0
- package/dist/phases/feature-analysis/analyzer.js +208 -0
- package/dist/phases/feature-analysis/context-fetcher.d.ts +26 -0
- package/dist/phases/feature-analysis/context-fetcher.js +134 -0
- package/dist/phases/feature-analysis/http-fallback.d.ts +20 -0
- package/dist/phases/feature-analysis/http-fallback.js +95 -0
- package/dist/phases/feature-analysis/mcp-server.d.ts +1 -0
- package/dist/phases/feature-analysis/mcp-server.js +144 -0
- package/dist/phases/feature-analysis/prompts-improvement.d.ts +8 -0
- package/dist/phases/feature-analysis/prompts-improvement.js +109 -0
- package/dist/phases/feature-analysis-verification/verifier.d.ts +37 -0
- package/dist/phases/feature-analysis-verification/verifier.js +147 -0
- package/dist/phases/task/agent.d.ts +10 -0
- package/dist/phases/task/agent.js +81 -0
- package/dist/phases/task/context.d.ts +16 -0
- package/dist/phases/task/context.js +50 -0
- package/dist/phases/task/index.d.ts +17 -0
- package/dist/phases/task/index.js +54 -0
- package/dist/phases/task/prompts.d.ts +9 -0
- package/dist/phases/task/prompts.js +28 -0
- package/dist/phases/technical-design/analyzer-helpers.d.ts +25 -0
- package/dist/phases/technical-design/analyzer-helpers.js +39 -0
- package/dist/phases/technical-design/analyzer.d.ts +21 -0
- package/dist/phases/technical-design/analyzer.js +461 -0
- package/dist/phases/technical-design/context-fetcher.d.ts +12 -0
- package/dist/phases/technical-design/context-fetcher.js +39 -0
- package/dist/phases/technical-design/http-fallback.d.ts +17 -0
- package/dist/phases/technical-design/http-fallback.js +151 -0
- package/dist/phases/technical-design/mcp-server.d.ts +1 -0
- package/dist/phases/technical-design/mcp-server.js +157 -0
- package/dist/phases/technical-design/prompts-improvement.d.ts +5 -0
- package/dist/phases/technical-design/prompts-improvement.js +93 -0
- package/dist/phases/technical-design-verification/verifier.d.ts +53 -0
- package/dist/phases/technical-design-verification/verifier.js +170 -0
- package/dist/services/feature-branches.d.ts +77 -0
- package/dist/services/feature-branches.js +205 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/workflow-runner/config/phase-configs.d.ts +5 -0
- package/dist/workflow-runner/config/phase-configs.js +120 -0
- package/dist/workflow-runner/core/feature-filter.d.ts +16 -0
- package/dist/workflow-runner/core/feature-filter.js +46 -0
- package/dist/workflow-runner/core/index.d.ts +8 -0
- package/dist/workflow-runner/core/index.js +12 -0
- package/dist/workflow-runner/core/pipeline-evaluator.d.ts +24 -0
- package/dist/workflow-runner/core/pipeline-evaluator.js +32 -0
- package/dist/workflow-runner/core/state-manager.d.ts +24 -0
- package/dist/workflow-runner/core/state-manager.js +42 -0
- package/dist/workflow-runner/core/workflow-logger.d.ts +20 -0
- package/dist/workflow-runner/core/workflow-logger.js +65 -0
- package/dist/workflow-runner/executors/phase-executor.d.ts +8 -0
- package/dist/workflow-runner/executors/phase-executor.js +248 -0
- package/dist/workflow-runner/feature-workflow-runner.d.ts +26 -0
- package/dist/workflow-runner/feature-workflow-runner.js +119 -0
- package/dist/workflow-runner/index.d.ts +2 -0
- package/dist/workflow-runner/index.js +2 -0
- package/dist/workflow-runner/pipeline-runner.d.ts +17 -0
- package/dist/workflow-runner/pipeline-runner.js +393 -0
- package/dist/workflow-runner/workflow-processor.d.ts +54 -0
- package/dist/workflow-runner/workflow-processor.js +170 -0
- package/package.json +1 -1
- package/dist/services/lifecycle-agent/__tests__/phase-criteria.test.d.ts +0 -4
- package/dist/services/lifecycle-agent/__tests__/phase-criteria.test.js +0 -133
- package/dist/services/lifecycle-agent/__tests__/transition-rules.test.d.ts +0 -4
- package/dist/services/lifecycle-agent/__tests__/transition-rules.test.js +0 -336
- package/dist/services/lifecycle-agent/index.d.ts +0 -24
- package/dist/services/lifecycle-agent/index.js +0 -25
- package/dist/services/lifecycle-agent/phase-criteria.d.ts +0 -57
- package/dist/services/lifecycle-agent/phase-criteria.js +0 -335
- package/dist/services/lifecycle-agent/transition-rules.d.ts +0 -60
- package/dist/services/lifecycle-agent/transition-rules.js +0 -184
- package/dist/services/lifecycle-agent/types.d.ts +0 -190
- 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
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EdsgerConfig } from '../../types/index.js';
|
|
2
|
+
export interface TaskResult {
|
|
3
|
+
success: boolean;
|
|
4
|
+
summary: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Execute a task using Claude Agent SDK.
|
|
8
|
+
* The agent has access to the codebase and can read/write files.
|
|
9
|
+
*/
|
|
10
|
+
export declare function executeTask(taskPrompt: string, systemPrompt: string, config: EdsgerConfig, verbose?: boolean): Promise<TaskResult>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
2
|
+
import { DEFAULT_MODEL } from '../../constants.js';
|
|
3
|
+
import { logInfo, logError } from '../../utils/logger.js';
|
|
4
|
+
function userMessage(content) {
|
|
5
|
+
return {
|
|
6
|
+
type: 'user',
|
|
7
|
+
message: { role: 'user', content: content },
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
async function* prompt(taskPrompt) {
|
|
11
|
+
yield userMessage(taskPrompt);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Execute a task using Claude Agent SDK.
|
|
15
|
+
* The agent has access to the codebase and can read/write files.
|
|
16
|
+
*/
|
|
17
|
+
export async function executeTask(taskPrompt, systemPrompt, config, verbose) {
|
|
18
|
+
let lastAssistantResponse = '';
|
|
19
|
+
try {
|
|
20
|
+
for await (const message of query({
|
|
21
|
+
prompt: prompt(taskPrompt),
|
|
22
|
+
options: {
|
|
23
|
+
systemPrompt: {
|
|
24
|
+
type: 'preset',
|
|
25
|
+
preset: 'claude_code',
|
|
26
|
+
append: systemPrompt,
|
|
27
|
+
},
|
|
28
|
+
model: DEFAULT_MODEL,
|
|
29
|
+
maxTurns: 1000,
|
|
30
|
+
permissionMode: 'bypassPermissions',
|
|
31
|
+
},
|
|
32
|
+
})) {
|
|
33
|
+
if (verbose) {
|
|
34
|
+
logInfo(`Received message type: ${message.type}`);
|
|
35
|
+
}
|
|
36
|
+
if (message.type === 'assistant' && message.message?.content) {
|
|
37
|
+
for (const content of message.message.content) {
|
|
38
|
+
if (content.type === 'text') {
|
|
39
|
+
lastAssistantResponse += content.text + '\n';
|
|
40
|
+
if (verbose) {
|
|
41
|
+
console.log(`\n${content.text}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else if (content.type === 'tool_use') {
|
|
45
|
+
if (verbose) {
|
|
46
|
+
console.log(`\n${content.name}: ${content.input.description || 'Running...'}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (message.type === 'result') {
|
|
52
|
+
if (message.subtype === 'success') {
|
|
53
|
+
logInfo('Task completed successfully');
|
|
54
|
+
return {
|
|
55
|
+
success: true,
|
|
56
|
+
summary: message.result || lastAssistantResponse || 'Task completed',
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
logError(`Task incomplete: ${message.subtype}`);
|
|
61
|
+
return {
|
|
62
|
+
success: false,
|
|
63
|
+
summary: lastAssistantResponse || `Task ended with status: ${message.subtype}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
success: !!lastAssistantResponse,
|
|
70
|
+
summary: lastAssistantResponse || 'No response received',
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
75
|
+
logError(`Task execution failed: ${errorMessage}`);
|
|
76
|
+
return {
|
|
77
|
+
success: false,
|
|
78
|
+
summary: `Execution failed: ${errorMessage}`,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ProductInfo } from '../../api/products.js';
|
|
2
|
+
import { type TaskInfo } from '../../api/tasks.js';
|
|
3
|
+
export interface TaskContext {
|
|
4
|
+
product: ProductInfo;
|
|
5
|
+
task: TaskInfo;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Fetch context for a product task:
|
|
9
|
+
* - Product info (name, description)
|
|
10
|
+
* - The task itself
|
|
11
|
+
*/
|
|
12
|
+
export declare function fetchTaskContext(task: TaskInfo, verbose?: boolean): Promise<TaskContext>;
|
|
13
|
+
/**
|
|
14
|
+
* Format task context into a prompt string
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatTaskContext(context: TaskContext): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { logInfo, logError } from '../../utils/logger.js';
|
|
2
|
+
import { getProduct } from '../../api/products.js';
|
|
3
|
+
/**
|
|
4
|
+
* Fetch context for a product task:
|
|
5
|
+
* - Product info (name, description)
|
|
6
|
+
* - The task itself
|
|
7
|
+
*/
|
|
8
|
+
export async function fetchTaskContext(task, verbose) {
|
|
9
|
+
try {
|
|
10
|
+
if (verbose) {
|
|
11
|
+
logInfo(`Fetching context for task: ${task.name}`);
|
|
12
|
+
logInfo(` Product ID: ${task.product_id}`);
|
|
13
|
+
}
|
|
14
|
+
const product = await getProduct(task.product_id, verbose);
|
|
15
|
+
if (verbose) {
|
|
16
|
+
logInfo(`Task context fetched:`);
|
|
17
|
+
logInfo(` Product: ${product.name}`);
|
|
18
|
+
}
|
|
19
|
+
return { product, task };
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
23
|
+
logError(`Failed to fetch task context: ${errorMessage}`);
|
|
24
|
+
throw new Error(`Context fetch failed: ${errorMessage}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Format task context into a prompt string
|
|
29
|
+
*/
|
|
30
|
+
export function formatTaskContext(context) {
|
|
31
|
+
const { product, task } = context;
|
|
32
|
+
return `# Task Context
|
|
33
|
+
|
|
34
|
+
## Product
|
|
35
|
+
- **Name**: ${product.name}
|
|
36
|
+
- **Product ID**: ${product.id}
|
|
37
|
+
- **Description**: ${product.description || 'No description'}
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Current Task
|
|
42
|
+
- **Task Name**: ${task.name}
|
|
43
|
+
- **Task ID**: ${task.id}
|
|
44
|
+
- **Priority**: ${task.priority} (1=low, 2=medium, 3=high, 4=urgent)
|
|
45
|
+
- **Description**: ${task.description || 'No description provided'}
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
**Your objective**: Complete the task described above within the context of this product.`;
|
|
50
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { EdsgerConfig } from '../../types/index.js';
|
|
2
|
+
import { type TaskInfo } from '../../api/tasks.js';
|
|
3
|
+
import { type TaskResult } from './agent.js';
|
|
4
|
+
export type { TaskResult };
|
|
5
|
+
export interface TaskOptions {
|
|
6
|
+
task: TaskInfo;
|
|
7
|
+
verbose?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Execute a product task:
|
|
11
|
+
* 1. Mark task as in_progress
|
|
12
|
+
* 2. Fetch product context
|
|
13
|
+
* 3. Build prompt with context + task description
|
|
14
|
+
* 4. Run Claude agent to complete the task
|
|
15
|
+
* 5. Mark task as completed or blocked
|
|
16
|
+
*/
|
|
17
|
+
export declare function runTask(options: TaskOptions, config: EdsgerConfig): Promise<TaskResult>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { logInfo, logError } from '../../utils/logger.js';
|
|
2
|
+
import { updateTaskStatus } from '../../api/tasks.js';
|
|
3
|
+
import { fetchTaskContext, formatTaskContext } from './context.js';
|
|
4
|
+
import { createTaskSystemPrompt, createTaskPrompt } from './prompts.js';
|
|
5
|
+
import { executeTask } from './agent.js';
|
|
6
|
+
/**
|
|
7
|
+
* Execute a product task:
|
|
8
|
+
* 1. Mark task as in_progress
|
|
9
|
+
* 2. Fetch product context
|
|
10
|
+
* 3. Build prompt with context + task description
|
|
11
|
+
* 4. Run Claude agent to complete the task
|
|
12
|
+
* 5. Mark task as completed or blocked
|
|
13
|
+
*/
|
|
14
|
+
export async function runTask(options, config) {
|
|
15
|
+
const { task, verbose } = options;
|
|
16
|
+
logInfo(`Starting task: ${task.name} (${task.id})`);
|
|
17
|
+
// Mark as in_progress
|
|
18
|
+
await updateTaskStatus(task.id, 'in_progress', verbose);
|
|
19
|
+
try {
|
|
20
|
+
// 1. Fetch context
|
|
21
|
+
if (verbose) {
|
|
22
|
+
logInfo('Fetching task context...');
|
|
23
|
+
}
|
|
24
|
+
const context = await fetchTaskContext(task, verbose);
|
|
25
|
+
// 2. Build prompts
|
|
26
|
+
const contextInfo = formatTaskContext(context);
|
|
27
|
+
const systemPrompt = createTaskSystemPrompt();
|
|
28
|
+
const taskPrompt = createTaskPrompt(contextInfo);
|
|
29
|
+
if (verbose) {
|
|
30
|
+
logInfo('Starting AI agent for task...');
|
|
31
|
+
}
|
|
32
|
+
// 3. Execute
|
|
33
|
+
const result = await executeTask(taskPrompt, systemPrompt, config, verbose);
|
|
34
|
+
// 4. Update status
|
|
35
|
+
if (result.success) {
|
|
36
|
+
await updateTaskStatus(task.id, 'completed', verbose);
|
|
37
|
+
logInfo(`Task completed: ${task.name}`);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
await updateTaskStatus(task.id, 'blocked', verbose);
|
|
41
|
+
logError(`Task blocked: ${task.name} - ${result.summary}`);
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
47
|
+
logError(`Task failed: ${task.name} - ${errorMessage}`);
|
|
48
|
+
await updateTaskStatus(task.id, 'blocked', verbose);
|
|
49
|
+
return {
|
|
50
|
+
success: false,
|
|
51
|
+
summary: `Failed: ${errorMessage}`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System prompt for product task execution.
|
|
3
|
+
* The agent works on a specific task within a product's codebase.
|
|
4
|
+
*/
|
|
5
|
+
export declare function createTaskSystemPrompt(): string;
|
|
6
|
+
/**
|
|
7
|
+
* Create the user prompt combining context and task instructions
|
|
8
|
+
*/
|
|
9
|
+
export declare function createTaskPrompt(contextInfo: string): string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System prompt for product task execution.
|
|
3
|
+
* The agent works on a specific task within a product's codebase.
|
|
4
|
+
*/
|
|
5
|
+
export function createTaskSystemPrompt() {
|
|
6
|
+
return `You are an AI software engineer working on a specific task for a product.
|
|
7
|
+
|
|
8
|
+
## Your Role
|
|
9
|
+
You are given a product context and a specific task to complete.
|
|
10
|
+
|
|
11
|
+
## Guidelines
|
|
12
|
+
1. Focus ONLY on the current task
|
|
13
|
+
2. Write clean, well-tested code
|
|
14
|
+
3. Use the available tools to read, understand, and modify the codebase
|
|
15
|
+
4. If the task is about implementation, write the actual code
|
|
16
|
+
5. If the task is about analysis or planning, provide detailed output
|
|
17
|
+
|
|
18
|
+
## Output
|
|
19
|
+
When done, provide a brief summary of what you accomplished for this task.`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create the user prompt combining context and task instructions
|
|
23
|
+
*/
|
|
24
|
+
export function createTaskPrompt(contextInfo) {
|
|
25
|
+
return `${contextInfo}
|
|
26
|
+
|
|
27
|
+
Please complete the task described above. Use the codebase tools available to you to implement the changes needed.`;
|
|
28
|
+
}
|
|
@@ -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>;
|