schema: add Idea + IdeaLog models, extend ClaudeJob/Question for ideas (M12 T-491)

- new enums IdeaStatus, ClaudeJobKind, IdeaLogType
- new models Idea (with @@unique([user_id, code]) + pbi_id @unique) and IdeaLog
- User.idea_code_counter Int @default(0) for IDEA-{nnn} code generation
- ClaudeJob.task_id nullable; new idea_id + kind fields + index
- ClaudeQuestion.story_id nullable; new idea_id field + index
- existing call sites narrowed to story-questions / task-jobs (idea-paths come in T-502+)
- includes the M12 plan doc copied from /Users/janpetervisser/.claude/plans

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-05-04 19:25:07 +02:00
parent 90343573f3
commit 300e426a4e
6 changed files with 508 additions and 120 deletions

View file

@ -28,6 +28,7 @@ export async function NotificationsBridge({ userId }: NotificationsBridgeProps)
status: 'open',
expires_at: { gt: new Date() },
product_id: { in: productIds },
story_id: { not: null },
},
orderBy: { created_at: 'desc' },
take: 100,
@ -44,19 +45,22 @@ export async function NotificationsBridge({ userId }: NotificationsBridgeProps)
},
})
const initial: NotificationQuestion[] = openQuestions.map((q) => ({
id: q.id,
product_id: q.product_id,
story_id: q.story_id,
task_id: q.task_id,
story_code: q.story.code,
story_title: q.story.title,
assignee_id: q.story.assignee_id,
question: q.question,
options: Array.isArray(q.options) ? (q.options as string[]) : null,
created_at: q.created_at.toISOString(),
expires_at: q.expires_at.toISOString(),
}))
const initial: NotificationQuestion[] = openQuestions.flatMap((q) => {
if (!q.story || q.story_id === null) return []
return [{
id: q.id,
product_id: q.product_id,
story_id: q.story_id,
task_id: q.task_id,
story_code: q.story.code,
story_title: q.story.title,
assignee_id: q.story.assignee_id,
question: q.question,
options: Array.isArray(q.options) ? (q.options as string[]) : null,
created_at: q.created_at.toISOString(),
expires_at: q.expires_at.toISOString(),
}]
})
return <NotificationsRealtimeMount initial={initial} />
}