feat(#135): implement Quality Gate Configuration System

Add database-backed quality gate configuration for workspaces with
full CRUD operations and default gate seeding.

Schema:
- Add QualityGate model with workspace relation
- Support for custom commands and regex patterns
- Enable/disable and ordering support

Service:
- CRUD operations for quality gates
- findEnabled: Get ordered, enabled gates
- reorder: Bulk reorder with transaction
- seedDefaults: Seed 4 default gates
- toOrchestratorFormat: Convert to orchestrator interface

Endpoints:
- GET /workspaces/:id/quality-gates - List
- GET /workspaces/:id/quality-gates/:gateId - Get one
- POST /workspaces/:id/quality-gates - Create
- PATCH /workspaces/:id/quality-gates/:gateId - Update
- DELETE /workspaces/:id/quality-gates/:gateId - Delete
- POST /workspaces/:id/quality-gates/reorder
- POST /workspaces/:id/quality-gates/seed-defaults

Default gates: Build, Lint, Test, Coverage (85%)

Tests: 25 passing with 95.16% coverage

Fixes #135

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-31 13:33:04 -06:00
parent a25e9048be
commit 4a2909ce1e
10 changed files with 980 additions and 0 deletions

View File

@@ -215,6 +215,7 @@ model Workspace {
cronSchedules CronSchedule[]
personalities Personality[]
llmSettings WorkspaceLlmSettings?
qualityGates QualityGate[]
@@index([ownerId])
@@map("workspaces")
@@ -1003,3 +1004,29 @@ model WorkspaceLlmSettings {
@@index([defaultPersonalityId])
@@map("workspace_llm_settings")
}
// ============================================
// QUALITY GATE MODULE
// ============================================
model QualityGate {
id String @id @default(uuid()) @db.Uuid
workspaceId String @map("workspace_id") @db.Uuid
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
name String
description String?
type String // 'build' | 'lint' | 'test' | 'coverage' | 'custom'
command String?
expectedOutput String? @map("expected_output")
isRegex Boolean @default(false) @map("is_regex")
required Boolean @default(true)
order Int @default(0)
isEnabled Boolean @default(true) @map("is_enabled")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz
@@unique([workspaceId, name])
@@index([workspaceId])
@@index([workspaceId, isEnabled])
@@map("quality_gates")
}