popeye-cli 1.6.0 → 1.8.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 (161) hide show
  1. package/README.md +240 -32
  2. package/cheatsheet.md +407 -0
  3. package/dist/cli/commands/db.d.ts +10 -0
  4. package/dist/cli/commands/db.d.ts.map +1 -0
  5. package/dist/cli/commands/db.js +240 -0
  6. package/dist/cli/commands/db.js.map +1 -0
  7. package/dist/cli/commands/doctor.d.ts +18 -0
  8. package/dist/cli/commands/doctor.d.ts.map +1 -0
  9. package/dist/cli/commands/doctor.js +255 -0
  10. package/dist/cli/commands/doctor.js.map +1 -0
  11. package/dist/cli/commands/index.d.ts +2 -0
  12. package/dist/cli/commands/index.d.ts.map +1 -1
  13. package/dist/cli/commands/index.js +2 -0
  14. package/dist/cli/commands/index.js.map +1 -1
  15. package/dist/cli/index.d.ts.map +1 -1
  16. package/dist/cli/index.js +3 -1
  17. package/dist/cli/index.js.map +1 -1
  18. package/dist/cli/interactive.d.ts.map +1 -1
  19. package/dist/cli/interactive.js +96 -0
  20. package/dist/cli/interactive.js.map +1 -1
  21. package/dist/generators/admin-wizard.d.ts +25 -0
  22. package/dist/generators/admin-wizard.d.ts.map +1 -0
  23. package/dist/generators/admin-wizard.js +123 -0
  24. package/dist/generators/admin-wizard.js.map +1 -0
  25. package/dist/generators/all.d.ts.map +1 -1
  26. package/dist/generators/all.js +10 -3
  27. package/dist/generators/all.js.map +1 -1
  28. package/dist/generators/database.d.ts +58 -0
  29. package/dist/generators/database.d.ts.map +1 -0
  30. package/dist/generators/database.js +229 -0
  31. package/dist/generators/database.js.map +1 -0
  32. package/dist/generators/fullstack.d.ts.map +1 -1
  33. package/dist/generators/fullstack.js +23 -7
  34. package/dist/generators/fullstack.js.map +1 -1
  35. package/dist/generators/index.d.ts +2 -0
  36. package/dist/generators/index.d.ts.map +1 -1
  37. package/dist/generators/index.js +2 -0
  38. package/dist/generators/index.js.map +1 -1
  39. package/dist/generators/templates/admin-wizard-python.d.ts +32 -0
  40. package/dist/generators/templates/admin-wizard-python.d.ts.map +1 -0
  41. package/dist/generators/templates/admin-wizard-python.js +425 -0
  42. package/dist/generators/templates/admin-wizard-python.js.map +1 -0
  43. package/dist/generators/templates/admin-wizard-react.d.ts +48 -0
  44. package/dist/generators/templates/admin-wizard-react.d.ts.map +1 -0
  45. package/dist/generators/templates/admin-wizard-react.js +554 -0
  46. package/dist/generators/templates/admin-wizard-react.js.map +1 -0
  47. package/dist/generators/templates/database-docker.d.ts +23 -0
  48. package/dist/generators/templates/database-docker.d.ts.map +1 -0
  49. package/dist/generators/templates/database-docker.js +221 -0
  50. package/dist/generators/templates/database-docker.js.map +1 -0
  51. package/dist/generators/templates/database-python.d.ts +54 -0
  52. package/dist/generators/templates/database-python.d.ts.map +1 -0
  53. package/dist/generators/templates/database-python.js +723 -0
  54. package/dist/generators/templates/database-python.js.map +1 -0
  55. package/dist/generators/templates/database-typescript.d.ts +34 -0
  56. package/dist/generators/templates/database-typescript.d.ts.map +1 -0
  57. package/dist/generators/templates/database-typescript.js +232 -0
  58. package/dist/generators/templates/database-typescript.js.map +1 -0
  59. package/dist/generators/templates/fullstack.d.ts.map +1 -1
  60. package/dist/generators/templates/fullstack.js +29 -0
  61. package/dist/generators/templates/fullstack.js.map +1 -1
  62. package/dist/generators/templates/index.d.ts +5 -0
  63. package/dist/generators/templates/index.d.ts.map +1 -1
  64. package/dist/generators/templates/index.js +5 -0
  65. package/dist/generators/templates/index.js.map +1 -1
  66. package/dist/state/index.d.ts +10 -0
  67. package/dist/state/index.d.ts.map +1 -1
  68. package/dist/state/index.js +22 -0
  69. package/dist/state/index.js.map +1 -1
  70. package/dist/types/consensus.d.ts +3 -0
  71. package/dist/types/consensus.d.ts.map +1 -1
  72. package/dist/types/consensus.js +1 -0
  73. package/dist/types/consensus.js.map +1 -1
  74. package/dist/types/database-runtime.d.ts +86 -0
  75. package/dist/types/database-runtime.d.ts.map +1 -0
  76. package/dist/types/database-runtime.js +61 -0
  77. package/dist/types/database-runtime.js.map +1 -0
  78. package/dist/types/database.d.ts +85 -0
  79. package/dist/types/database.d.ts.map +1 -0
  80. package/dist/types/database.js +71 -0
  81. package/dist/types/database.js.map +1 -0
  82. package/dist/types/index.d.ts +3 -0
  83. package/dist/types/index.d.ts.map +1 -1
  84. package/dist/types/index.js +6 -0
  85. package/dist/types/index.js.map +1 -1
  86. package/dist/types/tester.d.ts +138 -0
  87. package/dist/types/tester.d.ts.map +1 -0
  88. package/dist/types/tester.js +110 -0
  89. package/dist/types/tester.js.map +1 -0
  90. package/dist/types/workflow.d.ts +166 -0
  91. package/dist/types/workflow.d.ts.map +1 -1
  92. package/dist/types/workflow.js +14 -0
  93. package/dist/types/workflow.js.map +1 -1
  94. package/dist/workflow/db-setup-runner.d.ts +63 -0
  95. package/dist/workflow/db-setup-runner.d.ts.map +1 -0
  96. package/dist/workflow/db-setup-runner.js +336 -0
  97. package/dist/workflow/db-setup-runner.js.map +1 -0
  98. package/dist/workflow/db-state-machine.d.ts +30 -0
  99. package/dist/workflow/db-state-machine.d.ts.map +1 -0
  100. package/dist/workflow/db-state-machine.js +51 -0
  101. package/dist/workflow/db-state-machine.js.map +1 -0
  102. package/dist/workflow/execution-mode.js +2 -2
  103. package/dist/workflow/execution-mode.js.map +1 -1
  104. package/dist/workflow/index.d.ts +3 -0
  105. package/dist/workflow/index.d.ts.map +1 -1
  106. package/dist/workflow/index.js +3 -0
  107. package/dist/workflow/index.js.map +1 -1
  108. package/dist/workflow/task-workflow.d.ts +5 -0
  109. package/dist/workflow/task-workflow.d.ts.map +1 -1
  110. package/dist/workflow/task-workflow.js +172 -6
  111. package/dist/workflow/task-workflow.js.map +1 -1
  112. package/dist/workflow/tester.d.ts +120 -0
  113. package/dist/workflow/tester.d.ts.map +1 -0
  114. package/dist/workflow/tester.js +589 -0
  115. package/dist/workflow/tester.js.map +1 -0
  116. package/dist/workflow/workflow-logger.d.ts +1 -1
  117. package/dist/workflow/workflow-logger.d.ts.map +1 -1
  118. package/dist/workflow/workflow-logger.js.map +1 -1
  119. package/package.json +1 -1
  120. package/src/cli/commands/db.ts +281 -0
  121. package/src/cli/commands/doctor.ts +273 -0
  122. package/src/cli/commands/index.ts +2 -0
  123. package/src/cli/index.ts +4 -0
  124. package/src/cli/interactive.ts +102 -0
  125. package/src/generators/admin-wizard.ts +146 -0
  126. package/src/generators/all.ts +10 -3
  127. package/src/generators/database.ts +286 -0
  128. package/src/generators/fullstack.ts +26 -9
  129. package/src/generators/index.ts +12 -0
  130. package/src/generators/templates/admin-wizard-python.ts +431 -0
  131. package/src/generators/templates/admin-wizard-react.ts +560 -0
  132. package/src/generators/templates/database-docker.ts +227 -0
  133. package/src/generators/templates/database-python.ts +734 -0
  134. package/src/generators/templates/database-typescript.ts +238 -0
  135. package/src/generators/templates/fullstack.ts +29 -0
  136. package/src/generators/templates/index.ts +5 -0
  137. package/src/state/index.ts +29 -0
  138. package/src/types/consensus.ts +3 -0
  139. package/src/types/database-runtime.ts +69 -0
  140. package/src/types/database.ts +84 -0
  141. package/src/types/index.ts +50 -0
  142. package/src/types/tester.ts +136 -0
  143. package/src/types/workflow.ts +31 -0
  144. package/src/workflow/db-setup-runner.ts +391 -0
  145. package/src/workflow/db-state-machine.ts +58 -0
  146. package/src/workflow/execution-mode.ts +2 -2
  147. package/src/workflow/index.ts +3 -0
  148. package/src/workflow/task-workflow.ts +227 -5
  149. package/src/workflow/tester.ts +723 -0
  150. package/src/workflow/workflow-logger.ts +2 -0
  151. package/tests/generators/admin-wizard-orchestrator.test.ts +64 -0
  152. package/tests/generators/admin-wizard-templates.test.ts +366 -0
  153. package/tests/generators/cross-phase-integration.test.ts +383 -0
  154. package/tests/generators/database.test.ts +456 -0
  155. package/tests/generators/fe-be-db-integration.test.ts +613 -0
  156. package/tests/types/database-runtime.test.ts +158 -0
  157. package/tests/types/database.test.ts +187 -0
  158. package/tests/types/tester.test.ts +174 -0
  159. package/tests/workflow/db-setup-runner.test.ts +211 -0
  160. package/tests/workflow/db-state-machine.test.ts +117 -0
  161. package/tests/workflow/tester.test.ts +401 -0
