edsger 0.12.0 → 0.13.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.
Files changed (89) hide show
  1. package/dist/phases/feature-analysis/prompts.js +36 -3
  2. package/dist/utils/git-branch-manager.d.ts +4 -0
  3. package/dist/utils/git-branch-manager.js +61 -0
  4. package/package.json +1 -1
  5. package/.claude/settings.local.json +0 -28
  6. package/dist/api/features/__tests__/regression-prevention.test.d.ts +0 -5
  7. package/dist/api/features/__tests__/regression-prevention.test.js +0 -338
  8. package/dist/api/features/__tests__/status-updater.integration.test.d.ts +0 -5
  9. package/dist/api/features/__tests__/status-updater.integration.test.js +0 -497
  10. package/dist/commands/workflow/pipeline-runner.d.ts +0 -17
  11. package/dist/commands/workflow/pipeline-runner.js +0 -393
  12. package/dist/commands/workflow/runner.d.ts +0 -26
  13. package/dist/commands/workflow/runner.js +0 -119
  14. package/dist/commands/workflow/workflow-runner.d.ts +0 -26
  15. package/dist/commands/workflow/workflow-runner.js +0 -119
  16. package/dist/phases/code-implementation/analyzer-helpers.d.ts +0 -28
  17. package/dist/phases/code-implementation/analyzer-helpers.js +0 -177
  18. package/dist/phases/code-implementation/analyzer.d.ts +0 -32
  19. package/dist/phases/code-implementation/analyzer.js +0 -629
  20. package/dist/phases/code-implementation/context-fetcher.d.ts +0 -17
  21. package/dist/phases/code-implementation/context-fetcher.js +0 -86
  22. package/dist/phases/code-implementation/mcp-server.d.ts +0 -1
  23. package/dist/phases/code-implementation/mcp-server.js +0 -93
  24. package/dist/phases/code-implementation/prompts-improvement.d.ts +0 -5
  25. package/dist/phases/code-implementation/prompts-improvement.js +0 -108
  26. package/dist/phases/code-implementation-verification/verifier.d.ts +0 -31
  27. package/dist/phases/code-implementation-verification/verifier.js +0 -196
  28. package/dist/phases/code-refine/analyzer.d.ts +0 -41
  29. package/dist/phases/code-refine/analyzer.js +0 -561
  30. package/dist/phases/code-refine/context-fetcher.d.ts +0 -94
  31. package/dist/phases/code-refine/context-fetcher.js +0 -423
  32. package/dist/phases/code-refine-verification/analysis/llm-analyzer.d.ts +0 -22
  33. package/dist/phases/code-refine-verification/analysis/llm-analyzer.js +0 -134
  34. package/dist/phases/code-refine-verification/verifier.d.ts +0 -47
  35. package/dist/phases/code-refine-verification/verifier.js +0 -597
  36. package/dist/phases/code-review/analyzer.d.ts +0 -29
  37. package/dist/phases/code-review/analyzer.js +0 -363
  38. package/dist/phases/code-review/context-fetcher.d.ts +0 -92
  39. package/dist/phases/code-review/context-fetcher.js +0 -296
  40. package/dist/phases/feature-analysis/analyzer-helpers.d.ts +0 -10
  41. package/dist/phases/feature-analysis/analyzer-helpers.js +0 -47
  42. package/dist/phases/feature-analysis/analyzer.d.ts +0 -11
  43. package/dist/phases/feature-analysis/analyzer.js +0 -208
  44. package/dist/phases/feature-analysis/context-fetcher.d.ts +0 -26
  45. package/dist/phases/feature-analysis/context-fetcher.js +0 -134
  46. package/dist/phases/feature-analysis/http-fallback.d.ts +0 -20
  47. package/dist/phases/feature-analysis/http-fallback.js +0 -95
  48. package/dist/phases/feature-analysis/mcp-server.d.ts +0 -1
  49. package/dist/phases/feature-analysis/mcp-server.js +0 -144
  50. package/dist/phases/feature-analysis/prompts-improvement.d.ts +0 -8
  51. package/dist/phases/feature-analysis/prompts-improvement.js +0 -109
  52. package/dist/phases/feature-analysis-verification/verifier.d.ts +0 -37
  53. package/dist/phases/feature-analysis-verification/verifier.js +0 -147
  54. package/dist/phases/technical-design/analyzer-helpers.d.ts +0 -25
  55. package/dist/phases/technical-design/analyzer-helpers.js +0 -39
  56. package/dist/phases/technical-design/analyzer.d.ts +0 -21
  57. package/dist/phases/technical-design/analyzer.js +0 -461
  58. package/dist/phases/technical-design/context-fetcher.d.ts +0 -12
  59. package/dist/phases/technical-design/context-fetcher.js +0 -39
  60. package/dist/phases/technical-design/http-fallback.d.ts +0 -17
  61. package/dist/phases/technical-design/http-fallback.js +0 -151
  62. package/dist/phases/technical-design/mcp-server.d.ts +0 -1
  63. package/dist/phases/technical-design/mcp-server.js +0 -157
  64. package/dist/phases/technical-design/prompts-improvement.d.ts +0 -5
  65. package/dist/phases/technical-design/prompts-improvement.js +0 -93
  66. package/dist/phases/technical-design-verification/verifier.d.ts +0 -53
  67. package/dist/phases/technical-design-verification/verifier.js +0 -170
  68. package/dist/workflow-runner/config/phase-configs.d.ts +0 -5
  69. package/dist/workflow-runner/config/phase-configs.js +0 -120
  70. package/dist/workflow-runner/core/feature-filter.d.ts +0 -16
  71. package/dist/workflow-runner/core/feature-filter.js +0 -46
  72. package/dist/workflow-runner/core/index.d.ts +0 -8
  73. package/dist/workflow-runner/core/index.js +0 -12
  74. package/dist/workflow-runner/core/pipeline-evaluator.d.ts +0 -24
  75. package/dist/workflow-runner/core/pipeline-evaluator.js +0 -32
  76. package/dist/workflow-runner/core/state-manager.d.ts +0 -24
  77. package/dist/workflow-runner/core/state-manager.js +0 -42
  78. package/dist/workflow-runner/core/workflow-logger.d.ts +0 -20
  79. package/dist/workflow-runner/core/workflow-logger.js +0 -65
  80. package/dist/workflow-runner/executors/phase-executor.d.ts +0 -8
  81. package/dist/workflow-runner/executors/phase-executor.js +0 -248
  82. package/dist/workflow-runner/feature-workflow-runner.d.ts +0 -26
  83. package/dist/workflow-runner/feature-workflow-runner.js +0 -119
  84. package/dist/workflow-runner/index.d.ts +0 -2
  85. package/dist/workflow-runner/index.js +0 -2
  86. package/dist/workflow-runner/pipeline-runner.d.ts +0 -17
  87. package/dist/workflow-runner/pipeline-runner.js +0 -393
  88. package/dist/workflow-runner/workflow-processor.d.ts +0 -54
  89. package/dist/workflow-runner/workflow-processor.js +0 -170
