edsger 0.16.0 → 0.17.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 (102) hide show
  1. package/dist/commands/code-review/reviewer.js +5 -1
  2. package/dist/commands/init/index.js +5 -1
  3. package/dist/commands/refactor/refactor.js +5 -1
  4. package/dist/config.js +9 -10
  5. package/dist/phases/bug-fixing/analyzer.js +5 -1
  6. package/dist/phases/code-implementation/index.js +5 -1
  7. package/dist/phases/code-implementation-verification/agent.js +5 -1
  8. package/dist/phases/code-refine/context.js +41 -5
  9. package/dist/phases/code-refine/index.js +5 -1
  10. package/dist/phases/code-review/index.js +5 -1
  11. package/dist/phases/code-testing/analyzer.js +5 -1
  12. package/dist/phases/feature-analysis/agent.js +5 -1
  13. package/dist/phases/feature-analysis-verification/agent.js +5 -1
  14. package/dist/phases/functional-testing/analyzer.js +5 -1
  15. package/dist/phases/technical-design/index.js +5 -1
  16. package/dist/phases/technical-design-verification/agent.js +5 -1
  17. package/package.json +2 -2
  18. package/.claude/settings.local.json +0 -28
  19. package/dist/api/features/__tests__/regression-prevention.test.d.ts +0 -5
  20. package/dist/api/features/__tests__/regression-prevention.test.js +0 -338
  21. package/dist/api/features/__tests__/status-updater.integration.test.d.ts +0 -5
  22. package/dist/api/features/__tests__/status-updater.integration.test.js +0 -497
  23. package/dist/commands/workflow/pipeline-runner.d.ts +0 -17
  24. package/dist/commands/workflow/pipeline-runner.js +0 -393
  25. package/dist/commands/workflow/runner.d.ts +0 -26
  26. package/dist/commands/workflow/runner.js +0 -119
  27. package/dist/commands/workflow/workflow-runner.d.ts +0 -26
  28. package/dist/commands/workflow/workflow-runner.js +0 -119
  29. package/dist/phases/code-implementation/analyzer-helpers.d.ts +0 -28
  30. package/dist/phases/code-implementation/analyzer-helpers.js +0 -177
  31. package/dist/phases/code-implementation/analyzer.d.ts +0 -32
  32. package/dist/phases/code-implementation/analyzer.js +0 -629
  33. package/dist/phases/code-implementation/context-fetcher.d.ts +0 -17
  34. package/dist/phases/code-implementation/context-fetcher.js +0 -86
  35. package/dist/phases/code-implementation/mcp-server.d.ts +0 -1
  36. package/dist/phases/code-implementation/mcp-server.js +0 -93
  37. package/dist/phases/code-implementation/prompts-improvement.d.ts +0 -5
  38. package/dist/phases/code-implementation/prompts-improvement.js +0 -108
  39. package/dist/phases/code-implementation-verification/verifier.d.ts +0 -31
  40. package/dist/phases/code-implementation-verification/verifier.js +0 -196
  41. package/dist/phases/code-refine/analyzer.d.ts +0 -41
  42. package/dist/phases/code-refine/analyzer.js +0 -561
  43. package/dist/phases/code-refine/context-fetcher.d.ts +0 -94
  44. package/dist/phases/code-refine/context-fetcher.js +0 -423
  45. package/dist/phases/code-refine-verification/analysis/llm-analyzer.d.ts +0 -22
  46. package/dist/phases/code-refine-verification/analysis/llm-analyzer.js +0 -134
  47. package/dist/phases/code-refine-verification/verifier.d.ts +0 -47
  48. package/dist/phases/code-refine-verification/verifier.js +0 -597
  49. package/dist/phases/code-review/analyzer.d.ts +0 -29
  50. package/dist/phases/code-review/analyzer.js +0 -363
  51. package/dist/phases/code-review/context-fetcher.d.ts +0 -92
  52. package/dist/phases/code-review/context-fetcher.js +0 -296
  53. package/dist/phases/feature-analysis/analyzer-helpers.d.ts +0 -10
  54. package/dist/phases/feature-analysis/analyzer-helpers.js +0 -47
  55. package/dist/phases/feature-analysis/analyzer.d.ts +0 -11
  56. package/dist/phases/feature-analysis/analyzer.js +0 -208
  57. package/dist/phases/feature-analysis/context-fetcher.d.ts +0 -26
  58. package/dist/phases/feature-analysis/context-fetcher.js +0 -134
  59. package/dist/phases/feature-analysis/http-fallback.d.ts +0 -20
  60. package/dist/phases/feature-analysis/http-fallback.js +0 -95
  61. package/dist/phases/feature-analysis/mcp-server.d.ts +0 -1
  62. package/dist/phases/feature-analysis/mcp-server.js +0 -144
  63. package/dist/phases/feature-analysis/prompts-improvement.d.ts +0 -8
  64. package/dist/phases/feature-analysis/prompts-improvement.js +0 -109
  65. package/dist/phases/feature-analysis-verification/verifier.d.ts +0 -37
  66. package/dist/phases/feature-analysis-verification/verifier.js +0 -147
  67. package/dist/phases/technical-design/analyzer-helpers.d.ts +0 -25
  68. package/dist/phases/technical-design/analyzer-helpers.js +0 -39
  69. package/dist/phases/technical-design/analyzer.d.ts +0 -21
  70. package/dist/phases/technical-design/analyzer.js +0 -461
  71. package/dist/phases/technical-design/context-fetcher.d.ts +0 -12
  72. package/dist/phases/technical-design/context-fetcher.js +0 -39
  73. package/dist/phases/technical-design/http-fallback.d.ts +0 -17
  74. package/dist/phases/technical-design/http-fallback.js +0 -151
  75. package/dist/phases/technical-design/mcp-server.d.ts +0 -1
  76. package/dist/phases/technical-design/mcp-server.js +0 -157
  77. package/dist/phases/technical-design/prompts-improvement.d.ts +0 -5
  78. package/dist/phases/technical-design/prompts-improvement.js +0 -93
  79. package/dist/phases/technical-design-verification/verifier.d.ts +0 -53
  80. package/dist/phases/technical-design-verification/verifier.js +0 -170
  81. package/dist/workflow-runner/config/phase-configs.d.ts +0 -5
  82. package/dist/workflow-runner/config/phase-configs.js +0 -120
  83. package/dist/workflow-runner/core/feature-filter.d.ts +0 -16
  84. package/dist/workflow-runner/core/feature-filter.js +0 -46
  85. package/dist/workflow-runner/core/index.d.ts +0 -8
  86. package/dist/workflow-runner/core/index.js +0 -12
  87. package/dist/workflow-runner/core/pipeline-evaluator.d.ts +0 -24
  88. package/dist/workflow-runner/core/pipeline-evaluator.js +0 -32
  89. package/dist/workflow-runner/core/state-manager.d.ts +0 -24
  90. package/dist/workflow-runner/core/state-manager.js +0 -42
  91. package/dist/workflow-runner/core/workflow-logger.d.ts +0 -20
  92. package/dist/workflow-runner/core/workflow-logger.js +0 -65
  93. package/dist/workflow-runner/executors/phase-executor.d.ts +0 -8
  94. package/dist/workflow-runner/executors/phase-executor.js +0 -248
  95. package/dist/workflow-runner/feature-workflow-runner.d.ts +0 -26
  96. package/dist/workflow-runner/feature-workflow-runner.js +0 -119
  97. package/dist/workflow-runner/index.d.ts +0 -2
  98. package/dist/workflow-runner/index.js +0 -2
  99. package/dist/workflow-runner/pipeline-runner.d.ts +0 -17
  100. package/dist/workflow-runner/pipeline-runner.js +0 -393
  101. package/dist/workflow-runner/workflow-processor.d.ts +0 -54
  102. package/dist/workflow-runner/workflow-processor.js +0 -170