@@ -0,0 +1,238 @@
1
+ /**
2
+ * TypeScript backend database template functions
3
+ * Generates Prisma + pgvector files for future TS backend projects
4
+ * NOT wired into any generator in Phase 1 - templates exist for future use
5
+ */
6
+
7
+ /**
8
+ * Generate Prisma schema with PostgreSQL datasource and pgvector
9
+ */
10
+ export function generatePrismaSchema(projectName: string): string {
11
+ return `// Prisma schema for ${projectName}
12
+ // Learn more: https://pris.ly/d/prisma-schema
13
+
14
+ generator client {
15
+ provider = "prisma-client-js"
16
+ previewFeatures = ["postgresqlExtensions"]
17
+ }
18
+
19
+ datasource db {
20
+ provider = "postgresql"
21
+ url = env("DATABASE_URL")
22
+ extensions = [pgvector(map: "vector", schema: "public")]
23
+ }
24
+
25
+ model AppSettings {
26
+ id Int @id @default(autoincrement())
27
+ key String @unique
28
+ value String
29
+ createdAt DateTime @default(now()) @map("created_at")
30
+ updatedAt DateTime @updatedAt @map("updated_at")
31
+
32
+ @@map("app_settings")
33
+ }
34
+ `;
35
+ }
36
+
37
+ /**
38
+ * Generate PrismaClient singleton with connection handling
39
+ */
40
+ export function generatePrismaClient(projectName: string): string {
41
+ return `/**
42
+ * Prisma client singleton for ${projectName}.
43
+ *
44
+ * Ensures a single PrismaClient instance is reused across the application.
45
+ */
46
+
47
+ import { PrismaClient } from "@prisma/client";
48
+
49
+ const globalForPrisma = globalThis as unknown as {
50
+ prisma: PrismaClient | undefined;
51
+ };
52
+
53
+ export const prisma =
54
+ globalForPrisma.prisma ??
55
+ new PrismaClient({
56
+ log:
57
+ process.env.NODE_ENV === "development"
58
+ ? ["query", "error", "warn"]
59
+ : ["error"],
60
+ });
61
+
62
+ if (process.env.NODE_ENV !== "production") {
63
+ globalForPrisma.prisma = prisma;
64
+ }
65
+
66
+ export default prisma;
67
+ `;
68
+ }
69
+
70
+ /**
71
+ * Generate .env.example additions for Prisma
72
+ */
73
+ export function generatePrismaEnv(): string {
74
+ return `# Database
75
+ DATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"
76
+ `;
77
+ }
78
+
79
+ /**
80
+ * Generate Prisma seed script
81
+ */
82
+ export function generatePrismaSeed(): string {
83
+ return `/**
84
+ * Prisma seed script.
85
+ *
86
+ * Seeds the database with initial data using upsert pattern.
87
+ * Run with: npx prisma db seed
88
+ */
89
+
90
+ import { PrismaClient } from "@prisma/client";
91
+
92
+ const prisma = new PrismaClient();
93
+
94
+ async function main() {
95
+ console.log("Seeding database...");
96
+
97
+ // Upsert default app settings
98
+ await prisma.appSettings.upsert({
99
+ where: { key: "app_version" },
100
+ update: { value: "1.0.0" },
101
+ create: { key: "app_version", value: "1.0.0" },
102
+ });
103
+
104
+ console.log("Seeding complete.");
105
+ }
106
+
107
+ main()
108
+ .then(async () => {
109
+ await prisma.$disconnect();
110
+ })
111
+ .catch(async (e) => {
112
+ console.error(e);
113
+ await prisma.$disconnect();
114
+ process.exit(1);
115
+ });
116
+ `;
117
+ }
118
+
119
+ /**
120
+ * Generate database health check for Prisma
121
+ */
122
+ export function generatePrismaDbHealth(): string {
123
+ return `/**
124
+ * Database health check utilities.
125
+ *
126
+ * Tests connection and checks migration status.
127
+ */
128
+
129
+ import prisma from "./client";
130
+
131
+ export interface DbHealthResult {
132
+ connected: boolean;
133
+ migrations?: { current: string | null };
134
+ error?: string;
135
+ }
136
+
137
+ /**
138
+ * Check database connectivity and migration status.
139
+ */
140
+ export async function checkDbHealth(): Promise<DbHealthResult> {
141
+ try {
142
+ // Test basic connectivity
143
+ await prisma.$queryRaw\`SELECT 1\`;
144
+
145
+ // Check migration status
146
+ let currentMigration: string | null = null;
147
+ try {
148
+ const result = await prisma.$queryRaw<
149
+ Array<{ migration_name: string }>
150
+ >\`SELECT migration_name FROM _prisma_migrations ORDER BY finished_at DESC LIMIT 1\`;
151
+ currentMigration = result[0]?.migration_name ?? null;
152
+ } catch {
153
+ // _prisma_migrations table may not exist yet
154
+ }
155
+
156
+ return {
157
+ connected: true,
158
+ migrations: { current: currentMigration },
159
+ };
160
+ } catch (error) {
161
+ return {
162
+ connected: false,
163
+ error: error instanceof Error ? error.message : "Unknown error",
164
+ };
165
+ }
166
+ }
167
+ `;
168
+ }
169
+
170
+ /**
171
+ * Generate pgvector raw query helpers for Prisma
172
+ */
173
+ export function generatePrismaVectorHelpers(): string {
174
+ return `/**
175
+ * pgvector helpers using Prisma raw queries.
176
+ *
177
+ * Provides cosine similarity search and vector extension checks.
178
+ */
179
+
180
+ import prisma from "./client";
181
+
182
+ /**
183
+ * Perform cosine similarity search against a vector column.
184
+ */
185
+ export async function cosineSimilaritySearch(
186
+ tableName: string,
187
+ columnName: string,
188
+ queryVector: number[],
189
+ limit: number = 10
190
+ ): Promise<Array<{ id: number; similarity: number }>> {
191
+ const vectorStr = \`[\${queryVector.join(",")}]\`;
192
+
193
+ const results = await prisma.$queryRawUnsafe<
194
+ Array<{ id: number; similarity: number }>
195
+ >(
196
+ \`SELECT id, 1 - (\${columnName} <=> $1::vector) AS similarity \` +
197
+ \`FROM \${tableName} \` +
198
+ \`ORDER BY \${columnName} <=> $1::vector \` +
199
+ \`LIMIT $2\`,
200
+ vectorStr,
201
+ limit
202
+ );
203
+
204
+ return results;
205
+ }
206
+
207
+ /**
208
+ * Check if the pgvector extension is installed.
209
+ */
210
+ export async function checkVectorExtension(): Promise<boolean> {
211
+ try {
212
+ const result = await prisma.$queryRaw<Array<{ extname: string }>>\`
213
+ SELECT extname FROM pg_extension WHERE extname = 'vector'
214
+ \`;
215
+ return result.length > 0;
216
+ } catch {
217
+ return false;
218
+ }
219
+ }
220
+ `;
221
+ }
222
+
223
+ /**
224
+ * Generate Prisma DB index.ts with re-exports
225
+ */
226
+ export function generatePrismaDbInit(): string {
227
+ return `/**
228
+ * Database package re-exports.
229
+ */
230
+
231
+ export { prisma, default as PrismaClient } from "./client";
232
+ export { checkDbHealth, type DbHealthResult } from "./health";
233
+ export {
234
+ cosineSimilaritySearch,
235
+ checkVectorExtension,
236
+ } from "./vector";
237
+ `;
238
+ }
@@ -212,6 +212,35 @@ cd apps/frontend && npm run lint
212
212
  cd apps/backend && ruff check .