@@ -18,13 +18,28 @@ CRITICAL: Checklists are not optional suggestions - they are mandatory quality g
18
18
 
19
19
  CRITICAL: You are NOT a software engineer. You should NEVER write code, build projects, or modify files. Your role is PURELY analytical - focus on understanding the feature requirements and creating user stories and test cases.
20
20
 
21
+ **INVEST Principles for User Stories**:
22
+ Every user story you create MUST follow the INVEST criteria:
23
+
24
+ 1. **I - Independent**: Each user story should be self-contained and not depend on other stories. It can be developed, tested, and delivered independently without requiring other stories to be completed first.
25
+
26
+ 2. **N - Negotiable**: User stories are not contracts. They should be flexible enough to allow discussion and refinement between stakeholders. Focus on the "what" and "why", not the "how".
27
+
28
+ 3. **V - Valuable**: Every user story must deliver clear business value to the end user or stakeholder. If a story doesn't provide value, it shouldn't exist. Express the benefit clearly in the "so that" clause.
29
+
30
+ 4. **E - Estimable**: The story should be clear enough that the development team can estimate the effort required. Avoid vague or overly complex stories that cannot be reasonably estimated.
31
+
32
+ 5. **S - Small**: User stories should be small enough to be completed within a single sprint/iteration. If a story is too large, break it down into smaller, more manageable stories.
33
+
34
+ 6. **T - Testable**: Each user story must have clear acceptance criteria that can be verified. If you cannot define how to test it, the story is not ready.
35
+
21
36
  **Analysis Process**:
