edsger 0.19.2 → 0.19.4

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.
@@ -1,10 +1,11 @@
1
1
  import { query } from '@anthropic-ai/claude-agent-sdk';
2
2
  import { logInfo, logError } from '../../utils/logger.js';
3
3
  import { fetchBranchPlanningContext } from './context.js';
4
- import { createBranchPlanningSystemPrompt, createBranchPlanningPromptWithContext, formatContextForPrompt, formatExistingBranchesForPrompt, } from './prompts.js';
4
+ import { createBranchPlanningSystemPrompt, createBranchPlanningPromptWithContext, createImprovementPrompt, formatContextForPrompt, formatExistingBranchesForPrompt, } from './prompts.js';
5
5
  import { buildSuccessResult, buildErrorResult, buildNoChangeResult, validatePlannedBranches, sortBranchesByDependency, } from './outcome.js';
6
6
  import { createFeatureBranches, clearFeatureBranches, } from '../../services/feature-branches.js';
7
7
  import { logFeaturePhaseEvent } from '../../services/audit-logs.js';
8
+ import { getFeedbacksForPhase, formatFeedbacksForContext, } from '../../services/feedbacks.js';
8
9
  function userMessage(content) {
9
10
  return {
10
11
  type: 'user',
@@ -34,27 +35,71 @@ export const planFeatureBranches = async (options, config) => {
34
35
  }, verbose);
35
36
  // Fetch context
36
37
  const context = await fetchBranchPlanningContext(featureId, verbose);
37
- // Check if there are existing branches
38
- if (context.existing_branches.length > 0 && !replaceExisting) {
38
+ // Fetch feedbacks for branch_planning phase
39
+ let feedbacksContext = null;
40
+ let hasFeedbacks = false;
41
+ try {
42
+ feedbacksContext = await getFeedbacksForPhase({ featureId, verbose }, 'branch-planning');
43
+ hasFeedbacks = feedbacksContext.feedbacks.length > 0;
44
+ if (verbose) {
45
+ logInfo(`šŸ“‹ Feedbacks fetched: ${feedbacksContext.feedbacks.length} feedbacks found`);
46
+ }
47
+ }
48
+ catch (error) {
49
+ if (verbose) {
50
+ logError(`Failed to fetch feedbacks: ${error instanceof Error ? error.message : String(error)}`);
51
+ }
52
+ }
53
+ // Determine operation mode
54
+ const hasExistingBranches = context.existing_branches.length > 0;
55
+ const isIncrementalUpdate = hasExistingBranches && hasFeedbacks && !replaceExisting;
56
+ if (verbose) {
57
+ logInfo('\nšŸ“‹ Branch Planning Mode Decision:');
58
+ logInfo(` - Has existing branches: ${hasExistingBranches} (${context.existing_branches.length} branches)`);
59
+ logInfo(` - Has feedbacks: ${hasFeedbacks} (${feedbacksContext?.feedbacks.length || 0} feedbacks)`);
60
+ logInfo(` - Replace existing: ${replaceExisting || false}`);
61
+ logInfo(` - Mode: ${isIncrementalUpdate ? 'šŸ”„ Incremental Update' : hasExistingBranches && !replaceExisting ? 'āœ… No Change Needed' : '✨ New Planning'}`);
62
+ }
63
+ // Check if there are existing branches and no feedbacks - no change needed
64
+ if (hasExistingBranches && !hasFeedbacks && !replaceExisting) {
39
65
  if (verbose) {
40
- logInfo(`Feature already has ${context.existing_branches.length} branches planned.`);
66
+ logInfo(`Feature already has ${context.existing_branches.length} branches planned and no feedbacks to address.`);
41
67
  logInfo('Use replaceExisting: true to re-plan.');
42
68
  }
43
69
  return buildNoChangeResult(featureId, context.existing_branches.length);
44
70
  }
45
- // Clear existing branches if requested
46
- if (replaceExisting && context.existing_branches.length > 0) {
71
+ // Clear existing branches if requested (full re-plan)
72
+ if (replaceExisting && hasExistingBranches) {
47
73
  if (verbose) {
48
- logInfo(`Clearing ${context.existing_branches.length} existing branches...`);
74
+ logInfo(`Clearing ${context.existing_branches.length} existing branches for full re-plan...`);
49
75
  }
50
76
  await clearFeatureBranches({ featureId, verbose }, true);
51
77
  }
52
78
  // Format context for prompt
53
79
  const contextInfo = formatContextForPrompt(context.feature, context.product, context.user_stories, context.test_cases);
54
80
  const existingBranchesInfo = formatExistingBranchesForPrompt(context.existing_branches);
55
- // Create prompts
81
+ // Create prompts based on mode
56
82
  const systemPrompt = createBranchPlanningSystemPrompt(config, featureId);
57
- const userPrompt = createBranchPlanningPromptWithContext(featureId, contextInfo, existingBranchesInfo);
83
+ let userPrompt;
84
+ if (isIncrementalUpdate && feedbacksContext) {
85
+ // Incremental update mode: adjust existing branches based on feedbacks
86
+ if (verbose) {
87
+ logInfo('\nšŸŽÆ Feedbacks that will be addressed:');
88
+ feedbacksContext.feedbacks.forEach((fb, idx) => {
89
+ logInfo(` ${idx + 1}. [${fb.feedback_type}] ${fb.title}`);
90
+ logInfo(` ${fb.content.substring(0, 100)}${fb.content.length > 100 ? '...' : ''}`);
91
+ });
92
+ }
93
+ const feedbacksInfo = await formatFeedbacksForContext(feedbacksContext);
94
+ const currentPlanInfo = existingBranchesInfo || 'No existing branch plan documented.';
95
+ userPrompt = createImprovementPrompt(feedbacksInfo, currentPlanInfo);
96
+ // Add context info to the improvement prompt
97
+ userPrompt = `${userPrompt}\n\n## Feature Context\n\n${contextInfo}`;
98
+ }
99
+ else {
100
+ // New planning mode
101
+ userPrompt = createBranchPlanningPromptWithContext(featureId, contextInfo, existingBranchesInfo);
102
+ }
58
103
  if (verbose) {
59
104
  logInfo('Starting Claude Code query for branch planning...');
60
105
  }
@@ -74,6 +119,14 @@ export const planFeatureBranches = async (options, config) => {
74
119
  }
75
120
  // Sort branches by dependency
76
121
  const sortedBranches = sortBranchesByDependency(result.branches);
122
+ // For incremental update mode, clear existing branches before creating new ones
123
+ // This is because the AI may have reorganized the branch structure
124
+ if (isIncrementalUpdate && hasExistingBranches) {
125
+ if (verbose) {
126
+ logInfo(`šŸ”„ Clearing ${context.existing_branches.length} existing branches for incremental update...`);
127
+ }
128
+ await clearFeatureBranches({ featureId, verbose: false }, true);
129
+ }
77
130
  // Create branches in database with proper dependencies
78
131
  // We need to create them one by one to get IDs for base_branch_id
79
132
  const createdBranches = [];
@@ -104,7 +157,8 @@ export const planFeatureBranches = async (options, config) => {
104
157
  }
105
158
  }
106
159
  if (verbose) {
107
- logInfo(`āœ… Created ${sortedBranches.length} feature branches`);
160
+ const modeLabel = isIncrementalUpdate ? 'šŸ”„ Updated' : 'āœ… Created';
161
+ logInfo(`${modeLabel} ${sortedBranches.length} feature branches`);
108
162
  sortedBranches.forEach((b, idx) => {
109
163
  logInfo(` ${idx + 1}. ${b.name}`);
110
164
  if (b.scope) {
@@ -121,11 +175,16 @@ export const planFeatureBranches = async (options, config) => {
121
175
  metadata: {
122
176
  branches_created: sortedBranches.length,
123
177
  branch_names: sortedBranches.map((b) => b.name),
178
+ mode: isIncrementalUpdate ? 'incremental_update' : 'new_planning',
179
+ feedbacks_addressed: feedbacksContext?.feedbacks.length || 0,
124
180
  timestamp: new Date().toISOString(),
125
181
  },
126
182
  }, verbose);
183
+ const summaryPrefix = isIncrementalUpdate
184
+ ? `Updated branch plan based on ${feedbacksContext?.feedbacks.length || 0} feedbacks.`
185
+ : '';
127
186
  return buildSuccessResult(featureId, sortedBranches, result.summary ||
128
- `Created ${sortedBranches.length} branches for incremental development`, result.rationale);
187
+ `${summaryPrefix} ${sortedBranches.length} branches for incremental development`.trim(), result.rationale);
129
188
  }
130
189
  catch (error) {
131
190
  const errorMessage = error instanceof Error ? error.message : String(error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edsger",
3
- "version": "0.19.2",
3
+ "version": "0.19.4",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "edsger": "dist/index.js"