@@ -7,7 +7,11 @@ export const reviewWithClaudeSDK = async (config, staged = false, filePatterns)
7
7
  for await (const message of query({
8
8
  prompt: reviewPrompt,
9
9
  options: {
10
- systemPrompt: { type: 'preset', preset: 'claude_code', append: systemPrompt },
10
+ systemPrompt: {
11
+ type: 'preset',
12
+ preset: 'claude_code',
13
+ append: systemPrompt,
14
+ },
11
15
  model: config.claude.model || 'sonnet',
12
16
  },
13
17
  })) {
@@ -58,7 +58,11 @@ async function generateDocumentation(prompt, description, verbose) {
58
58
  for await (const message of query({
59
59
  prompt,
60
60
  options: {
61
- systemPrompt: { type: 'preset', preset: 'claude_code', append: createSystemPrompt() },
61
+ systemPrompt: {
62
+ type: 'preset',
63
+ preset: 'claude_code',
64
+ append: createSystemPrompt(),
65
+ },
62
66
  model: 'opus',
63
67
  permissionMode: 'bypassPermissions',
64
68
  },
@@ -15,7 +15,11 @@ export const runRefactor = async (options) => {
15
15
  for await (const message of query({
16
16
  prompt: refactorPrompt,
17
17
  options: {
18
- systemPrompt: { type: 'preset', preset: 'claude_code', append: systemPrompt },
18
+ systemPrompt: {
19
+ type: 'preset',
20
+ preset: 'claude_code',
21
+ append: systemPrompt,
22
+ },
19
23
  model: config.claude.model || 'sonnet',
20
24
  permissionMode: 'bypassPermissions',
21
25
  },
package/dist/config.js CHANGED
@@ -12,7 +12,7 @@ const DEFAULT_CONFIG = {
12
12
  '**/*.java',
13
13
  '**/*.cpp',
14
14
  '**/*.c',
15
- '**/*.h'
15
+ '**/*.h',
16
16
  ],
17
17
  exclude: [
18
18
  '**/node_modules/**',
@@ -24,28 +24,26 @@ const DEFAULT_CONFIG = {
24
24
  '**/*.spec.ts',
25
25
  '**/__tests__/**',
26
26
  '**/*.min.js',
27
- '**/*.bundle.js'
27
+ '**/*.bundle.js',
28
28
  ],
29
29
  severity: 'error',
30
30
  maxFiles: 50,
31
31
  claude: {
32
32
  model: 'opus',
33
- timeout: 120000
34
- }
33
+ timeout: 120000,
34
+ },
35
35
  };
36
36
  export const loadConfig = (configPath) => {
37
37
  const explorer = cosmiconfigSync('edsger');
38
- const result = configPath
39
- ? explorer.load(configPath)
40
- : explorer.search();
38
+ const result = configPath ? explorer.load(configPath) : explorer.search();
41
39
  const userConfig = result?.config || {};
42
40
  return {
43
41
  ...DEFAULT_CONFIG,
44
42
  ...userConfig,
45
43
  claude: {
46
44
  ...DEFAULT_CONFIG.claude,
47
- ...(userConfig.claude || {})
48
- }
45
+ ...(userConfig.claude || {}),
46
+ },
49
47
  };
50
48
  };
51
49
  export const validateConfig = (config) => {
@@ -62,7 +60,8 @@ export const validateConfig = (config) => {
62
60
  if (typeof config.maxFiles !== 'number' || config.maxFiles <= 0) {
63
61
  errors.push('maxFiles must be a positive number');
64
62
  }
65
- if (config.claude.timeout && (typeof config.claude.timeout !== 'number' || config.claude.timeout <= 0)) {
63
+ if (config.claude.timeout &&
64
+ (typeof config.claude.timeout !== 'number' || config.claude.timeout <= 0)) {
66
65
  errors.push('claude.timeout must be a positive number');
67
66
  }
68
67
  return errors;
@@ -54,7 +54,11 @@ export const fixTestFailures = async (options, config) => {
54
54
  for await (const message of query({
55
55
  prompt: prompt(bugFixPrompt),
56
56
  options: {
57
- systemPrompt: { type: 'preset', preset: 'claude_code', append: systemPrompt },
57
+ systemPrompt: {
58
+ type: 'preset',
59
+ preset: 'claude_code',
60
+ append: systemPrompt,
61
+ },
58
62
  model: config.claude.model || 'sonnet',
59
63
  maxTurns: 2000,
60
64
  permissionMode: 'bypassPermissions',
@@ -96,7 +96,11 @@ export const implementFeatureCode = async (options, config, checklistContext) =>
96
96
  for await (const message of query({
97
97
  prompt: prompt(currentPrompt),
98
98
  options: {
99
- systemPrompt: { type: 'preset', preset: 'claude_code', append: systemPrompt },
99
+ systemPrompt: {
100
+ type: 'preset',
101
+ preset: 'claude_code',
102
+ append: systemPrompt,
103
+ },
100
104
  model: config.claude.model || 'sonnet',
101
105
  maxTurns: 3000,
102
106
  permissionMode: 'bypassPermissions',
@@ -33,7 +33,11 @@ export async function verifyCodeImplementationCompliance(options, config) {
33
33
  for await (const message of query({
34
34
  prompt: prompt(verificationPrompt),
35
35
  options: {
36
- systemPrompt: { type: 'preset', preset: 'claude_code', append: systemPrompt },
36
+ systemPrompt: {
37
+ type: 'preset',
38
+ preset: 'claude_code',
39
+ append: systemPrompt,
40
+ },
37
41
  model: config.claude.model || 'sonnet',
38
42
  maxTurns: 1000,
39
43
  permissionMode: 'bypassPermissions',
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import { Octokit } from '@octokit/rest';
6
6
  import { getFeature } from '../../api/features/get-feature.js';
7
+ import { downloadImagesForClaudeCode } from '../../utils/image-downloader.js';
7
8
  /**
8
9
  * Extract owner, repo, and PR number from GitHub PR URL
9
10
  */
@@ -268,6 +269,39 @@ export async function fetchTestCases(featureId, verbose) {
268
269
  return [];
269
270
  }
270
271
  }
272
+ /**
273
+ * Process images in GitHub PR reviews and comments
274
+ * Downloads images from markdown content and replaces URLs with local paths
275
+ */
276
+ async function processGitHubContentImages(reviews, reviewThreads, featureId, verbose) {
277
+ if (verbose) {
278
+ console.log(`šŸ–¼ļø Processing images in GitHub PR content...`);
279
+ }
280
+ // Process review bodies
281
+ const processedReviews = await Promise.all(reviews.map(async (review) => {
282
+ if (!review.body)
283
+ return review;
284
+ const { processedMarkdown } = await downloadImagesForClaudeCode(review.body, featureId);
285
+ return { ...review, body: processedMarkdown };
286
+ }));
287
+ // Process comment bodies in review threads
288
+ const processedThreads = await Promise.all(reviewThreads.map(async (thread) => {
289
+ const processedComments = await Promise.all(thread.comments.map(async (comment) => {
290
+ if (!comment.body)
291
+ return comment;
292
+ const { processedMarkdown } = await downloadImagesForClaudeCode(comment.body, featureId);
293
+ return { ...comment, body: processedMarkdown };
294
+ }));
295
+ return { ...thread, comments: processedComments };
296
+ }));
297
+ if (verbose) {
298
+ console.log(`āœ… Finished processing images in GitHub PR content`);
299
+ }
300
+ return {
301
+ processedReviews,
302
+ processedThreads,
303
+ };
304
+ }
271
305
  /**
272
306
  * Fetch complete code refine context
273
307
  */
@@ -293,10 +327,12 @@ export async function fetchCodeRefineContext(featureId, githubToken, verbose) {
293
327
  fetchUserStories(featureId, verbose),
294
328
  fetchTestCases(featureId, verbose),
295
329
  ]);
296
- // Extract review comments from unresolved threads
297
- const reviewComments = prData.reviewThreads.flatMap((thread) => thread.comments);
330
+ // Process images in GitHub PR content (reviews and comments may contain markdown images)
331
+ const { processedReviews, processedThreads } = await processGitHubContentImages(prData.reviews, prData.reviewThreads, featureId, verbose);
332
+ // Extract review comments from unresolved threads (use processed threads)
333
+ const reviewComments = processedThreads.flatMap((thread) => thread.comments);
298
334
  if (verbose) {
299
- console.log(`šŸ“Š Summary: ${prData.reviews.length} reviews requesting changes, ${prData.reviewThreads.length} unresolved threads, ${reviewComments.length} total comments`);
335
+ console.log(`šŸ“Š Summary: ${processedReviews.length} reviews requesting changes, ${processedThreads.length} unresolved threads, ${reviewComments.length} total comments`);
300
336
  }
301
337
  return {
302
338
  featureId,
@@ -306,9 +342,9 @@ export async function fetchCodeRefineContext(featureId, githubToken, verbose) {
306
342
  pullRequestNumber: prNumber,
307
343
  owner,
308
344
  repo,
309
- reviews: prData.reviews,
345
+ reviews: processedReviews,
310
346
  reviewComments,
311
- reviewThreads: prData.reviewThreads,
347
+ reviewThreads: processedThreads,
312
348
  technicalDesign: feature.technical_design,
313
349
  userStories,
314
350
  testCases,
@@ -133,7 +133,11 @@ export const refineCodeFromPRFeedback = async (options, config) => {
133
133
  for await (const message of query({
134
134
  prompt: prompt(refinePrompt),
135
135
  options: {
136
- systemPrompt: { type: 'preset', preset: 'claude_code', append: systemPrompt },
136
+ systemPrompt: {
137
+ type: 'preset',
138
+ preset: 'claude_code',
139
+ append: systemPrompt,
140
+ },
137
141
  model: config.claude.model || 'sonnet',
138
142
  maxTurns: 2000,
139
143
  permissionMode: 'bypassPermissions',
@@ -172,7 +172,11 @@ export const reviewPullRequest = async (options, config) => {
172
172
  for await (const message of query({
173
173
  prompt: prompt(reviewPrompt),
174
174
  options: {
175
- systemPrompt: { type: 'preset', preset: 'claude_code', append: systemPrompt },
175
+ systemPrompt: {
176
+ type: 'preset',
177
+ preset: 'claude_code',
178
+ append: systemPrompt,
179
+ },
176
180
  model: config.claude.model || 'sonnet',
177
181
  maxTurns: 50, // Limited turns since this is just analysis
178
182
  permissionMode: 'bypassPermissions',
@@ -37,7 +37,11 @@ export const writeCodeTests = async (options, config) => {
37
37
  for await (const message of query({
38
38
  prompt: prompt(testingPrompt),
39
39
  options: {
40
- systemPrompt: { type: 'preset', preset: 'claude_code', append: systemPrompt },
40
+ systemPrompt: {
41
+ type: 'preset',
42
+ preset: 'claude_code',
43
+ append: systemPrompt,
44
+ },
41
45
  model: config.claude.model || 'sonnet',
42
46
  maxTurns: 3000,
43
47
  permissionMode: 'bypassPermissions',
@@ -43,7 +43,11 @@ export async function executeAnalysisQuery(currentPrompt, systemPrompt, config,
43
43
  for await (const message of query({
44
44
  prompt: prompt(currentPrompt),
45
45
  options: {
46
- systemPrompt: { type: 'preset', preset: 'claude_code', append: systemPrompt },
46
+ systemPrompt: {
47
+ type: 'preset',
48
+ preset: 'claude_code',
49
+ append: systemPrompt,
50
+ },
47
51
  model: config.claude.model || 'sonnet',
48
52
  maxTurns: 1000,
49
53
  permissionMode: 'bypassPermissions',
@@ -41,7 +41,11 @@ export async function verifyChecklistCompliance(options, config) {
41
41
  for await (const message of query({
42
42
  prompt: prompt(verificationPrompt),
43
43
  options: {
44
- systemPrompt: { type: 'preset', preset: 'claude_code', append: systemPrompt },
44
+ systemPrompt: {
45
+ type: 'preset',
46
+ preset: 'claude_code',
47
+ append: systemPrompt,
48
+ },
45
49
  model: config.claude.model || 'sonnet',
46
50
  maxTurns: 100,
47
51
  permissionMode: 'bypassPermissions',
@@ -59,7 +59,11 @@ export const runFunctionalTesting = async (options, config, checklistContext) =>
59
59
  for await (const message of query({
60
60
  prompt: prompt(testingPrompt),
61
61
  options: {
62
- systemPrompt: { type: 'preset', preset: 'claude_code', append: systemPrompt },
62
+ systemPrompt: {
63
+ type: 'preset',
64
+ preset: 'claude_code',
65
+ append: systemPrompt,
66
+ },
63
67
  model: config.claude.model || 'sonnet',
64
68
  maxTurns: 1000,
65
69
  permissionMode: 'bypassPermissions',
@@ -277,7 +277,11 @@ async function executeDesignQuery(designPrompt, systemPrompt, config, verbose) {
277
277
  for await (const message of query({
278
278
  prompt: prompt(designPrompt),
279
279
  options: {
280
- systemPrompt: { type: 'preset', preset: 'claude_code', append: systemPrompt },
280
+ systemPrompt: {
281
+ type: 'preset',
282
+ preset: 'claude_code',
283
+ append: systemPrompt,
284
+ },
281
285
  model: config.claude.model || 'sonnet',
282
286
  maxTurns: 1000,
283
287
  permissionMode: 'bypassPermissions',
@@ -48,7 +48,11 @@ export async function verifyTechnicalDesignCompliance(options, config) {
48
48
  for await (const message of query({
49
49
  prompt: prompt(verificationPrompt),
50
50
  options: {
51
- systemPrompt: { type: 'preset', preset: 'claude_code', append: systemPrompt },
51
+ systemPrompt: {
52
+ type: 'preset',
53
+ preset: 'claude_code',
54
+ append: systemPrompt,
55
+ },
52
56
  model: config.claude.model || 'sonnet',
53
57
  maxTurns: 100,
54
58
  permissionMode: 'bypassPermissions',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edsger",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "edsger": "dist/index.js"
@@ -53,4 +53,4 @@
53
53
  "optional": false
54
54
  }
55
55
  }
56
- }
56
+ }
@@ -1,28 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Read(//Users/steven/development/edsger/**)",
5
- "Bash(npm run build)",
6
- "Bash(node:*)",
7
- "Bash(git add:*)",
8
- "Bash(git commit:*)",
9
- "Bash(ls:*)",
10
- "Bash(cat:*)",
11
- "Bash(npm run typecheck:*)",
12
- "Bash(git diff:*)",
13
- "WebSearch",
14
- "WebFetch(domain:supabase.com)",
15
- "Bash(npm install:*)",
16
- "Bash(grep:*)",
17
- "Bash(npx supabase gen types typescript --help:*)",
18
- "Bash(git -C /Users/steven/development/edsger status)",
19
- "Bash(git -C /Users/steven/development/edsger diff)",
20
- "Bash(git -C /Users/steven/development/edsger log --oneline -5)",
21
- "Bash(git -C /Users/steven/development/edsger add supabase/migrations/20251231000000_drop_unused_views.sql)",
22
- "Bash(git -C /Users/steven/development/edsger commit -m \"$\\(cat <<''EOF''\nchore: drop unused database views\n\nRemove test_report_summary and user_stories_with_context views that are defined but never used in the application.\n\nšŸ¤– Generated with [Claude Code]\\(https://claude.com/claude-code\\)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>\nEOF\n\\)\")",
23
- "Bash(git -C /Users/steven/development/edsger commit -m \"$\\(cat <<''EOF''\nchore: drop unused database views\n\nRemove test_report_summary and user_stories_with_context views\nthat are defined but never used in the application.\n\nšŸ¤– Generated with [Claude Code]\\(https://claude.com/claude-code\\)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>\nEOF\n\\)\")"
24
- ],
25
- "deny": [],
26
- "ask": []
27
- }
28
- }
@@ -1,5 +0,0 @@
1
- /**
2
- * Specialized tests for status regression prevention
3
- * Focuses on the core business requirement: preventing backward status movement
4
- */
5
- export {};