22
37
  1. **Review Context**: Analyze the provided feature information, product context, and existing user stories/test cases
23
38
  2. **Identify Duplicates**: FIRST, carefully review existing draft artifacts to identify duplicates or redundant items
24
39
  - Compare titles, descriptions, and functionality coverage
25
40
  - Mark duplicate draft artifacts for deletion (include their IDs in deleted_user_story_ids/deleted_test_case_ids)
26
41
  3. **Business Analysis**: Think about different user types, use cases, workflows, and scenarios
27
- 4. **Create User Stories**: Generate new user stories following the "As a [user], I want [goal] so that [benefit]" format
42
+ 4. **Create User Stories**: Generate new user stories following the "As a [user], I want [goal] so that [benefit]" format, ensuring each story satisfies ALL INVEST criteria
28
43
  5. **Design Test Cases**: Create comprehensive test cases covering happy path, edge cases, and error scenarios
29
44
  6. **Avoid Duplication**: Ensure new stories and test cases add value without duplicating existing ones
30
45
  7. **Provide Results**: Output your analysis in the required JSON format with deletion lists populated
@@ -89,7 +104,15 @@ You MUST return ONLY a JSON object with your analysis results. Do NOT include an
89
104
  "title": "User story title",
90
105
  "description": "As a [user], I want [goal] so that [benefit]",
91
106
  "status": "draft",
92
- "differentiation": "REQUIRED: Explain how this differs from existing user stories. Reference specific existing story titles and explain what new scenario/user type/workflow this covers that is NOT already addressed."
107
+ "differentiation": "REQUIRED: Explain how this differs from existing user stories. Reference specific existing story titles and explain what new scenario/user type/workflow this covers that is NOT already addressed.",
108
+ "invest_compliance": {
109
+ "independent": "How this story can be developed independently",
110
+ "negotiable": "What aspects are open for discussion",
111
+ "valuable": "The specific business value delivered",
112
+ "estimable": "Why this story is clear enough to estimate",
113
+ "small": "Confirmation this fits within a sprint",
114
+ "testable": "How this story can be verified/tested"
115
+ }
93
116
  }
94
117
  ],
95
118
  "created_test_cases": [
@@ -152,7 +175,9 @@ deleted_test_case_ids: ["Duplicate test case", "Similar test"] // WRONG - these
152
175
  - Generic explanations like "covers different scenario" are NOT acceptable - be specific
153
176
 
154
177
  **Quality Guidelines**:
178
+ - User stories MUST satisfy all INVEST criteria (Independent, Negotiable, Valuable, Estimable, Small, Testable)
155
179
  - User stories should be clear, concise, and user-focused
180
+ - Each user story should be completable within a single sprint
156
181
  - Test cases should be comprehensive and cover all scenarios
157
182
  - Consider accessibility, security, and performance aspects
158
183
  - Think about different user types and permissions
@@ -314,7 +339,15 @@ You MUST return ONLY the JSON object below. Do NOT include any explanatory text,
314
339
  "title": "User story title",
315
340
  "description": "As a [user], I want [goal] so that [benefit]",
316
341
  "status": "draft",
317
- "differentiation": "REQUIRED: Explain how this differs from existing user stories"
342
+ "differentiation": "REQUIRED: Explain how this differs from existing user stories",
343
+ "invest_compliance": {
344
+ "independent": "How this story can be developed independently",
345
+ "negotiable": "What aspects are open for discussion",
346
+ "valuable": "The specific business value delivered",
347
+ "estimable": "Why this story is clear enough to estimate",
348
+ "small": "Confirmation this fits within a sprint",
349
+ "testable": "How this story can be verified/tested"
350
+ }
318
351
  }
