Update Saqel Platform: 2026-09-12 16:23:39

This commit is contained in:
Hamza-Ayed
2026-09-12 16:23:39 +03:00
parent f4d4f02853
commit 81fa8c5dc8
9 changed files with 585 additions and 115 deletions
@@ -586,7 +586,7 @@ const LabIdentity kFinanceBudgetToolIdentity = LabIdentity(
const LabIdentity kHistoryJordanChronologyToolIdentity = LabIdentity(
toolKey: 'history_jordan_chronology',
subjectAr: 'تاريخ الأردن',
subjectAr: 'التاريخ',
lessonAr: 'التسلسل الزمني التفاعلي',
);
@@ -339,8 +339,12 @@ class Grade10LabsRegistry {
if (s.contains('وطنية') || s.contains('مدنية') || s.contains('civics')) {
return 'التربية الوطنية والمدنية';
}
if (s.contains('أردن') || s.contains('اردن')) return 'تاريخ الأردن';
if (s.contains('تاريخ') || s.contains('history')) return 'التاريخ';
if (s.contains('تاريخ') ||
s.contains('أردن') ||
s.contains('اردن') ||
s.contains('history')) {
return 'التاريخ';
}
if (s.contains('رقمية') || s.contains('حاسوب') || s.contains('digital')) {
return 'المهارات الرقمية';
}
@@ -353,7 +357,11 @@ class Grade10LabsRegistry {
final direct = bySubject(norm);
if (direct.isNotEmpty) return direct;
return all
.where((e) => e.subjectAr.contains(norm) || norm.contains(e.subjectAr))
.where((e) =>
e.subjectAr == norm ||
(norm == 'التاريخ' && (e.subjectAr == 'التاريخ' || e.subjectAr == 'تاريخ الأردن')) ||
e.subjectAr.contains(norm) ||
norm.contains(e.subjectAr))
.toList();
}
@@ -361,9 +369,14 @@ class Grade10LabsRegistry {
/// Defaults to true in development so that the reviewer/teacher can immediately test the labs.
static bool previewModeEnabled = true;
/// Exact identity lookup.
/// Exact identity lookup strictly isolated per subject.
/// When [previewModeEnabled] is active or [allowPreview] is true, returns the lab for testing.
/// When false (strict production gate), returns ONLY when released & carrying a published bundle.
///
/// CRITICAL INTEGRITY RULE:
/// Never leak labs across subjects. A Physics lab must NEVER appear under History, Geography,
/// Digital Skills, Civics, or any other subject. If a subject has no matching candidate lab,
/// this method returns null immediately.
static Grade10LabEntry? findForLesson({
required String subjectTitle,
required String lessonTitle,
@@ -372,42 +385,55 @@ class Grade10LabsRegistry {
bool? allowPreview,
}) {
final usePreview = allowPreview ?? previewModeEnabled;
final candidates = bySubjectNormalized(subjectTitle);
// Subject Isolation Gate: If no candidate labs exist for this subject, return null immediately.
if (candidates.isEmpty) {
return null;
}
if (usePreview) {
// 1. Exact match on curriculumLessonId within candidate subject labs
if (curriculumLessonId != null && curriculumLessonId.isNotEmpty) {
final exact = entryForCurriculumLessonId(curriculumLessonId);
if (exact != null) return exact;
}
if (lessonId != null && lessonId.isNotEmpty) {
for (final e in all) {
if (e.identity.curriculumLessonId.contains(lessonId) ||
e.identity.toolKey == lessonId ||
e.identity.sourceMarkdown.contains(lessonId)) {
return e;
}
}
}
final candidates = bySubjectNormalized(subjectTitle);
if (candidates.isNotEmpty) {
final t = lessonTitle.toLowerCase();
for (final c in candidates) {
if (t.contains(c.lessonAr.toLowerCase()) ||
c.lessonAr.toLowerCase().contains(t)) {
if (c.identity.curriculumLessonId == curriculumLessonId) {
return c;
}
}
if (lessonId != null && lessonId.isNotEmpty) {
for (final c in candidates) {
if (c.identity.lessonKey == lessonId ||
c.identity.curriculumLessonId.endsWith(lessonId)) {
return c;
}
}
// 2. Lesson Title fuzzy matching strictly within candidate subject labs
final t = lessonTitle.toLowerCase().trim();
for (final c in candidates) {
final ct = c.lessonAr.toLowerCase().trim();
if (t == ct || (ct.length > 4 && (t.contains(ct) || ct.contains(t)))) {
return c;
}
}
// 3. Lesson Key / Tool Key match strictly within candidate subject labs
if (lessonId != null && lessonId.isNotEmpty) {
for (final c in candidates) {
if (c.identity.lessonKey == lessonId ||
c.identity.toolKey == lessonId ||
c.identity.curriculumLessonId.endsWith(lessonId) ||
c.identity.sourceMarkdown.contains(lessonId)) {
return c;
}
}
return null;
}
return null;
}
return publishedEntryForCurriculumLessonId(curriculumLessonId ?? '');
if (curriculumLessonId != null && curriculumLessonId.isNotEmpty) {
for (final c in candidates) {
if (c.identity.curriculumLessonId == curriculumLessonId && c.identity.isPublished) {
return c;
}
}
}
return null;
}
static Grade10LabEntry? entryForCurriculumLessonId(