CognxSafeTrack commited on
Commit ·
4967196
1
Parent(s): 8fde072
fix(ai): implement pedagogical leap fixes, pending_remediation, coherence locks and cache wipes
Browse files
apps/api/src/services/whatsapp.ts
CHANGED
|
@@ -124,9 +124,19 @@ export class WhatsAppService {
|
|
| 124 |
const { seedDatabase } = await import('@repo/database/seed');
|
| 125 |
const result = await seedDatabase(prisma);
|
| 126 |
console.log('[SEED] Result:', result.message);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
await scheduleMessage(user.id, result.seeded
|
| 128 |
-
? "✅ Seeding terminé !
|
| 129 |
-
: "ℹ️ Les données existent déjà.
|
| 130 |
);
|
| 131 |
} catch (err: any) {
|
| 132 |
console.error('[SEED] Error:', err.message);
|
|
@@ -181,7 +191,7 @@ export class WhatsAppService {
|
|
| 181 |
} else if (action === 'CONTINUE') {
|
| 182 |
// Determine if there is a pending exercise before advancing
|
| 183 |
const pendingProgress = await prisma.userProgress.findFirst({
|
| 184 |
-
where: { userId: user.id, exerciseStatus: 'PENDING' }
|
| 185 |
});
|
| 186 |
if (pendingProgress) {
|
| 187 |
await scheduleMessage(user.id, user.language === 'WOLOF'
|
|
@@ -324,7 +334,7 @@ export class WhatsAppService {
|
|
| 324 |
|
| 325 |
// Fallback to Exercise Response if nothing else matched
|
| 326 |
const pendingProgress = await prisma.userProgress.findFirst({
|
| 327 |
-
where: { userId: user.id, exerciseStatus: 'PENDING', trackId: activeEnrollment.trackId },
|
| 328 |
});
|
| 329 |
|
| 330 |
if (pendingProgress) {
|
|
|
|
| 124 |
const { seedDatabase } = await import('@repo/database/seed');
|
| 125 |
const result = await seedDatabase(prisma);
|
| 126 |
console.log('[SEED] Result:', result.message);
|
| 127 |
+
|
| 128 |
+
// 🚨 COGNITIVE CACHE CLEAR: Delete old BusinessProfile contexts to prevent agricultural hallucinations
|
| 129 |
+
try {
|
| 130 |
+
await (prisma as any).businessProfile.deleteMany({ where: { userId: user.id } });
|
| 131 |
+
await prisma.user.update({ where: { id: user.id }, data: { activity: null } });
|
| 132 |
+
console.log(`[SEED] Cleared cognitive cache for User ${user.id}`);
|
| 133 |
+
} catch (cacheErr: any) {
|
| 134 |
+
console.error('[SEED] Failed to clear cognitive cache:', cacheErr.message);
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
await scheduleMessage(user.id, result.seeded
|
| 138 |
+
? "✅ Seeding terminé ! Le Cache Cognitif a été réinitialisé.\nEnvoie INSCRIPTION pour commencer."
|
| 139 |
+
: "ℹ️ Les données existent déjà. Cache Cognitif purgé. Envoie INSCRIPTION."
|
| 140 |
);
|
| 141 |
} catch (err: any) {
|
| 142 |
console.error('[SEED] Error:', err.message);
|
|
|
|
| 191 |
} else if (action === 'CONTINUE') {
|
| 192 |
// Determine if there is a pending exercise before advancing
|
| 193 |
const pendingProgress = await prisma.userProgress.findFirst({
|
| 194 |
+
where: { userId: user.id, exerciseStatus: { in: ['PENDING', 'PENDING_REMEDIATION'] } }
|
| 195 |
});
|
| 196 |
if (pendingProgress) {
|
| 197 |
await scheduleMessage(user.id, user.language === 'WOLOF'
|
|
|
|
| 334 |
|
| 335 |
// Fallback to Exercise Response if nothing else matched
|
| 336 |
const pendingProgress = await prisma.userProgress.findFirst({
|
| 337 |
+
where: { userId: user.id, exerciseStatus: { in: ['PENDING', 'PENDING_REMEDIATION'] }, trackId: activeEnrollment.trackId },
|
| 338 |
});
|
| 339 |
|
| 340 |
if (pendingProgress) {
|
apps/whatsapp-worker/src/index.ts
CHANGED
|
@@ -192,11 +192,11 @@ const worker = new Worker('whatsapp-queue', async (job: Job) => {
|
|
| 192 |
nextDay = currentDay;
|
| 193 |
}
|
| 194 |
|
| 195 |
-
// 🚨 Hardening: If not qualified, we
|
| 196 |
await prisma.userProgress.update({
|
| 197 |
where: { userId_trackId: { userId, trackId } },
|
| 198 |
data: {
|
| 199 |
-
exerciseStatus: '
|
| 200 |
score: { increment: 0 }
|
| 201 |
} as any
|
| 202 |
});
|
|
|
|
| 192 |
nextDay = currentDay;
|
| 193 |
}
|
| 194 |
|
| 195 |
+
// 🚨 Hardening: If not qualified, we put the user in PENDING_REMEDIATION
|
| 196 |
await prisma.userProgress.update({
|
| 197 |
where: { userId_trackId: { userId, trackId } },
|
| 198 |
data: {
|
| 199 |
+
exerciseStatus: 'PENDING_REMEDIATION', // Stay in remediation until final success
|
| 200 |
score: { increment: 0 }
|
| 201 |
} as any
|
| 202 |
});
|
apps/whatsapp-worker/src/pedagogy.ts
CHANGED
|
@@ -41,6 +41,17 @@ export async function sendLessonDay(userId: string, trackId: string, dayNumber:
|
|
| 41 |
const activeEnrollment = user.enrollments[0];
|
| 42 |
const trackTitle = activeEnrollment?.track?.title || (isWolof ? 'XAMLÉ' : 'XAMLÉ (FR)');
|
| 43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
const trackDay = await prisma.trackDay.findFirst({
|
| 45 |
where: { trackId, dayNumber }
|
| 46 |
});
|
|
|
|
| 41 |
const activeEnrollment = user.enrollments[0];
|
| 42 |
const trackTitle = activeEnrollment?.track?.title || (isWolof ? 'XAMLÉ' : 'XAMLÉ (FR)');
|
| 43 |
|
| 44 |
+
// 🚨 COHÉRENCE CHECK: Prevent jumps > 1 point
|
| 45 |
+
const currentDay = activeEnrollment?.currentDay || 1;
|
| 46 |
+
if (dayNumber - currentDay > 1) {
|
| 47 |
+
console.error(`[CRITICAL] Cohérence Error: User ${userId} attempting to jump from ${currentDay} to ${dayNumber} sans remédiation.`);
|
| 48 |
+
await sendTextMessage(user.phone, isWolof
|
| 49 |
+
? "❌ Am na luy doxul ci sa njàng mi. Lëj-lëj la, dinañu ko lijjanti."
|
| 50 |
+
: "❌ Une erreur de synchronisation a été détectée sur ton parcours (Saut > 1). L'équipe technique a été notifiée."
|
| 51 |
+
);
|
| 52 |
+
return;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
const trackDay = await prisma.trackDay.findFirst({
|
| 56 |
where: { trackId, dayNumber }
|
| 57 |
});
|
packages/database/prisma/schema.prisma
CHANGED
|
@@ -211,5 +211,6 @@ enum ExerciseType {
|
|
| 211 |
|
| 212 |
enum ExerciseStatus {
|
| 213 |
PENDING
|
|
|
|
| 214 |
COMPLETED
|
| 215 |
}
|
|
|
|
| 211 |
|
| 212 |
enum ExerciseStatus {
|
| 213 |
PENDING
|
| 214 |
+
PENDING_REMEDIATION
|
| 215 |
COMPLETED
|
| 216 |
}
|