319
352
  ],
320
353
  "created_test_cases": [
@@ -22,6 +22,10 @@ export declare function resetUncommittedChanges(verbose?: boolean): void;
22
22
  * Check if a Git branch exists locally
23
23
  */
24
24
  export declare function branchExists(branch: string): boolean;
25
+ /**
26
+ * Check if a remote branch exists
27
+ */
28
+ export declare function remoteBranchExists(branch: string): boolean;
25
29
  /**
26
30
  * Switch to a specific Git branch, creating it if it doesn't exist
27
31
  */
@@ -76,6 +76,23 @@ export function branchExists(branch) {
76
76
  return false;
77
77
  }
78
78
  }
79
+ /**
80
+ * Check if a remote branch exists
81
+ */
82
+ export function remoteBranchExists(branch) {
83
+ try {
84
+ // Fetch remote refs first to ensure we have latest info
85
+ execSync('git fetch origin --prune', { encoding: 'utf-8', stdio: 'pipe' });
86
+ execSync(`git rev-parse --verify origin/${branch}`, {
87
+ encoding: 'utf-8',
88
+ stdio: 'pipe',
89
+ });
90
+ return true;
91
+ }
92
+ catch (error) {
93
+ return false;
94
+ }
95
+ }
79
96
  /**
80
97
  * Switch to a specific Git branch, creating it if it doesn't exist
81
98
  */
