@codemcp/workflows 4.10.1 → 4.10.2

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 (74) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/components/beads/beads-instruction-generator.d.ts +3 -4
  3. package/dist/components/beads/beads-instruction-generator.d.ts.map +1 -1
  4. package/dist/components/beads/beads-instruction-generator.js +12 -7
  5. package/dist/components/beads/beads-instruction-generator.js.map +1 -1
  6. package/dist/components/beads/beads-task-backend-client.d.ts.map +1 -1
  7. package/dist/components/beads/beads-task-backend-client.js +1 -4
  8. package/dist/components/beads/beads-task-backend-client.js.map +1 -1
  9. package/dist/plugin-system/beads-plugin.d.ts +70 -0
  10. package/dist/plugin-system/beads-plugin.d.ts.map +1 -0
  11. package/dist/plugin-system/beads-plugin.js +459 -0
  12. package/dist/plugin-system/beads-plugin.js.map +1 -0
  13. package/dist/plugin-system/index.d.ts +9 -0
  14. package/dist/plugin-system/index.d.ts.map +1 -0
  15. package/dist/plugin-system/index.js +9 -0
  16. package/dist/plugin-system/index.js.map +1 -0
  17. package/dist/plugin-system/plugin-interfaces.d.ts +99 -0
  18. package/dist/plugin-system/plugin-interfaces.d.ts.map +1 -0
  19. package/dist/plugin-system/plugin-interfaces.js +9 -0
  20. package/dist/plugin-system/plugin-interfaces.js.map +1 -0
  21. package/dist/plugin-system/plugin-registry.d.ts +44 -0
  22. package/dist/plugin-system/plugin-registry.d.ts.map +1 -0
  23. package/dist/plugin-system/plugin-registry.js +132 -0
  24. package/dist/plugin-system/plugin-registry.js.map +1 -0
  25. package/dist/server-config.d.ts.map +1 -1
  26. package/dist/server-config.js +28 -8
  27. package/dist/server-config.js.map +1 -1
  28. package/dist/tool-handlers/conduct-review.d.ts.map +1 -1
  29. package/dist/tool-handlers/conduct-review.js +1 -2
  30. package/dist/tool-handlers/conduct-review.js.map +1 -1
  31. package/dist/tool-handlers/proceed-to-phase.d.ts +0 -5
  32. package/dist/tool-handlers/proceed-to-phase.d.ts.map +1 -1
  33. package/dist/tool-handlers/proceed-to-phase.js +15 -93
  34. package/dist/tool-handlers/proceed-to-phase.js.map +1 -1
  35. package/dist/tool-handlers/start-development.d.ts +0 -13
  36. package/dist/tool-handlers/start-development.d.ts.map +1 -1
  37. package/dist/tool-handlers/start-development.js +29 -124
  38. package/dist/tool-handlers/start-development.js.map +1 -1
  39. package/dist/tool-handlers/whats-next.d.ts.map +1 -1
  40. package/dist/tool-handlers/whats-next.js +1 -0
  41. package/dist/tool-handlers/whats-next.js.map +1 -1
  42. package/dist/types.d.ts +2 -0
  43. package/dist/types.d.ts.map +1 -1
  44. package/package.json +2 -2
  45. package/src/components/beads/beads-instruction-generator.ts +12 -12
  46. package/src/components/beads/beads-task-backend-client.ts +1 -4
  47. package/src/plugin-system/beads-plugin.ts +641 -0
  48. package/src/plugin-system/index.ts +20 -0
  49. package/src/plugin-system/plugin-interfaces.ts +154 -0
  50. package/src/plugin-system/plugin-registry.ts +190 -0
  51. package/src/server-config.ts +30 -8
  52. package/src/tool-handlers/conduct-review.ts +1 -2
  53. package/src/tool-handlers/proceed-to-phase.ts +19 -135
  54. package/src/tool-handlers/start-development.ts +35 -205
  55. package/src/tool-handlers/whats-next.ts +1 -0
  56. package/src/types.ts +2 -0
  57. package/test/e2e/beads-plugin-integration.test.ts +1609 -0
  58. package/test/e2e/plugin-system-integration.test.ts +1729 -0
  59. package/test/unit/beads-plugin-behavioral.test.ts +512 -0
  60. package/test/unit/beads-plugin.test.ts +94 -0
  61. package/test/unit/plugin-error-handling.test.ts +240 -0
  62. package/test/unit/proceed-to-phase-plugin-integration.test.ts +150 -0
  63. package/test/unit/server-config-plugin-registry.test.ts +81 -0
  64. package/test/unit/start-development-goal-extraction.test.ts +22 -16
  65. package/test/utils/test-helpers.ts +3 -1
  66. package/tsconfig.build.tsbuildinfo +1 -1
  67. package/dist/components/server-components-factory.d.ts +0 -39
  68. package/dist/components/server-components-factory.d.ts.map +0 -1
  69. package/dist/components/server-components-factory.js +0 -62
  70. package/dist/components/server-components-factory.js.map +0 -1
  71. package/src/components/server-components-factory.ts +0 -86
  72. package/test/e2e/component-substitution.test.ts +0 -208
  73. package/test/unit/beads-integration-filename.test.ts +0 -93
  74. package/test/unit/server-components-factory.test.ts +0 -279
