popeye-cli 1.0.1 → 1.2.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 (216) hide show
  1. package/.env.example +24 -1
  2. package/CONTRIBUTING.md +275 -0
  3. package/OPEN_SOURCE_MANIFESTO.md +172 -0
  4. package/README.md +832 -123
  5. package/dist/adapters/claude.d.ts +19 -4
  6. package/dist/adapters/claude.d.ts.map +1 -1
  7. package/dist/adapters/claude.js +908 -42
  8. package/dist/adapters/claude.js.map +1 -1
  9. package/dist/adapters/gemini.d.ts +55 -0
  10. package/dist/adapters/gemini.d.ts.map +1 -0
  11. package/dist/adapters/gemini.js +318 -0
  12. package/dist/adapters/gemini.js.map +1 -0
  13. package/dist/adapters/grok.d.ts +73 -0
  14. package/dist/adapters/grok.d.ts.map +1 -0
  15. package/dist/adapters/grok.js +430 -0
  16. package/dist/adapters/grok.js.map +1 -0
  17. package/dist/adapters/openai.d.ts +1 -1
  18. package/dist/adapters/openai.d.ts.map +1 -1
  19. package/dist/adapters/openai.js +47 -8
  20. package/dist/adapters/openai.js.map +1 -1
  21. package/dist/auth/claude.d.ts +11 -9
  22. package/dist/auth/claude.d.ts.map +1 -1
  23. package/dist/auth/claude.js +107 -71
  24. package/dist/auth/claude.js.map +1 -1
  25. package/dist/auth/gemini.d.ts +58 -0
  26. package/dist/auth/gemini.d.ts.map +1 -0
  27. package/dist/auth/gemini.js +172 -0
  28. package/dist/auth/gemini.js.map +1 -0
  29. package/dist/auth/grok.d.ts +73 -0
  30. package/dist/auth/grok.d.ts.map +1 -0
  31. package/dist/auth/grok.js +211 -0
  32. package/dist/auth/grok.js.map +1 -0
  33. package/dist/auth/index.d.ts +14 -7
  34. package/dist/auth/index.d.ts.map +1 -1
  35. package/dist/auth/index.js +41 -6
  36. package/dist/auth/index.js.map +1 -1
  37. package/dist/auth/keychain.d.ts +20 -7
  38. package/dist/auth/keychain.d.ts.map +1 -1
  39. package/dist/auth/keychain.js +85 -29
  40. package/dist/auth/keychain.js.map +1 -1
  41. package/dist/auth/openai.d.ts +2 -2
  42. package/dist/auth/openai.d.ts.map +1 -1
  43. package/dist/auth/openai.js +30 -32
  44. package/dist/auth/openai.js.map +1 -1
  45. package/dist/cli/commands/auth.d.ts +1 -1
  46. package/dist/cli/commands/auth.d.ts.map +1 -1
  47. package/dist/cli/commands/auth.js +79 -8
  48. package/dist/cli/commands/auth.js.map +1 -1
  49. package/dist/cli/commands/create.d.ts.map +1 -1
  50. package/dist/cli/commands/create.js +15 -4
  51. package/dist/cli/commands/create.js.map +1 -1
  52. package/dist/cli/interactive.d.ts.map +1 -1
  53. package/dist/cli/interactive.js +1494 -114
  54. package/dist/cli/interactive.js.map +1 -1
  55. package/dist/config/defaults.d.ts +9 -1
  56. package/dist/config/defaults.d.ts.map +1 -1
  57. package/dist/config/defaults.js +19 -2
  58. package/dist/config/defaults.js.map +1 -1
  59. package/dist/config/index.d.ts +19 -0
  60. package/dist/config/index.d.ts.map +1 -1
  61. package/dist/config/index.js +33 -1
  62. package/dist/config/index.js.map +1 -1
  63. package/dist/config/schema.d.ts +47 -0
  64. package/dist/config/schema.d.ts.map +1 -1
  65. package/dist/config/schema.js +29 -1
  66. package/dist/config/schema.js.map +1 -1
  67. package/dist/generators/fullstack.d.ts +32 -0
  68. package/dist/generators/fullstack.d.ts.map +1 -0
  69. package/dist/generators/fullstack.js +497 -0
  70. package/dist/generators/fullstack.js.map +1 -0
  71. package/dist/generators/index.d.ts +4 -3
  72. package/dist/generators/index.d.ts.map +1 -1
  73. package/dist/generators/index.js +15 -1
  74. package/dist/generators/index.js.map +1 -1
  75. package/dist/generators/python.d.ts +17 -1
  76. package/dist/generators/python.d.ts.map +1 -1
  77. package/dist/generators/python.js +34 -20
  78. package/dist/generators/python.js.map +1 -1
  79. package/dist/generators/templates/fullstack.d.ts +113 -0
  80. package/dist/generators/templates/fullstack.d.ts.map +1 -0
  81. package/dist/generators/templates/fullstack.js +1004 -0
  82. package/dist/generators/templates/fullstack.js.map +1 -0
  83. package/dist/generators/typescript.d.ts +19 -1
  84. package/dist/generators/typescript.d.ts.map +1 -1
  85. package/dist/generators/typescript.js +37 -20
  86. package/dist/generators/typescript.js.map +1 -1
  87. package/dist/state/index.d.ts +108 -0
  88. package/dist/state/index.d.ts.map +1 -1
  89. package/dist/state/index.js +551 -4
  90. package/dist/state/index.js.map +1 -1
  91. package/dist/state/registry.d.ts +52 -0
  92. package/dist/state/registry.d.ts.map +1 -0
  93. package/dist/state/registry.js +215 -0
  94. package/dist/state/registry.js.map +1 -0
  95. package/dist/types/cli.d.ts +8 -0
  96. package/dist/types/cli.d.ts.map +1 -1
  97. package/dist/types/cli.js.map +1 -1
  98. package/dist/types/consensus.d.ts +186 -4
  99. package/dist/types/consensus.d.ts.map +1 -1
  100. package/dist/types/consensus.js +35 -3
  101. package/dist/types/consensus.js.map +1 -1
  102. package/dist/types/project.d.ts +76 -0
  103. package/dist/types/project.d.ts.map +1 -1
  104. package/dist/types/project.js +1 -1
  105. package/dist/types/project.js.map +1 -1
  106. package/dist/types/workflow.d.ts +217 -16
  107. package/dist/types/workflow.d.ts.map +1 -1
  108. package/dist/types/workflow.js +40 -1
  109. package/dist/types/workflow.js.map +1 -1
  110. package/dist/workflow/auto-fix.d.ts +45 -0
  111. package/dist/workflow/auto-fix.d.ts.map +1 -0
  112. package/dist/workflow/auto-fix.js +274 -0
  113. package/dist/workflow/auto-fix.js.map +1 -0
  114. package/dist/workflow/consensus.d.ts +70 -2
  115. package/dist/workflow/consensus.d.ts.map +1 -1
  116. package/dist/workflow/consensus.js +872 -17
  117. package/dist/workflow/consensus.js.map +1 -1
  118. package/dist/workflow/execution-mode.d.ts +10 -4
  119. package/dist/workflow/execution-mode.d.ts.map +1 -1
  120. package/dist/workflow/execution-mode.js +547 -58
  121. package/dist/workflow/execution-mode.js.map +1 -1
  122. package/dist/workflow/index.d.ts +14 -2
  123. package/dist/workflow/index.d.ts.map +1 -1
  124. package/dist/workflow/index.js +69 -6
  125. package/dist/workflow/index.js.map +1 -1
  126. package/dist/workflow/milestone-workflow.d.ts +34 -0
  127. package/dist/workflow/milestone-workflow.d.ts.map +1 -0
  128. package/dist/workflow/milestone-workflow.js +414 -0
  129. package/dist/workflow/milestone-workflow.js.map +1 -0
  130. package/dist/workflow/plan-mode.d.ts +80 -3
  131. package/dist/workflow/plan-mode.d.ts.map +1 -1
  132. package/dist/workflow/plan-mode.js +767 -49
  133. package/dist/workflow/plan-mode.js.map +1 -1
  134. package/dist/workflow/plan-storage.d.ts +386 -0
  135. package/dist/workflow/plan-storage.d.ts.map +1 -0
  136. package/dist/workflow/plan-storage.js +878 -0
  137. package/dist/workflow/plan-storage.js.map +1 -0
  138. package/dist/workflow/project-verification.d.ts +37 -0
  139. package/dist/workflow/project-verification.d.ts.map +1 -0
  140. package/dist/workflow/project-verification.js +381 -0
  141. package/dist/workflow/project-verification.js.map +1 -0
  142. package/dist/workflow/task-workflow.d.ts +37 -0
  143. package/dist/workflow/task-workflow.d.ts.map +1 -0
  144. package/dist/workflow/task-workflow.js +386 -0
  145. package/dist/workflow/task-workflow.js.map +1 -0
  146. package/dist/workflow/test-runner.d.ts +9 -0
  147. package/dist/workflow/test-runner.d.ts.map +1 -1
  148. package/dist/workflow/test-runner.js +101 -5
  149. package/dist/workflow/test-runner.js.map +1 -1
  150. package/dist/workflow/ui-designer.d.ts +82 -0
  151. package/dist/workflow/ui-designer.d.ts.map +1 -0
  152. package/dist/workflow/ui-designer.js +234 -0
  153. package/dist/workflow/ui-designer.js.map +1 -0
  154. package/dist/workflow/ui-setup.d.ts +58 -0
  155. package/dist/workflow/ui-setup.d.ts.map +1 -0
  156. package/dist/workflow/ui-setup.js +685 -0
  157. package/dist/workflow/ui-setup.js.map +1 -0
  158. package/dist/workflow/ui-verification.d.ts +114 -0
  159. package/dist/workflow/ui-verification.d.ts.map +1 -0
  160. package/dist/workflow/ui-verification.js +258 -0
  161. package/dist/workflow/ui-verification.js.map +1 -0
  162. package/dist/workflow/workflow-logger.d.ts +110 -0
  163. package/dist/workflow/workflow-logger.d.ts.map +1 -0
  164. package/dist/workflow/workflow-logger.js +267 -0
  165. package/dist/workflow/workflow-logger.js.map +1 -0
  166. package/dist/workflow/workspace-manager.d.ts +342 -0
  167. package/dist/workflow/workspace-manager.d.ts.map +1 -0
  168. package/dist/workflow/workspace-manager.js +733 -0
  169. package/dist/workflow/workspace-manager.js.map +1 -0
  170. package/package.json +2 -2
  171. package/src/adapters/claude.ts +1067 -47
  172. package/src/adapters/gemini.ts +373 -0
  173. package/src/adapters/grok.ts +492 -0
  174. package/src/adapters/openai.ts +48 -9
  175. package/src/auth/claude.ts +120 -78
  176. package/src/auth/gemini.ts +207 -0
  177. package/src/auth/grok.ts +255 -0
  178. package/src/auth/index.ts +47 -9
  179. package/src/auth/keychain.ts +95 -28
  180. package/src/auth/openai.ts +29 -36
  181. package/src/cli/commands/auth.ts +89 -10
  182. package/src/cli/commands/create.ts +13 -4
  183. package/src/cli/interactive.ts +1774 -142
  184. package/src/config/defaults.ts +19 -2
  185. package/src/config/index.ts +36 -1
  186. package/src/config/schema.ts +30 -1
  187. package/src/generators/fullstack.ts +551 -0
  188. package/src/generators/index.ts +25 -1
  189. package/src/generators/python.ts +65 -20
  190. package/src/generators/templates/fullstack.ts +1047 -0
  191. package/src/generators/typescript.ts +69 -20
  192. package/src/state/index.ts +713 -4
  193. package/src/state/registry.ts +278 -0
  194. package/src/types/cli.ts +8 -0
  195. package/src/types/consensus.ts +197 -6
  196. package/src/types/project.ts +82 -1
  197. package/src/types/workflow.ts +90 -1
  198. package/src/workflow/auto-fix.ts +340 -0
  199. package/src/workflow/consensus.ts +1180 -16
  200. package/src/workflow/execution-mode.ts +673 -74
  201. package/src/workflow/index.ts +95 -6
  202. package/src/workflow/milestone-workflow.ts +576 -0
  203. package/src/workflow/plan-mode.ts +924 -50
  204. package/src/workflow/plan-storage.ts +1282 -0
  205. package/src/workflow/project-verification.ts +471 -0
  206. package/src/workflow/task-workflow.ts +528 -0
  207. package/src/workflow/test-runner.ts +120 -5
  208. package/src/workflow/ui-designer.ts +337 -0
  209. package/src/workflow/ui-setup.ts +797 -0
  210. package/src/workflow/ui-verification.ts +357 -0
  211. package/src/workflow/workflow-logger.ts +353 -0
  212. package/src/workflow/workspace-manager.ts +912 -0
  213. package/tests/config/config.test.ts +1 -1
  214. package/tests/types/consensus.test.ts +3 -3
  215. package/tests/workflow/plan-mode.test.ts +213 -0
  216. package/tests/workflow/test-runner.test.ts +5 -3