@@ -179,6 +196,50 @@ export function switchToFeatureBranchAndRebase(featureBranch, baseBranch = 'main
179
196
  if (getCurrentBranch() !== featureBranch) {
180
197
  switchToBranch(featureBranch, verbose);
181
198
  }
199
+ // Sync with remote feature branch if it exists
200
+ // This handles the case where the branch was pushed from another machine
201
+ try {
202
+ // Check for uncommitted changes and reset if found before any git operations
203
+ if (hasUncommittedChanges()) {
204
+ if (verbose) {
205
+ logInfo(`⚠️ Found uncommitted changes. Resetting to clean state before sync...`);
206
+ }
207
+ resetUncommittedChanges(verbose);
208
+ }
209
+ // Fetch to get latest remote state
210
+ execSync('git fetch origin', { encoding: 'utf-8', stdio: 'pipe' });
211
+ // Check if remote feature branch exists
212
+ try {
213
+ execSync(`git rev-parse --verify origin/${featureBranch}`, {
214
+ encoding: 'utf-8',
215
+ stdio: 'pipe',
216
+ });
217
+ // Remote branch exists, sync with it
218
+ if (verbose) {
219
+ logInfo(`📥 Syncing with remote feature branch origin/${featureBranch}...`);
220
+ }
221
+ // Reset local branch to match remote branch
222
+ // This ensures we have all commits from the remote (e.g., from another machine)
223
+ execSync(`git reset --hard origin/${featureBranch}`, {
224
+ encoding: 'utf-8',
225
+ stdio: 'pipe',
226
+ });
227
+ if (verbose) {
228
+ logInfo(`✅ Synced local branch with origin/${featureBranch}`);
229
+ }
230
+ }
231
+ catch (e) {
232
+ // Remote branch doesn't exist, that's fine - we'll push later
233
+ if (verbose) {
234
+ logInfo(` Remote branch origin/${featureBranch} doesn't exist yet, will create on push`);
235
+ }
236
+ }
237
+ }
238
+ catch (error) {
239
+ if (verbose) {
240
+ logInfo(`⚠️ Could not sync with remote feature branch, continuing with local branch`);
241
+ }
242
+ }
182
243
  // Rebase feature branch with latest main
183
244
  if (verbose) {
184
245
  logInfo(`📥 Rebasing ${featureBranch} with origin/${baseBranch}...`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edsger",
3
- "version": "0.12.0",
3
+ "version": "0.13.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "edsger": "dist/index.js"
@@ -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 {};
@@ -1,338 +0,0 @@
1
- /**
2
- * Specialized tests for status regression prevention
3
- * Focuses on the core business requirement: preventing backward status movement
4
- */
5
- import { describe, it } from 'node:test';
6
- import assert from 'node:assert';
7
- import { isForwardProgression } from '../status-updater.js';
8
- import { STATUS_PROGRESSION_ORDER } from '../../../config/feature-status.js';
9
- describe('Regression Prevention Tests', () => {
10
- describe('Core Business Logic: Prevent Backlog Regression', () => {
11
- it('should prevent any status from regressing to backlog', () => {
12
- const allStatuses = STATUS_PROGRESSION_ORDER.slice(1); // All except backlog itself
13
- for (const status of allStatuses) {
14
- const result = isForwardProgression(status, 'backlog');
15
- assert.strictEqual(result, false, `Status ${status} should NOT be allowed to regress to backlog`);
16
- }
17
- });
18
- it('should allow progression from backlog to any other status', () => {
19
- const targetStatuses = STATUS_PROGRESSION_ORDER.slice(1); // All except backlog
20
- for (const targetStatus of targetStatuses) {
21
- const result = isForwardProgression('backlog', targetStatus);
22
- assert.strictEqual(result, true, `Should allow progression from backlog to ${targetStatus}`);
23
- }
24
- });
25
- it('should prevent regression from any status to ready_for_dev', () => {
26
- // Only backlog should be allowed to progress to ready_for_dev
27
- const higherStatuses = STATUS_PROGRESSION_ORDER.slice(2); // All except backlog and ready_for_dev
28
- for (const status of higherStatuses) {
29
- const result = isForwardProgression(status, 'ready_for_dev');
30
- assert.strictEqual(result, false, `Status ${status} should NOT regress to ready_for_dev`);
31
- }
32
- });
33
- it('should prevent all forms of backward progression in critical workflow', () => {
34
- // Test critical workflow progression points
35
- const criticalProgression = [
36
- 'backlog',
37
- 'ready_for_dev',
38
- 'feature_analysis',
39
- 'technical_design',
40
- 'code_implementation',
41
- 'functional_testing',
42
- 'deployment',
43
- 'shipped',
44
- ];
45
- // Test every possible backward combination
46
- for (let i = 0; i < criticalProgression.length; i++) {
47
- for (let j = 0; j < i; j++) {
48
- const currentStatus = criticalProgression[i];
49
- const targetStatus = criticalProgression[j];
50
- const result = isForwardProgression(currentStatus, targetStatus);
51
- assert.strictEqual(result, false, `Should prevent regression from ${currentStatus} to ${targetStatus}`);
52
- }
53
- }
54
- });
55
- });
56
- describe('CLI Phase Protection', () => {
57
- it('should identify scenarios where CLI phases could cause regression', () => {
58
- // Simulate CLI phases that could potentially cause issues
59
- const problematicScenarios = [
60
- {
61
- currentStatus: 'code_implementation',
62
- phase: 'feature-analysis',
63
- expectedTargetStatus: 'feature_analysis',
64
- description: 'CLI re-running feature analysis after code implementation',
65
- },
66
- {
67
- currentStatus: 'deployment',
68
- phase: 'technical-design',
69
- expectedTargetStatus: 'technical_design',
70
- description: 'CLI running technical design after deployment',
71
- },
72
- {
73
- currentStatus: 'shipped',
74
- phase: 'code-implementation',
75
- expectedTargetStatus: 'code_implementation',
76
- description: 'CLI attempting code implementation on shipped feature',
77
- },
78
- {
79
- currentStatus: 'testing_passed',
80
- phase: 'feature-analysis',
81
- expectedTargetStatus: 'feature_analysis',
82
- description: 'CLI re-analyzing feature after tests passed',
83
- },
84
- ];
85
- for (const scenario of problematicScenarios) {
86
- const result = isForwardProgression(scenario.currentStatus, scenario.expectedTargetStatus);
87
- assert.strictEqual(result, false, `Regression prevention should block: ${scenario.description}`);
88
- }
89
- });
90
- it('should allow valid CLI phase progressions', () => {
91
- const validScenarios = [
92
- {
93
- currentStatus: 'backlog',
94
- phase: 'feature-analysis',
95
- expectedTargetStatus: 'feature_analysis',
96
- description: 'CLI starting feature analysis from backlog',
97
- },
98
- {
99
- currentStatus: 'feature_analysis',
100
- phase: 'technical-design',
101
- expectedTargetStatus: 'technical_design',
102
- description: 'CLI progressing to technical design',
103
- },
104
- {
105
- currentStatus: 'technical_design',
106
- phase: 'code-implementation',
107
- expectedTargetStatus: 'code_implementation',
108
- description: 'CLI progressing to code implementation',
109
- },
110
- {
111
- currentStatus: 'functional_testing',
112
- phase: 'deployment',
113
- expectedTargetStatus: 'deployment',
114
- description: 'CLI progressing to deployment after testing',
115
- },
116
- ];
117
- for (const scenario of validScenarios) {
118
- const result = isForwardProgression(scenario.currentStatus, scenario.expectedTargetStatus);
119
- assert.strictEqual(result, true, `Valid progression should be allowed: ${scenario.description}`);
120
- }
121
- });
122
- });
123
- describe('Edge Cases and Boundary Conditions', () => {
124
- it('should handle same-status transitions correctly', () => {
125
- // Allow staying at the same status (for retries, re-runs, etc.)
126
- for (const status of STATUS_PROGRESSION_ORDER) {
127
- const result = isForwardProgression(status, status);
128
- assert.strictEqual(result, true, `Should allow staying at status ${status}`);
129
- }
130
- });
131
- it('should handle first and last status edge cases', () => {
132
- const firstStatus = STATUS_PROGRESSION_ORDER[0]; // 'backlog'
133
- const lastStatus = STATUS_PROGRESSION_ORDER[STATUS_PROGRESSION_ORDER.length - 1]; // 'shipped'
134
- // From first to last should be allowed
135
- const forwardResult = isForwardProgression(firstStatus, lastStatus);
136
- assert.strictEqual(forwardResult, true, 'Should allow progression from first to last status');
137
- // From last to first should be prevented
138
- const backwardResult = isForwardProgression(lastStatus, firstStatus);
139
- assert.strictEqual(backwardResult, false, 'Should prevent regression from last to first status');
140
- });
141
- it('should validate progression order is strictly enforced', () => {
142
- // Test every adjacent pair in the progression
143
- for (let i = 0; i < STATUS_PROGRESSION_ORDER.length - 1; i++) {
144
- const currentStatus = STATUS_PROGRESSION_ORDER[i];
145
- const nextStatus = STATUS_PROGRESSION_ORDER[i + 1];
146
- // Forward should be allowed
147
- const forwardResult = isForwardProgression(currentStatus, nextStatus);
148
- assert.strictEqual(forwardResult, true, `Should allow progression from ${currentStatus} to ${nextStatus}`);
149
- // Backward should be prevented
150
- const backwardResult = isForwardProgression(nextStatus, currentStatus);
151
- assert.strictEqual(backwardResult, false, `Should prevent regression from ${nextStatus} to ${currentStatus}`);
152
- }
153
- });
154
- it('should handle testing workflow regression scenarios', () => {
155
- // Testing has special rules - test specific edge cases
156
- const testingScenarios = [
157
- {
158
- from: 'testing_passed',
159
- to: 'testing_in_progress',
160
- shouldAllow: false,
161
- description: 'Should prevent going back from passed to in-progress',
162
- },
163
- {
164
- from: 'testing_passed',
165
- to: 'testing_failed',
166
- shouldAllow: true,
167
- description: 'Should allow going from passed to failed (possible if retested)',
168
- },
169
- {
170
- from: 'testing_failed',
171
- to: 'testing_passed',
172
- shouldAllow: false,
173
- description: 'Should prevent going from failed to passed (need to restart testing)',
174
- },
175
- {
176
- from: 'testing_in_progress',
177
- to: 'testing_failed',
178
- shouldAllow: true,
179
- description: 'Should allow marking in-progress tests as failed',
180
- },
181
- {
182
- from: 'testing_in_progress',
183
- to: 'testing_passed',
184
- shouldAllow: true,
185
- description: 'Should allow marking in-progress tests as passed',
186
- },
187
- ];
188
- for (const scenario of testingScenarios) {
189
- const result = isForwardProgression(scenario.from, scenario.to);
190
- assert.strictEqual(result, scenario.shouldAllow, scenario.description);
191
- }
192
- });
193
- it('should prevent skipping multiple phases backwards', () => {
194
- // Test skipping multiple phases in regression
195
- const skipBackwardTests = [
196
- {
197
- from: 'shipped',
198
- to: 'feature_analysis',
199
- skipCount: 'many phases',
200
- },
201
- {
202
- from: 'code_implementation',
203
- to: 'backlog',
204
- skipCount: 'many phases',
205
- },
206
- {
207
- from: 'deployment',
208
- to: 'ready_for_dev',
209
- skipCount: 'many phases',
210
- },
211
- ];
212
- for (const test of skipBackwardTests) {
213
- const result = isForwardProgression(test.from, test.to);
214
- assert.strictEqual(result, false, `Should prevent skipping ${test.skipCount} backwards from ${test.from} to ${test.to}`);
215
- }
216
- });
217
- it('should allow skipping multiple phases forward', () => {
218
- // Test skipping phases in forward direction (should be allowed)
219
- const skipForwardTests = [
220
- {
221
- from: 'backlog',
222
- to: 'code_implementation',
223
- description: 'Skip from backlog to code implementation',
224
- },
225
- {
226
- from: 'feature_analysis',
227
- to: 'deployment',
228
- description: 'Skip from analysis to deployment',
229
- },
230
- {
231
- from: 'technical_design',
232
- to: 'shipped',
233
- description: 'Skip from design to shipped',
234
- },
235
- ];
236
- for (const test of skipForwardTests) {
237
- const result = isForwardProgression(test.from, test.to);
238
- assert.strictEqual(result, true, `Should allow forward skip: ${test.description}`);
239
- }
240
- });
241
- });
242
- describe('Real-world Workflow Scenarios', () => {
243
- it('should handle hotfix scenario correctly', () => {
244
- // Hotfix: shipped feature needs bug fixing
245
- // Should allow progression to bug_fixing from shipped
246
- const result = isForwardProgression('shipped', 'bug_fixing');
247
- // Since bug_fixing comes before shipped in progression, this should be false
248
- assert.strictEqual(result, false, 'Should prevent regression from shipped to bug_fixing (hotfixes need new feature entries)');
249
- });
250
- it('should handle feature refinement scenarios', () => {
251
- // Feature refinement: going from code_implementation to code_refine
252
- const result1 = isForwardProgression('code_implementation', 'code_refine');
253
- assert.strictEqual(result1, true, 'Should allow progression from implementation to refinement');
254
- // But not the other way around
255
- const result2 = isForwardProgression('code_refine', 'code_implementation');
256
- assert.strictEqual(result2, false, 'Should prevent regression from refinement to implementation');
257
- });
258
- it('should handle review cycle scenarios', () => {
259
- // Review cycles: code_review -> pull_request -> code_review (if rejected)
260
- const reviewToPrep = isForwardProgression('code_review', 'pull_request');
261
- assert.strictEqual(reviewToPrep, true, 'Should allow progression from review to pull request');
262
- // But not back from pull_request to code_review
263
- const prepToReview = isForwardProgression('pull_request', 'code_review');
264
- assert.strictEqual(prepToReview, false, 'Should prevent regression from pull request to code review');
265
- });
266
- it('should handle deployment rollback scenarios', () => {
267
- // Deployment rollback: deployment -> functional_testing (to re-test)
268
- const deployToTest = isForwardProgression('deployment', 'functional_testing');
269
- assert.strictEqual(deployToTest, false, 'Should prevent regression from deployment to testing (rollbacks need new process)');
270
- });
271
- it('should validate complete workflow progression path', () => {
272
- // Simulate a complete feature lifecycle
273
- const completeWorkflow = [
274
- 'backlog',
275
- 'ready_for_dev',
276
- 'feature_analysis',
277
- 'feature_analysis_verification',
278
- 'technical_design',
279
- 'technical_design_verification',
280
- 'code_implementation',
281
- 'code_refine',
282
- 'code_review',
283
- 'pull_request',
284
- 'functional_testing',
285
- 'testing_in_progress',
286
- 'testing_passed',
287
- 'deployment',
288
- 'shipped',
289
- ];
290
- // Test each step in the workflow
291
- for (let i = 0; i < completeWorkflow.length - 1; i++) {
292
- const currentStatus = completeWorkflow[i];
293
- const nextStatus = completeWorkflow[i + 1];
294
- const result = isForwardProgression(currentStatus, nextStatus);
295
- assert.strictEqual(result, true, `Workflow step ${i + 1}: Should allow progression from ${currentStatus} to ${nextStatus}`);
296
- }
297
- // Test that you can't go backwards at any point in the workflow
298
- for (let i = 1; i < completeWorkflow.length; i++) {
299
- const currentStatus = completeWorkflow[i];
300
- const previousStatus = completeWorkflow[i - 1];
301
- const result = isForwardProgression(currentStatus, previousStatus);
302
- assert.strictEqual(result, false, `Workflow regression check ${i}: Should prevent regression from ${currentStatus} to ${previousStatus}`);
303
- }
304
- });
305
- });
306
- describe('Status Progression Order Validation', () => {
307
- it('should ensure progression order matches business workflow', () => {
308
- // Verify that the progression order makes business sense
309
- const criticalStatusPositions = {
310
- backlog: STATUS_PROGRESSION_ORDER.indexOf('backlog'),
311
- ready_for_dev: STATUS_PROGRESSION_ORDER.indexOf('ready_for_dev'),
312
- feature_analysis: STATUS_PROGRESSION_ORDER.indexOf('feature_analysis'),
313
- technical_design: STATUS_PROGRESSION_ORDER.indexOf('technical_design'),
314
- code_implementation: STATUS_PROGRESSION_ORDER.indexOf('code_implementation'),
315
- functional_testing: STATUS_PROGRESSION_ORDER.indexOf('functional_testing'),
316
- deployment: STATUS_PROGRESSION_ORDER.indexOf('deployment'),
317
- shipped: STATUS_PROGRESSION_ORDER.indexOf('shipped'),
318
- };
319
- // Verify logical ordering
320
- assert.ok(criticalStatusPositions.backlog < criticalStatusPositions.ready_for_dev, 'Backlog should come before ready_for_dev');
321
- assert.ok(criticalStatusPositions.ready_for_dev < criticalStatusPositions.feature_analysis, 'Ready for dev should come before feature analysis');
322
- assert.ok(criticalStatusPositions.feature_analysis < criticalStatusPositions.technical_design, 'Feature analysis should come before technical design');
323
- assert.ok(criticalStatusPositions.technical_design < criticalStatusPositions.code_implementation, 'Technical design should come before code implementation');
324
- assert.ok(criticalStatusPositions.code_implementation < criticalStatusPositions.functional_testing, 'Code implementation should come before functional testing');
325
- assert.ok(criticalStatusPositions.functional_testing < criticalStatusPositions.deployment, 'Functional testing should come before deployment');
326
- assert.ok(criticalStatusPositions.deployment < criticalStatusPositions.shipped, 'Deployment should come before shipped');
327
- });
328
- it('should prevent CLI from causing any backward movement', () => {
329
- // This test specifically addresses the original issue:
330
- // "After running CLI, in some phases, it update feature status to 'Backlog'"
331
- // No matter what the current status is, CLI should NEVER be able to set it to backlog
332
- for (const currentStatus of STATUS_PROGRESSION_ORDER.slice(1)) {
333
- const result = isForwardProgression(currentStatus, 'backlog');
334
- assert.strictEqual(result, false, `CLI should NEVER be able to regress ${currentStatus} to backlog`);
335
- }
336
- });
337
- });
338
- });
@@ -1,5 +0,0 @@
1
- /**
2
- * Integration tests for status updater functionality
3
- * Tests the complete flow including MCP calls and error handling
4
- */
5
- export {};