popeye-cli 1.1.0 → 1.2.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 (150) 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 +340 -27
  5. package/dist/adapters/claude.d.ts +28 -2
  6. package/dist/adapters/claude.d.ts.map +1 -1
  7. package/dist/adapters/claude.js +273 -20
  8. package/dist/adapters/claude.js.map +1 -1
  9. package/dist/adapters/grok.d.ts +73 -0
  10. package/dist/adapters/grok.d.ts.map +1 -0
  11. package/dist/adapters/grok.js +430 -0
  12. package/dist/adapters/grok.js.map +1 -0
  13. package/dist/adapters/openai.d.ts +1 -1
  14. package/dist/adapters/openai.d.ts.map +1 -1
  15. package/dist/adapters/openai.js +6 -1
  16. package/dist/adapters/openai.js.map +1 -1
  17. package/dist/auth/grok.d.ts +73 -0
  18. package/dist/auth/grok.d.ts.map +1 -0
  19. package/dist/auth/grok.js +211 -0
  20. package/dist/auth/grok.js.map +1 -0
  21. package/dist/auth/index.d.ts +9 -6
  22. package/dist/auth/index.d.ts.map +1 -1
  23. package/dist/auth/index.js +23 -6
  24. package/dist/auth/index.js.map +1 -1
  25. package/dist/cli/commands/auth.d.ts +1 -1
  26. package/dist/cli/commands/auth.d.ts.map +1 -1
  27. package/dist/cli/commands/auth.js +79 -8
  28. package/dist/cli/commands/auth.js.map +1 -1
  29. package/dist/cli/commands/create.d.ts.map +1 -1
  30. package/dist/cli/commands/create.js +15 -4
  31. package/dist/cli/commands/create.js.map +1 -1
  32. package/dist/cli/interactive.d.ts.map +1 -1
  33. package/dist/cli/interactive.js +406 -35
  34. package/dist/cli/interactive.js.map +1 -1
  35. package/dist/config/defaults.d.ts +3 -0
  36. package/dist/config/defaults.d.ts.map +1 -1
  37. package/dist/config/defaults.js +9 -0
  38. package/dist/config/defaults.js.map +1 -1
  39. package/dist/config/index.d.ts +9 -0
  40. package/dist/config/index.d.ts.map +1 -1
  41. package/dist/config/index.js +16 -3
  42. package/dist/config/index.js.map +1 -1
  43. package/dist/config/schema.d.ts +27 -0
  44. package/dist/config/schema.d.ts.map +1 -1
  45. package/dist/config/schema.js +24 -3
  46. package/dist/config/schema.js.map +1 -1
  47. package/dist/generators/fullstack.d.ts +32 -0
  48. package/dist/generators/fullstack.d.ts.map +1 -0
  49. package/dist/generators/fullstack.js +497 -0
  50. package/dist/generators/fullstack.js.map +1 -0
  51. package/dist/generators/index.d.ts +4 -3
  52. package/dist/generators/index.d.ts.map +1 -1
  53. package/dist/generators/index.js +15 -1
  54. package/dist/generators/index.js.map +1 -1
  55. package/dist/generators/python.d.ts +17 -1
  56. package/dist/generators/python.d.ts.map +1 -1
  57. package/dist/generators/python.js +34 -21
  58. package/dist/generators/python.js.map +1 -1
  59. package/dist/generators/templates/fullstack.d.ts +113 -0
  60. package/dist/generators/templates/fullstack.d.ts.map +1 -0
  61. package/dist/generators/templates/fullstack.js +1004 -0
  62. package/dist/generators/templates/fullstack.js.map +1 -0
  63. package/dist/generators/typescript.d.ts +19 -1
  64. package/dist/generators/typescript.d.ts.map +1 -1
  65. package/dist/generators/typescript.js +37 -21
  66. package/dist/generators/typescript.js.map +1 -1
  67. package/dist/types/cli.d.ts +4 -0
  68. package/dist/types/cli.d.ts.map +1 -1
  69. package/dist/types/cli.js.map +1 -1
  70. package/dist/types/consensus.d.ts +119 -2
  71. package/dist/types/consensus.d.ts.map +1 -1
  72. package/dist/types/consensus.js +12 -1
  73. package/dist/types/consensus.js.map +1 -1
  74. package/dist/types/project.d.ts +76 -0
  75. package/dist/types/project.d.ts.map +1 -1
  76. package/dist/types/project.js +1 -1
  77. package/dist/types/project.js.map +1 -1
  78. package/dist/types/workflow.d.ts +170 -16
  79. package/dist/types/workflow.d.ts.map +1 -1
  80. package/dist/types/workflow.js +26 -3
  81. package/dist/types/workflow.js.map +1 -1
  82. package/dist/workflow/consensus.d.ts +29 -3
  83. package/dist/workflow/consensus.d.ts.map +1 -1
  84. package/dist/workflow/consensus.js +334 -27
  85. package/dist/workflow/consensus.js.map +1 -1
  86. package/dist/workflow/execution-mode.d.ts +2 -0
  87. package/dist/workflow/execution-mode.d.ts.map +1 -1
  88. package/dist/workflow/execution-mode.js +20 -0
  89. package/dist/workflow/execution-mode.js.map +1 -1
  90. package/dist/workflow/index.d.ts +2 -0
  91. package/dist/workflow/index.d.ts.map +1 -1
  92. package/dist/workflow/index.js +11 -0
  93. package/dist/workflow/index.js.map +1 -1
  94. package/dist/workflow/milestone-workflow.d.ts +2 -0
  95. package/dist/workflow/milestone-workflow.d.ts.map +1 -1
  96. package/dist/workflow/milestone-workflow.js +19 -2
  97. package/dist/workflow/milestone-workflow.js.map +1 -1
  98. package/dist/workflow/plan-mode.d.ts +66 -2
  99. package/dist/workflow/plan-mode.d.ts.map +1 -1
  100. package/dist/workflow/plan-mode.js +187 -11
  101. package/dist/workflow/plan-mode.js.map +1 -1
  102. package/dist/workflow/plan-storage.d.ts +252 -8
  103. package/dist/workflow/plan-storage.d.ts.map +1 -1
  104. package/dist/workflow/plan-storage.js +580 -33
  105. package/dist/workflow/plan-storage.js.map +1 -1
  106. package/dist/workflow/project-verification.js +1 -1
  107. package/dist/workflow/project-verification.js.map +1 -1
  108. package/dist/workflow/task-workflow.d.ts +2 -0
  109. package/dist/workflow/task-workflow.d.ts.map +1 -1
  110. package/dist/workflow/task-workflow.js +23 -1
  111. package/dist/workflow/task-workflow.js.map +1 -1
  112. package/dist/workflow/test-runner.d.ts +8 -0
  113. package/dist/workflow/test-runner.d.ts.map +1 -1
  114. package/dist/workflow/test-runner.js +92 -0
  115. package/dist/workflow/test-runner.js.map +1 -1
  116. package/dist/workflow/workspace-manager.d.ts +342 -0
  117. package/dist/workflow/workspace-manager.d.ts.map +1 -0
  118. package/dist/workflow/workspace-manager.js +733 -0
  119. package/dist/workflow/workspace-manager.js.map +1 -0
  120. package/package.json +1 -1
  121. package/src/adapters/claude.ts +322 -25
  122. package/src/adapters/grok.ts +492 -0
  123. package/src/adapters/openai.ts +8 -2
  124. package/src/auth/grok.ts +255 -0
  125. package/src/auth/index.ts +27 -9
  126. package/src/cli/commands/auth.ts +89 -10
  127. package/src/cli/commands/create.ts +13 -4
  128. package/src/cli/interactive.ts +453 -34
  129. package/src/config/defaults.ts +9 -0
  130. package/src/config/index.ts +17 -3
  131. package/src/config/schema.ts +25 -3
  132. package/src/generators/fullstack.ts +551 -0
  133. package/src/generators/index.ts +25 -1
  134. package/src/generators/python.ts +65 -21
  135. package/src/generators/templates/fullstack.ts +1047 -0
  136. package/src/generators/typescript.ts +69 -21
  137. package/src/types/cli.ts +4 -0
  138. package/src/types/consensus.ts +135 -3
  139. package/src/types/project.ts +82 -1
  140. package/src/types/workflow.ts +58 -4
  141. package/src/workflow/consensus.ts +461 -31
  142. package/src/workflow/execution-mode.ts +32 -0
  143. package/src/workflow/index.ts +12 -0
  144. package/src/workflow/milestone-workflow.ts +24 -2
  145. package/src/workflow/plan-mode.ts +238 -10
  146. package/src/workflow/plan-storage.ts +835 -35
  147. package/src/workflow/project-verification.ts +1 -1
  148. package/src/workflow/task-workflow.ts +29 -1
  149. package/src/workflow/test-runner.ts +110 -0
  150. package/src/workflow/workspace-manager.ts +912 -0