@@ -18,7 +18,7 @@ describe('DEFAULT_CONFIG', () => {
18
18
 
19
19
  it('should have valid consensus defaults', () => {
20
20
  expect(DEFAULT_CONFIG.consensus.threshold).toBe(95);
21
- expect(DEFAULT_CONFIG.consensus.max_disagreements).toBe(5);
21
+ expect(DEFAULT_CONFIG.consensus.max_disagreements).toBe(10);
22
22
  expect(DEFAULT_CONFIG.consensus.escalation_action).toBe('pause');
23
23
  });
24
24
 
@@ -85,9 +85,9 @@ describe('ConsensusConfigSchema', () => {
85
85
  expect(result.success).toBe(false);
86
86
  });
87
87
 
88
- it('should reject maxIterations above 10', () => {
88
+ it('should reject maxIterations above 20', () => {
89
89
  const config = {
90
- maxIterations: 11,
90
+ maxIterations: 21,
91
91
  openaiKey: 'sk-test-key',
92
92
  openaiModel: 'gpt-4o' as const,
93
93
  };
@@ -140,7 +140,7 @@ describe('ConsensusConfigSchema', () => {
140
140
  describe('DEFAULT_CONSENSUS_CONFIG', () => {
141
141
  it('should have valid default values', () => {
142
142
  expect(DEFAULT_CONSENSUS_CONFIG.threshold).toBe(95);
143
- expect(DEFAULT_CONSENSUS_CONFIG.maxIterations).toBe(5);
143
+ expect(DEFAULT_CONSENSUS_CONFIG.maxIterations).toBe(10);
144
144
  expect(DEFAULT_CONSENSUS_CONFIG.openaiModel).toBe('gpt-4o');
145
145
  expect(DEFAULT_CONSENSUS_CONFIG.temperature).toBe(0.3);
146
146
  expect(DEFAULT_CONSENSUS_CONFIG.maxTokens).toBe(4096);
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Tests for plan-mode workflow
3
+ */
4
+
5
+ import { describe, it, expect } from 'vitest';
6
+ import { parsePlanMilestones } from '../../src/workflow/plan-mode.js';
7
+
8
+ describe('parsePlanMilestones', () => {
9
+ describe('with explicit task markers', () => {
10
+ it('should extract tasks with "### Task N:" format', () => {
11
+ const plan = `
12
+ # Development Plan
13
+
14
+ ## Milestone 1: Core Setup
15
+
16
+ ### Task 1: Create project structure
17
+ - **Description**: Set up the basic project directory structure
18
+ - **Acceptance Criteria**:
19
+ - All directories created
20
+ - Package.json initialized
21
+
22
+ ### Task 2: Implement user authentication
23
+ - **Description**: Build the authentication module
24
+ - **Acceptance Criteria**:
25
+ - Login endpoint works
26
+ - JWT tokens issued
27
+ `;
28
+
29
+ const milestones = parsePlanMilestones(plan);
30
+
31
+ expect(milestones.length).toBeGreaterThan(0);
32
+ const allTasks = milestones.flatMap(m => m.tasks);
33
+ expect(allTasks.length).toBeGreaterThanOrEqual(2);
34
+
35
+ const taskNames = allTasks.map(t => t.name.toLowerCase());
36
+ expect(taskNames.some(n => n.includes('create project structure'))).toBe(true);
37
+ expect(taskNames.some(n => n.includes('implement user authentication'))).toBe(true);
38
+ });
39
+
40
+ it('should extract tasks with actionable verbs from bullets', () => {
41
+ const plan = `
42
+ ## Implementation Phase
43
+
44
+ - Implement the REST API endpoints for user management
45
+ - Create the database schema for products
46
+ - Build the authentication middleware
47
+ - Set up Docker containerization
48
+ `;
49
+
50
+ const milestones = parsePlanMilestones(plan);
51
+ const allTasks = milestones.flatMap(m => m.tasks);
52
+
53
+ expect(allTasks.length).toBeGreaterThanOrEqual(4);
54
+ const taskNames = allTasks.map(t => t.name.toLowerCase());
55
+ expect(taskNames.some(n => n.includes('implement'))).toBe(true);
56
+ expect(taskNames.some(n => n.includes('create'))).toBe(true);
57
+ expect(taskNames.some(n => n.includes('build'))).toBe(true);
58
+ });
59
+ });
60
+
61
+ describe('filtering non-actionable content', () => {
62
+ it('should NOT extract plan metadata as tasks', () => {
63
+ const plan = `
64
+ ## Background & Context
65
+ - This project uses Python
66
+ - The team has experience with FastAPI
67
+
68
+ ## Goals & Objectives
69
+ - Improve developer experience
70
+ - Reduce deployment time
71
+
72
+ ## Implementation Timeline
73
+ - Week 1: Setup
74
+ - Week 2-3: Core development
75
+ - Week 4: Testing
76
+
77
+ ## Tasks
78
+ ### Task 1: Implement the core API
79
+ Description: Build the main API endpoints
80
+ `;
81
+
82
+ const milestones = parsePlanMilestones(plan);
83
+ const allTasks = milestones.flatMap(m => m.tasks);
84
+ const taskNames = allTasks.map(t => t.name.toLowerCase());
85
+
86
+ // Should NOT contain these non-actionable items
87
+ expect(taskNames.some(n => n.includes('this project uses'))).toBe(false);
88
+ expect(taskNames.some(n => n.includes('team has experience'))).toBe(false);
89
+ expect(taskNames.some(n => n.includes('improve developer'))).toBe(false);
90
+ expect(taskNames.some(n => n.includes('week 1'))).toBe(false);
91
+ expect(taskNames.some(n => n.includes('week 2'))).toBe(false);
92
+
93
+ // Should contain the actual task
94
+ expect(taskNames.some(n => n.includes('implement the core api'))).toBe(true);
95
+ });
96
+
97
+ it('should NOT extract file structure descriptions as tasks', () => {
98
+ const plan = `
99
+ ## Project Structure
100
+ - Final file structure showing project organization
101
+ - Directory layout for the application
102
+ - File naming conventions used
103
+
104
+ ## Implementation
105
+ - Create the main application entry point
106
+ - Build the user service module
107
+ `;
108
+
109
+ const milestones = parsePlanMilestones(plan);
110
+ const allTasks = milestones.flatMap(m => m.tasks);
111
+ const taskNames = allTasks.map(t => t.name.toLowerCase());
112
+
113
+ // Should NOT contain file structure descriptions
114
+ expect(taskNames.some(n => n.includes('final file structure'))).toBe(false);
115
+ expect(taskNames.some(n => n.includes('directory layout'))).toBe(false);
116
+ expect(taskNames.some(n => n.includes('naming conventions'))).toBe(false);
117
+
118
+ // Should contain implementation tasks
119
+ expect(taskNames.some(n => n.includes('create'))).toBe(true);
120
+ expect(taskNames.some(n => n.includes('build'))).toBe(true);
121
+ });
122
+
123
+ it('should NOT extract timeline estimates as tasks', () => {
124
+ const plan = `
125
+ ## Schedule
126
+ - Implementation timeline (5-week estimate)
127
+ - 2-week sprint for authentication
128
+ - 3 days for API documentation
129
+
130
+ ## Development Tasks
131
+ - Implement the payment processing module
132
+ - Create order management system
133
+ `;
134
+
135
+ const milestones = parsePlanMilestones(plan);
136
+ const allTasks = milestones.flatMap(m => m.tasks);
137
+ const taskNames = allTasks.map(t => t.name.toLowerCase());
138
+
139
+ // Should NOT contain timeline items
140
+ expect(taskNames.some(n => n.includes('implementation timeline'))).toBe(false);
141
+ expect(taskNames.some(n => n.includes('2-week sprint'))).toBe(false);
142
+ expect(taskNames.some(n => n.includes('3 days'))).toBe(false);
143
+
144
+ // Should contain implementation tasks
145
+ expect(taskNames.some(n => n.includes('implement the payment'))).toBe(true);
146
+ expect(taskNames.some(n => n.includes('create order'))).toBe(true);
147
+ });
148
+ });
149
+
150
+ describe('milestone organization', () => {
151
+ it('should group tasks into phases when no explicit milestones', () => {
152
+ const plan = `
153
+ # Implementation Tasks
154
+
155
+ 1. Create the database models
156
+ 2. Implement user registration
157
+ 3. Build login endpoint
158
+ 4. Set up JWT authentication
159
+ 5. Create profile management
160
+ 6. Implement password reset
161
+ 7. Build admin dashboard
162
+ `;
163
+
164
+ const milestones = parsePlanMilestones(plan);
165
+
166
+ // Should have at least one milestone
167
+ expect(milestones.length).toBeGreaterThan(0);
168
+
169
+ // Each milestone should have tasks
170
+ for (const milestone of milestones) {
171
+ expect(milestone.tasks.length).toBeGreaterThan(0);
172
+ }
173
+
174
+ // Total tasks should be preserved
175
+ const totalTasks = milestones.reduce((sum, m) => sum + m.tasks.length, 0);
176
+ expect(totalTasks).toBeGreaterThanOrEqual(7);
177
+ });
178
+
179
+ it('should respect explicit milestone sections', () => {
180
+ const plan = `
181
+ ## Milestone 1: Foundation
182
+ - Create project scaffolding
183
+ - Set up CI/CD pipeline
184
+
185
+ ## Milestone 2: Core Features
186
+ - Implement user authentication
187
+ - Build API endpoints
188
+ `;
189
+
190
+ const milestones = parsePlanMilestones(plan);
191
+ const milestoneNames = milestones.map(m => m.name.toLowerCase());
192
+
193
+ expect(milestoneNames.some(n => n.includes('foundation'))).toBe(true);
194
+ expect(milestoneNames.some(n => n.includes('core features'))).toBe(true);
195
+ });
196
+ });
197
+
198
+ describe('fallback behavior', () => {
199
+ it('should create a default milestone when no tasks found', () => {
200
+ const plan = `
201
+ This is just a description of the project with no actual tasks.
202
+ The project will do various things but no specific implementation steps are listed.
203
+ `;
204
+
205
+ const milestones = parsePlanMilestones(plan);
206
+
207
+ expect(milestones.length).toBeGreaterThan(0);
208
+ expect(milestones[0].tasks.length).toBeGreaterThan(0);
209
+ // Fallback creates "Set up project structure and dependencies" as first task
210
+ expect(milestones[0].tasks[0].name.toLowerCase()).toContain('set up');
211
+ });
212
+ });
213
+ });
@@ -93,8 +93,10 @@ FAILED tests/test_main.py::test_something
93
93
 
94
94
  const result = parseTestOutput(output, 'python');
95
95
 
96
- expect(result.success).toBe(false);
96
+ // No tests found is treated as success (no failures)
97
+ expect(result.success).toBe(true);
97
98
  expect(result.total).toBe(0);
99
+ expect(result.noTestsFound).toBe(true);
98
100
  });
99
101
  });
100
102
 
@@ -149,7 +151,7 @@ describe('getTestSummary', () => {
149
151
  const summary = getTestSummary(result);
150
152
 
151
153
  expect(summary).toContain('10/10 tests passed');
152
- expect(summary).toContain('');
154
+ expect(summary).toContain('PASS');
153
155
  });
154
156
 
155
157
  it('should summarize failed tests', () => {
@@ -165,7 +167,7 @@ describe('getTestSummary', () => {
165
167
 
166
168
  expect(summary).toContain('8/10 tests passed');
167
169
  expect(summary).toContain('2 failed');
168
- expect(summary).toContain('');
170
+ expect(summary).toContain('FAIL');
169
171
  });
170
172
 
171
173
  it('should handle error case', () => {