chore: sync schema + adapt to ACTIVE→OPEN, COMPLETED→CLOSED, EXCLUDED-task

Webapp had Prisma-schema migrated: SprintStatus.ACTIVE→OPEN,
SprintStatus.COMPLETED→CLOSED, plus new SprintStatus.ARCHIVED. Also new
TaskStatus.EXCLUDED. scrum4me-mcp Prisma client was 110 commits behind,
causing runtime errors when reading sprint.status from the live DB:

  Value 'OPEN' not found in enum 'SprintStatus'

Symptom: TASK_IMPLEMENTATION jobs in QUEUED status were claimed by
tryClaimJob (raw SQL succeeds), then getFullJobContext crashed on the
findUnique with the enum error → rollbackClaim → loop forever until
UNHEALTHY (5 consecutive failures).

Fix:
- Updated vendor/scrum4me submodule to current main (3c77342).
- Re-ran sync-schema.sh → prisma/schema.prisma now has
  SprintStatus { OPEN, CLOSED, ARCHIVED, FAILED } and
  TaskStatus including EXCLUDED.
- src/lib/tasks-status-update.ts: ACTIVE→OPEN, COMPLETED→CLOSED.
- src/status.ts: TASK_DB_TO_API + TASK_API_TO_DB krijgen EXCLUDED entry.
- src/tools/get-claude-context.ts: status: 'ACTIVE' → status: 'OPEN'.

Tests: 340 passed (38 files). Typecheck OK.

Na merge + docker rebuild met cache-bust pakt de runner sprint-tasks weer
op zonder enum-error.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Madhura68 2026-05-09 13:39:13 +02:00
parent 69fabc58f6
commit 233e0ef3b6
5 changed files with 31 additions and 9 deletions

View file

@ -56,6 +56,7 @@ enum TaskStatus {
REVIEW
DONE
FAILED
EXCLUDED
}
enum LogType {
@ -70,8 +71,9 @@ enum TestStatus {
}
enum SprintStatus {
ACTIVE
COMPLETED
OPEN
CLOSED
ARCHIVED
FAILED
}
@ -159,6 +161,7 @@ model User {
claude_jobs ClaudeJob[]
claude_workers ClaudeWorker[]
started_sprint_runs SprintRun[] @relation("SprintRunStartedBy")
push_subscriptions PushSubscription[]
@@index([active_product_id])
@@map("users")
@ -297,8 +300,9 @@ model Sprint {
id String @id @default(cuid())
product Product @relation(fields: [product_id], references: [id], onDelete: Cascade)
product_id String
code String @db.VarChar(30)
sprint_goal String
status SprintStatus @default(ACTIVE)
status SprintStatus @default(OPEN)
start_date DateTime? @db.Date
end_date DateTime? @db.Date
created_at DateTime @default(now())
@ -307,6 +311,7 @@ model Sprint {
tasks Task[]
sprint_runs SprintRun[]
@@unique([product_id, code])
@@index([product_id, status])
@@map("sprints")
}
@ -625,3 +630,18 @@ model ClaudeQuestion {
@@index([status, expires_at])
@@map("claude_questions")
}
model PushSubscription {
id String @id @default(cuid())
user User @relation(fields: [user_id], references: [id], onDelete: Cascade)
user_id String
endpoint String @unique
p256dh String
auth String
user_agent String?
created_at DateTime @default(now())
last_used_at DateTime @default(now())
@@index([user_id])
@@map("push_subscriptions")
}

View file

@ -140,15 +140,15 @@ export async function propagateStatusUpwards(
let nextStatus: SprintStatus
if (anyPbiFailed) nextStatus = 'FAILED'
else if (allPbisDone) nextStatus = 'COMPLETED'
else nextStatus = 'ACTIVE'
else if (allPbisDone) nextStatus = 'CLOSED'
else nextStatus = 'OPEN'
if (nextStatus !== sprint.status) {
await tx.sprint.update({
where: { id: sprint.id },
data: {
status: nextStatus,
...(nextStatus === 'COMPLETED' ? { completed_at: new Date() } : {}),
...(nextStatus === 'CLOSED' ? { completed_at: new Date() } : {}),
},
})
sprintChanged = true
@ -162,7 +162,7 @@ export async function propagateStatusUpwards(
// 3. Story → Sprint → SprintRun.findFirst({ status: active }) (geen
// task-job, bv. handmatige task-statuswijziging via UI).
let sprintRunChanged = false
if (nextSprintStatus === 'FAILED' || nextSprintStatus === 'COMPLETED') {
if (nextSprintStatus === 'FAILED' || nextSprintStatus === 'CLOSED') {
let resolvedRunId: string | null = sprintRunId ?? null
let cancelExceptJobId: string | null = null

View file

@ -6,6 +6,7 @@ const TASK_DB_TO_API = {
REVIEW: 'review',
DONE: 'done',
FAILED: 'failed',
EXCLUDED: 'excluded',
} as const satisfies Record<TaskStatus, string>
const TASK_API_TO_DB: Record<string, TaskStatus> = {
@ -14,6 +15,7 @@ const TASK_API_TO_DB: Record<string, TaskStatus> = {
review: 'REVIEW',
done: 'DONE',
failed: 'FAILED',
excluded: 'EXCLUDED',
}
const STORY_DB_TO_API = {

View file

@ -47,7 +47,7 @@ export function registerGetClaudeContextTool(server: McpServer) {
}
const activeSprint = await prisma.sprint.findFirst({
where: { product_id, status: 'ACTIVE' },
where: { product_id, status: 'OPEN' },
orderBy: { created_at: 'desc' },
select: { id: true, sprint_goal: true, status: true },
})

2
vendor/scrum4me vendored

@ -1 +1 @@
Subproject commit 77617e89ac830bc4a86fa7d41f16a5122a1d9689
Subproject commit 3c773421dacaf506bf35a8270249822cf509ccf3