213
213
  \`\`\`
214
214
 
215
+ ## Database
216
+
217
+ Database is **UNCONFIGURED** by default. The app runs without a database in limited mode.
218
+
219
+ ### Local Docker (recommended for development)
220
+
221
+ \`\`\`bash
222
+ # docker-compose starts PostgreSQL automatically
223
+ docker-compose up
224
+ \`\`\`
225
+
226
+ ### Managed Database
227
+
228
+ Set \`DATABASE_URL\` in \`apps/backend/.env\` to connect to a managed PostgreSQL instance (Neon, Supabase, etc.).
229
+
230
+ ### Health Check
231
+
232
+ \`\`\`bash
233
+ # Check database connectivity and migration status
234
+ curl http://localhost:8000/health/db
235
+ \`\`\`
236
+
237
+ ### Migrations
238
+
239
+ \`\`\`bash
240
+ cd apps/backend
241
+ alembic upgrade head
242
+ \`\`\`
243
+
215
244
  ## Apps
216
245
 
217
246
  ### Frontend (apps/frontend)
@@ -14,3 +14,8 @@ export * as websiteLandingTemplates from './website-landing.js';
14
14
  export * as websitePricingTemplates from './website-pricing.js';
15
15
  export * as websiteLayoutTemplates from './website-layout.js';
16
16
  export * as websiteSectionTemplates from './website-sections.js';
17
+ export * as databasePythonTemplates from './database-python.js';
18
+ export * as databaseTypescriptTemplates from './database-typescript.js';
19
+ export * as databaseDockerTemplates from './database-docker.js';
20
+ export * as adminWizardPythonTemplates from './admin-wizard-python.js';
21
+ export * as adminWizardReactTemplates from './admin-wizard-react.js';
@@ -15,6 +15,9 @@ import type {
15
15
  } from '../types/workflow.js';
16
16
  import type { ConsensusIteration } from '../types/consensus.js';
17
17
  import type { ProjectSpec } from '../types/project.js';
18
+ import { isWorkspace } from '../types/project.js';
19
+ import { DEFAULT_DB_CONFIG } from '../types/database.js';
20
+ import type { DbConfig } from '../types/database.js';
18
21
  import {
19
22
  loadState,
20
23
  saveState,
@@ -60,8 +63,14 @@ export async function createProject(
60
63
  consensusHistory: [],
61
64
  createdAt: now,
62
65
  updatedAt: now,
66
+ qaEnabled: true,
63
67
  };
64
68
 
69
+ // Set default DB config for workspace projects (fullstack / all)
70
+ if (isWorkspace(spec.language)) {
71
+ state.dbConfig = { ...DEFAULT_DB_CONFIG };
72
+ }
73
+
65
74
  await saveState(projectDir, state);
66
75
 
67
76
  // Register project in global registry
@@ -394,6 +403,26 @@ export async function storeWebsiteStrategyPath(
394
403
  return updateState(projectDir, { websiteStrategy: strategyPath });
395
404
  }
396
405
 
406
+ /**
407
+ * Update database configuration with partial updates
408
+ * Merges partial DbConfig updates into the existing config
409
+ *
410
+ * @param projectDir - The project root directory
411
+ * @param updates - Partial DbConfig updates to merge
412
+ * @returns The updated project state
413
+ */
414
+ export async function updateDbConfig(
415
+ projectDir: string,
416
+ updates: Partial<DbConfig>
417
+ ): Promise<ProjectState> {
418
+ const current = await loadProject(projectDir);
419
+ const currentDbConfig = current.dbConfig || { ...DEFAULT_DB_CONFIG };
420
+
421
+ return updateState(projectDir, {
422
+ dbConfig: { ...currentDbConfig, ...updates },
423
+ });
424
+ }
425
+
397
426
  /**
398
427
  * Mark the project as complete
399
428
  *
@@ -91,6 +91,8 @@ export interface ConsensusConfig {
91
91
  additionalReviewers?: AIProvider[];
92
92
  /** Custom reviewer persona for domain-specific reviews (e.g., marketing strategist for website projects) */
93
93
  reviewerPersona?: string;
94
+ /** Consensus threshold for test plans (default: 90, lower than code plan threshold) */
95
+ testPlanThreshold?: number;
94
96
  }
95
97
 
96
98
  /**
@@ -153,6 +155,7 @@ export const ConsensusConfigSchema = z.object({
153
155
  temperature: z.number().min(0).max(2).default(0.3),
154
156
  maxTokens: z.number().min(100).max(32000).default(4096),
155
157
  reviewerPersona: z.string().optional(),
158
+ testPlanThreshold: z.number().min(0).max(100).optional(),
156
159
  });
157
160
 
158
161
  /**
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Database runtime types and Zod schemas for Phase 2
3
+ * Defines setup pipeline results, readiness checks, and doctor output
4
+ */
5
+
6
+ import { z } from 'zod';
7
+ import { DbStatusSchema, DbSetupStepSchema } from './database.js';
8
+
9
+ /**
10
+ * Result of a single setup pipeline step
11
+ */
12
+ export const SetupStepResultSchema = z.object({
13
+ /** Which pipeline step */
14
+ step: DbSetupStepSchema,
15
+ /** Whether the step succeeded */
16
+ success: z.boolean(),
17
+ /** Human-readable status message */
18
+ message: z.string(),
19
+ /** Duration in milliseconds */
20
+ durationMs: z.number(),
21
+ /** Error details if step failed */
22
+ error: z.string().optional(),
23
+ });
24
+ export type SetupStepResult = z.infer<typeof SetupStepResultSchema>;
25
+
26
+ /**
27
+ * Full setup pipeline result
28
+ */
29
+ export const SetupResultSchema = z.object({
30
+ /** Whether the entire pipeline succeeded */
31
+ success: z.boolean(),
32
+ /** Individual step results */
33
+ steps: z.array(SetupStepResultSchema),
34
+ /** Total pipeline duration in milliseconds */
35
+ totalDurationMs: z.number(),
36
+ /** Final DB status after pipeline */
37
+ finalStatus: DbStatusSchema,
38
+ /** Error message if pipeline failed */
39
+ error: z.string().optional(),
40
+ });
41
+ export type SetupResult = z.infer<typeof SetupResultSchema>;
42
+
43
+ /**
44
+ * Single readiness check (used by doctor command)
45
+ */
46
+ export const ReadinessCheckSchema = z.object({
47
+ /** Check name */
48
+ name: z.string(),
49
+ /** Whether the check passed */
50
+ passed: z.boolean(),
51
+ /** Human-readable result message */
52
+ message: z.string(),
53
+ /** Severity level */
54
+ severity: z.enum(['critical', 'warning', 'info']),
55
+ });
56
+ export type ReadinessCheck = z.infer<typeof ReadinessCheckSchema>;
57
+
58
+ /**
59
+ * Full doctor readiness result
60
+ */
61
+ export const ReadinessResultSchema = z.object({
62
+ /** Overall health status */
63
+ healthy: z.boolean(),
64
+ /** Individual check results */
65
+ checks: z.array(ReadinessCheckSchema),
66
+ /** ISO timestamp of when checks ran */
67
+ timestamp: z.string(),
68
+ });
69
+ export type ReadinessResult = z.infer<typeof ReadinessResultSchema>;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Database configuration types and Zod schemas
3
+ * Defines DB lifecycle states, provisioning modes, and config tracking
4
+ */
5
+
6
+ import { z } from 'zod';
7
+
8
+ /**
9
+ * Database lifecycle status
10
+ */
11
+ export const DbStatusSchema = z.enum([
12
+ 'unconfigured',
13
+ 'configured',
14
+ 'applying',
15
+ 'ready',
16
+ 'error',
17
+ ]);
18
+ export type DbStatus = z.infer<typeof DbStatusSchema>;
19
+
20
+ /**
21
+ * Database provisioning mode
22
+ * - local_docker: PostgreSQL runs in Docker Compose
23
+ * - managed: External managed database (Neon, Supabase, etc.)
24
+ */
25
+ export const DbModeSchema = z.enum(['local_docker', 'managed']);
26
+ export type DbMode = z.infer<typeof DbModeSchema>;
27
+
28
+ /**
29
+ * Database provider (informational only)
30
+ */
31
+ export const DbProviderSchema = z.enum(['neon', 'supabase', 'other']);
32
+ export type DbProvider = z.infer<typeof DbProviderSchema>;
33
+
34
+ /**
35
+ * Backend ORM choice
36
+ */
37
+ export const BackendOrmSchema = z.enum(['sqlalchemy', 'prisma', 'drizzle']);
38
+ export type BackendOrm = z.infer<typeof BackendOrmSchema>;
39
+
40
+ /**
41
+ * Setup pipeline steps (forward compat for Phase 2)
42
+ */
43
+ export const DbSetupStepSchema = z.enum([
44
+ 'check_connection',
45
+ 'ensure_extensions',
46
+ 'apply_migrations',
47
+ 'seed_minimal',
48
+ 'readiness_tests',
49
+ 'mark_ready',
50
+ ]);
51
+ export type DbSetupStep = z.infer<typeof DbSetupStepSchema>;
52
+
53
+ /**
54
+ * Main database configuration tracking object
55
+ */
56
+ export const DbConfigSchema = z.object({
57
+ /** Whether DB layer was generated */
58
+ designed: z.boolean(),
59
+ /** Provisioning mode - unset until user configures */
60
+ mode: DbModeSchema.optional(),
61
+ /** Whether pgvector is included */
62
+ vectorRequired: z.boolean(),
63
+ /** Current lifecycle state */
64
+ status: DbStatusSchema,
65
+ /** Last error message */
66
+ lastError: z.string().optional(),
67
+ /** Number of migrations applied (updated by runner, not generator) */
68
+ migrationsApplied: z.number(),
69
+ /** ISO timestamp of last readiness check */
70
+ readinessCheckedAt: z.string().optional(),
71
+ });
72
+ export type DbConfig = z.infer<typeof DbConfigSchema>;
73
+
74
+ /**
75
+ * Default DB config for new fullstack/all projects
76
+ * vectorRequired: true because fullstack/all projects get pgvector by default
77
+ * mode is intentionally absent (unset until user configures provisioning)
78
+ */
79
+ export const DEFAULT_DB_CONFIG: DbConfig = {
80
+ designed: true,
81
+ status: 'unconfigured',
82
+ vectorRequired: true,
83
+ migrationsApplied: 0,
84
+ };
@@ -80,6 +80,56 @@ export {
80
80
  type ConsensusTrackingRecord,
81
81
  } from './consensus.js';
82
82
 
83
+ // Tester (QA) types
84
+ export {
85
+ TestVerdictSchema,
86
+ TestScopeSchema,
87
+ TestCommandSchema,
88
+ TestCaseSchema,
89
+ TestPlanOutputSchema,
90
+ TestRunReviewSchema,
91
+ FixStepSchema,
92
+ TestFixPlanSchema,
93
+ type TestVerdict,
94
+ type TestScope,
95
+ type TestCommand,
96
+ type TestCase,
97
+ type TestPlanOutput,
98
+ type TestRunReview,
99
+ type FixStep,
100
+ type TestFixPlan,
101
+ type DiscoveredTestCommands,
102
+ } from './tester.js';
103
+
104
+ // Database types
105
+ export {
106
+ DbStatusSchema,
107
+ DbModeSchema,
108
+ DbProviderSchema,
109
+ BackendOrmSchema,
110
+ DbSetupStepSchema,
111
+ DbConfigSchema,
112
+ DEFAULT_DB_CONFIG,
113
+ type DbStatus,
114
+ type DbMode,
115
+ type DbProvider,
116
+ type BackendOrm,
117
+ type DbSetupStep,
118
+ type DbConfig,
119
+ } from './database.js';
120
+
121
+ // Database runtime types
122
+ export {
123
+ SetupStepResultSchema,
124
+ SetupResultSchema,
125
+ ReadinessCheckSchema,
126
+ ReadinessResultSchema,
127
+ type SetupStepResult,
128
+ type SetupResult,
129
+ type ReadinessCheck,
130
+ type ReadinessResult,
131
+ } from './database-runtime.js';
132
+
83
133
  // CLI types
84
134
  export {
85
135
  EXIT_CODES,
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Tester (QA) skill type definitions
3
+ * Defines test planning, review, and fix plan structures
4
+ */
5
+
6
+ import { z } from 'zod';
7
+
8
+ /**
9
+ * Test verdict from the Tester's review
10
+ */
11
+ export const TestVerdictSchema = z.enum(['PASS', 'PASS_WITH_NOTES', 'FAIL']);
12
+ export type TestVerdict = z.infer<typeof TestVerdictSchema>;
13
+
14
+ /**
15
+ * Scope components that a test plan can cover
16
+ */
17
+ export const TestScopeSchema = z.enum(['frontend', 'backend', 'db', 'infra']);
18
+ export type TestScope = z.infer<typeof TestScopeSchema>;
19
+
20
+ /**
21
+ * A structured test command to execute
22
+ */
23
+ export const TestCommandSchema = z.object({
24
+ /** The shell command to run */
25
+ command: z.string().min(1),
26
+ /** Working directory (relative to project root) */
27
+ cwd: z.string().optional(),
28
+ /** Human-readable purpose of this command */
29
+ purpose: z.string().min(1),
30
+ /** Whether this command must pass for the test run to succeed */
31
+ required: z.boolean(),
32
+ });
33
+ export type TestCommand = z.infer<typeof TestCommandSchema>;
34
+
35
+ /**
36
+ * Individual test case in the test matrix
37
+ */
38
+ export const TestCaseSchema = z.object({
39
+ /** Unique identifier within the test plan */
40
+ id: z.string().min(1),
41
+ /** Category: unit, integration, e2e, smoke, lint, build */
42
+ category: z.string().min(1),
43
+ /** Human-readable description of what is being tested */
44
+ description: z.string().min(1),
45
+ /** What must be true for this test to pass */
46
+ acceptanceCriteria: z.string().min(1),
47
+ /** What evidence (log output, report) is needed to verify */
48
+ evidenceRequired: z.string().min(1),
49
+ /** Priority: critical, high, medium, low */
50
+ priority: z.enum(['critical', 'high', 'medium', 'low']),
51
+ });
52
+ export type TestCase = z.infer<typeof TestCaseSchema>;
53
+
54
+ /**
55
+ * Structured test plan output from the Tester
56
+ */
57
+ export const TestPlanOutputSchema = z.object({
58
+ /** What risks this test plan targets */
59
+ summary: z.string().min(1),
60
+ /** Components covered by this plan */
61
+ scope: z.array(TestScopeSchema).min(1),
62
+ /** Matrix of test cases with acceptance criteria */
63
+ testMatrix: z.array(TestCaseSchema).min(1),
64
+ /** Exact commands to execute (with cwd, purpose, required flag) */
65
+ commands: z.array(TestCommandSchema).min(1),
66
+ /** Top risks this test plan focuses on (3-7 items) */
67
+ riskFocus: z.array(z.string().min(1)).min(1),
68
+ /** What evidence (logs, reports) to capture */
69
+ evidenceRequired: z.array(z.string().min(1)).min(1),
70
+ /** Minimum verification always present: build, lint, smoke */
71
+ minimumVerification: z.array(z.string().min(1)).min(1),
72
+ /** Rationale if tester decides no custom tests are needed (min verification still applies) */
73
+ noTestsRationale: z.string().optional(),
74
+ });
75
+ export type TestPlanOutput = z.infer<typeof TestPlanOutputSchema>;
76
+
77
+ /**
78
+ * Post-run review from the Tester
79
+ */
80
+ export const TestRunReviewSchema = z.object({
81
+ /** Overall verdict */
82
+ verdict: TestVerdictSchema,
83
+ /** Summary of the review */
84
+ summary: z.string().min(1),
85
+ /** List of evidence that was checked */
86
+ evidenceReviewed: z.array(z.string().min(1)).min(1),
87
+ /** Specific failures found (empty array if PASS) */
88
+ failures: z.array(z.string()),
89
+ /** Missing evidence or coverage gaps */
90
+ gaps: z.array(z.string()),
91
+ /** Recommendations for improvement */
92
+ recommendations: z.array(z.string()),
93
+ /** Whether this verdict requires consensus (true if FAIL) */
94
+ requiresConsensus: z.boolean(),
95
+ });
96
+ export type TestRunReview = z.infer<typeof TestRunReviewSchema>;
97
+
98
+ /**
99
+ * Individual fix step in a TestFixPlan
100
+ */
101
+ export const FixStepSchema = z.object({
102
+ /** File to modify */
103
+ file: z.string().min(1),
104
+ /** Description of the change */
105
+ change: z.string().min(1),
106
+ /** Why this change is needed */
107
+ reason: z.string().min(1),
108
+ });
109
+ export type FixStep = z.infer<typeof FixStepSchema>;
110
+
111
+ /**
112
+ * Fix plan proposed by the Tester when tests fail
113
+ */
114
+ export const TestFixPlanSchema = z.object({
115
+ /** Which acceptance criteria failed */
116
+ failedCriteria: z.array(z.string().min(1)).min(1),
117
+ /** Root cause analysis from the Tester */
118
+ rootCauseAnalysis: z.string().min(1),
119
+ /** Ordered steps to fix the failures */
120
+ fixSteps: z.array(FixStepSchema).min(1),
121
+ /** Risks of introducing regressions */
122
+ regressionRisks: z.array(z.string()),
123
+ /** Strategy for re-testing after fix */
124
+ retestStrategy: z.string().min(1),
125
+ });
126
+ export type TestFixPlan = z.infer<typeof TestFixPlanSchema>;
127
+
128
+ /**
129
+ * Discovered test infrastructure for a project
130
+ */
131
+ export interface DiscoveredTestCommands {
132
+ testCmd: string | null;
133
+ lintCmd: string | null;
134
+ buildCmd: string | null;
135
+ typecheckCmd: string | null;
136
+ }