@@ -1,208 +0,0 @@
1
- /**
2
- * Component Substitution E2E Tests
3
- *
4
- * Tests that the strategy pattern component substitution works correctly
5
- * in different task backend configurations.
6
- */
7
-
8
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
9
- import { createTempProjectWithDefaultStateMachine } from '../utils/temp-files';
10
- import {
11
- DirectServerInterface,
12
- createSuiteIsolatedE2EScenario,
13
- assertToolSuccess,
14
- initializeDevelopment,
15
- } from '../utils/e2e-test-setup';
16
-
17
- vi.unmock('fs');
18
- vi.unmock('fs/promises');
19
-
20
- describe('Component Substitution', () => {
21
- let client: DirectServerInterface;
22
- let cleanup: () => Promise<void>;
23
-
24
- describe('Markdown Backend Strategy', () => {
25
- beforeEach(async () => {
26
- // Ensure markdown backend is detected
27
- process.env.TASK_BACKEND = 'markdown';
28
-
29
- const scenario = await createSuiteIsolatedE2EScenario({
30
- suiteName: 'component-substitution-markdown',
31
- tempProjectFactory: createTempProjectWithDefaultStateMachine,
32
- });
33
- client = scenario.client;
34
- cleanup = scenario.cleanup;
35
-
36
- await initializeDevelopment(client);
37
- });
38
-
39
- afterEach(async () => {
40
- delete process.env.TASK_BACKEND;
41
- if (cleanup) {
42
- await cleanup();
43
- }
44
- });
45
-
46
- it('should use markdown-based components for plan management', async () => {
47
- const result = await client.callTool('whats_next', {
48
- user_input: 'test markdown component substitution',
49
- });
50
- const response = assertToolSuccess(result);
51
-
52
- expect(response.phase).toBeTruthy();
53
- expect(response.instructions).toBeTruthy();
54
- expect(response.plan_file_path).toBeTruthy();
55
-
56
- // Verify plan file operations work with markdown backend
57
- expect(response.plan_file_path).toContain('.vibe');
58
- expect(response.plan_file_path).toMatch(/\.md$/);
59
- });
60
-
61
- it('should generate markdown-compatible instructions', async () => {
62
- const result = await client.callTool('whats_next', {
63
- user_input: 'create feature with markdown backend',
64
- });
65
- const response = assertToolSuccess(result);
66
-
67
- // Instructions should be generated using markdown-based strategy
68
- expect(response.instructions).toContain('Plan File Guidance');
69
- expect(response.instructions).toContain('Project Context');
70
- expect(typeof response.instructions).toBe('string');
71
- });
72
-
73
- it('should handle phase transitions with markdown backend', async () => {
74
- // Initialize conversation
75
- await client.callTool('whats_next', { user_input: 'start project' });
76
-
77
- const result = await client.callTool('proceed_to_phase', {
78
- target_phase: 'design',
79
- reason: 'requirements complete',
80
- review_state: 'not-required',
81
- });
82
- const response = assertToolSuccess(result);
83
-
84
- expect(response.phase).toBe('design');
85
- expect(response.instructions).toBeTruthy();
86
- });
87
- });
88
-
89
- describe('Backend Strategy Configuration', () => {
90
- // Note: Actual beads fallback testing requires specific environment setup
91
- // These tests document the expected behavior when backend fallback occurs
92
-
93
- it.todo('should fallback to default components when beads unavailable');
94
- it.todo('should generate compatible instructions with fallback strategy');
95
-
96
- // For now, focus on testing the factory pattern mechanism itself
97
- // rather than specific backend availability scenarios
98
- });
99
-
100
- describe('Component Factory Integration', () => {
101
- beforeEach(async () => {
102
- const scenario = await createSuiteIsolatedE2EScenario({
103
- suiteName: 'component-substitution-factory',
104
- tempProjectFactory: createTempProjectWithDefaultStateMachine,
105
- });
106
- client = scenario.client;
107
- cleanup = scenario.cleanup;
108
-
109
- await initializeDevelopment(client);
110
- });
111
-
112
- afterEach(async () => {
113
- if (cleanup) {
114
- await cleanup();
115
- }
116
- });
117
-
118
- it('should maintain consistent behavior across component substitutions', async () => {
119
- // Test multiple operations to ensure consistent component behavior
120
- const first = await client.callTool('whats_next', {
121
- user_input: 'first operation',
122
- });
123
- const firstResponse = assertToolSuccess(first);
124
-
125
- const second = await client.callTool('proceed_to_phase', {
126
- target_phase: 'design',
127
- reason: 'ready to design',
128
- review_state: 'not-required',
129
- });
130
- const secondResponse = assertToolSuccess(second);
131
-
132
- const third = await client.callTool('whats_next', {
133
- user_input: 'continue after transition',
134
- });
135
- const thirdResponse = assertToolSuccess(third);
136
-
137
- // All responses should be consistent and functional
138
- expect(firstResponse.conversation_id).toBe(
139
- secondResponse.conversation_id
140
- );
141
- expect(secondResponse.conversation_id).toBe(
142
- thirdResponse.conversation_id
143
- );
144
- expect(thirdResponse.phase).toBe('design');
145
- });
146
-
147
- it('should properly inject dependencies through factory pattern', async () => {
148
- const result = await client.callTool('whats_next', {
149
- user_input: 'test dependency injection',
150
- });
151
- const response = assertToolSuccess(result);
152
-
153
- // Verify that components work together properly (dependency injection successful)
154
- expect(response.instructions).toBeTruthy();
155
- expect(response.plan_file_path).toBeTruthy();
156
-
157
- // Components should be working together to produce complete responses
158
- expect(response.phase).toBeTruthy();
159
- expect(response.conversation_id).toBeTruthy();
160
- });
161
-
162
- it('should handle component errors gracefully', async () => {
163
- // Test that factory-created components handle edge cases
164
- const result = await client.callTool('whats_next', {
165
- user_input: '', // Empty input to test robustness
166
- });
167
- const response = assertToolSuccess(result);
168
-
169
- // Should still work with empty input
170
- expect(response.phase).toBeTruthy();
171
- expect(response.instructions).toBeTruthy();
172
- });
173
- });
174
-
175
- describe('Backend Detection Integration', () => {
176
- beforeEach(async () => {
177
- const scenario = await createSuiteIsolatedE2EScenario({
178
- suiteName: 'component-substitution-detection',
179
- tempProjectFactory: createTempProjectWithDefaultStateMachine,
180
- });
181
- client = scenario.client;
182
- cleanup = scenario.cleanup;
183
-
184
- await initializeDevelopment(client);
185
- });
186
-
187
- afterEach(async () => {
188
- if (cleanup) {
189
- await cleanup();
190
- }
191
- });
192
-
193
- it('should detect task backend and create appropriate components', async () => {
194
- const result = await client.callTool('whats_next', {
195
- user_input: 'test backend detection',
196
- });
197
- const response = assertToolSuccess(result);
198
-
199
- // Verify the factory correctly detected and created appropriate components
200
- expect(response.phase).toBeTruthy();
201
- expect(response.instructions).toBeTruthy();
202
-
203
- // The response should indicate which components are being used
204
- // (in practice, this would be markdown components since beads isn't available in tests)
205
- expect(response.plan_file_path).toMatch(/\.md$/);
206
- });
207
- });
208
- });
@@ -1,93 +0,0 @@
1
- /**
2
- * Unit tests for BeadsIntegration epic title formatting with filename
3
- *
4
- * Tests that epic titles include plan filenames correctly
5
- */
6
-
7
- import { describe, it, expect, beforeEach, vi } from 'vitest';
8
- import { BeadsIntegration } from '@codemcp/workflows-core';
9
-
10
- // Mock execSync to avoid actual beads CLI calls
11
- vi.mock('node:child_process', () => ({
12
- execSync: vi.fn().mockReturnValue('✓ Created issue: test-epic-123'),
13
- }));
14
-
15
- describe('BeadsIntegration - Epic Title with Filename', () => {
16
- let beadsIntegration: BeadsIntegration;
17
-
18
- beforeEach(() => {
19
- beadsIntegration = new BeadsIntegration('/test/project');
20
- });
21
-
22
- it('should include filename in epic title when provided', async () => {
23
- const { execSync } = await import('node:child_process');
24
- const mockExecSync = vi.mocked(execSync);
25
-
26
- await beadsIntegration.createProjectEpic(
27
- 'my-project',
28
- 'epcc',
29
- 'Build an awesome feature',
30
- 'development-plan-feature-auth.md'
31
- );
32
-
33
- // Verify that execSync was called with the expected title format
34
- expect(mockExecSync).toHaveBeenCalledWith(
35
- expect.stringContaining(
36
- 'bd create "my-project: epcc (development-plan-feature-auth.md)"'
37
- ),
38
- expect.any(Object)
39
- );
40
- });
41
-
42
- it('should use original title format when filename not provided', async () => {
43
- const { execSync } = await import('node:child_process');
44
- const mockExecSync = vi.mocked(execSync);
45
-
46
- await beadsIntegration.createProjectEpic(
47
- 'my-project',
48
- 'epcc',
49
- 'Build an awesome feature'
50
- );
51
-
52
- // Verify that execSync was called with the original title format
53
- expect(mockExecSync).toHaveBeenCalledWith(
54
- expect.stringContaining('bd create "my-project: epcc"'),
55
- expect.any(Object)
56
- );
57
-
58
- // Ensure it doesn't contain parentheses when no filename
59
- const call = mockExecSync.mock.calls[0][0] as string;
60
- expect(call).not.toContain('(');
61
- expect(call).not.toContain(')');
62
- });
63
-
64
- it('should handle various filename formats', async () => {
65
- const { execSync } = await import('node:child_process');
66
- const mockExecSync = vi.mocked(execSync);
67
-
68
- const testCases = [
69
- 'development-plan-main.md',
70
- 'development-plan-feature-dashboard.md',
71
- 'development-plan-bugfix-123.md',
72
- 'plan.md',
73
- ];
74
-
75
- for (const filename of testCases) {
76
- mockExecSync.mockClear();
77
-
78
- await beadsIntegration.createProjectEpic(
79
- 'test-project',
80
- 'waterfall',
81
- undefined,
82
- filename
83
- );
84
-
85
- expect(mockExecSync).toHaveBeenCalledWith(
86
- expect.stringContaining(
87
- `bd create "test-project: waterfall (${filename})"`
88
- ),
89
- expect.any(Object)
90
- );
91
- }
92
- });
93
- });
@@ -1,279 +0,0 @@
1
- /**
2
- * ServerComponentsFactory Tests
3
- *
4
- * Tests the factory pattern implementation for component creation
5
- * based on task backend configuration.
6
- */
7
-
8
- import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
9
- import { ServerComponentsFactory } from '../../src/components/server-components-factory.js';
10
- import {
11
- TaskBackendManager,
12
- type TaskBackendConfig,
13
- } from '@codemcp/workflows-core';
14
-
15
- // Mock TaskBackendManager
16
- vi.mock('@codemcp/workflows-core', async () => {
17
- const actual = await vi.importActual('@codemcp/workflows-core');
18
- return {
19
- ...actual,
20
- TaskBackendManager: {
21
- detectTaskBackend: vi.fn(),
22
- },
23
- };
24
- });
25
-
26
- describe('ServerComponentsFactory', () => {
27
- let factory: ServerComponentsFactory;
28
- let mockDetectTaskBackend: ReturnType<typeof vi.fn>;
29
-
30
- beforeEach(() => {
31
- mockDetectTaskBackend = vi.mocked(TaskBackendManager.detectTaskBackend);
32
- // Default to markdown backend
33
- mockDetectTaskBackend.mockReturnValue({
34
- backend: 'markdown',
35
- isAvailable: true,
36
- });
37
- });
38
-
39
- afterEach(() => {
40
- vi.clearAllMocks();
41
- });
42
-
43
- describe('Constructor', () => {
44
- it('should use TaskBackendManager.detectTaskBackend() when no options provided', () => {
45
- factory = new ServerComponentsFactory();
46
-
47
- expect(mockDetectTaskBackend).toHaveBeenCalled();
48
- });
49
-
50
- it('should use provided task backend configuration', () => {
51
- const customBackend: TaskBackendConfig = {
52
- backend: 'beads',
53
- isAvailable: true,
54
- };
55
-
56
- factory = new ServerComponentsFactory({ taskBackend: customBackend });
57
-
58
- // Should not call detectTaskBackend when explicit config provided
59
- expect(mockDetectTaskBackend).not.toHaveBeenCalled();
60
- });
61
-
62
- it('should handle undefined options gracefully', () => {
63
- factory = new ServerComponentsFactory(undefined);
64
-
65
- expect(mockDetectTaskBackend).toHaveBeenCalled();
66
- });
67
- });
68
-
69
- describe('createPlanManager', () => {
70
- it('should create default PlanManager for markdown backend', () => {
71
- mockDetectTaskBackend.mockReturnValue({
72
- backend: 'markdown',
73
- isAvailable: true,
74
- });
75
-
76
- factory = new ServerComponentsFactory();
77
- const planManager = factory.createPlanManager();
78
-
79
- expect(planManager).toBeDefined();
80
- expect(planManager.constructor.name).toBe('PlanManager');
81
- });
82
-
83
- it('should create default PlanManager when beads backend unavailable', () => {
84
- mockDetectTaskBackend.mockReturnValue({
85
- backend: 'beads',
86
- isAvailable: false,
87
- });
88
-
89
- factory = new ServerComponentsFactory();
90
- const planManager = factory.createPlanManager();
91
-
92
- expect(planManager).toBeDefined();
93
- expect(planManager.constructor.name).toBe('PlanManager');
94
- });
95
-
96
- it('should create BeadsPlanManager for beads backend when available', () => {
97
- // Now that BeadsPlanManager is implemented, test that it's created correctly
98
- const beadsBackend: TaskBackendConfig = {
99
- backend: 'beads',
100
- isAvailable: true,
101
- };
102
-
103
- factory = new ServerComponentsFactory({ taskBackend: beadsBackend });
104
- const planManager = factory.createPlanManager();
105
-
106
- expect(planManager).toBeDefined();
107
- expect(planManager.constructor.name).toBe('BeadsPlanManager');
108
- });
109
-
110
- it('should create consistent instances across multiple calls', () => {
111
- factory = new ServerComponentsFactory();
112
-
113
- const planManager1 = factory.createPlanManager();
114
- const planManager2 = factory.createPlanManager();
115
-
116
- // Should create new instances (not singletons)
117
- expect(planManager1).not.toBe(planManager2);
118
- expect(planManager1.constructor.name).toBe(planManager2.constructor.name);
119
- });
120
- });
121
-
122
- describe('createInstructionGenerator', () => {
123
- it('should create default InstructionGenerator for markdown backend', () => {
124
- mockDetectTaskBackend.mockReturnValue({
125
- backend: 'markdown',
126
- isAvailable: true,
127
- });
128
-
129
- factory = new ServerComponentsFactory();
130
- const instructionGenerator = factory.createInstructionGenerator();
131
-
132
- expect(instructionGenerator).toBeDefined();
133
- expect(instructionGenerator.constructor.name).toBe(
134
- 'InstructionGenerator'
135
- );
136
- });
137
-
138
- it('should create default InstructionGenerator when beads backend unavailable', () => {
139
- mockDetectTaskBackend.mockReturnValue({
140
- backend: 'beads',
141
- isAvailable: false,
142
- });
143
-
144
- factory = new ServerComponentsFactory();
145
- const instructionGenerator = factory.createInstructionGenerator();
146
-
147
- expect(instructionGenerator).toBeDefined();
148
- expect(instructionGenerator.constructor.name).toBe(
149
- 'InstructionGenerator'
150
- );
151
- });
152
-
153
- it('should create BeadsInstructionGenerator for beads backend when available', () => {
154
- // Now that BeadsInstructionGenerator is implemented, test that it's created correctly
155
- const beadsBackend: TaskBackendConfig = {
156
- backend: 'beads',
157
- isAvailable: true,
158
- };
159
-
160
- factory = new ServerComponentsFactory({ taskBackend: beadsBackend });
161
- const instructionGenerator = factory.createInstructionGenerator();
162
-
163
- expect(instructionGenerator).toBeDefined();
164
- expect(instructionGenerator.constructor.name).toBe(
165
- 'BeadsInstructionGenerator'
166
- );
167
- });
168
-
169
- it('should create InstructionGenerator with proper dependency injection', () => {
170
- factory = new ServerComponentsFactory();
171
- const instructionGenerator = factory.createInstructionGenerator();
172
-
173
- expect(instructionGenerator).toBeDefined();
174
- expect(instructionGenerator.constructor.name).toBe(
175
- 'InstructionGenerator'
176
- );
177
-
178
- // Verify the instance is functional (dependency was injected correctly)
179
- // without checking internal implementation details
180
- expect(typeof instructionGenerator.generateInstructions).toBe('function');
181
- });
182
-
183
- it('should create consistent instances across multiple calls', () => {
184
- factory = new ServerComponentsFactory();
185
-
186
- const instructionGenerator1 = factory.createInstructionGenerator();
187
- const instructionGenerator2 = factory.createInstructionGenerator();
188
-
189
- // Should create new instances (not singletons)
190
- expect(instructionGenerator1).not.toBe(instructionGenerator2);
191
- expect(instructionGenerator1.constructor.name).toBe(
192
- instructionGenerator2.constructor.name
193
- );
194
- });
195
- });
196
-
197
- describe('getTaskBackend', () => {
198
- it('should return the current task backend configuration', () => {
199
- const customBackend: TaskBackendConfig = {
200
- backend: 'beads',
201
- isAvailable: true,
202
- };
203
-
204
- factory = new ServerComponentsFactory({ taskBackend: customBackend });
205
- const taskBackend = factory.getTaskBackend();
206
-
207
- expect(taskBackend).toEqual(customBackend);
208
- });
209
-
210
- it('should return detected task backend when no explicit config provided', () => {
211
- const detectedBackend: TaskBackendConfig = {
212
- backend: 'markdown',
213
- isAvailable: true,
214
- };
215
- mockDetectTaskBackend.mockReturnValue(detectedBackend);
216
-
217
- factory = new ServerComponentsFactory();
218
- const taskBackend = factory.getTaskBackend();
219
-
220
- expect(taskBackend).toEqual(detectedBackend);
221
- });
222
- });
223
-
224
- describe('Backend Integration', () => {
225
- it('should handle unknown backend types gracefully', () => {
226
- const unknownBackend: TaskBackendConfig = {
227
- backend: 'beads' as TaskBackendConfig['backend'],
228
- isAvailable: true,
229
- };
230
- // Simulate an unknown backend type for testing
231
- (unknownBackend as unknown as { backend: string }).backend =
232
- 'unknown-backend';
233
-
234
- factory = new ServerComponentsFactory({ taskBackend: unknownBackend });
235
-
236
- // Should fall back to default implementations
237
- const planManager = factory.createPlanManager();
238
- const instructionGenerator = factory.createInstructionGenerator();
239
-
240
- expect(planManager.constructor.name).toBe('PlanManager');
241
- expect(instructionGenerator.constructor.name).toBe(
242
- 'InstructionGenerator'
243
- );
244
- });
245
-
246
- it('should handle backend availability flag correctly', () => {
247
- const unavailableBackend: TaskBackendConfig = {
248
- backend: 'beads',
249
- isAvailable: false,
250
- };
251
-
252
- factory = new ServerComponentsFactory({
253
- taskBackend: unavailableBackend,
254
- });
255
-
256
- // Should fall back to default implementations when backend unavailable
257
- const planManager = factory.createPlanManager();
258
- const instructionGenerator = factory.createInstructionGenerator();
259
-
260
- expect(planManager.constructor.name).toBe('PlanManager');
261
- expect(instructionGenerator.constructor.name).toBe(
262
- 'InstructionGenerator'
263
- );
264
- });
265
- });
266
-
267
- describe('Future Extensibility', () => {
268
- // These tests document the expected behavior once beads implementations are created
269
- it.todo(
270
- 'should create BeadsPlanManager when beads backend is available and implemented'
271
- );
272
- it.todo(
273
- 'should create BeadsInstructionGenerator when beads backend is available and implemented'
274
- );
275
- it.todo(
276
- 'should support additional backends (github, linear) through same factory pattern'
277
- );
278
- });
279
- });