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.
- package/README.md +240 -32
- package/cheatsheet.md +407 -0
- package/dist/cli/commands/db.d.ts +10 -0
- package/dist/cli/commands/db.d.ts.map +1 -0
- package/dist/cli/commands/db.js +240 -0
- package/dist/cli/commands/db.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +18 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +255 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/index.d.ts +2 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +2 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +3 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/interactive.d.ts.map +1 -1
- package/dist/cli/interactive.js +96 -0
- package/dist/cli/interactive.js.map +1 -1
- package/dist/generators/admin-wizard.d.ts +25 -0
- package/dist/generators/admin-wizard.d.ts.map +1 -0
- package/dist/generators/admin-wizard.js +123 -0
- package/dist/generators/admin-wizard.js.map +1 -0
- package/dist/generators/all.d.ts.map +1 -1
- package/dist/generators/all.js +10 -3
- package/dist/generators/all.js.map +1 -1
- package/dist/generators/database.d.ts +58 -0
- package/dist/generators/database.d.ts.map +1 -0
- package/dist/generators/database.js +229 -0
- package/dist/generators/database.js.map +1 -0
- package/dist/generators/fullstack.d.ts.map +1 -1
- package/dist/generators/fullstack.js +23 -7
- package/dist/generators/fullstack.js.map +1 -1
- package/dist/generators/index.d.ts +2 -0
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +2 -0
- package/dist/generators/index.js.map +1 -1
- package/dist/generators/templates/admin-wizard-python.d.ts +32 -0
- package/dist/generators/templates/admin-wizard-python.d.ts.map +1 -0
- package/dist/generators/templates/admin-wizard-python.js +425 -0
- package/dist/generators/templates/admin-wizard-python.js.map +1 -0
- package/dist/generators/templates/admin-wizard-react.d.ts +48 -0
- package/dist/generators/templates/admin-wizard-react.d.ts.map +1 -0
- package/dist/generators/templates/admin-wizard-react.js +554 -0
- package/dist/generators/templates/admin-wizard-react.js.map +1 -0
- package/dist/generators/templates/database-docker.d.ts +23 -0
- package/dist/generators/templates/database-docker.d.ts.map +1 -0
- package/dist/generators/templates/database-docker.js +221 -0
- package/dist/generators/templates/database-docker.js.map +1 -0
- package/dist/generators/templates/database-python.d.ts +54 -0
- package/dist/generators/templates/database-python.d.ts.map +1 -0
- package/dist/generators/templates/database-python.js +723 -0
- package/dist/generators/templates/database-python.js.map +1 -0
- package/dist/generators/templates/database-typescript.d.ts +34 -0
- package/dist/generators/templates/database-typescript.d.ts.map +1 -0
- package/dist/generators/templates/database-typescript.js +232 -0
- package/dist/generators/templates/database-typescript.js.map +1 -0
- package/dist/generators/templates/fullstack.d.ts.map +1 -1
- package/dist/generators/templates/fullstack.js +29 -0
- package/dist/generators/templates/fullstack.js.map +1 -1
- package/dist/generators/templates/index.d.ts +5 -0
- package/dist/generators/templates/index.d.ts.map +1 -1
- package/dist/generators/templates/index.js +5 -0
- package/dist/generators/templates/index.js.map +1 -1
- package/dist/state/index.d.ts +10 -0
- package/dist/state/index.d.ts.map +1 -1
- package/dist/state/index.js +22 -0
- package/dist/state/index.js.map +1 -1
- package/dist/types/consensus.d.ts +3 -0
- package/dist/types/consensus.d.ts.map +1 -1
- package/dist/types/consensus.js +1 -0
- package/dist/types/consensus.js.map +1 -1
- package/dist/types/database-runtime.d.ts +86 -0
- package/dist/types/database-runtime.d.ts.map +1 -0
- package/dist/types/database-runtime.js +61 -0
- package/dist/types/database-runtime.js.map +1 -0
- package/dist/types/database.d.ts +85 -0
- package/dist/types/database.d.ts.map +1 -0
- package/dist/types/database.js +71 -0
- package/dist/types/database.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/tester.d.ts +138 -0
- package/dist/types/tester.d.ts.map +1 -0
- package/dist/types/tester.js +110 -0
- package/dist/types/tester.js.map +1 -0
- package/dist/types/workflow.d.ts +166 -0
- package/dist/types/workflow.d.ts.map +1 -1
- package/dist/types/workflow.js +14 -0
- package/dist/types/workflow.js.map +1 -1
- package/dist/workflow/db-setup-runner.d.ts +63 -0
- package/dist/workflow/db-setup-runner.d.ts.map +1 -0
- package/dist/workflow/db-setup-runner.js +336 -0
- package/dist/workflow/db-setup-runner.js.map +1 -0
- package/dist/workflow/db-state-machine.d.ts +30 -0
- package/dist/workflow/db-state-machine.d.ts.map +1 -0
- package/dist/workflow/db-state-machine.js +51 -0
- package/dist/workflow/db-state-machine.js.map +1 -0
- package/dist/workflow/execution-mode.js +2 -2
- package/dist/workflow/execution-mode.js.map +1 -1
- package/dist/workflow/index.d.ts +3 -0
- package/dist/workflow/index.d.ts.map +1 -1
- package/dist/workflow/index.js +3 -0
- package/dist/workflow/index.js.map +1 -1
- package/dist/workflow/task-workflow.d.ts +5 -0
- package/dist/workflow/task-workflow.d.ts.map +1 -1
- package/dist/workflow/task-workflow.js +172 -6
- package/dist/workflow/task-workflow.js.map +1 -1
- package/dist/workflow/tester.d.ts +120 -0
- package/dist/workflow/tester.d.ts.map +1 -0
- package/dist/workflow/tester.js +589 -0
- package/dist/workflow/tester.js.map +1 -0
- package/dist/workflow/workflow-logger.d.ts +1 -1
- package/dist/workflow/workflow-logger.d.ts.map +1 -1
- package/dist/workflow/workflow-logger.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/db.ts +281 -0
- package/src/cli/commands/doctor.ts +273 -0
- package/src/cli/commands/index.ts +2 -0
- package/src/cli/index.ts +4 -0
- package/src/cli/interactive.ts +102 -0
- package/src/generators/admin-wizard.ts +146 -0
- package/src/generators/all.ts +10 -3
- package/src/generators/database.ts +286 -0
- package/src/generators/fullstack.ts +26 -9
- package/src/generators/index.ts +12 -0
- package/src/generators/templates/admin-wizard-python.ts +431 -0
- package/src/generators/templates/admin-wizard-react.ts +560 -0
- package/src/generators/templates/database-docker.ts +227 -0
- package/src/generators/templates/database-python.ts +734 -0
- package/src/generators/templates/database-typescript.ts +238 -0
- package/src/generators/templates/fullstack.ts +29 -0
- package/src/generators/templates/index.ts +5 -0
- package/src/state/index.ts +29 -0
- package/src/types/consensus.ts +3 -0
- package/src/types/database-runtime.ts +69 -0
- package/src/types/database.ts +84 -0
- package/src/types/index.ts +50 -0
- package/src/types/tester.ts +136 -0
- package/src/types/workflow.ts +31 -0
- package/src/workflow/db-setup-runner.ts +391 -0
- package/src/workflow/db-state-machine.ts +58 -0
- package/src/workflow/execution-mode.ts +2 -2
- package/src/workflow/index.ts +3 -0
- package/src/workflow/task-workflow.ts +227 -5
- package/src/workflow/tester.ts +723 -0
- package/src/workflow/workflow-logger.ts +2 -0
- package/tests/generators/admin-wizard-orchestrator.test.ts +64 -0
- package/tests/generators/admin-wizard-templates.test.ts +366 -0
- package/tests/generators/cross-phase-integration.test.ts +383 -0
- package/tests/generators/database.test.ts +456 -0
- package/tests/generators/fe-be-db-integration.test.ts +613 -0
- package/tests/types/database-runtime.test.ts +158 -0
- package/tests/types/database.test.ts +187 -0
- package/tests/types/tester.test.ts +174 -0
- package/tests/workflow/db-setup-runner.test.ts +211 -0
- package/tests/workflow/db-state-machine.test.ts +117 -0
- 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';
|
package/src/state/index.ts
CHANGED
|
@@ -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
|
*
|
package/src/types/consensus.ts
CHANGED
|
@@ -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
|
+
};
|
package/src/types/index.ts
CHANGED
|
@@ -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
|
+
}
|