@@ -31,6 +31,24 @@ export interface GenerationResult {
31
31
  error?: string;
32
32
  }
33
33
 
34
+ /**
35
+ * TypeScript generator options for workspace/monorepo support
36
+ */
37
+ export interface TypeScriptGeneratorOptions {
38
+ /** Base directory for project (defaults to outputDir/projectName) */
39
+ baseDir?: string;
40
+ /** Override auto-derived package name */
41
+ packageName?: string;
42
+ /** Adjust paths for monorepo structure */
43
+ workspaceMode?: boolean;
44
+ /** Skip Docker files (fullstack uses root docker-compose) */
45
+ skipDocker?: boolean;
46
+ /** Skip README (fullstack has root README) */
47
+ skipReadme?: boolean;
48
+ /** Generate frontend project (React + Vite + Tailwind) instead of Node.js */
49
+ frontend?: boolean;
50
+ }
51
+
34
52
  /**
35
53
  * Create a directory if it doesn't exist
36
54
  */
@@ -50,14 +68,28 @@ async function writeFile(filePath: string, content: string): Promise<void> {
50
68
  *
51
69
  * @param spec - Project specification
52
70
  * @param outputDir - Output directory
71
+ * @param options - Generator options for workspace/monorepo support
53
72
  * @returns Generation result
54
73
  */
55
74
  export async function generateTypeScriptProject(
56
75
  spec: ProjectSpec,
57
- outputDir: string
76
+ outputDir: string,
77
+ options: TypeScriptGeneratorOptions = {}
58
78
  ): Promise<GenerationResult> {
79
+ const {
80
+ baseDir,
81
+ packageName: customPackageName,
82
+ workspaceMode = false,
83
+ skipDocker = false,
84
+ skipReadme = false,
85
+ // frontend option reserved for future frontend-specific generation
86
+ } = options;
87
+
59
88
  const projectName = spec.name || 'my-project';
60
- const projectDir = path.join(outputDir, projectName);
89
+ const packageJsonName = customPackageName || projectName;
90
+
91
+ // In workspace mode with baseDir, use it directly; otherwise create subdirectory
92
+ const projectDir = baseDir || path.join(outputDir, projectName);
61
93
  const filesCreated: string[] = [];
62
94
 
63
95
  try {
@@ -65,15 +97,19 @@ export async function generateTypeScriptProject(
65
97
  await ensureDir(projectDir);
66
98
  await ensureDir(path.join(projectDir, 'src'));
67
99
  await ensureDir(path.join(projectDir, 'tests'));
68
- await ensureDir(path.join(projectDir, 'data'));
69
- await ensureDir(path.join(projectDir, 'docs'));
100
+
101
+ // Only create data/docs dirs in standalone mode
102
+ if (!workspaceMode) {
103
+ await ensureDir(path.join(projectDir, 'data'));
104
+ await ensureDir(path.join(projectDir, 'docs'));
105
+ }
70
106
 
71
107
  // Generate and write files
72
108
  const files: Array<{ path: string; content: string }> = [
73
109
  // Root files
74
110
  {
75
111
  path: path.join(projectDir, 'package.json'),
76
- content: generatePackageJson(projectName, spec.idea),
112
+ content: generatePackageJson(packageJsonName, spec.idea),
77
113
  },
78
114
  {
79
115
  path: path.join(projectDir, 'tsconfig.json'),
@@ -99,18 +135,6 @@ export async function generateTypeScriptProject(
99
135
  path: path.join(projectDir, '.env.example'),
100
136
  content: generateEnvExample(),
101
137
  },
102
- {
103
- path: path.join(projectDir, 'README.md'),
104
- content: generateReadme(projectName, spec.idea),
105
- },
106
- {
107
- path: path.join(projectDir, 'Dockerfile'),
108
- content: generateDockerfile(projectName),
109
- },
110
- {
111
- path: path.join(projectDir, 'docker-compose.yml'),
112
- content: generateDockerCompose(projectName),
113
- },
114
138
 
115
139
  // Source files
116
140
  {
@@ -123,13 +147,37 @@ export async function generateTypeScriptProject(
123
147
  path: path.join(projectDir, 'tests', 'index.test.ts'),
124
148
  content: generateTestFile(projectName),
125
149
  },
150
+ ];
126
151
 
127
- // Data placeholder
128
- {
152
+ // Add README if not skipped
153
+ if (!skipReadme) {
154
+ files.push({
155
+ path: path.join(projectDir, 'README.md'),
156
+ content: generateReadme(projectName, spec.idea),
157
+ });
158
+ }
159
+
160
+ // Add Docker files if not skipped
161
+ if (!skipDocker) {
162
+ files.push(
163
+ {
164
+ path: path.join(projectDir, 'Dockerfile'),
165
+ content: generateDockerfile(projectName),
166
+ },
167
+ {
168
+ path: path.join(projectDir, 'docker-compose.yml'),
169
+ content: generateDockerCompose(projectName),
170
+ }
171
+ );
172
+ }
173
+
174
+ // Add data placeholder in standalone mode
175
+ if (!workspaceMode) {
176
+ files.push({
129
177
  path: path.join(projectDir, 'data', '.gitkeep'),
130
178
  content: '',
131
- },
132
- ];
179
+ });
180
+ }
133
181
 
134
182
  // Write all files
135
183
  for (const file of files) {
package/src/types/cli.ts CHANGED
@@ -71,6 +71,10 @@ export interface AuthStatus {
71
71
  authenticated: boolean;
72
72
  keyLastFour?: string;
73
73
  };
74
+ grok?: {
75
+ authenticated: boolean;
76
+ keyLastFour?: string;
77
+ };
74
78
  }
75
79
 
76
80
  /**
@@ -9,13 +9,23 @@ import type { OpenAIModel } from './project.js';
9
9
  /**
10
10
  * Supported AI providers for reviews and arbitration
11
11
  */
12
- export type AIProvider = 'openai' | 'gemini';
12
+ export type AIProvider = 'openai' | 'gemini' | 'grok';
13
13
 
14
14
  /**
15
15
  * Supported Gemini models
16
16
  */
17
17
  export type GeminiModel = 'gemini-2.0-flash' | 'gemini-1.5-pro' | 'gemini-1.5-flash';
18
18
 
19
+ /**
20
+ * Grok model type (flexible string - API evolves fast)
21
+ */
22
+ export type GrokModel = string;
23
+
24
+ /**
25
+ * Default Grok model
26
+ */
27
+ export const DEFAULT_GROK_MODEL = 'grok-3';
28
+
19
29
  /**
20
30
  * Result of a consensus review from OpenAI or Gemini
21
31
  */
@@ -62,8 +72,10 @@ export interface ConsensusConfig {
62
72
  maxIterations: number;
63
73
  openaiKey?: string;
64
74
  geminiKey?: string;
75
+ grokKey?: string;
65
76
  openaiModel: OpenAIModel;
66
77
  geminiModel: GeminiModel;
78
+ grokModel: GrokModel;
67
79
  reviewer: AIProvider;
68
80
  arbitrator: AIProvider;
69
81
  enableArbitration: boolean;
@@ -81,11 +93,12 @@ export interface ConsensusConfig {
81
93
  /**
82
94
  * Default consensus configuration
83
95
  */
84
- export const DEFAULT_CONSENSUS_CONFIG: Omit<ConsensusConfig, 'openaiKey' | 'geminiKey'> = {
96
+ export const DEFAULT_CONSENSUS_CONFIG: Omit<ConsensusConfig, 'openaiKey' | 'geminiKey' | 'grokKey'> = {
85
97
  threshold: 95,
86
98
  maxIterations: 10,
87
99
  openaiModel: 'gpt-4o',
88
100
  geminiModel: 'gemini-2.0-flash',
101
+ grokModel: DEFAULT_GROK_MODEL,
89
102
  reviewer: 'openai',
90
103
  arbitrator: 'gemini',
91
104
  enableArbitration: true,
@@ -99,13 +112,18 @@ export const DEFAULT_CONSENSUS_CONFIG: Omit<ConsensusConfig, 'openaiKey' | 'gemi
99
112
  /**
100
113
  * Zod schema for AI provider
101
114
  */
102
- export const AIProviderSchema = z.enum(['openai', 'gemini']);
115
+ export const AIProviderSchema = z.enum(['openai', 'gemini', 'grok']);
103
116
 
104
117
  /**
105
118
  * Zod schema for Gemini model
106
119
  */
107
120
  export const GeminiModelSchema = z.enum(['gemini-2.0-flash', 'gemini-1.5-pro', 'gemini-1.5-flash']);
108
121
 
122
+ /**
123
+ * Zod schema for Grok model (flexible string)
124
+ */
125
+ export const GrokModelSchema = z.string().default(DEFAULT_GROK_MODEL);
126
+
109
127
  /**
110
128
  * Zod schema for consensus config validation
111
129
  */
@@ -114,8 +132,10 @@ export const ConsensusConfigSchema = z.object({
114
132
  maxIterations: z.number().min(1).max(20).default(10),
115
133
  openaiKey: z.string().optional(),
116
134
  geminiKey: z.string().optional(),
135
+ grokKey: z.string().optional(),
117
136
  openaiModel: z.enum(['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'o1-preview', 'o1-mini']),
118
137
  geminiModel: GeminiModelSchema.default('gemini-2.0-flash'),
138
+ grokModel: GrokModelSchema.default(DEFAULT_GROK_MODEL),
119
139
  reviewer: AIProviderSchema.default('openai'),
120
140
  arbitrator: AIProviderSchema.default('gemini'),
121
141
  enableArbitration: z.boolean().default(true),
@@ -173,3 +193,115 @@ export interface EscalationDetails {
173
193
  unresolvable_concerns: string[];
174
194
  suggestedActions: string[];
175
195
  }
196
+
197
+ /**
198
+ * App target for fullstack reviews
199
+ */
200
+ export type ReviewAppTarget = 'frontend' | 'backend' | 'unified';
201
+
202
+ /**
203
+ * Tagged concern/recommendation with app context
204
+ */
205
+ export interface TaggedItem {
206
+ app: ReviewAppTarget;
207
+ content: string;
208
+ }
209
+
210
+ /**
211
+ * Per-app consensus scores for fullstack projects
212
+ */
213
+ export interface AppConsensusScores {
214
+ frontend?: number;
215
+ backend?: number;
216
+ unified: number; // Combined/overall score
217
+ }
218
+
219
+ /**
220
+ * Per-app feedback for fullstack reviews
221
+ */
222
+ export interface AppFeedback {
223
+ app: ReviewAppTarget;
224
+ score: number;
225
+ concerns: string[];
226
+ recommendations: string[];
227
+ analysis: string;
228
+ }
229
+
230
+ /**
231
+ * Fullstack-aware consensus result
232
+ */
233
+ export interface FullstackConsensusResult extends ConsensusResult {
234
+ /** Per-app breakdown of scores */
235
+ appScores: AppConsensusScores;
236
+ /** Concerns tagged by app */
237
+ taggedConcerns: TaggedItem[];
238
+ /** Recommendations tagged by app */
239
+ taggedRecommendations: TaggedItem[];
240
+ /** Per-app feedback breakdown */
241
+ appFeedback: AppFeedback[];
242
+ /** Whether this is a fullstack project review */
243
+ isFullstack: boolean;
244
+ }
245
+
246
+ /**
247
+ * Fullstack consensus iteration with per-app tracking
248
+ */
249
+ export interface FullstackConsensusIteration extends ConsensusIteration {
250
+ /** Per-app scores for this iteration */
251
+ appScores?: AppConsensusScores;
252
+ /** Per-app approval status */
253
+ appApproved?: {
254
+ frontend?: boolean;
255
+ backend?: boolean;
256
+ unified: boolean;
257
+ };
258
+ }
259
+
260
+ /**
261
+ * Correction/revision record for tracking all changes
262
+ */
263
+ export interface CorrectionRecord {
264
+ id: string;
265
+ timestamp: string;
266
+ app: ReviewAppTarget;
267
+ previousScore: number;
268
+ newScore: number;
269
+ concerns: string[];
270
+ changes: string[];
271
+ reviewer: AIProvider;
272
+ }
273
+
274
+ /**
275
+ * Complete consensus tracking for a plan level (master/milestone/task)
276
+ */
277
+ export interface ConsensusTrackingRecord {
278
+ planLevel: 'master' | 'milestone' | 'task';
279
+ planId: string;
280
+ milestoneName?: string;
281
+ taskName?: string;
282
+ isFullstack: boolean;
283
+
284
+ /** Overall consensus status */
285
+ overallScore: number;
286
+ overallApproved: boolean;
287
+ totalIterations: number;
288
+
289
+ /** Per-app consensus status (fullstack only) */
290
+ frontendScore?: number;
291
+ frontendApproved?: boolean;
292
+ frontendIterations?: number;
293
+
294
+ backendScore?: number;
295
+ backendApproved?: boolean;
296
+ backendIterations?: number;
297
+
298
+ /** All corrections/revisions made */
299
+ corrections: CorrectionRecord[];
300
+
301
+ /** Timestamps */
302
+ startedAt: string;
303
+ completedAt?: string;
304
+
305
+ /** Final status */
306
+ status: 'in-progress' | 'approved' | 'escalated' | 'failed';
307
+ }
@@ -8,9 +8,90 @@ import { z } from 'zod';
8
8
  /**
9
9
  * Supported output languages for generated projects
10
10
  */
11
- export const OutputLanguageSchema = z.enum(['python', 'typescript']);
11
+ export const OutputLanguageSchema = z.enum(['python', 'typescript', 'fullstack']);
12
12
  export type OutputLanguage = z.infer<typeof OutputLanguageSchema>;
13
13
 
14
+ /**
15
+ * Commands configuration for a workspace app
16
+ */
17
+ export interface WorkspaceAppCommands {
18
+ test: string;
19
+ lint: string;
20
+ build: string;
21
+ dev: string;
22
+ typecheck?: string;
23
+ }
24
+
25
+ /**
26
+ * Docker configuration for a workspace app
27
+ */
28
+ export interface WorkspaceAppDocker {
29
+ dockerfile: string;
30
+ imageName: string;
31
+ context: string;
32
+ }
33
+
34
+ /**
35
+ * Single app configuration in a workspace
36
+ */
37
+ export interface WorkspaceApp {
38
+ name: string;
39
+ path: string;
40
+ language: 'python' | 'typescript';
41
+ commands: WorkspaceAppCommands;
42
+ docker?: WorkspaceAppDocker;
43
+ /** Dependencies on other apps or shared packages */
44
+ dependsOn?: string[];
45
+ /** Files to include as context for AI code generation */
46
+ contextRoots?: string[];
47
+ /** UI spec path (frontend only) */
48
+ uiSpec?: string;
49
+ }
50
+
51
+ /**
52
+ * Shared configuration in a workspace
53
+ */
54
+ export interface WorkspaceShared {
55
+ /** OpenAPI spec path for contract-first development */
56
+ contracts?: string;
57
+ /** Generator command for FE client from OpenAPI */
58
+ contractsGenerator?: string;
59
+ }
60
+
61
+ /**
62
+ * Repo-level commands for workspace orchestration
63
+ */
64
+ export interface WorkspaceCommands {
65
+ testAll: string;
66
+ lintAll: string;
67
+ buildAll: string;
68
+ devAll?: string;
69
+ }
70
+
71
+ /**
72
+ * Docker configuration at workspace level
73
+ */
74
+ export interface WorkspaceDocker {
75
+ composePath: string;
76
+ /** Root-level compose for convenience symlink */
77
+ rootComposeSymlink?: boolean;
78
+ }
79
+
80
+ /**
81
+ * Workspace configuration for fullstack projects
82
+ */
83
+ export interface WorkspaceConfig {
84
+ version: '1.0';
85
+ apps: {
86
+ frontend?: WorkspaceApp;
87
+ backend?: WorkspaceApp;
88
+ };
89
+ shared?: WorkspaceShared;
90
+ /** Repo-level commands that orchestrate across apps */
91
+ commands: WorkspaceCommands;
92
+ docker: WorkspaceDocker;
93
+ }
94
+
14
95
  /**
15
96
  * Supported OpenAI models for consensus reviews
16
97
  */
@@ -16,15 +16,25 @@ export type WorkflowPhase = z.infer<typeof WorkflowPhaseSchema>;
16
16
  /**
17
17
  * Project status
18
18
  */
19
- export const ProjectStatusSchema = z.enum(['pending', 'in-progress', 'complete', 'failed']);
19
+ export const ProjectStatusSchema = z.enum(['pending', 'in-progress', 'complete', 'failed', 'paused']);
20
20
  export type ProjectStatus = z.infer<typeof ProjectStatusSchema>;
21
21
 
22
22
  /**
23
23
  * Status of a task or milestone
24
24
  */
25
- export const TaskStatusSchema = z.enum(['pending', 'in-progress', 'complete', 'failed']);
25
+ export const TaskStatusSchema = z.enum(['pending', 'in-progress', 'complete', 'failed', 'paused']);
26
26
  export type TaskStatus = z.infer<typeof TaskStatusSchema>;
27
27
 
28
+ /**
29
+ * Per-app consensus tracking (for fullstack projects)
30
+ */
31
+ export interface AppConsensusTracking {
32
+ score?: number;
33
+ iterations?: number;
34
+ approved?: boolean;
35
+ feedbackDoc?: string; // Path to app-specific feedback
36
+ }
37
+
28
38
  /**
29
39
  * Individual task within a milestone
30
40
  */
@@ -44,8 +54,26 @@ export interface Task {
44
54
  planDoc?: string; // Path to task plan document
45
55
  testResultsDoc?: string; // Path to test results document
46
56
  implementationComplete?: boolean; // Whether code implementation finished (for resume)
57
+
58
+ // Per-app consensus tracking (fullstack projects)
59
+ frontendConsensus?: AppConsensusTracking;
60
+ backendConsensus?: AppConsensusTracking;
61
+ unifiedConsensus?: AppConsensusTracking;
62
+
63
+ // App target (which app this task affects)
64
+ appTarget?: 'frontend' | 'backend' | 'unified';
47
65
  }
48
66
 
67
+ /**
68
+ * Zod schema for per-app consensus tracking
69
+ */
70
+ export const AppConsensusTrackingSchema = z.object({
71
+ score: z.number().optional(),
72
+ iterations: z.number().optional(),
73
+ approved: z.boolean().optional(),
74
+ feedbackDoc: z.string().optional(),
75
+ });
76
+
49
77
  /**
50
78
  * Zod schema for Task
51
79
  */
@@ -64,6 +92,11 @@ export const TaskSchema = z.object({
64
92
  planDoc: z.string().optional(),
65
93
  testResultsDoc: z.string().optional(),
66
94
  implementationComplete: z.boolean().optional(),
95
+ // Per-app consensus tracking (fullstack)
96
+ frontendConsensus: AppConsensusTrackingSchema.optional(),
97
+ backendConsensus: AppConsensusTrackingSchema.optional(),
98
+ unifiedConsensus: AppConsensusTrackingSchema.optional(),
99
+ appTarget: z.enum(['frontend', 'backend', 'unified']).optional(),
67
100
  });
68
101
 
69
102
  /**
@@ -80,12 +113,24 @@ export interface Milestone {
80
113
  consensusScore?: number; // Consensus score for milestone plan
81
114
  consensusIterations?: number; // Number of iterations to reach consensus
82
115
  consensusApproved?: boolean; // Whether milestone plan was approved
83
- planDoc?: string; // Path: docs/milestone_N_plan.md
116
+ planDoc?: string; // Path: docs/plans/milestone-N/plan.md
84
117
  // Milestone completion review
85
118
  completionReview?: string; // Code review and summary
86
119
  completionScore?: number; // Consensus score for completion
87
120
  completionApproved?: boolean; // Whether milestone completion was approved
88
121
  completionDoc?: string; // Path: docs/milestone_N_complete.md
122
+
123
+ // Per-app consensus tracking (fullstack projects)
124
+ frontendConsensus?: AppConsensusTracking;
125
+ backendConsensus?: AppConsensusTracking;
126
+ unifiedConsensus?: AppConsensusTracking;
127
+
128
+ // Feedback document paths (fullstack - separate by app)
129
+ feedbackDocs?: {
130
+ frontend?: string; // docs/plans/milestone-N/frontend/feedback.md
131
+ backend?: string; // docs/plans/milestone-N/backend/feedback.md
132
+ unified?: string; // docs/plans/milestone-N/unified/feedback.md
133
+ };
89
134
  }
90
135
 
91
136
  /**
@@ -106,6 +151,15 @@ export const MilestoneSchema = z.object({
106
151
  completionScore: z.number().optional(),
107
152
  completionApproved: z.boolean().optional(),
108
153
  completionDoc: z.string().optional(),
154
+ // Per-app consensus tracking (fullstack)
155
+ frontendConsensus: AppConsensusTrackingSchema.optional(),
156
+ backendConsensus: AppConsensusTrackingSchema.optional(),
157
+ unifiedConsensus: AppConsensusTrackingSchema.optional(),
158
+ feedbackDocs: z.object({
159
+ frontend: z.string().optional(),
160
+ backend: z.string().optional(),
161
+ unified: z.string().optional(),
162
+ }).optional(),
109
163
  });
110
164
 
111
165
  /**
@@ -137,7 +191,7 @@ export const ProjectStateSchema = z.object({
137
191
  id: z.string(),
138
192
  name: z.string(),
139
193
  idea: z.string(),
140
- language: z.enum(['python', 'typescript']),
194
+ language: z.enum(['python', 'typescript', 'fullstack']),
141
195
  openaiModel: z.enum(['gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'o1-preview', 'o1-mini']),
142
196
  phase: WorkflowPhaseSchema,
143
197
  status: ProjectStatusSchema,