سجل التغييرات
مُحدَّث يدويًا للموجة الأولى، بترتيب زمني عكسي. يُضاف قيد في سجل التغييرات ضمن طلب الدمج نفسه لأي تغيير في الخادم يمسّ المواصفة.
أقسام جلسة التقييم (WP-STT)، 2026-10-15
لا عملية مُضافة أو محذوفة. ثلاث استجابات في جلسة التقييم تحمل حقولًا جديدة إضافية (في الاستجابة فقط) لأزرار أقسام الطالب:
sectionsفيStartDiagnosticResponse(POST /api/diagnostic-sessions/start) وStartReDiagnosticResponse(POST /api/diagnostic-sessions/start/re-diagnostic) وDiagnosticStateResponse(GET /api/diagnostic-sessions/{id}/state): مصفوفة{ key, total }[]بترتيب النموذج، وkeyواحد منtext1أوtext2أوwordsأوspellingأوroots. تُحسب من خطة النموذج المثبّتة للجلسة. الجلسة التي ليس لها خطة نموذج تُرجع[].state.sectionKeyفي كل استجابة تحملStudentSessionState(البدء، بدء إعادة التقييم، الحالة، الاستئناف، الإجابة): قسم السؤال الحالي، أوnull.- الحقلان للعرض فقط، وليسا درجة.
«إجراء التقييم» — صفحة التقييم للمعلّم وإعادة القياس، 2026-10-14
ثلاث عمليات جديدة (من 452 إلى 455 عمليّة). الترحيلان 20261014100000_measurement_void و20261014200000_skill_snapshot_no_evidence_row. النشر: شغّل الترحيلين؛ لا شيء يُزرع أو يُنشر.
getTeacherTaqyeemGET /api/teacher/classes/{classId}/taqyeem?window=(الوسمteacher-views، والشكلTdvTaqyeem؛ للمعلّم، والصفّ من صفوفه، دون تسجيل وصول). قراءة واحدة لصفّ وفترة (إن لم تُحدَّد فالفترة الافتراضية للصفّ):windowsوwindowState(openTriggerأو null، وcanOpen) وblueprintالصفّ (statusok/not_screened/legacy_skill_cell/catalog_gapوmeasures) وsummary(enrolledوcompleteوremainingلكلّ خانة) وdayPlan(لكلّ خانة:studentCountوminutesPerStudentوtotalMinutes) وstudents[]بأربع خانات —digitalوoral_textوoral_familiar_wordsوoral_pseudowords— لكلّ منها{ status, attemptId, at, result, restarts }. قيمstatus: doneوin_progressوnot_startedوstoppedوrestarted_pendingوunavailable. أعداد فقط، بلا نسبة للصفّ، وبلا رمز دخول الصفّ. 404 لصفّ ليس من صفوف المستدعي.voidTaqyeemAttemptPOST /api/teacher/classes/{classId}/taqyeem/void(الوسمmeasurement-void؛ للمعلّم،RECORD_TEACHER_ACTION). الجسم{ kind, targetId, reason }: kinddigital_sitting/oral_text/oral_word_list، وreasonstudent_not_ready/technical_interruption/started_by_mistake/other(بلا نصّ حرّ). 201 يُعيد سطر الإعادة (academicYearوevidenceWindowهما سنة المحاولة وفترتها، وendedActiveSittingصحيح حين أُنهيت جلسة رقمية مفتوحة). المحاولة تبقى محفوظة ولا تُحتسب في القرارات والاتجاهات والقراءات؛ 404 خارج النطاق، و409 already_voided، و422 not_a_window_sitting. المحاولة البديلة تُربط بسطر الإعادة في الخادم (supersedesVoidId)؛ لا حقل جديد على العميل.getStudentReadingSheetGET /api/classes/{classId}/students/{studentId}/reading-sheet.pdf?passageId=(الوسمreading-assessment؛ لمعلّم الصفّ، والطالب مسجَّل فيه). ورقة النصّ A4 لطالب واحد بصيغةapplication/pdfدون رمز QR؛ لا تكتب دفعة ولا بندًا مخطّطًا ولا ملفًّا مخزَّنًا (تجاوز المشرف العامّ يُسجَّل في التدقيق، كما في كلّ مسارات الوحدة). 404 خارج النطاق.
أشكال تغيّرت:
getAdminAuditLogGET /api/admin/audit-log: يُضافmeasurement_voidإلىeventType(وإلىkindفي السطر)؛ وأسطر الإعادة تحمل الحقلين الاختياريّينvoidKindوvoidReason، وactorUserId= المعلّم، وtargetStudentIdوtargetClassId، والمعرّفvoid:<int>الذي يقرؤه أيضًاgetAdminAuditEventGET /api/admin/audit-log/{id}.markOrfErrorPOST /api/orf/assessments/{id}/markو**stopOrfAssessment** POST /api/orf/assessments/{id}/stop: 409جديد (السببvoided) لجلسة أُعيدت.getSkillStatusGET /api/sse/students/{id}/skill-status: adrRuleIdوssrRuleIdقابلان لأن يكونا null. يكونان null معًا (معdoNotDecideYetصحيح) فقط في سطر «لا أدلّة» الذي يُكتب حين أُعيدت كلّ محاولات الفترة؛ اقرأ المهارة حينها غير مُقيَّمة.
راجع مرجع الواجهة البرمجية للأشكال الكاملة.
حذف جداول العيّنة المجهولة، 2026-10-09
لا تغيير في الواجهة البرمجية. يحذف الترحيل 20261009220000_drop_teaser_tables الجداول teaser_item_set وteaser_session وteaser_lead والنوع TeaserSessionStatus. لم يُكتب فيها شيء منذ إيقاف العيّنة المجهولة في اليوم نفسه.
- لم يعد محو بيانات البالغين يحذف صفوف العيّنة، فلم تعد
countsتضمّ المفتاحteaser_lead. - لا يُحتفَظ بأيّ صفّ. تُحذف الصفوف التي تحمل بريدًا إلكترونيًا أو رقم واتساب مع باقي الصفوف، دون تصدير.
إيقاف دعوة تسجيل مفتاح المرور، 2026-10-09
لا عمليات جديدة ولا محذوفة (452 عمليّة). يُحذف حقلان كانا يغذّيان وحدهما دعوة تسجيل مفتاح المرور بعد الدخول، وقد أزالتها الواجهة:
MeResponse.passkey({ registered, promptSuppressed }) لم يعد يُعاد منgetMeGET /api/auth/me.passkeyPromptSuppressedيخرج منUserPreferencesResponse(GET/PATCH /api/users/me/preferences) ومنPatchUserPreferencesBody. جسم الطلب صارم، فالعميل الذي ما يزال يرسل المفتاح يتلقّى400.- ترحيل
20261009140000_drop_passkey_prompt_suppressedيحذف العمودuser_preferences.passkeyPromptSuppressed. - دون تغيير: الدخول بمفتاح المرور وإدارته (
/api/auth/webauthn/*).
إيقاف العيّنة المجهولة وإزالة بقايا العرض التجريبي، 2026-10-09
حُذفت ثلاث عمليات (الوسم teaser): postTeaserSession POST /api/teaser/sessions وpostTeaserFinish POST /api/teaser/sessions/{id}/finish وpostTeaserLead POST /api/teaser/leads تُعيد الآن 404. ينخفض الإجمالي المنشور من 455 إلى 452 عمليّة. توقّفت الصفحة الرئيسية عن عرض أداة «جرِّب سؤالًا» حين انتقل المسار ”/” إلى الصفحة الرئيسية الجديدة، ولم يعد أيّ جزء آخر يستدعي هذه المسارات.
- حُذف معها: حدّ المعدّل
teaser_startوالأمرpnpm seed:teaserودليل «واجهة برمجة العيّنة المجهولة». - لم يعد الاتحاد
UserProfileيضمّ العضوDEMO_ADMIN، ولم تعد مسارات المستخدمين تذكرDEMO_ORG_NO_OUTBOUND. لم يكن أيّ منهما قابلًا للإرجاع منذ إيقاف مستأجر العرض التجريبي في 2026-09-23. وحُذف دليل «مستأجر العرض التجريبي» كذلك. - لا ترحيلات. تبقى الجداول
teaser_item_setوteaser_sessionوteaser_leadكما هي دون كتابة جديدة إلى أن يُتّخذ قرار منفصل بشأن صفوفها. ما يزال محو بيانات البالغين يحذف صفّteaser_leadالذي يحمل عنوان الشخص.
قوائم الكلمات — القوائم الشفويّة لكلّ صفّ وفترة، 2026-10-08
ثماني عمليات جديدة (الوسم admin-word-lists؛ لمشرف النظام العامّ فقط؛ كلّ نداء يكتب سجلّ التجاوز audit_event). لا ترحيلات.
listAdminWordListsGET /api/admin/word-lists?organizationId=— كلّ القوائم في النطاق (العامّة وحدها بلا معامل؛ العامّة + المؤسّسة عند تسميتها)، بكلّ الحالات والإصدارات معassessmentsCount؛ وcells= كلّ (صفّ × مهارة × فترة) تُقاس بحسب قواعد الصفّ، معmin/maxوpickedListId(القائمة التي يُقدَّم بها معلّم هذا النطاق: قائمة الفترة أوّلًا ثمّ «ALL»؛ قائمة المؤسّسة قبل العامّة؛ ثمّ أحدث إصدار)؛ وskillsبتسمياتها للمعلّم.getAdminWordListGET /api/admin/word-lists/{id}— القائمة معversions(المعرّف نفسه، النطاق نفسه).validateAdminWordListPOST /api/admin/word-lists/validate— فحص جافّ بقواعد الاستيراد نفسها (validateWordList+ فحص التكرار والتقاطع بين الصفوف، صارcheckWordListAgainstScope):{ ok, reject?, warnings }بلا كتابة.createAdminWordListPOST /api/admin/word-lists— الإصدار 1 مسوّدة؛publish(افتراضيًّا true) يجعلها مفعّلة في المعاملة نفسها.422بشكل الفحص عند الرفض؛409 external_id_taken.patchAdminWordListPATCH /api/admin/word-lists/{id}— المسوّدة في مكانها؛ القائمة المفعّلة → إصدار جديد مفعّل مع إيقاف المصدر؛ الموقوفة → مسوّدة جديدة.ifVersion→412 stale. الردّ يحملmadeVersion.publishAdminWordList/retireAdminWordList/restoreAdminWordListPOST /api/admin/word-lists/{id}/publish|retire|restore—409 invalid_state | newer_version_operational | another_version_operational؛ الإيقاف يعيدleavesCellEmpty.- تغيير:
pickListsForWindow(قراءة المعلّمGET /api/word-lists) يقدّم قائمة المؤسّسة على العامّة عند تساوي رتبة الفترة. وDTO المشرف يحملreadingNoteAr، ملاحظة قاعدة القراءة التي يراها المعلّم.
بناء التقييم — معاينة الجلسة وتعديلها لكلّ مؤسّسة ومدرسة، 2026-10-08
عمليتان جديدتان (GET /api/admin/taqyeem/preview وPUT /api/admin/taqyeem/forms/{formId}/positions؛ الوسم admin-taqyeem؛ لمشرف النظام العامّ فقط). لا ترحيلات.
previewTaqyeem(organizationIdإلزامي،schoolId?،grade1–4،windowBOY|MOY|EOY): الجلسة التي يجلس لها طالب يسيّرها لأوّل مرّة في هذا النطاق — الخليّة بمصدرها (global | org | school) ونوعها (measures | skills | not_screened | unset)، وخطّة الجلسة نفسها التي يبنيها بدء الجلسة (النموذج المختار، ترتيب الأسئلة بـformPosition، موضع الاستراحة،configReleaseId)، وكلّ سؤال بالإسقاط نفسه الذي يُرسَل للطالب (ServedItem) مع كتلةauthoring(الإجابة الصحيحة) وmeta(organizationId،updatedAtلـ If-Match، المقياس، الموضع)، والقطع، والمقاييس بأعدادها، وwarnings(no_operational_form،invalid_cellبسببbuildMeasurePlanحرفيًا،provisional_scoring_table،legacy_cell،thin_pool،alternate_form،not_screened،unset). لا يكتب شيئًا سوى سجلّ تجاوز المشرف (audit_event)؛Cache-Control: no-store. ترتيب الخيارات في المعاينة بمفتاح ثابت (taqyeem-preview) فيختلف عمّا يراه طالب بعينه؛ الأسئلة وتسلسلها متطابقان.moveTaqyeemFormPositions(الجسم{ moves: [{ itemId, formPosition, ifMatch }] }، 1–60): إعادة ترتيب أسئلة النموذج داخل المقياس نفسه (تبديل مواضع المجموعة نفسها فقط)، بمعاملة واحدة عبر مسار تعديل المحتوى نفسه (item_revisionلكلّ سؤال منقول، الصورة السابقة{ formPosition }).412 staleلسؤال تغيّر منذ القراءة،409 concurrent_move،422 not_a_permutation | cross_measure | item_not_in_form،404نموذج خارج النطاق. الرابط الوسيط إيجابي (formPosition + 1000000) لأنّ قيدitem_bank_content_role_fieldsيمنع الموضع السالب.- لا تغيير في
PATCH /api/items/{id}ولا في مخطّط التقييم الأوّلي؛ الصفحة تستخدمهما كما هما. تغيير داخلي:servedItem/authoringItemانتقلا إلىitems/served-projection.tsبلا تغيير في الإخراج.
رابط دخول الصف صالح سنة كاملة، 2026-10-06
لا عملية جديدة ولا تغيير في الشكل. صار loginCodeExpiresAt في GET /api/classes وPOST /api/classes
وGET /api/classes/{classId}/login-cards وPOST /api/classes/{classId}/login-code/rotate يقع بعد 365 يومًا من إصدار
الرمز أو تجديده (كان 30)، فيبقى الرابط المدفوع إلى أجهزة المختبر صالحًا طوال العام الدراسي. إنشاء الصف واستيراد القوائم
والانتقال إلى السنة التالية تضبط تاريخ الانتهاء من الثابت نفسه الذي يستخدمه التجديد. الترحيل
20261006100000_class_code_ttl_365_days يمنح الرمز الحالي لكلّ صف فعّال في السنة الدراسية النشطة لمؤسسته سنة كاملة من
تاريخ النشر، ويجعل القيمة الافتراضية للعمود 365 يومًا. أما الرمز الذي استُبدل بتجديد، والصف المحذوف، وصف سنة مغلقة، فتبقى
على تاريخ انتهائها القديم، فيظلّ الرابط القديم إليها يعيد 410. ما زال المعلّم يجدّد الرابط يدويًا إذا تسرّب، وتعرض لوحة المعلّم
الآن تاريخ الانتهاء ما دام أبعد من 30 يومًا.
رمز الطالب من رقمين ودائم؛ ورمز الصف ينتهي، 2026-10-04
عملية جديدة واحدة وعدّة عمليات تتغيّر في شكلها (جديد POST /api/classes/{classId}/login-code/rotate؛ وتتغيّر POST /api/auth/student/quickcode وGET /api/auth/student/class-preview وGET /api/classes وGET /api/classes/{classId}/login-cards وأجسام طلب رمز الطالب واستجابته).
- رمز الطالب. صار
quickCodeرقمين، من 01 إلى 99، فريدًا بين طلاب الصف الفعّالين (يتّسع الصف لـ 99 طالبًا كحدّ أقصى) ولا ينتهي أبدًا. لم يعدquickCodeExpiresAtيُعاد أو يُكتب. والرمز نفسه هو كلمة مرور الدخول المنزلي. حُوِّل كلّ الطلاب الحاليين بسكربت لمرة واحدة (convert:student-codes-2-digit)؛ ويجب إعادة طباعة كلّ البطاقات المطبوعة. - رمز الصف. يحمل
Class.loginCodeالآنloginCodeExpiresAt(30 يومًا؛ يضيفهClassResponseواستجابة بطاقات الدخول).POST /api/classes/{classId}/login-code/rotate(rotateClassLoginCode؛ الجسم{ onlyIfExpired? }؛ الصلاحيةMANAGE_CLASS_STUDENTSأوMANAGE_ORG؛ 10 تجديدات كلّ 15 دقيقة للمستخدم) يصدر رمزًا جديدًا بمدّة جديدة وينهي الرابط القديم فورًا؛ ويكتب كلّ تجديد سجلًا فيAuthEventLogمن النوعclass_login_code_rotated(detail:manualأوexpired_on_copy). وonlyIfExpiredهو التجديد التلقائي عند النسخ، ولا يفعل شيئًا إذا كان الرمز ساريًا. - الدخول. يُرفض رمز الصف المنتهي كالرمز المجهول (
401 QUICKCODE_INVALID_OR_EXPIRED). وGET /api/auth/student/class-previewيجيب410 CLASS_CODE_EXPIRED، وتعرض صفحة الطالب «انتهى هذا الرابط، اطلب الرابط الجديد من معلّمك». وصيغةclassIdالمباشرة لدخول الطالب مرفوضة في الإنتاج. وصار قفل الدخول المنزلي وللبالغين 10 محاولات فاشلة كلّ 15 دقيقة (كان 5).
تجربة المعلّمة الجديدة — الإصدار الأوّل، 2026-10-01
لا عملية جديدة؛ تتغيّر واحدة في سلوكها.
- المفتاح. يُنشر الإصدار بـ
TEACHER_V3_ORGS="*"، فتعيدGET /api/auth/meالقيمةfeatures.teacherV3: trueلكلّ معلّم في كلّ مؤسسة. لا تغيير في العقد؛ القيمة""هي الرجوع خلال هذا الإصدار. - تقرير وليّ الأمر. حين يطلب معلّمٌ
POST /api/parent/pdf/{childId}يُكتب سطر واحد فيstudent_data_access_log(export_pdf، طالب واحد، دون معرّفه) قبل الملفّ؛ وإن تعذّرت الكتابة يُعاد500«Export could not be recorded» دون ملفّ. وليّ الأمر والمسؤول لا يكتبان شيئًا. - التفضيلات. يقرأ تطبيق الويب
GET /api/users/me/preferencesمرّة عند بدء الجلسة لكلّ الأدوار البالغة، ويُعيد التباين وخطّ القراءة إلى إعداد الجهاز عند الخروج. لا تغيير في العقد.
يوم التدريب، 2026-10-01
عملية جديدة واحدة؛ وتتغيّر خمس (الجديدة GET /api/practice/students/{studentId}/training-sessions/{trainingSessionId}؛ وتتغيّر GET /api/practice/students/{studentId}/training-sessions وGET /api/reports/students/{id}/sessions/{kind}/{sessionId} وGET /api/practice/queues/current/next-item وPOST /api/practice/queues/current/submit-response وGET /api/practice/queues/current/state؛ أُعيد توليد openapi:check، 394 مسارًا). الترحيلات 20261001310000 و20261001310100. النشر: نفّذ الترحيلات، ثمّ config:publish، ثمّ حوّل الحركة، ثمّ seed-main. تكتب الترحيلات أيضًا قواعد اليوم وقواعد الخطوات المساعدة الـ19 وأعمدة الخطوات المساعدة في سياسات المستويات، فيعمل يوم التدريب قبل تنفيذ البذرة.
- يوم التدريب. يُخطَّط يوم قائمة التدريب بالمستويات مرّة واحدة حين يُفتح (أوّل طلب للسؤال التالي أو أوّل إجابة في اليوم المدرسي)، ويُحفظ مع إصدار الإعدادات وتوقيت المدرسة: أهداف اليوم (هدف واحد افتراضيًا يُختار بالتناوب، وثانٍ فقط لإكمال اليوم)، وعدد الأسئلة (3 تمارين × 4، ولا يزيد أبدًا على ما يستطيع مستوى الطالب تقديمه)، وحصّة الخطوات المساعدة، وسؤال ختام واحد، وحدّ 17 دقيقة من الوقت الفعلي. الأعداد في صفّ
engine_parametersالمسمّىtraining_session_rulesوفي صفوفtraining_level_policy(مؤقّتة). تاريخ التدريب هو اليوم المحلّي للمدرسة (Asia/Amman للأردن، وAsia/Hebron لفلسطين). - الأسئلة الباقية. صار
AssignTrainingResponse.itemCount(الإرسال) و«الأسئلة الباقية» للطالب يعدّان كل أهداف التدريب في القائمة، كل سؤال مرّة واحدة، ومعه سؤال ينتظر محاولته الثانية. لا تغيير في الشكل. - قائمة أيّام التدريب. تضيف صفوف
GET /api/practice/students/{studentId}/training-sessionsالحقلid(معرّف اليوم)، وtargets(skillIdوskillLabelArوlevelNumberوlevelNameArلكل هدف مخطّط، بترتيب الخطّة، في المستوى الذي فُتح عليه اليوم)، وsupportSteps(الخطوات المساعدة التي ظهرت في ذلك اليوم)، وexitDone(أُجيب عن سؤال الختام)، وansweredCount(عدد الأسئلة التي أجاب عنها في ذلك اليوم: أسئلة التدريب وسؤال الختام، سؤالًا سؤالًا، بلا إجابات الخطوات المساعدة). الأربعة null في يوم فُتح قبل مستويات التدريب. - يوم تدريب واحد. يعيد
GET /api/practice/students/{studentId}/training-sessions/{trainingSessionId}(getStudentTrainingDay) الحقولidوdateوtimeZoneوleveledوplannedExercisesوquestionsPerExerciseوtargets(لكل هدفquestionsAnsweredوfirstTryCorrectوsecondTriesوhintedAnswersوsupportAnswers) وsupportSteps(idوالهدف ومستواه وsupportSkillsوfiredAtوansweredوcorrect، من الأقدم) وexit(plannedوansweredوcorrect، أو null) وendedوendReason(doneأوcapأوwindow_closed، وnull ما دام اليوم مفتوحًا) وfeedbackوfeedbackAt. الوصول: معلّمة أحد صفوف الطالب أو مالكة مجموعة دعم هو فيها؛ وفريق العمل على مستوى المؤسسة. اليوم المجهول أو يوم طالب آخر أو الطالب من خارج مؤسسة المستدعي404؛ والطالب من المؤسسة الذي لا تدرّسه المعلّمة403؛ وtrainingSessionIdالذي ليس uuid422. - تفاصيل الجلسة. يضيف
GET /api/reports/students/{id}/sessions/{kind}/{sessionId}الحقلtrainingGroupsفي قائمة تدريب بالمستويات: الإجابات مجمّعة حسب هدف التدريب (targetSkillIdوtargetLabelArوlevelNameAr: مستوى أحدث إجابة في الهدف)، ثمّ حسبrole(ordinaryوretryوsupportوexit، ولكلٍّlabelArوansweredوcorrect). إجابة الخطوة المساعدة تبقى تحت الهدف الذي ساعدت عليه؛ ومهارتها لا تكون أبدًا صفًّا فيskills. null في كل جلسة أخرى. - ردود التدريب. تضيف ردود السؤال التالي والإجابة والحالة الحقل
step(kindبقيمةtargetأوbridgeأوexit؛ وstartsBridge؛ وstrategyPromptArأو null). ويضيفhintفي ردّ الإجابة الحقلkind(itemأوlight_hintأوclearer_hintأوgeneric)، ويضيف ردّ الإجابةexplanation({ textAr }بعد الخطأ الثاني، أو null). ويضيفtrainingالحقلينphase(practiceأوexitأوdone) وexit(plannedوdone). لا يحمل أيّ ردّ للطالب مستوى التدريب ولا اسمه ولا نمط السؤال ولا رمز القاعدة ولا المهارة الداعمة ولا صنف الترتيب. - الخطوات المساعدة. حين يخطئ الطالب في سؤالين مختلفين من المقياس والنمط نفسيهما في يوم واحد، يحصل على خطوة مساعدة قصيرة من جدول
training_bridge_rule(19 صفًّا، تُفحص عند النشر)، ثمّ يعود إلى هدفه. لا خطوات في المستويين 3 و4، وخطوة واحدة في كل مرّة، ضمن حصّة اليوم. كل خطوة تظهر تُسجَّل صفًّا لا يُعدَّل فيtraining_bridge_episode، ومعها جملة مقدّمتها (يعرضstrategyPromptArتلك الجملة نفسها). إجابات الخطوات المساعدة لا تغيّر المستوى أبدًا، ولا تُحسب في أسئلة اليوم ولا في سؤال الختام، ولا تطلق تنبيه تدريب، ولا تكتب دليلًا ولا حالة. - قوائم تدريب المكتبة. قائمة التدريب من مكتبة الجلسات التي فيها عدّة مهارات فرعية صارت تقدّم كل مهاراتها، لا الأولى فقط.
- تطبيق الويب. يرى الطالب مقدّمة قصيرة قبل الخطوة المساعدة، وتلميحًا أوضح، وشرحًا قصيرًا بعد الخطأ الثاني، و«السؤال الأخير» في شريط الخطوات؛ وأُزيل سؤال المزاج في نهاية الجلسة. وتعرض بطاقة «التدريب» للمعلّمة مهارات كل يوم ومستوياتها، وعدد الأسئلة المُجابة («أجاب عن n سؤالًا»)، و«خطوات مساعدة: n» و«سؤال الختام ✓»، وتجمع تفاصيل الجلسة يوم التدريب حسب الهدف بعنوان «المهارة · المستوى». ثلاث عبارات جديدة للطالب تحتاج تسجيلًا (
bridge-introوlast-questionوback-to-training).
مستويات التدريب وتنبيهات التدريب، 2026-10-01
ثلاث عمليات جديدة؛ وتتغيّر ثلاث (الجديدة GET /api/training/students/{studentId}/levels وGET /api/training/alerts وPOST /api/training/alerts/{alertId}/acknowledge، بالوسم training-progress؛ وتتغيّر GET /api/reports/students/{id}/sub-skill-report وGET /api/reports/students/{id}/session-results وGET /api/reports/students/{id}/sessions/{kind}/{sessionId}؛ أُعيد توليد openapi:check، 393 مسارًا). الترحيلات 20261001300000 و20261001300100 و20261001300200. النشر: نفّذ الترحيلات، ثمّ config:publish، ثمّ حوّل الحركة، ثمّ seed-main. تكتب الترحيلات صفوف القواعد أيضًا، فيعمل التدريب قبل تنفيذ البذرة.
- مستويات التدريب. صار إرسال المعلّمة «تدريب» يبذر قائمة تدريب بالمستويات: يتدرّب الطالب على كل هدف (مقياس رقمي بمهارته الحاملة، أو مهارة منفردة) في مستوى من جدول
training_level(1 تأسيس، 2 تعزيز، 3 تطبيق، 4 إثراء). يبدأ المستوى من أحدث تقييم هذا العام الدراسي (أو من فحص أعمق اكتمل بعده)، ويصعد بعد 80 % صحيحة على الأقل من آخر 8 إجابات محسوبة في يومَي تدريب مختلفين على الأقل، وينزل بعد كتلتين مغلقتين متتاليتين من 8 إجابات كلّ منهما دون 60 %. الإجابة المحسوبة محاولة أولى مستقلّة بلا تلميح، غير مستبعدة وغير سريعة جدًّا. لا يصل شيء عن المستويات إلى واجهة الطالب البرمجية. الأعداد في صفّengine_parametersالمسمّىtraining_progression(مؤقّتة)؛ وleveledTrainingEnabled: falseيُبقي القوائم الجديدة على مسار المستويات القديم (band). - المستويات. يعيد
GET /api/training/students/{studentId}/levelsالقيمة{ studentId, academicYear, levels }. في كل صفّskillIdوskillLabelArوmeasureCodeوlevel(numberوnameAr) وsince(يوم مدرسيYYYY-MM-DD) وstartedFrom(screenأوexperience_typeأوbacktrack) وlastMove(directionبقيمةupأوdownأوrebaseline، وat، وfromLevel) أو null، وopenAlerts(alertIdوkindوacknowledged). تبقى القائمة فارغة حتى يبدأ إرسالٌ التدريبَ بالمستويات. الطالب الذي لا يصل إليه المستدعي404؛ والدور الذي لا يملكVIEW_OWN_CLASSESولاRUN_BACKOFFICE403. - التنبيهات. يأخذ
GET /api/training/alertsواحدًا فقط منclassIdأوgroupId(وإلا422 VALIDATION_ERROR) وstatus(openافتراضيًا، أوall). الصفوف من الأحدث، على طلاب النطاق الحاليين:alertIdوstudentIdوfullNameArوskillIdوskillLabelArوmeasureCodeوlevelNumberوlevelNameArوkindوtitleArوmessageArوraisedAtوacknowledgedAtوstatus(openأوacknowledgedأوresolved) وevidence(sessionsبالتاريخ وعدد الإجابات المحسوبة والصحيحة؛ وdaysAtLevel). قيمةkindإمّاno_progress_at_level(آخر 3 أيام تدريب منتهية في المستوى، في كلّ منها 3 إجابات محسوبة على الأقل، كلّها دون 60 %) وإمّاsupport_review_suggested(21 يومًا في المستوى 1 مع 3 أيام تدريب على الأقل، اقتراح فقط). يُغلق التنبيه حين يتغيّر المستوى. النطاق المجهول أو التابع لمؤسسة أخرى404؛ والصفّ الذي لا تدرّسه المعلّمة أو المجموعة التي لا تملكها403 NOT_CLASS_TEACHER. - الاطّلاع. يعيد
POST /api/training/alerts/{alertId}/acknowledgeالقيمة{ alertId, acknowledgedAt }ويسجّل من اطّلع على التنبيه، مرّة واحدة. لا يغيّر شيئًا آخر: يبقى التنبيه مفتوحًا، ويبقى المستوى، ولا يُكتب حدث إتقان.409معreasonبقيمةalready_resolved(تُفحص أوّلًا) أوalready_acknowledged؛ و403حين لم تعد المعلّمة تصل إلى الطالب؛ و404للتنبيه المجهول أو التابع لمؤسسة أخرى. - مستوى التدريب في التقرير. يضيف
MeasureResult.trainingLevel(فيperSkillStatus[].measureوdiagnostic[].measureوmeasuresفي تفاصيل الجلسة) الحقلsource:trainingهو مستوى الطالب المحفوظ الآن لتلك المهارة الحاملة في العام الدراسي للصفّ، وscreenهو المستوى الذي يبدأ منه التدريب حسب التقييم حين لم يبدأ التدريب بعد. - الإشعارات. نوعان جديدان،
training_no_progressوtraining_support_review_suggested(action_required، لمعلّمات صفّ الطالب، ويُحفظان 30 يومًا)، معsourceEntityTypeبقيمةtraining_progress_alertومعرّف التنبيه فيsourceEntityId. تحمل الحمولةstudentId(معرّف مستخدم الطالب نصًّا رقميًا، وكذلك الآن فيskill_alert_assignedوstudent_alert_assigned) وclassIdوstudentNameوalertIdوskillIdوskillLabelArوlevelNumberوlevelNameAr، وdaysAtLevelفي اقتراح المراجعة. عمليات قائمة الإشعارات كما هي. - التدريب. يحصل السؤال الذي يُعرض مرّة أخرى على محاولتيه الخاصّتين (قاعدة المحاولتين لكل عرض، لا لكل قائمة). وتأتي قطوع المستويات القديمة (band) من صفّ
practice_band_routingبالقيم نفسها، ولم تعد قائمة التدريب القديمة تعرض أسئلة نماذج التقييم ولا أسئلة الجسور. - تطبيق الويب. تعرض صفحة الطالب بطاقة «مستويات التدريب»، وتعرض صفحة التنبيهات «تنبيهات التدريب» مع «اطّلعت»، ويفتح نوعا الإشعار مستويات تدريب الطالب، ويقول سطر المقياس هل مستوى التدريب «حسب التدريب الحالي» أم «حسب نتيجة التقييم». انظر استخدام المنصّة: المعلّم.
قوائم الكلمات الموقوتة ومستوى القراءة الجهرية في الصفّ الثاني، 2026-10-01
عملية جديدة واحدة؛ تتغيّر أربع (الجديدة GET /api/word-lists/{id}/sheet.pdf؛ وتتغيّر GET /api/word-lists وPOST /api/word-lists/assessments وPOST /api/orf/assessments/{id}/stop وGET /api/orf/assessments/{id}؛ أُعيد توليد openapi:check، 390 مسارًا). الترحيلان 20261001400000 (تعبئة بيانات لمرّة واحدة) و20261001410000. النشر: نفّذ الترحيلين، ثمّ config:publish، ثمّ حوّل الحركة، ثمّ seed-main (توقيت القوائم يأتي من البذرة وحدها؛ وحتى تنفيذها تبقى القوائم غير موقوتة ولا يتعطّل شيء)، ثمّ أعد تنفيذ عبارات التعبئة مرّة أخرى للجلسات التي أُنهيت أثناء التحويل.
- قوائم موقوتة. تُقرأ قائمة الكلمات للمدّة التي يسمّيها إعدادها (60 ثانية للقائمتين حاليًا). للقائمة الموقوتة يأخذ
POST /api/word-lists/assessmentsالحقلlast_word_index(يبدأ من 0، آخر كلمة وصل إليها الطالب) والحقلelapsed_seconds(من 1 حتى المدّة)؛ والقائمة غير الموقوتة ترفضlast_word_index. الكلمات المحاوَلة هي آخر كلمة زائد واحد، وتُهمل العلامات بعدها، والكلمات الصحيحة في الدقيقة تُحسب على الثواني الفعلية، فالطالب الذي ينهي مبكرًا يُقاس على الزمن الذي قرأ فيه. - الاستجابة. تضيف
timedوerrorsوwcpmوlastWordIndexوelapsedSecondsوaccuracyBandوrateBandوbandBasis(accuracyأوrateأوlower_of) وprovisional. صارbandقابلًا لأن يكون null: تُصنَّف الدقّة والسرعة كلّ منهما وفق جدول قطع القراءة الجهرية، ويحدّد الأساس المُعَدّ قيمةbandالواحدة، والقطع الفارغ يسجّل القراءة بلا مستوى (projection.skippedReason: not_banded؛ ولا يدخل شيء في صورة المهارات). لا يُرجع إلى الحدود المُعَدّة إلا حين يغيب صفّ الدقّة كلّه. - الرفض (
422، ولا يُكتب شيء):word_list_timing_requiredوword_list_elapsed_exceeds_durationوword_list_last_word_out_of_rangeوword_list_not_timedوword_list_grade_mismatch، والجديدword_list_window_mismatch(القائمة تخصّ نافذة تقييم واحدة والقراءة ستُحفظ تحت نافذة أخرى). - اختيار القائمة. يأخذ
GET /api/word-listsالحقلstudentIdفيعيد قوائم نافذة هذا الطالب وحدها (قوائم تلك النافذة أوّلًا، ثمّ القوائم الصالحة لكلّ النوافذ)؛ و404أو403حين يكون الطالب خارج النطاق. تضيف كلّ قائمةtiming(timedوdurationSeconds) وwordsPerRow(5 حين لا تسمّي القائمة عددًا) وassessmentWindow. - ورقة الطالب. يعيد
GET /api/word-lists/{id}/sheet.pdfورقة A4 التي يقرأ منها الطالب: الكلمات في صفوف شبكة التصحيح نفسها، من اليمين إلى اليسار، بلا أرقام. اسم الملف ASCII فيfilenameوعربي فيfilename*. والنصّ المطبوع الذي لا يجتاز مرشّح اللغة يُجاب بـ422معreason: language_safety_blocked. - لماذا ينطبق مستوى القراءة الجهرية. يضيف
POST /api/orf/assessments/{id}/stopالحقلrateCut(appliedأوwithheld_in_windowأوno_norm، ولا يغيب أبدًا) والحقلprovisional. تعنيwithheld_in_windowأنّ النافذة تسجّل السرعة بلا قطع، وأنّ المستوى هو مستوى الدقّة (projection.accuracyBand)؛ وهذا اليوم هو الصفّ الثاني في بداية العام ومنتصفه. ويضيفGET /api/orf/assessments/{id}الحقلrateCut(null حتى الإنهاء) وaccuracyBandوprovisional. الثلاثة هي ما سجّله الإنهاء، فلا يغيّر أيّ تعديل لاحق في الإعدادات وصف جلسة قديمة. - ملخّصات الطلاقة تحتسب الجلسات الفورية. صار الإنهاء يكتب صفَّي
cbm_scoresتحت النافذة التي حدّدها البدء، مع الصفّ الذي حُدّد له القطع، فتحتسبهما ملخّصات الطلاقة للمدرسة وللصفّ التي تقرأ حسب النافذة. ويملأ ترحيل التعبئة نافذة الصفوف السابقة من الأدلّة التي سجّلها الإنهاء نفسه. والجلسة غير المرتبطة بمهارة تسجّل قراءتها على الجلسة وحدها ولا تكتب صفًّا فيcbm_scores(كان إنهاؤها يفشل).
مجال فيه مهارة ضعيفة واحدة بين مهارات مقيسة قليلة، 2026-10-01
لا عمليات جديدة؛ أشكال الاستجابة كما هي. صفوف القاعدة تأتي من البذرة وحدها: نفّذ seed-main ثمّ config:publish بعد النشر.
- مجال التقييم الذي قيست فيه مهارات قليلة (أربع على الأكثر) وثبت ضعف واحدة منها فقط صار يُقرأ
isolated_skill_needعبر القاعدة المؤقّتةDDR-PRV-01(الحدّDTH-PRV-01)، حيث لم تنطبق قبلها أيّ قاعدة من قواعد الشريكة فبقي المجال بلا حالة. وثغرة القواعد في مجال واحد صارت تؤجّل ذلك المجال وحده، لا الجلسة كلّها. تبقى القاعدة مؤقّتة حتى تجيب الشريكة عنQ-SSE-DDR-SOLE-1.
التقييم بالمقاييس: نموذج واحد ومستوى لكل مقياس، 2026-10-01
لا عمليات جديدة؛ تتغيّر إحدى عشرة (عمليات /api/admin/diagnostic-blueprint الأربع، وPOST /api/diagnostic-sessions/start وPOST /api/diagnostic-sessions/start/re-diagnostic وGET /api/reports/students/{id}/sub-skill-report وGET /api/reports/students/{id}/session-results وGET /api/reports/students/{id}/sessions/{kind}/{sessionId} وGET /api/parent/children/{childId}/growth وPOST /api/admin/delivery/dry-run-replay؛ أُعيد توليد openapi:check). الترحيلات 20261001210000 و20261001211000 و20261001220000. النشر: شغّل الترحيلات، ثم seed-main (جداول الدرجات وقواعد المستويات وأربع قواعد لغوية تأتي من البذرة فقط) وconfig:publish.
- خلايا المقاييس. يقبل
PUT /api/admin/diagnostic-blueprint/{grade}/{cycle}الحقلmeasures(رموز مقاييس التقييم بترتيب العرض) بدلsubSkillIds؛ أرسل واحدًا منهما فقط. تُشتقّsubSkillIdsللخليّة من المهارات الحاملة للمقاييس. أسباب422:duplicate_measureوmeasure_not_in_gradeوno_digital_measureوcarrier_conflictوcatalog_gap. الخليّة التي لا يخدم مقاييسها أي نموذج تقييم معتمد تُنشر معmeasureWarnings(no_operational_form)، أو تُرفض422 no_operational_formمعstrict: true. والمقياس الذي يُصحَّح بجدول مؤقّت يحتاجacknowledgeProvisional: true(وإلا422 provisional_scoring_table)، ويُرفض على المستوى العام422 provisional_not_publishable_globally. تحمل الخلاياmeasures(فارغ لخليّة المهارات) وprovisional؛ ويضيف GET الحقلينmeasureOptionsوforms؛ وتحمل صفوف السجلّmeasures. - الجلسة. جلسة خليّة المقاييس تعرض نموذج تقييم واحدًا بترتيبه، بحدّ الوقت الخاص بالصف، وفي الصفين الثالث والرابع
breakBefore: trueبعد آخر سؤال على القطعة (ويبقيها/stateو/resumeحتى الإجابة التالية). إن لم يوجد نموذج معتمد:firstItemId: nullمعreason: no_screening_form. وبداية إعادة التقييم تعيدreasonنفسه، وفي نافذة المقاييس تعيد الخليّة كلّها. - جسم إعادة التقييم. لم يعد
POST /api/diagnostic-sessions/start/re-diagnosticيشترطsubSkillIds. نافذة المقاييس تتجاهل الحقل وتعيد الخليّة كلّها، ونافذة المهارات من دونه تردّ422 sub_skills_required. - التقارير. مخطّط جديد
MeasureResult(labelArوrawوmaxوcompleteوincompleteReasonمعincompleteReasonArوlevelوtrainingLevelوprovisionalوsessionId). يحملهperSkillStatus[].measureفي تقرير الطالب وdiagnostic[].measureفي نتائج الجلسات على صف المهارة الحاملة للمقياس (فارغ على صف المهارة). وتضيف بطاقةREAD_COMPالحقلcomposite(MeasureComposite، درجة الفهم من 12 للاطّلاع فقط، لا تدخل أي تجميع). وتضيف تفاصيل الجلسةmeasures، لكلّ منهاitems(MeasureItemReview: الترتيب والنمط والمهارة وصحّ أو خطأ وإجابة الطفل)، دون نص السؤال ولا الإجابة الصحيحة أبدًا. - الأهل. يضيف
GET /api/parent/children/{childId}/growthالحقلmeasures: [{ labelAr, statusLabel }](ParentMeasureDTO): المقاييس المكتملة من آخر تقييم، لكلّ منها إحدى أربع عبارات، بلا أرقام ولا رموز. ويطبع ملف PDF للأهل الأسطر نفسها. - الإعادة التجريبية. يقبل
POST /api/admin/delivery/dry-run-replayالحقلينpinnedItemBankIdوformServeلإعادة عرض سؤال من نموذج تقييم.
استيراد محتوى الشريكة، 2026-10-01
لا عمليات جديدة؛ تتغيّر سبع (POST /api/items/import وGET /api/items/import وGET /api/items/import/{batchId} وPOST /api/items/import/{batchId}/approve وGET /api/items وGET /api/items/{id} وPOST /api/orf/assessments/{id}/stop؛ أُعيد توليد openapi:check). الترحيلات من 20261001200000 إلى 20261001200800. النشر: شغّل الترحيلات، ثم seed-main (صفوف الإعداد الجديدة تأتي من البذرة فقط) وconfig:publish.
contentKindعند الاستيراد. يقبلPOST /api/items/importالحقلcontentKind:item(الافتراضي)؛ وcontent_bundle، دفعة تدريب أو جسر{ passages, items }تمرّ ببوابة القطع ثم ببوابة الأسئلة (ويضيف الردّpassageImportBatchIdوpassageCounts)؛ وscreening_form، نموذج واحد يُستورد وحدةً واحدة (صفّ مرفوض يرفض النموذج كلّه ولا يُحفظ شيء، والردّ200معformRejected: true؛ ويضيف الردّscreeningFormId)؛ وscaffold_prompt؛ وword_list. الحقلsourceDeclaredمطلوب للأنواع التي تحمل أسئلة فقط (422بدونه).- التقارير. يعرض
GET /api/items/import/{batchId}دفعات الأسئلة ونماذج التقييم ومكتبة التلميحات وقوائم الكلمات (لا دفعات القطع أبدًا):contentKind، وsourceDeclared(فارغ للتلميحات والقوائم)، وعلى كل صفpassageIdوwordListIdوscaffoldPromptIdبجانبitemBankId. ويضمّrejectReasonأسباب العقود (form_item_count_mismatchوmeasure_not_in_gradeوform_rejectedوأسبابprompt_*الثلاثة وword_list_*الخمسة، والباقي في المخطط). ويصفّيGET /api/items/importبحسبcontentKind(الافتراضيitem). - الاعتماد. يُعتمد نموذج التقييم وحدةً واحدة:
exceptionsيعيد422معform_is_one_unit، وتُرقّى معه الأسئلة التي بلا تقدير صعوبة، وتُسحب النسخة الحيّة السابقة لـform_idنفسه. وتسحب قوائم الكلمات والتلميحات النسخة الحيّة السابقة لـlist_idأوprompt_id. ويضيف الردّretired. - صفوف الأسئلة. الصف الذي فيه
content_role(screeningأوtarget_trainingأوbridge_practice) يحملmeasure_codeوitem_patternوform_idوform_positionوtraining_levelوbridge_target_skill_id، وتُفحص مقابل صفوف الإعداد المنشورة؛ وتحدّد المنصّةcontent_purpose. أسئلة التقييم لا تُقدَّم إلا داخل نموذجها، وأسئلة الجسر لا تُقدَّم إلا في خطوة الجسر، ولم تُفعَّل هذه الخطوة بعد. - الإقرار والحجم. الاستيراد الذي يحمل أسئلة (
itemوcontent_bundleوscreening_form) يحتاجagreementSignoff(من راجع التطابق العربي خارج المنصّة ومتى؛ ويُحفظ في تقرير الدفعة). بدونه يكون الردّ422معagreement_signoff_required، ولا يُحفظ شيء. وحجم الملف بعد فكّ الترميز محدود لكل نوع (itemوcontent_bundleعشرة ميغابايت، وscreening_formاثنان، وscaffold_promptوword_listواحد)، وإلا فالردّ413. - النماذج. ردّ كل نموذج يحمل
formProblems(missingPositionsوduplicatePositionsوcountMismatchوmeasuresNotInGrade). والنموذج الذي ينقصه مقياس كامل يُرفض، ويسمّيcountMismatchالمقياس معgot: 0. - النطاق والنسخ.
form_idوlist_idوprompt_idفريدة لكل مؤسسة (والفارغ مشترك)، فاعتماد نسخة مؤسسة لا يسحب النسخة المشتركة أبدًا. واعتماد نسخة أقدم بينما نسخة أحدث حيّة يعيد409معnewer_version_operational. والملف نفسه من مؤسسة أخرى استيرادٌ خاص بها، لا إعادة للاستيراد السابق. - عرض التأليف. يضيف
GET /api/itemsوGET /api/items/{id}معview=authoringالحقلينcontentRoleوscreeningFormId. ونسخ سؤال تقييم يعيد422(form_item_not_duplicable)؛ وPATCHيُخرج سؤال تدريب أو جسر عن عقده يعيد422مع سبب العقد. - دقّة القراءة الجهرية. يُطبَّق صفّ المعيار الأخصّ. الصفّ الفارغ يسجّل الدقّة دون مستوى (
accuracyBand: nullعند الإيقاف)، ويكونskippedReasonهوnot_bandedحين لا يكون للسرعة مستوى أيضًا. ولا يُرجع إلى الحدّين 95 و90 إلا حين لا يوجد صفّ مطابق.
الواجهة ترسل التدريب، 2026-10-01
لا عمليات جديدة. هذا عميل الواجهة لعمليات «تدريب» في القيد التالي.
- من أين يبدأ الإرسال. صفحة الجلسات («+ جلسة جديدة» ← «تدريب اليوم»، ثم الصفّ كلّه أو مجموعة دعم أو طلاب تختارهم)، ولوحة الصفّ، ورأس مجموعة الدعم، وصفحة الطالب («تعيين التدريب» عبر
assign-training). ويرسل فريق أمل من/admin/trainingومعه دائمًاonBehalfOfTeacherUserId(معلّمة الصفّ منGET /api/classes/{classId}/teachers، أو صاحبة المجموعة). - مفتاح منع التكرار واحد لكل جسم طلب. في الفتح الواحد للنافذة تحتفظ الواجهة بمفتاح
X-Idempotency-Keyواحد لكل جسم مختلف ترسله. إرسال الجسم نفسه مرّة أخرى (إعادة محاولة بعد انقطاع، أو «إعادة الإرسال» لطالب نتيجتهfailed) يستعمل المفتاح نفسه، فيُعيد الخادم الإرسال الأصلي بدل الفتح مرّتين. والجسم المتغيّر (وقت آخر، أو هدف آخر، أو معلّمة أخرى) يأخذ مفتاحًا جديدًا. ويتّبعassign-trainingالقاعدة نفسها، ويُعاد إرسال ردّه503ذيreason: failedبالمفتاح نفسه. - الأخطاء التي تسمّيها الواجهة.
422window_already_over/window_too_short/until_time_required/on_behalf_required/on_behalf_not_a_teacher، و409empty_target، و403on_behalf_teacher_not_in_scope. ويعرض422idempotency_key_reusedسطر إعادة المحاولة الهادئ ويترك ذلك المفتاح، فتحمل المحاولة التالية مفتاحًا جديدًا. ويقول429RATE_LIMITEDمتى تُعاد المحاولة، منRetry-After(بالدقائق الكاملة، ودقيقة حين يغيب الرأس أو لا يُكشف)، بلا عدّ تنازلي. وأيّ خطأ آخر، ومنه503TRAINING_UNAVAILABLE(training_window_catalog_unavailable، أوfailedفيassign-training)، سطر هادئ واحد لإعادة المحاولة. والطالب الذي نتيجتهsend_closed(أو ردّassign-trainingبـ409send_closed) نهائي: لا «إعادة الإرسال»، وحين يكونsend_closedسبب كل من لم يُفتح لهم تعرض النتيجة إرسالًا جديدًا بمفتاح جديد. وعند الإنهاء المبكر يكتفي409already_closedو409nothing_openبتحديث القائمة. - صفوف صفحة الجلسات وقائمة الطلاب. صفّ التدريب ذو
subtype: "personal"يفتح/teacher/sessions/training/{dispatchId}(وقد يحملclassId: ""؛ تعرض الشارةclassNameAr، أوsupportGroupNameArلإرسال إلى مجموعة). يُعرض كل وقت إغلاق بصيغةHH:MMبالمنطقة الزمنيةtimeZoneالتي يحملها ردّه (Asia/Hebronلمدرسة في فلسطين، وAsia/Ammanلغيرها)، ويُحسب الوقت التقديري في خطوة التأكيد بـtimeZoneالذي يُعيدهGET /api/training/window-options. وتُعرِّف القائمةُoutcomeبإحدى النتائج السبع المخزّنة أوnull، ولا تكونfailedأبدًا. - خطوة الوقت وسطر التأكيد. بساعة المدرسة (
timeZoneفي خيارات الوقت) يُعطَّل خيار نهاية الدوام حين يمضيschoolDayEndsAtأو يبقى أقلّ منminMinutes، مع سببه، ويُختار الدرس بدل الافتراضي المعطَّل. ويقول سطر التأكيد إنّ التدريب سيُرسل («سيُرسل التدريب إلى N طالبًا حتى HH:MM.»)، لا إنّه سيُفتح لكل طالب؛ والنتيجة تذكر العدد الحقيقي. - صفحة الجلسات. الإرسال الذي لم يفتح التدريب لأيّ طالب ليس سطرًا في القائمة (قاعدة الخادم)؛ وتعرض الواجهة نتيجته من ردّ الإرسال أو التعيين الذي لديها.
- جهة الطالب. لا تستدعي صفحة التدريب مسار الإنشاء المحذوف أبدًا: تبدأ بـ
GET …/current/state، وتعرض «لا يوجد تدريب الآن» (مع زرّ «الرئيسية» للعودة) عند404training_not_open، وتُنهي اليوم بهدوء عند409training_closedأوwindowClosed: true. وعند إعادة تحميل الصفحة يُقدَّم السؤال الذي يسمّيهinFlightItemIdمن جديد، وإعادة التحميل بعدwindowClosed: trueتنتهي عند شاشة النهاية. والإجابة المحفوظة على الجهاز دون اتصال التي يرفضها الخادم لاحقًا بـ409training_closedتُحذف من الجهاز ويُبلَّغ عنها بالحدثoffline_queue_eventذيop: refused_window_closed.
التدريب يُفتح فقط حين ترسله المعلّمة، لوقت محدّد — 2026-10-01
أربع عمليات جديدة (GET /api/training/window-options، POST /api/training/dispatches، POST /api/training/dispatches/{dispatchId}/close، GET /api/training/dispatches/{dispatchId}/progress)، وعملية حُذفت (POST /api/practice/queues/seed/{diagnosticSessionId} يُجيب الآن 404)، وتتغيّر عدّة أشكال (أُعيد توليد المواصفة). الترحيلات 20261001100000–20261001100200. النشر: قبل بدء الدوام — شغّل الترحيلات، ثم config:publish فورًا (خيارات الوقت تُقرأ من الإصدار النشط)، ثم النشر (deploy/cloud-run/DEPLOY.md).
- لا يُفتح تدريب من تلقاء نفسه. ترسل المعلّمة التدريب إلى صفّ أو مجموعة دعم تملكها أو طلاب تختارهم، لوقت: هذه الحصّة، أو اليوم حتى نهاية الدوام، أو حتى وقت تكتبه (
POST /api/training/dispatches، معX-Idempotency-Keyاختياريًا). يُبنى تدريب كل طالب من آخر تقييم أنهاه هذا العام الدراسي. تذكر الاستجابةoutcomeلكل طالب (opened_new_queue،opened_existing_queue،trained_today،no_assessment_yet،no_practiceable_subskills،deeper_assessment_pending،catalog_session_active)، وتكون201حتى لو لم يُفتح شيء. إعادة الإرسال بالمفتاح نفسه تُعيد الإرسال الأصلي (200،replayed: true). - خيارات الوقت صفوف إعداد. يعرضها
GET /api/training/window-optionsمع اسمها العربي وأرقامها والخيار الافتراضي وما إذا كانت القيمة مؤقّتة. الاختيار الخاطئ422معreason:unknown_window،until_time_required،window_already_over،window_too_short. - يُقدَّم التدريب فقط ما دام الوقت مفتوحًا. خارج الوقت يُجيب
GET …/current/next-itemوGET …/current/stateبـ404معreason: training_not_open. بعد انتهاء الوقت يمكن الإجابة عن سؤال ظهر قبله خلال مهلة قصيرة: تحمل استجابة الإرسالwindowClosed: trueولا سؤال بعده. بعد المهلة يُجيب الإرسال409training_closedولا يُسجَّل شيء. يبقى «كيف كان التدريب؟» مطلوبًا. جلسات المكتبة غير مقيّدة بوقت. - حقل حُذف. لم يعد
practiceSeedSessionIdفيGET /api/student/next-actionوGET /api/student/today-plan؛ يُعرض التدريب فقط ما دام الوقت مفتوحًا. - «تعيين التدريب» (
POST /api/practice/students/{studentId}/assign-training) إرسال لطالب واحد: جسم اختياري{ windowCode?, untilLocalTime?, onBehalfOfTeacherUserId? }؛ و201يُعيد{ queueId, itemCount, dispatchId, outcome, closesAt }؛ والتعيين الثاني يُكمل التدريب (201، لا409 queue_already_active)؛ والنتائج الأخرى أسباب409، ومنها الآنtrained_todayوcatalog_session_active. ويكسبcurrentTrainingفي قراءة أيام التدريب الحقولclosesAtوopenوwindowLabelArوالقيمةopenedBy: "staff". - صفحة الجلسات. يعرض
GET /api/teacher/sessions?kind=trainingالإرسالات أيضًا (subtype: "personal"، والحالةopenأوclosed)، وصار للمؤشّر ثلاثة أجزاء (المؤشّرات القديمة بجزأين ما زالت تعمل).GET /api/training/dispatches/{dispatchId}/progressهو قائمة الطلاب (حالات وأعداد فقط)، وPOST …/closeيُنهي الإرسال مبكرًا للجميع (409 already_closedبعد انتهائه). - فريق أمل نيابةً عن المعلّمة. على الفريق (
RUN_BACKOFFICE/ المشرف العام) تسمية المعلّمة (onBehalfOfTeacherUserId، ويجب أن تكون صاحبة الهدف). كل إرسال من الفريق يكتب حدث تدقيق واحدًا،training_activated_on_behalf. - الانتقال. التدريبات التي فُتحت تلقائيًا قبل هذا الإصدار تبقى حتى منتصف الليل التالي بتوقيت المؤسسة، ثم تنتهي. وأوّل إرسال من المعلّمة يفتح التدريب لطالب يُنهي مهلة ذلك الطالب قبل ذلك.
- بعد المراجعة. خطأ عند طالب واحد لا يُفشل الإرسال كلّه بعد الآن: نتيجته
failed(المخطّطTrainingSendRecipientOutcome، معqueue: null، ويُحسب فيcounts.notOpened؛ ولا تُخزَّن، فتعرض القائمةoutcome: null)، وإعادة الإرسال بالمفتاح نفسه تكتبه ما دام الإرسال مفتوحًا. الإرسال الذي انتهى وقته أو أُنهي لا يُفتح من جديد: إعادته بالمفتاح نفسه تُجيب عندئذsend_closedلمثل هذا الطالب (نتيجة في الردّ فقط مثلfailed؛ لا تُعِد الإرسال، بل افتح تدريبًا جديدًا)، ويُجيبassign-trainingبـ409send_closed. وإنهاء إرسال لم يفتح شيئًا409nothing_open. والمفتاح المستعمل لطلب مختلف422idempotency_key_reused، في الإرسال وفيassign-training؛ ويقبلassign-trainingالمفتاحX-Idempotency-Keyوإعادته200. كل وقت في التدريب يحملtimeZoneالمدرسة: خيارات الوقت، وwindowفي الإرسال، وdispatchفي قائمة الطلاب، وcurrentTraining، وردّassign-training. ويسمّيGET /api/practice/queues/current/stateالحقلinFlightItemId(السؤال المعروض الذي لم يُجب عنه بعد، أوnull). ويكسب سطر صفحة الجلساتsupportGroupNameAr(وclassNameArهو""لإرسال إلى مجموعة)، ويعرض عنوانه الفرعي وقت الإنهاء الفعلي لإرسال أُنهي مبكرًا. وإعداد الأوقات المعطوب503TRAINING_UNAVAILABLEمعreason: training_window_catalog_unavailable، وassign-trainingالذي تعذّرت كتابته503TRAINING_UNAVAILABLEمعreason: failed. ولمساري الإرسال حدّ:429RATE_LIMITEDبعد 6 في الدقيقة، مع الرأسRetry-After.
واجهة المعلّم v3 — «التعليم المتمايز» و«الخطط» وتكليف مجموعة المهارة والتسليم «مختلط» (المرحلة S4)، 2026-09-30
5 عمليات جديدة؛ صار amal-api.yaml يضمّ 402 مسارًا و435 عملية.
- في
wp-tdv3.yaml(الوسمteacher-views):getTeacherDifferentiation(GET /api/teacher/classes/{classId}/differentiation?sort=&domain=)،getTeacherSkillPage(…/differentiation/{subSkillId})،getTeacherSkillGroupDetail(…/differentiation/{subSkillId}/groups/{groupKey})،listTeacherPlans(GET /api/teacher/plans?classId=). - في
wp-sbc-be.yaml:deliverSessionMixed(POST /api/sessions/{id}/deliver-mixed).
تغيّر:
- يقبل
POST /api/sessions/from-blueprintالحقول الاختياريةassignmentContext { subSkillId, groupKeys? }وtargetStudentIdsوmediumByStudent، وصار جسمه صارمًا (مفتاح غير معروف ← 422). - يُجاب الجسم الجديد بـ
deliveryPlanوtargetedCountوdeduplicated، والجسم الذي لا يحمل الحقول الجديدة يُجاب كما كان حرفًا بحرف. - حدّ إنشاء الجلسات 30 جلسة لكل معلّم في 15 دقيقة (429
RATE_LIMITEDمعretryAfter). - يضيف
POST /api/sessions/{id}/acceptالحقلينevidenceWindowوnotEnrolled. - صار
PATCH /api/sessions/{id}/editصارمًا، ويرفض حذف المهارة الأساسية من مسودة موجّهة إلى مجموعة (409anchor_skill_removed). - يرفض
distribute-onlineوgenerate-pdfsجلسةً خُطّط لها وسيط آخر (409delivery_plan_mismatch). - أُضيفت القيمة
mixedإلى وسائط التسليم.
الترحيلات: 20261002100700_wp_tdv3_delivery_mode_mixed (قيمة التعداد وحدها) و20261002100800_wp_tdv3_session_target (مصفوفات الهدف، وخطة الوسيط، والبصمة، ووسيط كل مستلم، والفترة المحسوبة، مع 4 قيود CHECK وفهرسين). يُعاد تأريخ الاثنين عند الدمج في الفرع الأمّ بعد مزامنته.
- تكليف المجموعة يستهدف طلاب المجموعات المختارة كما تعرضهم صفحة المهارة، تمامًا. المجموعة التي تغيّرت ترفض الكتابة كلّها (409
group_stale). المستلمون عند القبول هم المستهدفون الذين ما زالوا مسجّلين، والصفر لا يتّسع أبدًا إلى الصف كلّه. - النقرة نفسها مرّتين خلال 120 ثانية تعيد الجلسة الأولى (
deduplicated: trueمع حالتها الفعلية). - «مختلط» يثبّت وسيط كل طالب عند القبول، و
deliver-mixedيسلّم الوسيطين في خطوة واحدة، وإعادة المحاولة آمنة. - صار توزيع الجلسة يقرأ فترة التقييم الحالية للصف وعامه الدراسي (كان يقرأ بداية العام، وقد يلتقط صفًّا من عام سابق).
واجهة المعلّم v3 — خلفية صفحة «التقييمات» (المرحلة S3)، 2026-09-30
4 عمليات جديدة؛ صار amal-api.yaml يضمّ 397 مسارًا و430 عملية — wp-tdv3.yaml (الوسم teacher-views): getTeacherAssessments (GET /api/teacher/classes/{classId}/assessments?window=)، getTeacherAssessmentComparison (…/assessments/comparison)، getTeacherAssessmentDetails (…/assessments/details?window=&domain=)، exportTeacherAssessmentResults (…/assessments/export?window=، بصيغة text/csv). تغيّر: يضيف GET /api/admin/audit-log النوع student_data_access (صفوف student_data_access_log — اطلاع المعلّمين والمديرين والمشرفين والمسؤولين على بيانات أطفال بأسمائهم وتصديرها، D-R12)، والرابط المباشر access:<id>، وثلاثة حقول تقبل القيمة الفارغة actorPersona وsubjectStudentCount وtargetClassId، وسقفًا لـoffset قدره 2000 (422 فوقه)؛ ويعرض GET /api/admin/activity الصفوف نفسها في عرض الأمان بالمصدر access مع classId.
- كل رقم يخصّ فترة واحدة من هذا العام الدراسي؛ لا رقم يجمع بين فترتين؛ والمقارنة من حالة إلى حالة (أعداد الانتقال)، ولا متوسط أبدًا.
- كل نسبة حصة من الطلاب المقيَّمين مع أعدادها؛ تحمل R7–R9 الحقل
dataSufficiencyوتُظهر الواجهة الأعداد وحدها ما دام غير كافٍ (D-R11). - التصدير بكلمات الحالة فقط، ويُكتب بعد صفّ
export_csvفي سجل الاطلاع (500 عند تعذّره)، بحدّ 20 تصديرًا لكل معلّم في 15 دقيقة (429)، وبسقفexportMaxRows(422، دون اقتطاع أبدًا)، ويُرفض بـ503 دون محتوى إن لم تكن قواعد اللغة مفعّلة. - يظهر الفحص الأعمق
approved_not_startedحتى أول إجابة في جلسته، ثمin_progress(D-R14).
تجربة المعلّم v3 — حساب معلّم الدعم (S15)، 2026-09-30
لا عمليات جديدة (عدد مسارات amal-api.yaml وعملياته لم يتغيّر). ترحيل واحد:
20261002100600_wp_tdv3_learning_support_flag (teacher_profile.learningSupport، القيمة الافتراضية false).
- يضيف
GET /api/auth/meالحقلlearningSupport(للمعلّم: قيمة منطقية؛ لكلّ دور آخر:null) والحقلlastTeacherClassId(الصفّ المخزَّن عبرPUT /api/users/me/last-classما دام المعلّم مسندًا إليه، وإلّاnull). - يضيف
GET /api/users/{id}(للمعلّم) الحقلprofile.learningSupport؛ ويقبلPATCH /api/users/{id}الحقلteacher.learningSupport(قيمة منطقية؛ لمسؤول المؤسّسة وحده). يسجّل سطر التدقيق تعديلًا على ملفّ المعلّم (fields: ["teacher"])، دون اسم الإعداد ودون قيمته. للعرض فقط: لا يقرؤه نطاق وصول أيّ مسار ولا صلاحياته. ثبت ذلك بطريقتين: مجموعة اختبارات تقلب الحقل (معطّل ← مفعّل ← معطّل) على كلّ قراءة في الشريحتين اللتين يستخدمهما المعلّم اليوم (wp-tdv3،wp-support-groups) فتجد الحالة والمحتوى متطابقين؛ ويحرس كلَّ مسار آخر فحصٌ للمصدر لا يسمح بالحقل إلّا في خمسة ملفّات (ليس بينها مساعد نطاق أو صلاحيات).
واجهة المعلّم v3 — الأساس الخلفي (المرحلة S2)، 2026-09-29
7 عمليات جديدة؛ صار amal-api.yaml يضمّ 393 مسارًا و426 عملية — wp-tdv3.yaml (الوسم teacher-views): getTeacherClasses، getTeacherClassHome، getTeacherClassNeeds، listTeacherNeeds، listTeacherStudents؛ وputMyLastClass (PUT /api/users/me/last-class) وputMyTeacherGender (PUT /api/users/me/teacher-gender)، كلاهما في wp-a3.yaml. تغييرات: يضيف GET /api/auth/me الحقول features.teacherV3 وteacherGender وtimeZone؛ ويقبل PATCH /api/users/{id} الحقل teacher.gender وتعرضه تفاصيل المستخدم للمسؤول؛ ويردّ POST /api/alerts/{id}/acknowledge و/dismiss بـ409 حين لا يعود التنبيه مفتوحًا. الترحيلات 20261002100000_wp_tdv3_last_teacher_class (عمود اختياري user_preferences.lastTeacherClassId)، 20261002100100_bundle_recommendation_current_idx، 20261002100200_wp_tdv3_target_sub_skill، 20261002100300_wp_tdv3_cbm_alert_open_series (شغّلوا فحص القراءة المسبق في deploy/cloud-run/DEPLOY.md أولًا) و20261002100400_wp_tdv3_cbm_alert_trend_signal_at و20261002100500_wp_tdv3_teacher_gender (عمود اختياري teacher_profile.gender) — كلها بعد 20260929050000_p3c5_snake_case_tables في main، وهو مطبَّق في الإنتاج.
- للمعلّم فقط؛ الرفض 403 من بوابة الصلاحيات وحدها، و404 لكل ما هو خارج النطاق. مفتاح الواجهة الجديدة (
TEACHER_V3_ORGS) يغيّر العرض وحده — كل مسارات/api/teacher/*تجيب بالشيء نفسه والمفتاح مفعّل أو معطّل. - كل نسبة محسوبة من الطلاب المقيَّمين؛ «لم يُقيَّم بعد» و«قيد المراجعة» أعداد لا تدخل في المقام.
- كل قراءة تسمّي طفلًا وصلت إليه المعلّمة عبر مجموعة دعم فقط تكتب سطرًا واحدًا في سجلّ الوصول، وإن تعذّرت كتابته لا تُرسَل القراءة.
- قراءات الاحتياجات تقبل عائلة واحدة أو قائمة عائلات مفصولة بفواصل، ومؤشّر صفحات مربوطًا بتلك القائمة، و
reach=groupفي R3b (طلاب مجموعات الدعم الخاصة بالمعلّمة). يحمل كل صفsubSkillIdوsubSkillNameArوheldForImplementation، وبحسب النوعcbm {alertType, severity}أوplanIdأوactivation. - إصلاح: الإقرار أو التأجيل المتأخر كان يعيد كتابة تنبيه مغلق أو مؤجّل. صار الانتقالان لا يعملان إلا على تنبيه مفتوح؛ وإلا فـ409 ولا يُكتب شيء ولا يُسجَّل إجراء للمعلّمة.
- إصلاح: تنبيه قياس واحد لكل سلسلة قياس. صار تنبيه القياس المفتوح يسمّي المهارة التي قيست، فلا تمحو سلسلة ثانية للطفل نفسه الأولى؛ ويقرأ نظام الاستجابة للتدخّل آخر إشارة كتبها مُصدِر التنبيه (
trendSignalAt) لا آخر تحديث للصف. - صيغة مخاطبة المعلّم (
FEMALE/MALE/ دون تحديد — وتُستخدم صيغة المذكّر): يحدّدها المعلّم (PUT /api/users/me/teacher-gender، لنفسه فقط، دون سطر تدقيق) أو مسؤول النظام في مؤسسته (PATCH /api/users/{id}، ويسجّل سطر التدقيق تعديلًا على ملفّ المعلّمfields: ["teacher"]دون اسم الإعداد ودون قيمته)؛ لا تُعاد إلا في/meالخاص بالمستخدم وفي تفاصيل المستخدم للمسؤول، ولا تظهر في أي قائمة، ولا يقرأها أي قرار. و/me.timeZoneمشتقّة من دولة المؤسسة (الأردنAsia/Amman، فلسطينAsia/Hebron). - يُختم عند التفعيل هدفُ الخطة من المهارات الفرعية (
bundle_assignment.targetSubSkillId). ويقبل استقبال النشاطalert_action.surface = "needs"(كان يرفضه، والحدث المرفوض يُسقط دفعته كلها).
بطاقة المساعدة المختصرة بصيغة مخاطبة المعلّم — 2026-09-27
لا عمليات جديدة. مُعامل استعلام اختياري واحد على عملية موجودة (WP-TDV3 S6c؛ الشريحة wp-onb-be.yaml).
GET /api/teacher/help/cheat-sheet.pdf?form=f|m. المُعاملformاختياري ومغلق:fأوm، وأيّ قيمة أخرى تُرجع 422. من دونه يبقى ملف PDF مطابقًا بايتًا ببايت لما كان يُقدَّم من قبل، فلا يتغيّر أيّ مستدعٍ حاليّ. ومعه تُكتب الأسطر التسعة التي تخاطب المعلّم أو تسمّيه (ستّة أسطر بضمير المخاطَب، وعنوان رمز التجاوز «تعديل المعلّم/المعلّمة للحزمة (خروج)»، وعنوانا الصفحتين «دليل التهيئة السريع للمعلّم/للمعلّمة …») بتلك الصيغة. ولم تتغيّر البوابة (معلّم) ولا النطاق ولا الحدثcheat_sheet_downloaded.- نصوص الخادم الموجّهة إلى المعلّم لم تتغيّر. رسائل المساعدة والمتابعة وسير العمل والاستجابة للتدخّل تحتفظ بأشكال استجاباتها، وتبقى مكتوبة بصيغة المؤنّث؛ والواجهة تعرضها بصيغة القارئ.
نصوص القراءة الجهرية، وسطر طريقة القراءة، واستيراد محتوى أدقّ — 2026-09-29
لا عمليات جديدة. حقول جديدة ومعامل استعلام واحد جديد (أُعيد توليد openapi:check). الترحيلان 20261001600000_ci_enum_values و20261001600100_ci_oral_text_reading_convention. النشر: شغّل الترحيلين؛ لا حاجة إلى seed ولا إلى config:publish.
GET /api/passages: كل صفّ يحملpurpose(comprehension|oral_text)، وتقبل القائمة معاملًا اختياريًا?purpose=. المرشِّح يضيّق النطاق المعتاد للمستدعي فقط (النصوص العامة ونصوص مؤسسته) ولا يوسّعه أبدًا. نص القراءة الجهرية يُقرأ ويُصحَّح ولا يُسأل عنه: ربطه بسؤال يُجيب422unknown_passage.readingNoteAr(نص أوnull): السطر العربي الواحد الذي يقول للمعلّمة كيف يُقرأ آخر الكلمات، فيGET /api/orf/passagesوPOST /api/orf/assessments/startوPOST /api/reading-assessments/planned/{id}/startوGET /api/word-lists. يكونnullحين لا يحدّد المحتوى طريقة قراءة. وللصفّ الذي له نصوص قراءة جهرية لا يعرضGET /api/orf/passagesغيرها.- بوابة الاستيراد (أمر على الخادم
content:import، وليس مسار API): نص القراءة الجهرية (content:import oral-texts) الذي يخالف قواعده يُرفض بالسببoral_text_invalidمع اسم الحقل؛ ونوع النصtextTypeحصرًاnarrativeأوinformational؛ والكلمة غير الحقيقية المستعملة في قائمة صفّ آخرword_list_duplicate؛ والحرف الذي عليه شدّة وسكون معًا يُرفض؛ وتكرارmetadata.partner_item_idيرفض نموذج التقييم، وإعادة إرسال النموذج تُظهر الفرق سؤالًا سؤالًا؛ و--manifestيقرأ ملف التسليم من الشريك؛ والدفعات التي صاغها الذكاء الاصطناعي أو التجريبية لا تُعتمد من سطر الأوامر أبدًا. - الصعوبة المبدئية: إصدار المعادلة الآن
v2(حدّ المتطلّب المعرفي يقرأ أسماء عمليات القراءة التي في العقد). القيم المحفوظة لا يُعاد حسابها. - العرض: خيارات
CHOOSE_CORRECT_SPELLINGلا تُقرأ بصوت أبدًا (نصّ السؤال يُقرأ). وتبقى خيارات الاختيار بترتيب مختلف في كل عرض، والتصحيح بمعرّف الخيار. - الأدلّة: عقود الشريك في
content-pipeline/partner-handoff/(والجديد13-oral-texts.md).
اقتراح الفحص الأعمق يتبع تصحيح المعلّمة — 2026-09-27
لا عمليات جديدة. يكسب GET /api/backtrack/students/{studentId} الحقل firedSignals، وتكسب قائمة الحالات القيمة withdrawn (لا تُعيد هذه القراءة اقتراحًا مسحوبًا أبدًا)؛ وصار لجسم ردّ 409 في الموافقة مخطّطه الخاص BacktrackApproveConflict؛ أُعيد توليد المواصفة. الترحيلات من 20261001050000 إلى 20261001050600 (قيود على صفوف جدولَي إعداد، وعبارة سبب لكل قاعدة، والحالة الجديدة، وقواعد الاقتراح الخمس نفسها، ومهلة حجز الموافقة). النشر: شغّل الترحيلات ثم seed-main وconfig:publish. قواعد الاقتراح تصل الآن مع الترحيلات، فيمكن أن يُفتح الفحص قبل تشغيل seed-main؛ وما زال seed-main لازمًا لصفوف سرعة القراءة الجهرية، ويرفض config:publish الكتالوج الذي لا يجتاز الفحوص الجديدة. وفي قاعدة بيانات لم تملأها البذرة بعد، ينتظر فحص رموز مهارات القواعد تشغيل seed-main (بتحذير في السجلّ) بدل الرفض.
- الاقتراح الذي لم تُجب عنه المعلّمة يتحدّث مع كل تصحيح. قائمة كلمات تُصحَّح بعد القراءة الجهرية تقوّي سببه الآن (يتغيّر
reasonCode، مثلًا إلىSEVERE_TEXT_ACCURACY_WITH_DECODING_SIGNAL). وإذا أعادت قراءة لاحقة الدقّة إلى المدى المتوقّع يُسحب الاقتراح: وقبول المسحوب أو رفضه409. وإذا انخفضت الدقّة مجدّدًا في النافذة نفسها يعود الاقتراح. بعد أن تقبل المعلّمة أو ترفض، لا تغيّره أي قراءة لاحقة. - اقتراح هذا العام وحده يؤخّر التدريب ما دام بلا جواب. إرسال «تدريب» و«تعيين التدريب» ينتظران (
deeper_assessment_pending) اقتراحًا لم تُجب عنه المعلّمة في هذا العام الدراسي، وفحصًا جلسته مفتوحة، أو قبلته المعلّمة خلال آخر 10 دقائق (ما زالت الموافقة تفتحه)، في أي عام. الاقتراح المسحوب، أو الذي بقي بلا جواب من العام الدراسي الماضي، أو موافقة توقّفت في منتصفها قبل أكثر من 10 دقائق، لا يؤخّر التدريب بعد الآن. والدقائق العشر هي صفّbacktrackفيengine_parameters. - القراءة تعرض ما يؤخّر التدريب. يُعيد
GET /api/backtrack/students/{studentId}أوّلًا الاقتراح الذي يؤخّر تدريب الطالب (ولو كان فحصًا مفتوحًا من عام سابق). وإن لم يوجد، يُعيد أحدث اقتراح في هذا العام الدراسي، أوnullإن لم يوجد أو كان مسحوبًا. واقتراح نافذة أحدث يسحب الاقتراح الذي لم يُجَب عنه في نافذة أقدم من العام نفسه. - قبول الاقتراح يذكر سبب الرفض. يحمل ردّ
409منPOST /api/backtrack/{id}/approveالحقلreasonبقيم محدّدة:not_recommendable، أوrecommendation_expired(اقتراح بقي من عام دراسي آخر)، أوapproval_in_progress(موافقة أخرى تفتحه الآن)، أوsession_already_active، أوrediagnostic_too_soon. يُحجز الاقتراح قبل أن تُفتح جلسته، وتُربط الجلسة به في الخطوة نفسها التي يُؤرشَف فيها تدريب الطالب السابق. فإن تعذّر فتح الجلسة، أو فُتحت بلا أسئلة تُعرض (noEligibleItem: true)، أو فشلت في الطريق، يبقى الاقتراحrecommendedولا يبقى شيء مفتوحًا ويبقى تدريب الطالب. وإن وصل رفض في اللحظة نفسها تُغلق الجلسة التي فُتحت للتوّ. وموافقة توقّفت في منتصفها يمكن تكرارها بعد 10 دقائق، ويمكن رفض اقتراح في حالةapproved. - السبب يذكر كل الإشارات. يجمع
reasonArالآن عبارة الدقّة مع عبارة لكل إشارة ظهرت من قوائم الكلمات أو الفهم (كان يذكر واحدة)، وعبارة الفهم لم تعد توحي بسبب. ويسرد الحقل الجديدfiredSignalsكل قاعدة ظهرت:{ ruleId, kind: opens | strengthens, signal, clauseAr, provisional }، والقاعدة التي فتحت الفحص أوّلًا. وقيمةprovisionalهي المسجّلة لحظة الاقتراح. الاقتراحات السابقة لتحديث الفحص الأعمق تبقى على سطرها القديم وقائمة فارغة. - إعداد أكثر أمانًا. ترفض قاعدة البيانات قاعدة اقتراح تنقصها الحقول التي يحتاجها مصدرها، أو قائمة مطابقة فارغة، أو عبارة فارغة، أو مستوى بدء تدريب أقلّ من 1، أو قاعدة سرعة جهرية صفّها ليس من
G1إلىG6، أو قاعدتَي سرعة جهرية عامّتين للإصدار نفسه. ويرفضconfig:publishأيضًا قيمة نطاق أو حالة غير معروفة، أو رمز مهارة غير معروف أو غير نشط، أو قيمةmeasureلا يسجّلها نوع دليل القاعدة (قاعدة قراءة جهرية تقرأ مقياس قائمة الكلمات مثلًا)، أو إصدارين نشطين للقاعدة نفسها. - إيقاف الفحص من الإعداد وحده. اجعل كل قاعدة تفتح الفحص غير نشطة وشغّل
config:publish: يُنشر الإصدار مع تحذير في السجلّ (config_release.catalog_warning)، ولا يُفتح اقتراح جديد، وتبقى الاقتراحات القائمة كما هي. وتبقى التي لم يُجَب عنها مؤخِّرة للتدريب حتى تُرفض؛ ويسحبها الأمرpnpm --filter server backtrack:withdraw-open --org <id>لمؤسسة واحدة (ويرفض ما دام الفحص يعمل). - حقلان في الـDTO. كل اقتراح في ردود القراءة والموافقة وعدم الاعتماد يحمل
academicYear(العام الدراسي للصفّ نفسه، مثل"2026-2027") وclaimStale(صحيح فقط لصفّapprovedانتهت مدّة حجزه؛ والموافقة عندئذ تحجزه من جديد). ويوثّق عدم الاعتماد أنّه يقبلrecommendedوapproved. - البطاقة في صفحة الطالب (الواجهة). تعرض البطاقة كل ما تُعيده القراءة: اقتراحًا ينتظر القرار، أو صفًّا
approved، أو جلسة مفتوحة (من أيّ عام دراسي، فهي ما زالت تؤخّر التدريب)، أو قراءة مكتملة، أو لا شيء (null). تُعرض الموافقة علىrecommended، وعلى صفّapprovedحين تنتهي مدّة حجزه فقط (claimStale)؛ وعدم الاعتماد علىrecommendedوapproved. والصفّ من عام دراسي أسبق من صفّ الطالب الحالي (academicYear) يضيف «فحص أعمق مفتوح من عام دراسي سابق — ينهيه الطالب أوّلًا.». لكل409في الموافقة سطر هادئ بحسبreasonثمّ تُقرأ البطاقة من جديد؛ وapproval_in_progressيُقرأ «يجري فتح الفحص الآن — حدّثي الصفحة بعد لحظة.». ومعnoEligibleItem: true(لا سؤال يُقدَّم، ومنه مسار كل خطواته تصحّحها المعلّمة) تقول البطاقة «لا توجد أسئلة مناسبة الآن — يبقى الاقتراح قائمًا.» ويبقى زرّ الموافقة.
متى يُقترح الفحص الأعمق للأساسيات — 2026-09-27
لا عمليات جديدة. يتغيّر شكل GET /api/backtrack/students/{studentId} بالإضافة فقط: صار trigger وreasonCode نصّين بدل قائمتين ثابتتين، وصار في readout للفحص المكتمل حقل جديد trainingRecommendation (أُعيد توليد المواصفة). الترحيل 20261001010000 (جدول إعداد عامّ جديد وعمود جديد في إعداد التسلسل). النشر: شغّل الترحيل ثم seed-main وconfig:publish.
- يُقترح الفحص فقط حين تكون دقّة قراءة الفقرة جهرًا دون المتوقّع بوضوح. القراءة البطيئة الدقيقة، أو ضعف الفهم وحده، أو ضعف قوائم الكلمات وحده، لم تعد تقترح الفحص. صار
triggerهو القاعدة التي فتحت الفحص (TEXT_ACCURACY_SEVERE)، وتبقى الاقتراحات الأقدم علىA/B. - قوائم الكلمات والفهم تشرح السبب. قيمة
reasonCodeهيSEVERE_TEXT_ACCURACY، أو هي نفسها مع_WITH_DECODING_SIGNAL(قائمة الكلمات غير الحقيقية) أو_WITH_ACCESS_SIGNAL(قائمة الكلمات المشكولة) أو_WITH_COMPREHENSION(ضعف واسع في الفهم). اعرضreasonArلا الرمز. هذه القواعد صفوف إعداد، فقد تزيد القائمة. - الاقتراحات تتبع تصحيح المعلّمة. إنهاء تصحيح قراءة جهرية أو قائمة كلمات يعيد فحص الاقتراح فورًا، ولا يُقترح شيء يعتمد على القراءة الجهرية قبل تصحيحها.
- بعد الفحص: اقتراح تدريب. الفحص المكتمل الذي حدّد نقطة بدء واضحة يُعيد
readout.trainingRecommendation{ skillId, skillNameAr, level }: تدريب على تلك المهارة من المستوى الأول، ترسله المعلّمة. لا يبدأ شيء تلقائيًا. قيمتهnullإذا لم يحدّد الفحص نقطة بدء أو اكتمل قبل هذا التحديث.
سرعة القراءة الجهرية تُقارَن بمعيار نافذة التقييم — 2026-09-27
لا عمليات جديدة، ولم يتغيّر شكل أي طلب أو استجابة (أُعيد توليد المواصفة: وصف حقل واحد). الترحيل 20261001000000 (جدول إعداد عامّ واحد جديد). النشر: شغّل الترحيل ثم seed-main وconfig:publish لتصبح صفوف الإعداد الجديدة سارية.
- معيار السرعة يتبع نافذة التقييم. صار
POST /api/orf/assessments/startيحدّد معيار النافذة التي تُسجَّل فيها القراءة (النافذة المفتوحة للطفل اليوم، وإلا آخر تقييم مكتمل هذا العام الدراسي): بداية العام بمعيار نهاية الصف السابق، ومنتصفه بمعيار مؤقّت بين المعيارين، ونهايته بمعيار الصف نفسه. كانت كل قراءة تُقارَن سابقًا بمعيار نهاية العام. القراءة التي لا نافذة لها تبقى على معيار نهاية العام كما كانت. POST /api/cbm/probesيحدّد معيارassessmentWindowالخاصّ بالقياس، والقياس الذي لا نافذة له لم يتغيّر.- حين لا يكون للنافذة معيار سرعة (الصف الثاني في بداية العام ومنتصفه: لا معيار للقراءة الجهرية في الصف السابق)، يُسجَّل المعدّل رقمًا خامًا بلا حكم، وتُقيَّم دقّة القراءة وحدها وفق الإعداد:
projection.writtenقيمتهtrue، وprojection.accuracyBandمحدَّد، وprojection.rateBandقيمتهnull. أيّ صفّ ونافذة يتبعان ذلك صفُّ إعداد لا برمجة، والصف الأول لم يتغيّر. في هاتين النافذتين يُحكم على مجال دقّة القراءة وطلاقتها بالدقّة وحدها، فتبقى صورة القراءة قابلة للتحديد.
متابعات القراءة والمطابقة — 2026-09-26
لا عمليات جديدة، ولم يتغيّر شكل أي طلب أو استجابة (openapi:check سليم). لا ترحيل.
- المحاولة الأولى الخاطئة في سؤال الترتيب لم تعد تُعيد حكمًا لكل موضع. شاشة الطالب تُعيد كل البطاقات للمحاولة الثانية، فلم تكن هذه الأحكام تُستعمل. ما زالت أسئلة المطابقة وأسئلة الفراغات المتعددة تُعيدها، والكشف بعد المحاولة الثانية لم يتغيّر.
- إصلاح: الاستراحة بعد النص الطويل كانت تتبع نصّ السؤال الحالي. صارت تقرأ نسخة السؤال المُجاب والسؤال التالي التي عُرضت على الطفل فعلًا، فتعديل السؤال أثناء الجلسة لا يضيف استراحة ولا يحذفها.
- استوديو الأسئلة: الزوج الفارغ الجديد أو المعنى الإضافي الفارغ يُظهر ملاحظة هادئة («أكمل الصفوف الفارغة أو احذفها.») بدل خطأ أحمر. يبقى الحفظ معطّلًا حتى يُملأ الصف أو يُحذف، ولا تظهر القواعد الحمراء إلا للأخطاء الحقيقية مثل تكرار المعنى.
- قاعدة مفتاح المطابقة في الاستوديو تُقارَن بقاعدة الخادم. القاعدة في وحدة خادم واحدة بلا اعتماديات، واختبار يشغّل النسختين على الحالات نفسها.
المكافآت تتبع النموّ المقيس فقط — 2026-09-29
- تعديل القواعد لا يمنح مكافأة مجال. بلوغ المجال مستوى «متمكّن» يتطلّب أدلة جديدة خلف المجال، لا مجرّد إعادة حساب.
- لا تكتمل الخطة إلا إذا حقّقت معايير النجاح. اختيار سبب الخروج «حقّق المعايير» لخطة لم تمرّ بمراجعة تحقّق المعايير لا يمنح شيئًا.
- مكافأة طلاقة واحدة عند كل تجاوز. الاتجاه الذي يتجاوز خط الهدف يمنح مكافأة واحدة، والقياسات الإضافية التي تُبقيه فوقه لا تمنح المزيد. الهبوط ثم تجاوز جديد يمنح مكافأة جديدة.
كل جداول قاعدة البيانات تُسمّى بالأحرف الصغيرة والشرطة السفلية — 2026-09-29
لا عمليات جديدة، ولم يتغيّر شكل أي طلب أو استجابة (openapi:check سليم). الترحيل 20260929050000. النشر: شغّل الترحيل ثم الإطلاق مباشرة دون فاصل، وأي استعلام SQL محفوظ يذكر اسم جدول بالصيغة القديمة بين علامتَي تنصيص يجب تعديله (deploy/cloud-run/DEPLOY.md).
- أُعيدت تسمية آخر 17 جدولًا كانت ما تزال تحمل أسماءها البرمجية، مثل
"User"إلىapp_user، و"StudentProfile"إلىstudent_profile، و"ClassStudent"إلىclass_student، و"AuthEventLog"(مع أقسامه الشهرية) إلىauth_event_log. كانت بقية الجداول تتبع هذا الأسلوب أصلًا. أسماء الأعمدة لم تتغيّر. - الجدول
Userصارapp_userلاuser. كلمةuserمحجوزة في SQL: الاستعلامSELECT count(*) FROM userدون علامات تنصيص يُعيد صفًّا واحدًا فيه اسم دور قاعدة البيانات بدل أن يفشل. - لا تنتقل أي بيانات. إعادة التسمية تغيّر فهرس قاعدة البيانات فقط؛ قورن عدد الصفوف ومحتواها جدولًا جدولًا قبل الترحيل وبعده على قاعدة بيانات فيها بيانات، وجُرِّب على القاعدة بعد التسمية تسجيل الدخول وجلسة تشخيص والمهامّ الليلية.
روابط الدخول ورموزه تُحفظ مُجزَّأة فقط، ومؤشّر واحد لمدير كل مدرسة — 2026-09-29
لا عمليات جديدة. قد تُعيد GET /api/principals/{id} وملف مدير المدرسة في GET /api/users/{id} القيمة schoolId: null (مدير مدرسة حُذف أو مُحيت بياناته لم تعد له مدرسة)؛ ولم يتغيّر أي شكل آخر، وما زالت قائمة المدارس تُعيد principalUserId (أُعيد توليد openapi:check). الترحيلات 20260929040000–20260929043000. النشر: شغّل فحص مديري المدارس (قراءة فقط) قبل الترحيل، ثم مهمّة نشر الإعدادات بعده (deploy/cloud-run/DEPLOY.md).
- كل قيمة دخول تُستعمل مرة واحدة تُحفظ مُجزَّأة فقط. روابط استعادة كلمة المرور، وروابط الدخول السحرية، وتحدّيات مفاتيح المرور، وحالة الدخول بحساب Google، ورمز التسليم بعد الدخول بحساب Google، كلها الآن في جدول واحد ولا يُحفظ منها إلا بصمة SHA-256. كان
challengeIdلمفتاح المرور وstateالخاص بـ Google ورمز التسليم?code=يُحفظ كما أُرسل، فكانت نسخة من قاعدة البيانات تكفي لإتمام دخول شخص آخر خلال الدقائق القليلة التي تصلح فيها. ما زالت كل قيمة صالحة لمرة واحدة ولوقت قصير، وتُرفض قيمة من نوع إذا قُدِّمت على أنها من نوع آخر. الروابط والرموز الصادرة قبل التحديث تبقى صالحة بعده. - إصلاح: لم يكن استيراد القوائم من جديد قادرًا على نقل مدير مدرسة إلى مدرسة أخرى. كان الاستيراد يرفض الدفعة كلها على أنها قديمة. صار لكل مدير مدرسة مؤشّر واحد إلى مدرسته، والنقل يُحرّر المدرسة السابقة.
- مدير واحد لكل مدرسة تفرضه قاعدة البيانات على سجل المدير نفسه، وهو ما تقرؤه فحوص الصلاحيات دائمًا. حذف مدير المدرسة أو محو بياناته يُحرّر المدرسة، ويبقى سجله (مستواه).
- لا تغيير على المستخدمين: أُزيل جدول الأدوار غير المستعمل وجدول ملف مدير المدارس الفارغ. دور المستخدم هو شخصيّته، ونطاق مدارس مدير المدارس محفوظ كما كان.
النقاط والشارات ولوحات التقدّم تمتلئ من تقدّم حقيقي — 2026-09-29
لا عمليات جديدة، ولم يتغيّر شكل أي طلب أو استجابة (openapi:check سليم). لا ترحيل.
- إصلاح: كان رصيد النقاط صفرًا لكل طالب، وكانت لوحات التقدّم كلها أصفارًا. لم تكن اللحظات المقيسة التي تستحق حدث إتقان تُسجَّل. صارت تُسجَّل الآن في معاملة قاعدة البيانات نفسها التي يُتّخذ فيها القرار:
- انتقال مهارة من «متابعة» إلى «متمكّن» بناءً على أدلة جديدة (
subskill_state_up)؛ - تحسّن مهارة من ضعف إلى «متابعة» (
skill_status_transition)؛ - وصول مجال إلى «متمكّن» (
domain_status_escalation)؛ - اتجاه طلاقة أعلى من خطّ الهدف (
cbm_trend_above_goal)؛ - ارتفاع مستوى الصعوبة في التدريب (
band_progression)؛ - انتهاء خطة دعم لأنها حقّقت معيارها (
bundle_completion).
- انتقال مهارة من «متابعة» إلى «متمكّن» بناءً على أدلة جديدة (
- ما لا يُحتفى به. أول تقييم (لا نموّ يُقاس منه بعد)، والقرار الذي لم يُحسم أو الذي لم يُقيَّم مجاله إلا جزئيًا، ونافذة اتجاه فيها تراجع حادّ، والخطة المنتهية لسبب آخر، وإعادة القرار على الأدلة نفسها: لا شيء من هذا يُسجَّل. وكل لحظة تُسجَّل مرة واحدة، فتكرار القرار نفسه لا يضيف شيئًا.
- لا يُسجَّل بعد، عن قصد. «تحقيق هدف خطوة في الحزمة» (الخطط بلا خطوات في الموجة الأولى)، ورفع مستوى الدعم المتدرّج (لا يتغيّر إلا بتعديل من المعلّمة، لا بقياس).
- لوحات التقدّم للصف ولصفوف المعلّمة وللمدرسة تُقرأ من هذه الأحداث عند الطلب. ولا لوحة تقدّم للطلاب، كما كان.
رصد الإجابات السريعة من زمن الإجابة — 2026-09-29
لا عمليات جديدة، ولم يتغيّر شكل أي طلب أو استجابة. الترحيل 20260929020000_p3c2_rbm_detector. النشر: شغّل مهمة نشر إصدار الإعدادات بعد الترحيل وقبل الإطلاق (deploy/cloud-run/DEPLOY.md)، وإلا توقّف رمز القرار الجديد عند إصدار لا يحتوي العتبة الجديدة.
- مؤشرات السلوك تأتي الآن من إجابات حقيقية. الإجابة التي تُعطى في أقل من 300 ملّي ثانية (زمن السؤال بعد طرح زمن الإيقاف المؤقت) تُسجَّل مرة واحدة إجابةً سريعة (RBM-01) مرتبطةً بتلك الإجابة. وإذا كانت 40٪ أو أكثر من الإجابات المُقاسة زمنيًا لمهارة في جلسة واحدة سريعة، تُسجَّل الجلسة أيضًا مرة واحدة على أنها تخمين سريع محتمل (RBM-02). إجابات الورق والإجابات التي لم يُقَس زمنها لا تُعلَّم أبدًا. قبل ذلك لم يكن شيء يسجّل هذه المؤشرات، فلم تؤثّر في أي قرار.
- ما الذي يغيّره المؤشر. الإجابة السريعة الواحدة معلومة فقط: تبقى الحالة كما هي، ولقطة حالة المهارة تذكر المؤشر. أما نسبة الإجابات السريعة على مهارة بوابية أو أساسية ضعيفة فلا تؤكّد الضعف ولا تفتح مجموعة التحقّق القصيرة، بل تحيل المهارة إلى مراجعة قصيرة لصلاحية القياس. المؤشر لا يغيّر أي علامة ولا يُنشئ ضعفًا أبدًا.
- العتبات من الإعدادات. حدّ 300 ملّي ثانية هو العتبة الجديدة
TH-RAPID-ITEM-01، ونسبة 40٪ هيTH-RAPID-SS-01(ولم تكن لها قيمة). تُقرآن من إصدار الإعدادات الفعّال. حدّ 300 ملّي ثانية قيمة عمل مؤقتة إلى أن يؤكّد الشريك الرقم. ومحرّك أنماط الأخطاء في التدريب يستعمل الحدّ نفسه بدل نسخته الخاصة. - إعادة حساب القرار لا تكرّر المؤشرات. يُخزَّن كل مؤشر مرة واحدة لكل إجابة (أو جلسة) وقاعدة ومجموعة عتبات. العتبة المعدَّلة تسجّل مؤشرات جديدة بعد نشرها، والقرارات تقرأ فقط المؤشرات المسجّلة بالعتبات الحالية.
الحصص المباشرة تفتح أنشطتها، وحُذفت جداول غير مستخدمة، وأسماء المجالات تتبع تصنيف المهارات — 2026-09-29
حُذفت مسارات: مسارات جهاز العرض المخصَّص (POST .../personalized-projector/setup وGET .../answer-key وPOST .../mark وPOST .../commit)، وPOST /api/sync/sessions/{id}/observation، وGET /api/skill-dependencies. لم يعد POST /api/sync/sessions يقبل personalizedProjector، ولم يعد ملخّص الحصة يسرد الملاحظات، ولم يعد GET /api/sub-skills/{id} يضمّن dependencies. لم يكن تطبيق الويب يستدعي أيًّا منها (أُعيد توليد المواصفة وopenapi:check سليم). الترحيلات 20260929030000–20260929033000.
- إصلاح: لم يكن الطالب يستطيع الإجابة في الحصة المباشرة. بدء الحصة يفتح الآن أول نشاط فيها، وكل «التالي» يفتح النشاط الذي يليه، ويذكر تدفّق الاستطلاع النشاط الذي يجيب عنه كل جهاز. قبل ذلك لم يُفتح أي نشاط، فلم يكن لدى شاشة الطالب ما تُرسل الإجابة إليه.
- جهاز العرض المخصَّص وملاحظات القراءة الجهرية ينتقلان إلى الموجة الثانية. حُذفت مساراتهما وجداولهما الثلاثة.
- حُذفت جداول لم يستخدمها أحد: قوالب الأنشطة الجماعية، وبيانات جودة الجلسة، وخريطة تبعيات المهارات الفارغة دائمًا، ولقطات لوحات الصدارة (تُحسب اللوحات عند قراءتها)، وفهرسا فئات الأخطاء وقواعد الأدلة (صارت فئات الأخطاء الثلاث عشرة قيدًا على جدول الأنماط الدقيقة).
- بيانات جاهزية الإحماء تُحفظ في جلسة الإحماء نفسها. تُكتب مرة واحدة عند اكتمال الإحماء ولا يمكن تغييرها بعد ذلك.
- جدول واحد لإعدادات المحرّكات. حدود أمانة التنفيذ، وأسابيع الخروج عن المسار، وحدّ اتجاه الطلاقة، وأوزان توصية الجلسات، ونِسَب حاجة الصف صارت في جدول واحد بإصدارات هو
engine_parameters. القيم لم تتغيّر. النشر: شغّلpnpm config:publishبعدmigrate deploy. - أسماء المجالات تطابق تصنيف المهارات. مؤشرات المجالات لدى مدير المدرسة ومدير المدارس تستخدم الآن أسماء المجالات العربية نفسها المستخدمة في بقية المنصة (مثلًا «دقة وطلاقة القراءة» بدل «الطلاقة والدقة»). أُرسلت التسميات السابقة إلى الشريك للتأكيد.
- خريطة علاقات المهارات تغطّي المهارات الثمانين كلها. المهارتان اللتان أُضيفتا بعد خريطة الشريك (VOCAB-C06 وMORPH-C01) معلَّمتان بأن الشريك لم يربطهما بعد، ولم تُخترَع لهما أي علاقة.
استوديو الأسئلة يؤلّف أسئلة مطابقة الكلمة بمعناها — 2026-09-26
لا عمليات جديدة، ولم يتغيّر شكل أي طلب أو استجابة (openapi:check سليم). لا ترحيل.
- قالب إنتاج جديد
COMPREHENSION_WORD_MATCHING(productionKind {kind: "match_pairs"}) مثبَّت على نوع السؤال بالاسم نفسه، ويظهر فيGET /api/templates. يحتاج قطعة مرتبطة ومفتاح أزواج صحيحًا: الشرط الجديدneedsMatchPairsيطبّق القاعدة نفسها التي تطبّقها بوابة الاستيراد وPATCH /api/items/{id}(من 2 إلى 6 أزواج، كلمات ومعانٍ غير مكرّرة، معانٍ إضافية مختلفة عن الحقيقية، 8 معانٍ على الأكثر). لا يأخذ السؤال القالب إن لم يستوفِها (يعيدPOST /api/items/previewوالتعديل 422 مع السبب بالعربية). ولا يغيّر القالب ما يُقدَّم للطالب: النوع نفسه يقدّم لوحةmatch_pairs. أما قوالب المطابقة التجريبية (PAIR_DRAG_COLUMNSوDRAG_MATCH_BOARDوMATCH_LETTER_FORMSوRHYME_MATCH) فتبقى للمعاينة فقط. - النوع مشتقّ التقديم: لا يُسنَد إليه قالب اختيار من متعدد أو اختيار متعدد، ولا يُسنِد التعبئة التلقائية إليه إلا قالبه.
- يحرّر استوديو الأسئلة الأزواج والمعاني الإضافية، ويوقف الحفظ بالقواعد نفسها، ويقيّم لوحة الطالب في المعاينة.
النشر: شغّل
seed-mainمرة واحدة ليصل صفّ القالب (وصفّ نوع السؤال من P8) إلى جداول الكتالوج.
القرارات تقرأ حكم العام الدراسي الحالي، والقياس المتأخر يحتفظ بعامه، وغياب مفتاح منصات التعلّم يُبلَّغ بوضوح — 2026-09-28
ثلاثة مسارات صار لها ردّ 503 موثَّق (أُعيد توليد المواصفة وopenapi:check سليم)، ولم يتغيّر شكل أي طلب أو استجابة آخر.
- إصلاح: كان نقل المستوى قد يعتمد على حكم متابعة من العام الماضي. صارت أدلة نقل المستوى، وإشارة المتابعة في نظام الاستجابة للتدخّل، وإشارة النموّ في أمانة التنفيذ، وضابط التفعيل، وملفّ غرفة البيانات، تقرأ حكم العام الدراسي الحالي للطالب فقط. كانت في بداية العام الجديد تقرأ حكم حزيران الماضي بجانب قياسات هذا العام التي لم تُسجَّل بعد. غياب حكم في هذا العام يُعدّ «لم يُقرَّر بعد».
- إصلاح: كان القياس المُدخَل متأخرًا يُنسب إلى العام الجديد. قياس المتابعة أو قراءة الطلاقة أو قراءة قائمة الكلمات المؤرَّخة قبل الترفيع تحتفظ الآن بالعام الدراسي للصف الذي كان فيه الطالب حينها، فلا تتسرّب إلى أول قرار في العام الجديد.
- غياب مفتاح تشفير منصات التعلّم يُبلَّغ بوضوح. صار رفع ملفات OneRoster وقراءة المساقات ومعاينة الاستيراد تجيب بـ
503 SSO_NOT_CONFIGUREDبدل خطأ 500 عامّ، ولا يُخزَّن شيء. والمزامنة التي لا تستطيع فتح التفويض تسجّل تشغيلًا فاشلًا (token_key_missing) وتُبقي الاتصال فعّالًا. - ترتيب ثابت لسجلّ قرارات المستوى. القرارات المتّخذة في اللحظة نفسها تُعرض من الأحدث بحسب ترتيب تسجيلها، وبالترتيب نفسه في كل مرة.
الأوقات بمنطقة زمنية، وبصمة واحدة مملّحة لعنوان IP، وتشفير رموز منصات التعلّم — 2026-09-28
لا عمليات جديدة، ولم يتغيّر شكل أي طلب أو استجابة (openapi:check سليم). الترحيلات 20260928030000_p3b3_timestamptz و20260928031000_p3b3_ip_hash_single_helper و20260928032000_p3b3_lms_tokens_encrypted.
- كل وقت مخزَّن لحظةٌ محدّدة. كان 62 عمودًا بلا منطقة زمنية، في جداول المستخدمين والجلسات ورموز الدخول وسجلّ أحداث الدخول والمؤسسات والمدارس والصفوف والتسجيل ومنصات التعلّم والتجربة. صارت كلها
timestamptz، وحُوّلت على أنها بتوقيت UTC فلم تتغيّر أي لحظة مخزّنة. كانت جلسة قاعدة البيانات التي تعمل بمنطقة زمنية أخرى تقرؤها مُزاحة بفارق تلك المنطقة. أُعيد بناء سجلّ أحداث الدخول بأقسامه الشهرية نفسها. - عناوين IP المخزّنة بصمات مملّحة دائمًا. كان سجلّ أحداث الدخول ورموز رابط الدخول يحفظان بصمة غير مملّحة يمكن عكسها إلى العنوان، وكان سجلّ التدقيق الأمني يحفظ العنوان نفسه. صارت كلها تحفظ البصمة المملّحة نفسها التي يستعملها نموذج التواصل والتجربة. الملح مشتقّ من
AUTH_JWT_SECRETوليس مفتاح التوقيع نفسه. مُسحت القيم القديمة لأنه لا يمكن تمليحها بعد تخزينها. - رموز ربط منصات التعلّم مشفّرة. رموز الوصول والتحديث من Google Classroom وملفات OneRoster تُشفَّر بخوارزمية AES-256-GCM بالمفتاح الجديد
LMS_TOKEN_KEY، وقاعدة البيانات ترفض الرمز غير المشفّر. من دون المفتاح يُجيب ربط المنصة بالرمز 503 ولا يُخزَّن شيء. الاتصال الذي كان يحمل رموزًا غير مشفّرة أُعيد إلى الحالةrevoked، فيعيد المسؤول ربطه. النشر: أنشئ السرّlms-token-keyقبل النشر (deploy/cloud-run/DEPLOY.md).
متابعة التقدّم والطلاقة لكل سنة دراسية، وقرارات المستوى تسجّل انتقالها — 2026-09-28
لا عمليات جديدة. تضاف حقول إلى استجابتين ويضيق حقل في طلب واحد (أُعيد توليد openapi:check). الترحيل 20260928010000_p3b1_year_window_tier.
- إصلاح: خطة امتدت عبر العطلة الصيفية كانت تحكم على السنة الجديدة من قياسات السنة الماضية. صارت أدلة المتابعة وأحكامها وتنبيهات التراجع الحاد تحمل السنة الدراسية (مثل
2026-2027) مأخوذة من صف الطالب. الحكم يقرأ أدلة سنته فقط، وإعادة الحساب في سنة جديدة حكم جديد، لا حكم السنة الماضية على أنه «محسوم من قبل». - إصلاح: التراجع في سنة جديدة كان يعيد استخدام تنبيه السنة الماضية المفتوح. تنبيه التراجع الحاد ينتقل مع الطالب إلى صفه الجديد، فكان التراجع في السنة الجديدة يجد تنبيه السنة الماضية المفتوح للنافذة نفسها ولا يفتح تنبيهه. صار يُحفظ تنبيه مفتوح واحد لكل طالب وصف وسنة دراسية ونافذة. البوابات التي تسأل «هل ما زال تنبيه مفتوحًا» لم تتغيّر: التنبيه الذي لم يُراجَع من سنة سابقة ما زال يعني المراجعة أولًا.
- إصلاح: ملخّص الطلاقة قد يعرض قراءة السنة الماضية على أنها قراءة هذه السنة. قياسات القراءة الجهرية (
cbm_scores) تحمل سنتها الدراسية، وملخّصا الطلاقة للصف والمدرسة يقرآن قياسات سنة كل صف فقط. - الحقل
windowفيPOST /api/monitoring/evidenceيقبلBOYأوMOYأوEOYفقط (كان أي نص يُخزَّن كما هو؛ صار خطأ 400). النوافذ المخزّنة قيم نافذة محدّدة النوع. GET /api/monitoring/alertsيعيدacademicYearلكل تنبيه، وassessmentWindowIdصارBOYأوMOYأوEOYأو فارغًا.- قرارات المستوى تسجّل الانتقال الذي أحدثته. يعيد
GET /api/students/{id}/tier-decisionsالحقلينfromTierوtoTierلكل قرار، ويعرضهما سجل القرارات في غرفة البيانات. يُكتبان مع تغيير المستوى نفسه، فلم يعد التصعيد في أعلى مستوى (دون انتقال) يلتبس بانتقال حقيقي. وترفض قاعدة البيانات قرارًا جديدًا بدونهما أو بانتقال لا يطابق نوع القرار. - لقطات حالة المهارة والمجال والمجال الكبير يجب أن تحمل سنة دراسية. أُزيلت القيمة الافتراضية الفارغة وصار شكل السنة مُتحقَّقًا منه.
- الصفوف الموجودة أُعطيت السنة الدراسية لصف الطالب وقت كتابة الصف (القاعدة نفسها في تغيير 2026-09-26). وقرارات المستوى السابقة أُعطيت
fromTierوtoTierبإعادة تشغيل قرارات كل طالب بالترتيب؛ وحيث لا تنتهي الإعادة عند مستوى الطالب الحالي تبقى فارغة ولا تُخمَّن. والنافذة المخزّنة التي ليستBOYأوMOYأوEOYتوقف الترحيل وتذكر القيمة.
مراجع حقيقية، وسجلّات تدقيق تحميها قاعدة البيانات، ومفردات لهجة واحدة — 2026-09-28
لا عمليات جديدة، ولم يتغيّر شكل أي استجابة (openapi:check سليم). الترحيلات 20260928020000_p3b2_soft_ref_fks و20260928020100_p3b2_append_only_triggers و20260928020200_p3b2_controlled_vocabularies.
- صار 43 مرجعًا كانت أرقامًا مجرّدة مفاتيحَ أجنبية حقيقية: جلسات الدرس المتزامن ومشاركوها ومجموعاتها وأنشطتها وإجاباتها، وطلبات المدير، وأحكام المتابعة ولقطات الالتزام بالتنفيذ وقرارات مستوى الدعم وتثبيت التجميع، والجلسات المولَّدة ومخطّطاتها وعمليات التجميع، وجلسات القراءة الجهرية ونصوصها، وصفوف الأدلّة ولقطات الحالة المُطلِقة وقيود عكس النقاط، ومؤشّرات بنك الأسئلة. يُرفض أي صف يشير إلى طالب أو جلسة أو خطة أو نص غير موجود، أو إلى مدرسة أو جلسة متزامنة لمؤسسة أخرى.
- كل صف لدرجة القراءة الجهرية يشير الآن إلى جلسة القراءة التي أُخذ منها (
cbm_scores.oralReadingAssessmentId). ربط الترحيلُ الصفوفَ الموجودة. - الطلب
POST /api/sync/sessions/{id}/responsesيعيد 404 إذا لم يكنactivityRunIdنشاطًا في تلك الجلسة. كان يخزّن أي نص. - صارت 22 جدولًا إضافيًا للإلحاق فقط بقادح في قاعدة البيانات، منها سجلّات الدخول والأمان، ومراجعات الأسئلة والنصوص، وخطط المتابعة، وعلامات تعديل البرنامج، وسجلّات الجلسات، وتنبيهات المنصّة، وأحداث التهيئة، وعمليات التجميع، وسجلّات الوصول والإعداد، وسجلّ الملفات. مسار المحو يفتح نافذة الصيانة حول الصفوف التي يمحوها فقط.
- مفردات لهجة واحدة. تُخزَّن لهجة الطالب في البيت بالقيمتين
msaوlevantine، وهما القيمتان المستعملتان في الأسئلة وفي التسليم. واجهة المستخدمين وملف القائمة ما زالتا تقبلانMSAوLEVوتعيدانهما. - استيراد الأسئلة يتحقّق من
dialect_tagsوevidence_type. وسوم اللهجة المقبولة هيmsaوlevantineوlevبأي حالة أحرف. يُحذف رمزا البلدPSوJO. أي وسم آخر يرفض الصف بسببmissing_metadata، وكذلك قيمةevidence_typeالتي ليست نوعَ دليل. حُوّلت الأسئلة المخزّنة: صار["msa","PS"]هو["msa"]، والأسئلة الستة من الشريك التي كان نوع دليلهاaudioصارت بلا نوع دليل.
رحلة الطالب v2 — القطعة بجانب أسئلتها، مطابقة الكلمة بمعناها، وتقييم كل جزء على حدة — 2026-09-26
لوحة الشريك D-02 (2026-09-26) وقرارات محمد الأربعة في اليوم نفسه. لا عمليات جديدة. الترحيلان
20260928040000_practice_opened_by و20260928040100_comprehension_word_matching.
- نوع سؤال جديد
COMPREHENSION_WORD_MATCHING(استراتيجية التصحيحpair_mapping): يسحب الطفل كل كلمة إلى معناها. المفتاحinteractionKey = {kind: "match_pairs", pairs: [{l, r}], extraRights?: [...]}بالنصوص (من 2 إلى 6 أزواج، كلمات ومعانٍ غير مكرّرة، ومعانٍ إضافية مختلفة عن الحقيقية، و8 معانٍ على الأكثر). تتحقّق منه بوابة الاستيراد وPATCH /api/items/{id}وتحفظانه بصيغة موحّدة؛ ويحتاج — ككل صفوفCOMPREHENSION_*— إلى قطعة وعملية قراءة وموضع إجابة. يُقدِّمGET /api/items/{id}?view=servedالحقلinteraction = {kind: "match_pairs", left, right}: الكلمات بترتيب التأليف والمعاني بترتيب ثابت في الجلسة لا يطابق الكلمات صفًا بصف. والإجابة{v: 1, kind: "match_pairs", pairs: [{l, r}]}، وتُصحَّح كلها أو لا شيء (يبقى θ ثنائيًا). - تقييم كل جزء في التدريب (
POST /api/practice/queues/current/submit-response): تحمل الاستجابةparts: [{part, correct}]بعد الخطأ الأول في سؤال ذي أجزاء (زوج مطابقة: الجزء هو الكلمة؛ فراغ في إكمال متعدد: الجزء رقم الفراغ من 0؛ موضع في ترتيب: الجزء رقم الموضع من 0) — أحكام فقط بلا إجابات. وبعد الخطأ الثاني يذكرcorrectAnswer.parts: [{part, answer}]الأجزاء التي بقيت خاطئة فقط. وكلاهماnullللأسئلة ذات الإجابة الواحدة. ويبقى الحكم المحفوظ وθ على مستوى السؤال كله. - استراحة التقييم المعمّق بعد القطع الطويلة فقط: استُبدل
partSizeفي حالة الجلسة بـbreakBefore: boolean—trueعلى السؤال الذي يلي قطعة قراءة من 80 كلمة فأكثر. - أي تدريب مفتوح: يحمل
GET /api/practice/students/{id}/training-sessionsالحقلcurrentTraining({openedAt, openedBy: "automatic" | "teacher"} | null)، من العمود الجديدstudent_session_practice.openedByUserId(يُملأ حين تستخدم المعلّمة «تعيين التدريب»).
قواعد القرار تُقرأ من أعمدة ذات أنواع محدّدة، وحذف الجلسات المنتهية وسجلّات تحديد المحاولات — 2026-09-27
لا عمليات جديدة، ولم يتغيّر شكل أي طلب أو استجابة (openapi:check سليم). الترحيلان 20260927030000_p3a3_typed_rule_columns و20260927030100_p3a3_drop_duplicate_auth_indexes.
- قواعد حالة المهارة لم تعد تعتمد على JSON مخزّن في حقل الملاحظات. صارت أعمدةً ذات أنواع محدّدة: علامة الحوكمة في القاعدة ADR-GOV-01، ومجموعات الأنماط البديلة في قواعد ADR وPAC وSSR، ونطاق قواعد CIS وحدّها الأعلى من البنود وشرط فتح البند الثالث، ومعرّفات قواعد الأنماط وحالات المجال وربط المجالات الكبيرة. كانت الملاحظات التي يتعذّر تحليلها تُعامَل كأنها فارغة، فقد تتحوّل ADR-GOV-01 بصمت إلى قاعدة عادية. الملاحظات الآن للتوثيق فقط.
- قواعد الملف الشخصي تُتحقّق منها ولا تُخمَّن. نمط كل قاعدة عمود JSON يُتحقّق من صحته. قرار منع التداخل وقائمة الصفوف والمعدِّلات المسموحة ومستوى الثقة أعمدة ذات أنواع محدّدة. كانت عبارة الثقة غير المعروفة تصبح
moderate، والنمط الذي يتعذّر تحليله يجعل القاعدة لا تطابق أحدًا (أو تطابق الجميع في القاعدة الأساسية). البذر يرفض الآن مثل هذا الصف. - القيمة الناقصة أو غير الصحيحة في قاعدة توقف إعادة الحساب بخطأ مسمّى (
SseRuleValueErrorوProfileCatalogValueError) بدل قيمة افتراضية. ونشر إصدار الإعدادات يرفض النمط غير الصحيح أيضًا. الإصدارات المنشورة قبل هذا التغيير ما زالت قابلة لإعادة التشغيل: تُحوَّل صفوفها المخزّنة عند القراءة، والمحتوى القديم التالف خطأ. - حوّل الترحيل الصفوف الموجودة من النص القديم. مجموعات القواعد المحمّلة مطابقة لما كانت عليه بايتًا ببايت، فلم يتغيّر أي قرار.
- يحذف
auth:purgeالليلي الآن الجلسات التي انتهت صلاحيتها منذ أكثر منAUTH_PURGE_INACTIVE_SESSION_DAYSيومًا ولو لم يسجّل أحد الخروج. كان يحذف الجلسات الملغاة فقط، فتبقى بصمات رموزها إلى الأبد. ويحذف كذلك صفوف تحديد المحاولات الهادئة بعد انقضاء نافذة كل محدِّد وغير المقفلة. مفاتيح هذه الصفوف هي البريد أو العنوان الذي يكتبه أي شخص، فكان الجدول ينمو بلا حدّ. التشغيل يُبلغ عن عدد جديدrateLimitWindow. - حُذف فهرسان يكرّران الفهرس الفريد على العمود نفسه:
Session.tokenوUser.email.
سلسلة قرارات الاستجابة للتدخّل: إشارات كانت تُقرأ ولا تُكتب — 2026-09-27
لا عمليات جديدة، ولم يتغيّر شكل أي استجابة (openapi:check سليم). صارت بعض الحقول تحمل قيمة بعد أن كانت فارغة دائمًا. الترحيلات من 20260927020000 إلى 20260927025000.
- «التأكيد والتصعيد» من المعلّم يصل الآن إلى المراجِع. الطلب
POST /api/workflow/reviewمعdispositionType: escalatedيفتح طلب مراجعة لمستوى الدعم في القائمة نفسها التي يقرؤها المدير والمعتمِد (tier_review_requestمع حزمة قرار)، وtierReviewRequestIdفي الاستجابة هو معرّف هذا الطلب. إذا كانت للطفل مراجعة جارية ارتبط التصعيد بها. حُذف الجدول القديمteacher_review_requestلأن أحدًا لم يكن يقرؤه. - تُرفض جلسة الحزمة ما دام تنبيه التراجع الحادّ مفتوحًا. صار قيد مُجمِّع الجلسات يقرأ تنبيه التراجع الحادّ المفتوح (التنبيه الذي يراجعه المعلّم). كان يقرأ نوع تنبيه لا يكتبه شيء، فلم يرفض أي جلسة. حُذف من
rti_alertالنوعانacute_regression_reviewوtier_review_dueلأنهما لم يُكتبا قط. - الخطة المُنهاة تُظهر سبب إنهائها. سجلّ الخطط لدى المدير (
GET /api/principal/students/{id}/plan?includeHistory=true) يعيدexitReasonCodeوتسميته من انتقال الإنهاء في سجلّ حالات الخطة. حُذفت تسعة أعمدة منbundle_assignmentلم تُكتب قط. وصارactivePlan.objectTypeفي تقرير الطالب يُؤخذ من تعريف الحزمة فيظهر بقيمته. - إشارة «غرفة البيانات مطلوبة» تعمل. يُحتسب الطالب في صفه إذا كانت له حزمة قرار مفتوحة لمراجعة المستوى أو لمراجعة الاستمرار (مسودة أو قيد المراجعة). كانت تقرأ عمودًا لا يكتبه شيء فلم تظهر قط.
- مستوى الدعم الموصى به في شارة المستوى صار يظهر. كل قرار في مستوى الدعم يضبط
recommendedSupportIntensityعلى ما يوافق المستوى الناتج (universalأوtargetedأوintensive)، وعُبّئت الصفوف الموجودة. - لم تعد أحكام المتابعة تتكرّر. إعادة الحساب على الأدلّة والوصفة والقواعد نفسها تعيد الحكم المخزَّن بدل كتابة حكم جديد، والدليل الجديد يضيف حكمًا واحدًا. تسجيل دليل واحد يكتب الآن حكمًا واحدًا لا حكمين.
- إعدادات الأمانة في التطبيق والمتابعة صارت إعدادات حقيقية. حدود تقدير الأمانة (0.80 / 0.60 / 0.40) وإعدادات المتابعة (الخروج عن المسار بعد 3 أسابيع، ودورة تخطيط من 6 أسابيع ما زال الشريك مدينًا بها ضمن Q-FID-CYCLE) صارت صفوفًا مزروعة في كل إصدار إعدادات، والمحمِّلات ترفض العمل من دونها بدل قيم افتراضية مخفية. النشر: شغّل مهمة نشر الإعدادات بعد الترحيلات.
كل مدرسة تحدّد متى يبدأ عامها الدراسي، والفحص ينتظر الترحيل إلى العام الجديد — 2026-09-26
عمليات تغيّرت: POST /api/schools وPATCH /api/schools/{id} وكل استجابة للمدرسة تحمل schoolYearStartsOn؛ وGET /api/organizations/{orgId}/school-years واستجابة الترحيل تحملان rolloverDue وrolloverDueSchoolIds؛ وقد يردّ POST /api/diagnostic-sessions/start بالرمز 409 والسبب year_not_rolled_over؛ وأُضيفت القيمة year_not_rolled_over إلى screeningState في خطة يوم الطالب وإلى projection.skippedReason في القراءة الجهرية وقوائم الكلمات (openapi:check سليم). الترحيل 20260928050000_school_year_start_per_school.
- قاعدة واحدة للعام الدراسي. كان الفحص يحسب العام الدراسي من 1 آب بينما تمتد صفوف
school_yearمن 1 أيلول، فكان جانب الطالب وصفوف الأعوام يختلفان في شهر آب على أيّ عام هو (فحص نهاية العام في حزيران كان يتوقّف احتسابه في 1 آب). صار العام الدراسي يبدأ في 1 أيلول في كل مكان ما لم تحدّد المدرسة بدايتها. schoolYearStartsOnللمدرسة: بصيغة"MM-DD"بين07-01و10-31على التقويم المحلي للمؤسسة، وnullتعني 1 أيلول. يحدّد «هذا العام الدراسي» في الفحص (فحص واحد لكل نافذة في العام). على المدرسة التي تفتح أبوابها في أواخر آب (افتتحت المدارس الحكومية في الأردن في 23 آب 2026) أن تضبطه، وإلا احتُسبت فحوصها في آب ضمن العام السابق. القيمة غير الصالحة تُرفض بالرمز 422.- إصلاح: كان الفحص الذي يُجرى قبل الترحيل يُسجَّل تحت العام الماضي. إذا كانت نافذة فحص مفتوحة وصفّ الطالب ما زال يحمل عامًا دراسيًا انتهى بحسب يوم بداية مدرسته، فلا يُعرض الفحص ولا يبدأ (
year_not_rolled_over، والرمز 409 عند البدء، حتى إن سمّى المعلّم أو المشرف النافذة)، وتُحفظ القراءة الجهرية أو قائمة الكلمات التي يقيّمها المعلّم من دون أن تدخل في صورة المهارات (skippedReason: year_not_rolled_over)، ويرى الطفل لوحة الانتظار الهادئة نفسها كما في أي يوم لا مهمة فيه. قبل ذلك كانت الجلسة تُخزَّن تحت تسمية العام الماضي، وبعد الترحيل يبدو كأن الطالب فُحص من قبل. rolloverDueفي العام الدراسي النشط يصبح صحيحًا حين تبدأ أيّ مدرسة من مدارس المؤسسة عامها التالي، وrolloverDueSchoolIdsتسمّي هذه المدارس. رحّل العام (POST …/school-years/{yearId}/promote) لإعادة فتح الفحص.- يبقى
startsOnوendsOnفي صفschool_yearعلى البداية الافتراضية (1 أيلول ← 31 آب) وهما للعرض فقط. والطالب الذي لا صف له يُحسب عامه من البداية الافتراضية على التقويم المحلي (كان 1 آب وبتوقيت UTC).
أدلّة الفحص والملفات التعليمية تُحفظ لكل سنة دراسية — 2026-09-26
لا عمليات جديدة، ولم يتغيّر شكل أي طلب أو استجابة (openapi:check سليم). الترحيل 20260927010000_p3a1_windowed_rows_academic_year.
- إصلاح: كان الفحص الجديد للطالب العائد يُحسم جزئيًا من فحص العام الماضي. الصفوف التي تُحسب منها حالة المهارة (إجابات الفحص لكل مهارة، ونتائج القراءة الجهرية وقوائم الكلمات، وإجابات مجموعات التأكيد المصغّرة ونتائجها، ومراجعات الصلاحية، وتصنيفات الأنماط، ونتائج الجلسات) كانت تُخزَّن حسب نافذة التقييم (
BOYوMOYوEOY) من دون سنة دراسية. لذلك كان فحصBOYفي السنة الثانية يقرأ صفوفBOYمن السنة الأولى أيضًا، ويحتسب مهارات العام الماضي ضمن تغطية المجال هذا العام، وقد يلتقط مجموعة تأكيد مصغّرة لم تكتمل في العام الماضي. صار كل صف من هذه الصفوف يحمل سنته الدراسية (مثل2026-2027) المأخوذة من صف الطالب، ولا يقرأ أي قرار إلا صفوف السنة الحالية. - إصلاح: جلسة لم تكتمل في العام الماضي كانت تمنع جلسة هذا العام أو تُستأنف مكانها. صارت جلسات التشخيص ومجموعات التأكيد المستحقة تحمل السنة الدراسية أيضًا، وقاعدة «جلسة مفتوحة واحدة لكل نافذة» صارت لكل سنة دراسية.
- إصلاح: قد يُسجَّل الملف التعليمي مرتين، أو يُطابَق ملف العام الماضي. قاعدة «ملف معلّق واحد لكل طالب وسنة دراسية ونافذة وملف ومجموعة قواعد» تفرضها قاعدة البيانات الآن: حسابان متزامنان يتركان صفًا واحدًا، وحساب السنة الدراسية الجديدة ينشئ ملفًا معلّقًا جديدًا لا ملف العام الماضي.
- الصفوف الموجودة أُعطيت السنة الدراسية للصف الذي كان فيه الطالب وقت كتابة الصف (وإلا فالسنة الدراسية للمؤسسة التي تشمل ذلك التاريخ، وإلا فالسنة الدراسية التقويمية التي تبدأ في 1 آب). مراجعات الصلاحية المعروضة في تقارير المعلّم هي مراجعات السنة الدراسية الحالية.
رحلة الطالب (النسخة 2) — المهمة الثانية على أجزاء، النجوم والشارات، فحص الصوت — 2026-09-26
وفق مسار الشريك J-00 (§0 و§4 و§8) والقرارين D-A وD-D. الفحص الأعمق على أجزاء: صارت حالة جلسة الطالب (start
وstate وresume وresponses) تحمل partSize — 6 لجلسة d_triggered وnull لغيرها — ويعرض المشغّل شاشة استراحة بعد
كل جزء مكتمل (عرض فقط: لم يتغيّر اختيار الأسئلة ولا قاعدة التوقّف ولا الحدّ الزمني). وبطاقة second_assessment في
today-plan صارت resume: false حتى الإجابة الأولى. النجوم والشارات (D-A): أُضيف reward (stars وnewBadge، وnull
عند إعادة الإرسال) إلى POST /api/practice/training/today/feedback، وrewards (stars وbadges[]) إلى
GET /api/student/today-plan — نجمة لكل يوم تدريب منتهٍ، وشارات للجهد (1 و5 و10 و20 يومًا) وللمواظبة (3 أيام في أسبوع)؛
تُشتقّ من training_session، وليست نقاط خبرة ولا تُرتَّب. النشاط: نوعان جديدان من العميل: student_login_completed
(mode وmsToLogin وfailedAttempts وhelpOpened — دون أي شيء مما كُتب) وsound_check (heard وplays)؛ وأُضيف task
اختياريًا إلى next_action_result. أُصلح: رفضُ دفعة النشاط في كل تحميل للصفحة الرئيسية (بسبب المفتاح task)، وخطأ
الترطيب عند استئناف جلسة من بطاقة الصفحة الرئيسية الذي كان يُضيّع أول نقرة للطفل.
رحلة الطالب (النسخة 2) — يوم التدريب: محاولتان، «كيف كان التدريب؟»، «تعيين التدريب» — 2026-09-26
وفق مسار الشريك J-00 والعرض التفاعلي D-01. أصبح التدريب يومًا تدريبيًا: تمرين التفكير ثم التمارين ثم سؤال
«كيف كان التدريب؟» الإلزامي. محاولتان لكل سؤال: الخطأ الأوّل يُبقي السؤال نفسه مع تلميح المشتّت المختار؛ والمحاولة
الثانية تُسجَّل لكنها لا تُحتسب أبدًا في القياس (θ وتوجيه الكتلة 80/60 ومحرّك الأنماط تقرأ المحاولة الأولى فقط)؛ والخطأ
الثاني يكشف الإجابة الصحيحة. تدريب واحد في اليوم، ولا تدريب ما دام فحص أعمق مقترحًا أو معتمدًا أو مفتوحًا. لم يعد
الإحماء قابلًا للتخطّي، ولم يعد يسبق التقييم. الواجهة البرمجية: حقول جديدة outcome وattempt وcorrectAnswer وtraining
في submit-response، وretry وtraining في next-item، وretryItemId وtraining في queues/current/state (قراءة فقط)؛
وعمليات جديدة: POST /api/practice/training/today/feedback وGET /api/practice/students/{studentId}/training-sessions
وPOST /api/practice/students/{studentId}/assign-training. جدول جديد training_session. أُصلح: إعادة التحقّق من قائمة
التسجيلات الصوتية عند كل تحميل، وقبول أحداث plan_action التي ترسلها بطاقة الفحص الأعمق.
قوائم التدريب وتنبيهات التراجع الحادّ عند إعادة القياس أو الانتقال بين الصفوف — 2026-09-26
لا عمليات جديدة، ولم يتغيّر شكل أي استجابة.
- إعادة التشخيص تحفظ سجلّ قائمة التدريب المنتهية. ما زال فتح إعادة التشخيص يؤرشف كل قوائم التدريب السابقة، لكن القائمة غير المنتهية وحدها (نشطة أو متوقفة) تصبح
abandoned. القائمة التي أنهاها الطفل تبقىcomplete(مؤرشفة) ولا يُعاد كتابتها. - تنبيه التراجع الحادّ المفتوح ينتقل مع الطالب. عند تسجيل الطالب في صف آخر (انتقال، أو استيراد قائمة، أو ترفيع السنة الدراسية) تنتقل تنبيهاته المفتوحة إلى الصف الجديد: يراها المعلّم الجديد، وإذا قيس التراجع نفسه مجددًا في الصف الجديد وُجد التنبيه القائم بدل فتح تنبيه ثانٍ.
مراجعة بنية قاعدة البيانات × البرنامج التجريبي الأول: توحيد الفرعين — 2026-09-26
لا عمليات جديدة، ولم يتغيّر شكل أي طلب أو استجابة (openapi:check سليم، 389 مسارًا). الترحيلات: أربعة ترحيلات تمهيدية (20260923125000 و20260925045000 و20260925055000 و20260925090000) تسمح لترحيلات البرنامج التجريبي المنشورة ولترحيلات المراجعة بالعمل بترتيب زمني واحد، وترحيلان لنقل البيانات (20260926010050 و20260926050050)، وزوج التوحيد 20260926110000 / 20260926110100.
- تبقى مراجعة الأساس هي الأحدث (D-SYNC-1). مفاتيح لقطات المهارة والمجال والمجال الكبير هي (الطالب، المهارة أو المجال، السنة الدراسية، النافذة، بصمة الإعدادات،
basisRevision): الأساس نفسه تحت القواعد نفسها لا يكتب صفًّا جديدًا، والأساس المتغيّر (مجموعة تأكيد قصيرة تحسم مهارة معلّقة، أو قياس قراءة جهرية جديد في النافذة نفسها) يضيف مراجعة جديدة. كل قراءة «للأحدث» ترتّب بالسنة ثم إصدار الإعدادات ثم مراجعة الأساس ثم وقت الحساب ثم المعرّف، وأُعيد بناء أعداد لوحة المدير بهذه القاعدة. - بيانات البرنامج التجريبي صارت في الجداول الموحّدة. مستوى الدعم عند كل محاولة تدريب في صفّ الإجابة (
item_response)، ونوع تجربة التدريب ومؤشّر الاستبدال فيstudent_session_practice(ونوع التجربة يسمّي إصدار الإعدادات الذي قُرئ منه)، وتوصية الفحص الأعمق تشير إلى جلستها بمفتاح أجنبي حقيقي وسجلّها فيstatus_transition، ونتيجة قائمة الكلمات تحمل معرّف طالب واحدًا وإصدار الإعدادات الذي جاء منه المستوى. نُقلت الصفوف الموجودة ولم يُحذف منها شيء. - كتالوجات البرنامج التجريبي صارت جزءًا من إصدارات الإعدادات — عشرة جداول يملكها الشريك تُلتقط في كل إصدار وتُقرأ منه.
- سلسلة الملف ثم تنبيهات الاستجابة للتدخّل تعمل مع كل مصدر أدلّة (التشخيص، والقراءة الجهرية، وقوائم الكلمات، وإعادة الحساب بعد مجموعة التأكيد)، لا عند إنهاء التشخيص فقط.
- أداة
purge:demo-tenantsتعمل على أي إصدار من المخطّط (تقرأ ترتيب الحذف من قاعدة البيانات الحيّة) — تُشغَّل قبل النشر كما يشترط WP-S10.
مراجعة بنية قاعدة البيانات — المرحلة 1C: جدول مرحلي واحد لاستيراد القوائم ونظام إدارة التعلّم — 2026-09-26
لا عمليات جديدة، ولم يتغيّر شكل أي طلب أو استجابة (openapi:check سليم). الترحيلان 20260926100000_import_job و20260926100100_import_job_drop_legacy.
- صارت دفعات استيراد ملفات القوائم ومعاينات استيراد نظام إدارة التعلّم تُحفظ في جدولين فقط،
import_jobوimport_row، مع نوعroster_csvأوlms_roster. نسخ الترحيل كل دفعة ومعاينة وصفّ مع الإبقاء على معرّفات الدفعات والمعاينات (ومعرّفات صفوف القوائم)، فيبقى معالج الاستيراد المفتوح يعمل. حُذفت الجداولroster_import_batchوroster_import_rowوlms_import_preview. يبقى سجلّ عمليات مزامنة نظام إدارة التعلّم سجلًّا مستقلًّا لا يُعدَّل، وصار يذكر المعاينة التي أنشأتها كل عملية أو اعتمدتها. - إصلاح: إعادة اعتماد معاينة قديمة من نظام إدارة التعلّم كانت تعيد آخر عملية مزامنة للاتصال بدل عمليتها هي. صارت تعيد عملية تلك المعاينة.
- إصلاح: اعتماد المعاينة نفسها مرّتين في اللحظة نفسها كان قد يضيف الأشخاص مرّتين ويسجّل عمليتَي مزامنة. صار الاعتماد الثاني ينتظر ثم يعيد نتيجة الأوّل.
- إصلاح: المزامنة الليلية التلقائية كانت تظهر في سجلّ المزامنة كأنها اعتماد يدوي من المسؤول. صارت تظهر بـ
triggeredBy: cronوautoApplied: true. - إصلاح: محو بيانات شخص صار يزيل صفوفه أيضًا من معاينات نظام إدارة التعلّم التي اعتُمدت (كان يُنظّف المعاينات التي تنتظر المراجعة فقط). وتُحسب هذه الصفوف في
countsباسمimport_row(بدلroster_import_rowوlms_import_preview).
مراجعة بنية قاعدة البيانات — المرحلة 2e-2: محو حساب مستخدم بالغ — 2026-09-25
عملية جديدة POST /api/users/{userId}/erase (الوسم erasure، الملف wp-erasure.yaml). الترحيل 20260926070000_audit_action_person_erased.
- يستطيع المسؤول العام الآن محو بيانات معلّم أو وليّ أمر أو مدير أو مدير مدارس أو مسؤول في مكانها، بالطريقة نفسها التي يُمحى بها الطالب. تُزال الأسماء والبريد الإلكتروني واسم المستخدم والهاتف ومرجع الموظّف ومفاتيح المرور وربط Google ونظام إدارة التعلّم والإشعارات الموجّهة إلى الشخص، ورقم هاتف وليّ الأمر وربطه بأطفاله. ويُزال عنوان بريد الشخص أينما سجّله تاريخ تسجيل الدخول، حتى على سجلّ حساب آخر (مثلًا بصفته مستلم رمز دخول طفله). يُغلق إسناده إلى الصفوف، وتُؤرشَف مجموعات الدعم التي يملكها، ويُمسح ربط المدير بمدرسته ونطاق مدير المدارس، ويُلغى اتصال نظام إدارة التعلّم الذي أنشأه (الرموز المخزّنة كانت له). أمّا الخطط والقرارات والاجتماعات والطلبات التي قام بها فتبقى بالمعرّف نفسه، الذي صار يشير إلى حساب بلا هوية يظهر باسم «مستخدم محذوف».
- ضوابط الأمان. يحدّد الطلب المؤسسة (
nullلحساب فريق أمل)، وأيّ شخص خارجها يعيد 404. يُرفض الطالب بالرمز 422PERSONA_MISMATCHمع الإشارة إلى عملية محو الطالب. يُرفض محو حسابك أنت (409SELF_ACTION_FORBIDDEN) ومحو آخر مسؤول عام نشط (409LAST_SUPER_ADMIN)، ويتشارك إيقاف الحساب أو حذفه والمحو قفلًا واحدًا لهذا الفحص. محو آخر مسؤول نشط في المؤسسة مسموح، ويُبلَّغ عنه بـlastOrgAdmin: true. - سجلّ تدقيق واحد (
person_erased) فيه الدور وأعداد الصفوف لكل جدول، ولا يحوي أبدًا القيم الممحوّة. إعادة التنفيذ تعيدalreadyErased: trueولا تغيّر شيئًا. - إصلاحات في محو الطالب (صار المحوان يستخدمان قائمة واحدة لما يعرّف الشخص): بقيت تفضيلات واجهة الطالب (خطّ عسر القراءة، التباين) وسجلّ تحديد محاولات الدخول المرتبط باسم المستخدم بعد المحو؛ وصارا يُزالان الآن. وتزيل القائمة المشتركة أيضًا سجلات التسجيل التجريبي والعرض التمهيدي التي تحمل عنوان بريد الشخص.
مراجعة بنية قاعدة البيانات — المرحلة 2: جدول واحد لجلسات الطالب — 2026-09-25
لا عمليات جديدة؛ أشكال الاستجابات كما هي (openapi:check ناجح بلا فرق في المواصفة). الترحيلان 20260926050000_student_session و20260926050100_retire_session_tables.
- صارت جلسات التشخيص وقوائم التدريب ومجموعات التأكيد جدولاً واحداً هو
student_session، فيه حقلkindقيمتهdiagnosticأوpracticeأوconfirmation، ولكل نوع جدول تفاصيل للحقول الخاصة به. إعادة التشخيص جلسة تشخيص عليها علامة إعادة التشخيص، وليست نوعاً رابعاً، لأنها تمرّ بالمسار نفسه وتخضع لقاعدة «جلسة مفتوحة واحدة لكل نافذة» نفسها. نسخ الترحيل كل جلسة وكل قائمة بمعرّفها نفسه، فتبقى الروابط إليها صالحة؛ وحُذفت الجداولassessment_sessionوpractice_queueوconfirmation_request. - لكل الأنواع قيم الحالة نفسها (
activeوpausedوcompleteوabandoned) وطابعا البدء والانتهاء نفساهما، وتُخزَّن نافذة التقييم بحالة أحرف واحدة (BOYوMOYوEOYبأحرف كبيرة). طلب التأكيد الذي كانopenصارactive، وresolvedصارcomplete. - صارت لمجموعة التأكيد جلستها. لم يكن لها من قبل صفّ جلسة: كانت الأسئلة المعروضة فيها وإجاباتها تحمل اسم جلسة مصطنعاً (
confirm-<رقم>). الآن تشير إلى جلسة التأكيد كأي مسار آخر. وصارت للإجابات والأسئلة المعروضة ونتائج الجلسات ونتائج كتل التدريب ومستلمي جلسات المعلم مفاتيح أجنبية حقيقية إلى الجلسة التي تنتمي إليها، فلا تشير إجابة إلى جلسة غير موجودة. - إصلاح: طلبا تأكيد مفتوحان للمهارة نفسها. لم يكن شيء يمنع وجود طلبي تأكيد مفتوحين للطالب والمهارة والنافذة نفسها. صارت قاعدة البيانات لا تسمح إلا بواحد، وصار فتحه متسلسلاً. أبقى الترحيل أحدث الطلبين المكرّرين مفتوحاً وأغلق الأقدم.
- إصلاح: قاعدة «قائمة تدريب نشطة واحدة» تُطبَّق الآن داخل كل مؤسسة ولا تحسب القوائم المؤرشفة.
- سجلّ حالات لكل الأنواع. صارت تغييرات حالة قوائم التدريب ومجموعات التأكيد تُسجَّل في جدول سجلّ الحالات، كما كانت جلسات التشخيص تُسجَّل.
مراجعة بنية قاعدة البيانات — المرحلة 2g: الصفوف الدراسية والشُّعب والسنوات الدراسية — 2026-09-25
لا عمليات جديدة، ولا تغيير في شكل الاستجابات (openapi:check بلا فروق). الترحيلات
20260926060000_class_school_year_required و20260926060100_class_id_composite_fks و
20260926060200_student_grade_history_every_change.
- كل شعبة تنتمي إلى سنة دراسية. صار الحقل
Class.schoolYearIdإلزاميًا. أعاد الترحيل كتابة التسميات غير المعيارية (“2026/2027” و”2026/27” تصبحان “2026-2027”)، والتسمية التي لا تدلّ على سنة تأخذ السنة الفعّالة للمؤسسة. وأنشأ السنوات الناقصة، وربط كل شعبة بسنة مؤسستها التي تحمل تسميتها. لم يعد ممكنًا أن تختلف تسميةacademicYearللشعبة عن تسمية سنتها، ولا أن تشير الشعبة إلى سنة مؤسسة أخرى؛ ترفض قاعدة البيانات الحالتين. - إصلاح: تنبيه التراجع الحادّ المفتوح يتبع الطالب الآن. يسجّل التنبيه الشعبة التي أُطلق فيها. وكان استثناء
التجميع الذكي وقائمة تنبيهات المعلّم (
GET /api/monitoring/alerts) وقائمة «مراجعة فورية» لدى المدير تعتمد على تلك الشعبة لتحديد من يرى التنبيه. فالطالب الذي انتقل إلى شعبة أخرى أثناء تراجع حادّ كان يمكن أن يُجمَع مع زملائه في الشعبة الجديدة (QA_004)، ولم يكن المعلّم الجديد ولا مدير المدرسة الجديدة يريان التنبيه، بينما بقي ظاهرًا لدى السابقين. أصبحت الثلاثة تعتمد الآن على شعبة الطالب الحالية. - إصلاح: الترفيع السنوي يرفع كل طالب صفًّا واحدًا انطلاقًا من صفّه هو. قد تضمّ الشعبة طلابًا من أكثر من صفّ (FR-SES-7). كان الترفيع يعطي كل طالب الصفّ التالي للشعبة، فيصبح طالب الصفّ الأول في شعبة الصفّ الثاني في الصفّ الثالث. أصبح هذا الطالب الآن في الصفّ الثاني.
- يُسجَّل كل تغيير في صفّ الطالب. صفّ الطالب (
StudentProfile.gradeLevel) هو صفّه هو، ولا يُستمَدّ من صفّ الشعبة. كان الترفيع وحده يترك أثرًا؛ أمّا الآن فتعديل المعلّم (PATCH /api/students/{id}) وتعديل المسؤول (PATCH /api/users/{id}) وإعادة استيراد قائمة الطلاب أو بيانات نظام إدارة التعلّم التي تستبدل الصفّ، يضيف كلٌّ منها صفًّا فيstudent_grade_historyيذكر السبب (correctionأوimport) ومن أجرى التغيير. تتولّى دالة واحدة كل تغييرات الصفّ، ويرفض فحص جديد (lint:student-grade-single-write-path) أي شيفرة أخرى تكتب الصفّ. - معرّفات الشعب في الجداول الأخرى يجب أن تعود إلى المؤسسة نفسها. لم يعد ممكنًا أن تشير التسجيلات وإسناد المعلّمين ومحفّزات المسح ونتائج المجموعات الذكية وأعضاؤها وتنبيهات التراجع الحادّ وطلبات المدير ومسوّدات سير العمل وربط مقرّرات نظام إدارة التعلّم ولقطات لوحة المتصدّرين إلى شعبة من مؤسسة أخرى؛ تفرض قاعدة البيانات ذلك. ويجب أن تكون شعبة عضو المجموعة هي شعبة مجموعته.
- أُزيل الحقل
school_dashboard_snapshot.schoolId. لم يكن يقرؤه أي شيء، وكان يبقى مشيرًا إلى المدرسة القديمة إذا نُقلت الشعبة إلى مدرسة أخرى.
مراجعة بنية قاعدة البيانات — المرحلة 2: إصدارات محتوى الأسئلة — 2026-09-25
لا عمليات جديدة، ولا تغيير في شكل الاستجابات. الترحيلان 20260926040000_item_content و20260926040100_item_content_drop_legacy (P2b).
- صار لمحتوى السؤال إصدارات. نصّ السؤال وخياراته ومفتاح الإجابة والمشتّتات والوسائط وإعدادات التفاعل وقالب العرض والنصّ القرائي الذي يستخدمه، كلها الآن في
item_content، صفّ لكل إصدار لا يتغيّر بعد كتابته. ويبقى فيitem_bankتصنيف السؤال وحالته ومصدره، ورقم إصداره الحالي. التعديل في «استوديو الأسئلة» يضيف إصدارًا جديدًا ولا يعيد كتابة السؤال في مكانه. - العرض يتذكّر الإصدار الذي أظهره. كل عرض لسؤال (إلكتروني أو ورقي) يسجّل رقم إصدار المحتوى (
served_task_instance.contentVersion). تُصحَّح الإجابة على ذلك الإصدار، ويرى الطالب في شاشته، والمعلّم في مراجعة الإجابات وفي تصحيح الورقة المطبوعة، ذلك الإصدار نفسه ولو عُدّل السؤال بعد عرضه. في السابق كانت كلها تقرأ أحدث محتوى، فكان تعديل المفتاح أثناء الجلسة (أو بين طباعة الورقة وتصحيحها) قد يجعل الإجابة الصحيحة خاطئة. - للنصوص القرائية إصدارات بالطريقة نفسها (
passage_content). كل إصدار من السؤال يشير إلى إصدار النصّ الذي كُتب عليه. تعديل النصّ يضيف إصدارًا جديدًا للنصّ وينقل كل سؤال على ذلك النصّ إلى إصدار جديد يشير إليه: العروض الجديدة تُظهر النصّ الجديد، والعروض السابقة تحتفظ بالنصّ الذي عُرض. - المعايرة. انتقلت المعايرة الحالية إلى
item_calibration_state، ووسوم تحليل الأخطاء إلىitem_error_target. صار محرّك التقدير يقرأ لقطات المعايرة المجمّدة عند إصدار المعايرة المثبّت للجلسة، ولا يستخدم لقطة إلا لإجابات إصدار المحتوى الذي قيست عليه. السؤال الذي أُعيدت معايرته بعد التثبيت يُقدَّر الآن بصعوبته المعايَرة السابقة، وكان من قبل يرجع إلى الصعوبة المبدئية. ويستخدم ترتيب أسئلة التدريب المحلِّلَ نفسه، وكان من قبل يأخذ أي صعوبة معايَرة مخزّنة ولو لم تجتز شرط 300 إجابة. ومهمة المعايرة لا تجمع إلا إجابات الإصدار الحالي لكل سؤال، وتسجّل ذلك الإصدار في كل لقطة، وتمسح علامة «المعايرة قديمة» عند إعادة المعايرة. - سجلّ تعديلات «استوديو الأسئلة» (
GET /api/items/{id}/revisionsوGET /api/passages/{id}/revisions) يعيد الحقول نفسها. ويسجّل كل قيد الآن أيضًا إصدار المحتوى الذي أنشأه التعديل، ويحتفظ بالقيم السابقة لحقول التصنيف المعدّلة فقط، لأن إصدار المحتوى السابق يحمل المحتوى القديم كاملًا. وصارPassageDetail.versionيعيد إصدار المحتوى الحالي للنصّ. - حُذف: 14 عمودًا من
item_bankلم يكن أي شيء يقرؤها (requiresInferenceوdokSmeConfirmedوposTagsوlemmasوsamerMaxLevelوcamelsFeatureTagsوnearDuplicateOfوrtiSensitiveوreportableوsoloSchemaVersionوversionوdeltaSeوinfitMnsqوoutfitMnsq)، وpassages.version.
مراجعة بنية قاعدة البيانات — المرحلة 2 — 2026-09-25
- نموذج واحد لاستيراد المحتوى (P2d، الترحيلان
20260926020000_content_importو20260926020100_content_import_drop_legacy). كان لاستيراد الأسئلة ولاستيراد مخططات الجلسات مجموعتان منفصلتان من جداول الدفعات وسجلّ الصفوف واعتماد المختصّين؛ وصارتا تتشاركان مجموعة واحدة:content_import_batchوcontent_import_logوcontent_import_approval، مع حقلcontentKindقيمتهitemأوsession_blueprintأوpassage. نسخ الترحيل كل الصفوف القديمة وأبقى معرّفات الدفعات كما هي، فتبقى الأسئلة والمخططات مرتبطة بالدفعة التي أنشأتها؛ وحُذفت الجداول الستة القديمة. وصارت قاعدة البيانات تفرض قواعد كل نوع: بصمة ملف الدفعة فريدة داخل نوعها (الملف نفسه إذا أُرسل إلى بوابتي استيراد يصبح استيرادين)، ولا يحمل المصدرَ المعلَن وإصدارَ معادلة δ_prior إلا دفعاتُ الأسئلة، ولا يشير كل صفّ في السجلّ إلا إلى صفّ واحد على الأكثر من نوع دفعته، ولا تسجّل كل بوابة إلا أسباب الرفض الخاصة بها. لا تغيير في الواجهة البرمجية: تعيد نقاط استيراد الأسئلة ومخططات الجلسات الاستجابات نفسها؛ ولا ترى كلٌّ منها إلا دفعات نوعها، فمعرّف دفعة من نوع آخر يعيد 404. - صار للنصوص دفعة استيراد. النصوص التي تحمّلها سكربتات التعبئة وتجهيز النسخة التجريبية تمرّ الآن بمسار جديد لاستيراد النصوص: دفعة واحدة لكل ملف نصوص، وإعادة استيراد الملف نفسه لا تغيّر شيئًا، والنص الموجود يبقى كما هو، والنص الجديد يسجّل الدفعة التي أنشأته (
importBatchId). أما النصوص التي تُكتب يدويًا عبرPOST /api/passagesفتبقى بلا دفعة كما كانت. - المرحلة 2e — محو بيانات طالب. عملية جديدة
POST /api/students/{studentId}/erase(الوسمerasure، الملفwp-erasure.yaml). ترحيل20260926030000_audit_action_student_erased. يستطيع المسؤول العام محو هوية طالب في مكانها عندما تطلب الأسرة ذلك. تُزال الأسماء والبريد الإلكتروني واسم المستخدم والهاتف ومرجع المدرسة وتاريخ الميلاد ورمز الدخول ومفاتيح المرور وربط حساب Google ونظام إدارة التعلّم وروابط وليّ الأمر. وتُحذف من التخزين أوراق القراءة المطبوعة (وملفات الصفّ المضغوطة التي تحتويها) والصفحات الممسوحة وتسجيلات القراءة، وكذلك الإشعارات المتعلّقة بالطفل. أمّا الإجابات والنتائج والأدلّة والقرارات فتبقى بالمعرّف نفسه، وهو يشير الآن إلى سجلّ بلا هوية يظهر باسم «طالب محذوف». يحدّد الطلب المؤسسة (طالب مؤسسة أخرى يعيد 404)، ويأخذ رمز سبب من كتالوج رموز التجاوز (النطاقall؛ لا نصّ حرّ). تكتب العملية سجلّ تدقيق واحدًا فيه أعداد الصفوف لكل جدول، ولا تحفظ القيم الممحوّة أبدًا. تكرار الطلب يعيدalreadyErased: trueولا يغيّر شيئًا. لا يمكن التراجع عنها. دليل التشغيل:docs/runbooks/erasure.md.
مراجعة بنية قاعدة البيانات — المرحلة 2: جدول واحد للإجابات وسجلّ واحد لتقدير القدرة (θ) — 2026-09-25
لا عمليات جديدة، وأشكال الاستجابات لم تتغيّر (أُعيد توليد amal-api.yaml بلا فرق). الترحيلان 20260926010000_item_response و20260926010100_retire_answer_tables.
- صارت كل إجابة طالب صفًّا واحدًا في
item_responseأيًّا كان المسار: التشخيص، أو التدريب، أو الورقة، أو التأكيد، أو نقطة المحرّك المستقلة. يذكر الصف مصدر الإجابة (source)، والجلسة أو قائمة التدريب أو الجلسة المولَّدة التي تنتمي إليها، والعرض الذي أجابت عنه (إجابة واحدة على الأكثر لكل عرض). والإجابات التي تعذّر فيها تحميل الصوت أو الصورة تُحفظ لكنها تُعلَّمexcluded، ولا يقرؤها أي عدّ ولا تقدير θ ولا معايرة. - أُعيدت تسمية
diagnostic_sessionإلىtheta_estimate، ويشير كل صف فيه إلى الإجابة التي قدّرها. تُكتب الإجابة وتقديرها في المعاملة نفسها، فلا يوجد تقدير بلا إجابة ولا إجابة مقدَّرة بلا تقديرها. سابقًا كان التدريب يكتب التقدير أولًا ثم الإجابة في معاملة ثانية، فإذا استُبدلت قائمة التدريب بينهما بقي تقدير بلا إجابة. - أُلغي:
practice_response، وdiagnostic_excluded_submit، وإجابات الورق التي كانت تُخزَّن بصيغة JSON داخلstudent_task_result(الذي صار يحمل نتائج كتل التدريب فقط). نقل الترحيل الصفوف الموجودة إلىitem_response. - أعداد كانت خاطئة: كان عدّ تدريب الطالب عند المعلم يحسب الإجابة المكرّرة للسؤال نفسه مرتين، ويعرض إجابات الورق كأنها «كتل» تدريب فارغة؛ وكانت خطة اليوم عند الطالب تحسب السؤال الذي تعذّر تحميله كأنه أُجيب؛ ولم تكن المعايرة تقرأ إجابات الورق، وكانت تقرأ إجابات التدريب التي تعذّر تحميلها. صُحّح كل ذلك.
- يعيد
GET /api/engine/sessions/{id}و…/by-student/{studentId}الحقول نفسها كما كانت؛ وتُقرأinputResponsesوpauseMsوaudioReplayMsالآن من الإجابة المرتبطة.
مراجعة بنية قاعدة البيانات — المرحلة 1C: توحيد سجلّات التدقيق — 2026-09-25
لا عمليات جديدة؛ أشكال الاستجابات لم تتغيّر (حُدّث وصف ثلاث عمليات). ترحيل 20260925050000_audit_consolidation.
- سجلّ حالات واحد لخمسة كيانات. كان لكلٍّ من تعيينات الملف وتعيينات الحِزم وجلسات التقييم ومستويات التدريب وطلبات المدير نسخته الخاصة من الجدول نفسه: “من حالة، إلى حالة، مَن، لماذا، متى”. صارت كلها تتشارك جدولًا واحدًا لا يقبل التعديل،
status_transition، يحميه مُشغِّل منع التعديل في قاعدة البيانات (كانت أحداث طلبات المدير محميّة بفحص الشيفرة فقط). نُسخت كل الصفوف الموجودة. ولا يزال انتقال كل كيان لا يُكتب إلا من كاتبه الخاص (فحص جديدlint:status-transition-single-write-path)، وصار كل انتقال يسجّل الطلب الذي أحدثه. - جدول تدقيق واحد لأحداث الفاعلين العامة. قراءات المشرف الأعلى عبر المؤسسات، وتقمّص الشخصيات في النسخة التجريبية، وتغيير قائد المجموعة في الحصة المتزامنة، صارت كلها تُكتب في جدول واحد لا يقبل التعديل،
audit_event، بقائمة إجراءات مغلقة وحمولة محدّدة النوع لكل إجراء (فحص جديدlint:audit-event-single-write-path). نُسخت الصفوف الموجودة بمعرّفاتها، فلا تزال روابط سجلّ التدقيق وسجلّ النشاط (bypass:<id>وimp:<id>) تعمل. ويعيد سجلّ التدقيق وسجلّ النشاط ومراقبة النسخ التجريبية الاستجابات نفسها كما كانت. - تبقى الجداول ذات العقد الخاص منفصلة: أحداث تسجيل الدخول، وسجلّ اطّلاع المدير على بيانات الطلاب، ومحاولات النص الحرّ المرفوضة (يُخزَّن فيها الطول فقط، لا النص أبدًا)، وقياسات النشاط، وإجراءات المعلم، وعلامات السياق، وتدقيق القرارات، وتنبيهات المنصّة، وتغييرات المعايير، وتغييرات إعدادات إمكانية الوصول.
- تقسيم شهري لستة جداول أحداث (المرحلة 1C، المجموعة C9، ترحيل
20260925060000_month_partitioning). صارت قياسات النشاط وأحداث تسجيل الدخول ومحاولات تقديم المهام وأحداث الإحماء وسجلّ الاطّلاع على بيانات الطلاب وaudit_eventمقسّمة حسب الشهر (قسم لكل شهر بتوقيت UTC إضافةً إلى قسم احتياطي). نُسخت كل الصفوف الموجودة. تبدأ المهمة الليلية (purge:nightly) الآن بـpartitions:ensureالتي تُبقي أقسام ثلاثة أشهر قادمة جاهزة، لذا يجب أن تبقى مجدولة؛ ويحذف تنظيف النشاط بعد 90 يومًا الأشهر المنتهية كاملةً بدل حذف الصفوف واحدًا واحدًا. لا يُقسَّم سجلّ أحداث الحصة المتزامنة لأن تسلسل كل حصة يجب أن يبقى فريدًا. لا تغيير في الواجهة البرمجية.
مراجعة بنية قاعدة البيانات — المرحلة 1C: السنوات الدراسية والانتقال إلى السنة التالية — 2026-09-25
عمليتان جديدتان في amal-api.yaml (الوسم tenancy). ترحيل 20260925020000_school_year.
- صارت السنة الدراسية سجلًّا لا نصًّا حرًّا. لكل مؤسسة سنوات دراسية (
school_year: تسمية مثل “2026-2027”، من ١ أيلول إلى ٣١ آب، وحالة: مخطَّطة أو فعّالة أو مغلقة)، ولا تكون في المؤسسة إلا سنة فعّالة واحدة على الأكثر، وتفرض قاعدة البيانات ذلك. يشير كل صفّ إلى سنته، وتبقى تسميةacademicYearفي الصف مطابقة لها دائمًا. رُبطت الصفوف الموجودة بسنوات أُنشئت من تسمياتها: أحدث تسمية في كل مؤسسة فعّالة، والأقدم مغلقة. - صارت كتابة الصفوف تتحقّق من التسمية. يرفض
POST /api/classesوPATCH /api/classes/{id}(واستيراد القوائم بملفات CSV) الآن أي تسمية سنتاها غير متتاليتين، مثل “2026-2028”، بالرمز 422. وتحمل استجابات الصف الحقلschoolYearId. - جديد: يعرض
GET /api/organizations/{orgId}/school-yearsسنوات المؤسسة من الأحدث إلى الأقدم، مع عدد الصفوف في كل سنة. - جديد: ينقل
POST /api/organizations/{orgId}/school-years/{yearId}/promoteالسنة الفعّالة إلى السنة التالية (أو إلىtoLabel) دفعة واحدة: تُغلق السنة القديمة وتصبح الجديدة فعّالة؛ ويُنشأ لكل صفّ صفّ في السنة الجديدة أعلى بدرجة في المدرسة والشعبة نفسيهما؛ وينتقل كل طالب مسجَّل برمز الدخول نفسه، ويتقدّم صفّه، ويُسجَّل التغيير في سجلّ جديد للصفوف لا يقبل التعديل. لا يُنقل المعلمون: تبدأ الصفوف الجديدة بلا معلم. ويخرج طلاب الصف الرابع من نطاق الصفوف ١–٤؛ فيُلغى تسجيلهم ولا يُنشأ لهم صف. وتشغيله مرة ثانية للسنة نفسها لا يغيّر شيئًا ويعيدalreadyPromoted: true. يتطلّب صلاحيةMANAGE_SCHOOLS؛ ومعرّفات مؤسسة أخرى تعيد 404.
مراجعة بنية قاعدة البيانات — المرحلة 1B: إصدارات الإعدادات — 2026-09-24
لا عمليات جديدة؛ ملف amal-api.yaml لم يتغيّر. ترحيل 20260924130000_config_release.
- كل كتالوج من كتالوجات الشريك يُجمَّد الآن في إصدار إعدادات. تُعاد تعبئة الكتالوجات من مصنّف الشريك بحسب الرمز الطبيعي، وكان ذلك يكتب فوق القواعد التي حُسبت بها القرارات السابقة. تبقى الجداول الحيّة حاملةً للقواعد الحالية؛ وخطوة نشر جديدة تأخذ لقطة من الكتالوجات الـ٨٨ المسجّلة إلى تاريخ غير قابل للتعديل ومعنوَن بالمحتوى، ولا يحدث ذلك إلا إذا تغيّر شيء فعلًا. الكتالوجات التي لم تتغيّر تتشارك لقطة واحدة عبر الإصدارات، والتراجع عن كتالوج يُنشئ إصدارًا فعّالًا جديدًا يعيد استخدام اللقطة الأقدم.
- كل صفّ قرار يسجّل الإصدار الذي اتُّخذ القرار في ظلّه. لقطات حالة المهارة والمجال والمجال الكلّي، وتصنيفات الأنماط، وتعيينات الملف، وتوصيات الحِزم وتعييناتها، ونتائج التجميع الذكي، وخطط المتابعة، وتنبيهات القياس والتراجع الحادّ، وتنبيهات الاستجابة للتدخّل، وسجلّات قرار المستوى، وحِزم القرار، كلها تحمل
configReleaseIdإلزاميًا. تملؤه قاعدة البيانات بالإصدار الفعّال، وترفض الإدراج إن لم يوجد إصدار. الصفوف المكتوبة قبل هذا الترحيل تشير إلى الإصدار ١، وهو خطّ أساس صريح لم يُلتقط محتواه. - يشغّل المشغّلون
pnpm config:publishمرة بعد نشر هذا الترحيل (وبعد أي تغيير في الكتالوجات خارج التعبئة). التعبئة تنشر تلقائيًا في خطوتها الأخيرة. - صار فحص انحراف المخطط يتحقّق أيضًا من وجود كل دالة في قاعدة البيانات يعتمد عليها المخطط.
- صار محرّك حالة المهارات يقرّر من الإصدار الفعّال لا من الجداول الحيّة (الخطوة 1B-2a). أي تعديل على كتالوج حيّ لم يُنشر لا يستطيع تغيير قرار؛ وكل لقطة مهارة ومجال ومجال كلّي تسجّل الإصدار الذي قرأه المحرّك فعلًا. ومحاكاة المسؤول تقارن القواعد المقترحة بذلك الإصدار.
- صارت كل مرحلة قرار تقرأ الإصدار الفعّال (المسار أ من الخطوة 1B-2): ملفات الطلاب، وتوصيات الحِزم وتفعيلها، والتجميع الذكي، وسير التفعيل، والمتابعة، وتنبيهات الاستجابة للتدخّل وقرارات المستوى، واتجاهات الطلاقة، وحِزم غرفة البيانات، والأمانة في التنفيذ. وكل صفّ مثبَّت يسجّل الإصدار الذي قرأته المرحلة فعلًا. أما القوائم والتسميات للقراءة فقط فتبقى تعرض الكتالوجات الحالية.
- أُلغيت أرقام إصدارات الطبقات في محرّك حالة المهارات (المسار ب من الخطوة 1B-2، الترحيل
20260924140000). تغيير في الواجهة البرمجية: صفوف المهارة والمجال والنمط والسلوك التي يعيدهاGET /api/sse/students/{id}/*لم تعد تحملadrRuleVersionوssrRuleVersionوddrRuleVersionوddrLcRuleVersionوpatternDefRuleVersionوrbmRuleVersion؛ ويحمل كل صفّ بدلهاconfigReleaseId، أي الإصدار الذي ضمّ كل طبقات القواعد دفعة واحدة. معرّفات القواعد (أيّ قاعدة انطبقت) لم تتغيّر. وصارت اللقطات مفهرسة ببصمة لكتالوجات المحرّك وحدها، فلا يكرّرها تغيير في كتالوج لا علاقة له، وأي تغيير في قواعد المحرّك ينتج قرارًا جديدًا بدل الإبقاء الصامت على القديم. و«الأحدث» في كل مكان يعني أحدث سنة دراسية، ثم أحدث إصدار، ثم أحدث حساب. - أُلغيت أرقام الإصدارات الخمسة في تعيينات ملفات الطلاب (الترحيل
20260924150000). تغيير في الواجهة البرمجية: صفّ الملف الذي يعيدهGET /api/profile/{studentId}يحملconfigReleaseIdبدلprofileRuleSetVersionوcdpRuleSetVersionوpgaRuleSetVersionوnarrativeTextSetVersionوaliasSetVersion. وأي تغيير في كتالوج من كتالوجات الملف ينتج ملفًا معلّقًا جديدًا يراجعه المعلم، ولا يفعل ذلك تغيير في كتالوج لا علاقة له. - انتقلت توصيات الحِزم والتجميع ومسودات التفعيل إلى الإصدار (الترحيل
20260924160000). صارت التوصيات مفهرسة ببصمة كتالوجات الحِزم الستة؛ وكان أي تعديل على كتالوج حِزم غير خريطة الملف إلى الحزمة يُتجاهَل بصمت للطلاب الذين لديهم توصية. تغيير في الواجهة البرمجية: يعيدPOST /api/cluster/recompute/{classId}الحقلconfigReleaseIdبدلruleSetVersion، وتحمل مسودات سير العملpinnedClusterConfigReleaseIdبدلpinnedClusterRuleSetVersion(وحُدِّث معالج التفعيل لدى المعلم). ولم تعد صفوف توصيات الحِزم وتعييناتها تحملconfigVersionsوruleVersion. - صار التحفيز يثبّت الإصدار (الترحيل
20260924170000). نقاط الخبرة والشارات ومستويات الشخصية والسلاسل تسجّل إصدار الإعدادات الذي قُرئت منه قواعد النقاط وكتالوج الشارات؛ ويحتفظ عكس النقاط عند سحب شارة بإصدار النقاط التي يلغيها، وتُعاد تثبيت الشخصية والسلسلة عند كل تحديث. تغيير في الواجهة البرمجية: يعيد سجلّ التحفيز للمسؤول (GET /api/admin/gamification/audit) الحقلconfigReleaseIdلكل معاملة نقاط بدلruleSetVersion، ويعرضه جدول السجلّ تحت «إصدار الإعدادات». - صارت المتابعة وقرارات المستوى وحزم القرار والتزام التنفيذ تثبّت الإصدار (الترحيل
20260924180000). تُسقط خطط المتابعة ومراجعاتها وسجلّات قرارات المستوى ومسارات حزم القرار وصفوف التزام التنفيذ أعمدة الإصدار الخاصة بكل كتالوج، وتسجّل إصدار الإعدادات بدلها. وصارت عتبات تقييم الالتزام وإعدادات تتبّع الانقطاع جزءًا من كل إصدار، فلا يغيّر تعديلٌ غير منشور عليها أيّ تقييم. تغيير في الواجهة البرمجية: يعيدGET /api/monitoring/status/{bundleAssignmentId}الحقلmonitoringPlan.configReleaseIdبدلrecipeVersionوcriterionVersion، ويعيدGET /api/students/{id}/tier-decisionsالحقلconfigReleaseIdبدلmovementRuleVersionId. - صارت مستويات الدعم والمهام المقدَّمة تثبّت الإصدار (الترحيل
20260924190000). يسجّل تعيين مستوى الدعم للطالب الإصدارَ الذي حُدّد منه مستواه الأول، ويبقى كما هو عند تعديل المعلّم لأنّ المستوى الجديد قرار المعلّم ويُسجَّل في سجلّ الإجراءات. وتنسخ كل مهمة مقدَّمة إصدارَ مستواها (فارغ حين لا يُطبَّق مستوى: المسابير والمهام بلا حزمة والمهام الورقية). تغيير في الواجهة البرمجية: يعيدGET /api/delivery/log/{taskInstanceId}الحقلscaffoldConfigReleaseIdبدلscaffoldRuleVersion. - صارت سجلّات عرض السرديات ومؤشرات الأنماط الفرعية تثبّت الإصدار (الترحيل
20260924200000). يسجّل كل عرض سردي لكل جمهور الإصدارَ الذي قُرئت منه مجموعة النصوص بدل رقم إصدارها. وصار سلّم الأنماط الفرعية أثناء التدريب يقرأ كتالوجَي أنماط الأخطاء والمشتّتات من الإصدار النشط، فلا يغيّر تعديلٌ غير منشور على نمطٍ ما يُحتسب من أخطاء، وتُعاد تثبيت حالة المؤشر عند كل خطوة محتسبة. لا تغيير في الواجهة البرمجية. - صار كل صفّ قرار يسمّي إصداره صراحةً، ولم يعد بإمكان القرارات القراءة من جداول الكتالوج الحيّة (الترحيلان
20260924210000و20260924220000). لم يعد لعمودconfigReleaseIdقيمة افتراضية في قاعدة البيانات: الكتابة التي تنسى إصدارها تُرفض بدل أن تأخذ الإصدار النشط بصمت. وصارت محمّلات الكتالوج تقرأ من الإصدار النشط افتراضيًّا، ويرفض فحص جديد (lint:config-read-from-release) أي قراءة حيّة للكتالوج خارج العرض والتحقّق والأدوات. وتعديل قواعد اللغة من شاشة المسؤول ينشر إصدارًا الآن، فيسري التعديل فورًا كما كان. تغييرات في الواجهة البرمجية: لم يعدPOST /api/assembly/sessionيقبلassemblyRuleVersion(تُستخدم قواعد الإصدار النشط) وتعيد عمليات التجميعconfigReleaseId؛ وتعيد تنبيهات الجودةqaConfigReleaseIdبدلqaChecksSetVersion؛ ويعيد سجلّ التقديمrenderConfigReleaseIdللمهام الإلكترونية، ولا يُملأrenderRuleVersionإلا للمهام الورقية. - صار الطالب نشطًا في صفّ واحد فقط في آنٍ واحد، وتفرض ذلك قاعدة البيانات (المجموعة C8 من المرحلة 1C، الترحيل
20260925030000). يسمح فهرس فريد جزئي بصفّClassStudentنشط واحد لكل طالب، ويتوقّف الترحيل ويذكر الطلاب بأسمائهم إن كان لدى أحدهم تسجيلان نشطان. وصارت الطرق الأربع لإضافة الأشخاص (الإنشاء من المسؤول، والاستيراد من نظام إدارة التعلّم، واستيراد ملفات القوائم، وتعبئة العرض التجريبي) تمرّ بكاتب واحد وقاعدة هوية واحدة: يُطابَق الشخص داخل المؤسسة فقط، ولا يُربط بريد إلكتروني تملكه مؤسسة أخرى أبدًا. تغيير في السلوك: حين يُدرج استيراد نظام إدارة التعلّم طالبًا مسجّلًا تحت صفّ آخر مربوط، يُنقل الطالب (ويُغلق تسجيله القديم كنقل) بدل تسجيله في الصفّين، ويُتجاوز صفّ الاستيراد المربوط بصفّ خارج المؤسسة (ويُحسب فيrowsSkipped). لم يتغيّر شكل أي طلب أو استجابة. - صارت لوحات مدير المدرسة تقرأ أعدادًا محفوظة للحالات (المرحلة 1C، البند C6، الترحيل
20260925040000_school_dashboard_snapshot). يحفظ جدول جديد،school_dashboard_snapshot، عدد طلاب كل شعبة في كل مجال وحالة وفترة وسنة دراسية. تعيد كتابتَه إعادةُ حساب المجالات الكلية في المعاملة نفسها، ويعيدpnpm dashboard:rebuildبناءه (ويعمل كل ليلة ضمنpurge:nightlyليلتقط تغييرات التسجيل)، وقد عبّأه الترحيل بالبيانات الحالية. صارت بطاقات لوحة المدرسة وأعداد التنبيهات فيها، وصفحة التنبيهات، وتاريخ «آخر تقييم» في صفحات الشعب تقرأ هذه الأعداد. قبل ذلك كان كل طلب يطوي تاريخ لقطات كل طالب. الأرقام نفسها، مع استثناء واحد: صفّ السنة الماضية لطالب عائد لم يعد يُحسب بدل فترة هذه السنة. لا تغيير في الواجهة البرمجية.
مراجعة بنية قاعدة البيانات — المرحلة 1A: معرّف واحد للطالب، ومفاتيح أجنبية حقيقية — 2026-09-24
لا عمليات جديدة؛ ملف amal-api.yaml لم يتغيّر. ترحيلات 20260924100000_student_id_unification و20260924110000_student_fks و20260924120000_subskill_fks.
- صار
StudentProfile.idمساويًا لـUser.idبالبناء. كان وجود متسلسلتين عدديتين مستقلتين للطالب الواحد هو الخلل المتكرّر في المنصة: أي انتقال ضائع بينهما يقرأ بيانات طفل آخر بدل أن يفشل. أعاد الترحيل كتابة كل الأعمدة المفهرسة بمعرّف الملف الشخصي إلى معرّف المستخدم (على خطوتين حتى لا يتصادم أي فهرس فريد)، وثبّت مُشغِّلًا قبل الإدراج يُبقيid = userIdلكل ملف جديد؛ وأي تعديل يكسر المساواة يُرفض. لم يتغيّر أي عقد في الواجهة البرمجية — كل مسار يقبل الرقم نفسه الذي كان يقبله، وصار الرقم الوحيد. studentIdمفتاح أجنبي حقيقي في ٥٣ جدول قياس وقرار، بمنع الحذف، أُضيف بصيغةNOT VALIDثمVALIDATEكي لا يحتاج الإنتاج قفلًا طويلًا. معرّف طالب مختلق أو يتيم يفشل الآن عند الإدراج، ولا يمكن حذف طالب من تحت تاريخه القياسي (المحو يبقى إخفاءً للهوية في المكان).subSkillId/skillIdمفتاح أجنبي حقيقي في ٢٥ عمودًا من جداول الأدلة والتقديم والمعايرة إلى كتالوج المهارات، بما فيها الأعمدة القابلة للفراغ. لم يعد ممكنًا كتابة صف دليل لمهارة غير موجودة يتجاهله كل قارئ بصمت.- الاختبارات التي كانت تُثبت الانتقال بين الفضاءين صارت تُثبت الثابت الموحّد؛ والبيانات التجريبية ذات المعرّفات المختلقة أُعطيت ملفات حقيقية.
مراجعة بنية قاعدة البيانات — البندان ٩ و١٠: حذف الجداول الميتة، وتقييد مجمّع الاتصالات — 2026-09-23
لا عمليات جديدة؛ ملف amal-api.yaml لم يتغيّر. ترحيل 20260923170000_drop_dead_config_tables.
- حُذف ٢٠ جدولًا (من ٢٧٥ إلى ٢٥٥ نموذجًا). تسعة عشر جدول إعدادات تعكس أوراق الشريك لم تُملأ يومًا ولم يقرأها أي كود، إضافةً إلى
trend_verdict(بلا كاتب ولا قارئ)، وثلاثة تعدادات لا يستعملها سواها، وعمودا تدقيق لم يُكتبا قط، وعرض واحد غير مستعمل. القواعد التي تصفها تلك الأوراق مطبّقة في الكود، والأوراق نفسها تبقى المرجع فيdocs/product/partner-inputs. لا يعود جدول إلا مع قارئه. - حجم مجمّع الاتصالات رقم تختاره العمليات. يُضاف
PRISMA_CONNECTION_LIMITوPRISMA_POOL_TIMEOUTإلىDATABASE_URLلكل نسخة خادم (٤ و٢٠ ثانية على البيئة الرئيسية، ٣ على العرض التوضيحي). ترقية مستوى Cloud SQL وتفعيل تجميع الاتصالات المُدار موثّقان فيdeploy/cloud-run/DEPLOY.mdكخطوتين قبل التوسّع بعد التجريب.
مراجعة بنية قاعدة البيانات — البندان ٧ و٨: قراءة «الأحدث» في قاعدة البيانات، ومهمة التنظيف الدوري — 2026-09-23
لا عمليات جديدة؛ ملف amal-api.yaml لم يتغيّر. ترحيل 20260923160000_current_row_indexes.
- «الأحدث» يُحسم في SQL. كان تقرير الصف للمعلمة (شبكة المهارات، بطاقات المجالات، منحنيات الاتجاه)، وسلسلة
/trendsللمدير، وإشارات الحالات للمدير تجلب كل صفوف اللقطات لطلاب الصف ثم تختار الأحدث في الخادم بحسب وقت الحساب. صارت الآن تستخدمDISTINCT ONبقاعدة الحداثة الحتمية — السنة الدراسية الحالية أولًا، ثم نسخة القاعدة، ثم نسخة البذرة، ثم وقت الحساب، ثم المعرّف — على فهارس جديدة، فلا يعود صفّ قديم يتفوّق على إعادة حساب بنسخة قواعد أحدث، ويتناسب حجم البيانات المنقولة مع عدد الطلاب لا مع تاريخهم، وتُشتق سنة الاتجاه من عمودacademicYearنفسه. - إصلاح مفتاحي ربط بلا فهرس —
diagnostic_session.sessionIdوClass.schoolId— إضافةً إلىrequestIdفي سجل النشاط. - مهمة التنظيف الدوري موجودة. يحذف
pnpm auth:purgeرموز إعادة التعيين والروابط السحرية المستهلكة أو المنتهية منذ أكثر من ٧ أيام، وتحدّيات مفاتيح المرور، وحالات OAuth، ومعاينات الاستيراد المنتهية، والجلسات غير النشطة منذ ٣٠ يومًا (سجل التدقيقauth_event_logلا يُمسّ)؛ ويجمعهاpnpm purge:nightlyمعactivity:purge. لم يكن أيّ منهما مجدولًا؛ أوامر إنشاء مهمة Cloud Run وجدولتها فيdeploy/cloud-run/DEPLOY.mdويجب تنفيذها لكل بيئة.
مراجعة بنية قاعدة البيانات — البندان ٥ و٦: منع التعديل على مستوى قاعدة البيانات، وسلسلة القرار بعد التقييم، ومقام نسبة الالتزام — 2026-09-23
لا عمليات جديدة؛ ملف amal-api.yaml لم يتغيّر. ترحيلات 20260923140000_append_only_triggers و20260923150000_planned_cycle_weeks.
- «الإضافة فقط» صارت تفرضها قاعدة البيانات نفسها لا فاحص المصدر. تعمل الدالة
amal_append_only()قبل أي تعديل أو حذف على ٣٩ جدولًا من عمود القياس (أحداث الإتقان، النقاط، لقطات الحالة الثلاث، صفوف الأدلة، سجل θ، الإجابات، درجات القياس المرجعي، سجلات قرارات المستوى، سجل التشغيل، جداول التاريخ، لقطات المعايرة). أي تعديل أو حذف يفشل برسالةappend-only: … is forbidden (V-6)— من Prisma أو psql أو خدمة المعايرة أو أي مكان. المخرج الوحيد هوSET LOCAL amal.maintenance = 'on'داخل معاملة (إعادة ضبط العرض التوضيحي، ترحيلات التعبئة لمرة واحدة، قواعد بيانات الاختبار). وصارت بوابة الانحراف تتحقق من وجود المُشغِّلات التسعة والثلاثين بعد كلmigrate deploy. - إنهاء التقييم يواصل الآن إلى الملف الشخصي وتقييم التنبيهات. بعد وصول اللقطات، يعيد الخادم حساب ملف الطالب لتلك النافذة ويقيّم تنبيهات الطبقة الثانية في نظام الاستجابة للتدخل — وكان كلاهما لا يُستدعى إلا من مُولِّد بيانات العرض التوضيحي، فلم يكن لأي طالب حقيقي ملف، ولم يجد مسار توصية الحزمة ما يقرؤه. توصية الحزمة نفسها تبقى قرار المعلمة.
- نسبة الالتزام صار لها مقام. يُثبَّت
sessionsPlannedوdosageBandفيbundle_assignmentعند كل تفعيل (فردي، جماعي، عبر سير العمل) من نطاق الجرعة في الكتالوج: الحد الأدنى الأسبوعي («3–5x/week» ← 3) × طول دورة التخطيط (plannedCycleWeeks، افتراضيًا ٦ أسابيع، بانتظار قرار الشريك). قبل ذلك كانت النسبة تُحسب دائمًا على ٠ ← «غير معروف» ← فتُمنع كل ترقية مستوى بقاعدة TM_BLOCK_01.
مراجعة بنية قاعدة البيانات — إصلاحات المرحلة صفر — 2026-09-23
أربعة إصلاحات صحّة نتجت عن المراجعة الكاملة لمخطط قاعدة البيانات (docs/product/db-structure-review-2026-09-23.md). لا عمليات جديدة؛ ملف amal-api.yaml لم يتغيّر. ترحيلات 20260923120000_restore_session_blueprint_tags_gin و20260923130000_snapshot_academic_year.
- لقطات الحالة صارت مفهرسة بالسنة الدراسية. أُضيف عمود
academicYear(«2026-2027») إلى مفاتيحskill_status_snapshotوdomain_status_snapshotوmacro_domain_status_snapshot. قبل ذلك كان تقييم بداية السنة الثانية لطالب عائد — بنسخة القواعد نفسها — يصطدم بصفّ السنة الأولى ويُهمَل بوصفه «مكرّرًا» مع سطر سجل فقط، فلا تتحدّث أي حالة. تُستنتج السنة من الصف النشط للطالب، وعُبِّئت الصفوف القديمة بالطريقة نفسها. مسارات القراءة لم تتغيّر. - المعايرة لم تعد تحسب التدريب مرّتين. كان مُحمِّل بيانات راش يجمع
practice_responseمع كل صفوفdiagnostic_session، بينما يكتب المحرّك صفًّا فيdiagnostic_sessionلكل إجابة تدريب أيضًا. الآن تُقرأ منdiagnostic_sessionالصفوف المرتبطة بجلسة تقييم فقط. كل قيم الصعوبة المنشورة قبل هذا التاريخ حُسبت على بيانات تدريب مكرّرة وستُعاد معايرتها في التشغيل التالي (نسخة جديدة، لا تعديل في المكان). - استيراد منصات التعلّم لم يعد يربط مستخدمًا عبر المؤسسات. كانت خطوة الاعتماد تطابق البريد الإلكتروني عالميًا، فيُربط بريد يملكه مستخدم في مؤسسة أخرى بصفوف المؤسسة المستوردة بصمت. المطابقة الآن محصورة بالمؤسسة، ويُتخطّى الصفّ ويُحسب ضمن
rowsSkipped. - بوابة انحراف المخطط في التكامل المستمر (
pnpm db:check-drift). تعمل بعدmigrate deploy: يجب أن يطابقschema.prismaالترحيلات المُعادة، ويجب أن تبقى كل كائنات SQL الخام التي لا يستطيع Prisma تمثيلها (٣٢ فهرسًا جزئيًا/GIN، وعرضان، و١٨ قيد CHECK مسجّلة فيprisma/raw-sql-objects.json) موجودة. أثناء بنائها تبيّن أن الترحيل20260624221545كان قد حذف فعلًا فهرس وسوم قوالب الجلسات في كل البيئات؛ أُعيد وأُعلن في المخطط حتى يتوقفmigrate devعن اقتراح حذفه.
تشغيل إثبات المرحلة التجريبية الأولى على منظومة حقيقية — سبعة عيوب أُصلحت في اليوم نفسه (2026-09-24)
pnpm --filter server seed:pilot-proof ينشئ مستأجر إثبات (مؤسّسة · صفّ أوّل برمز دخول · معلّمة بكلمة مرور · ستّة أطفال برموز سريعة · نافذة منتصف العام مفتوحة اليوم)، ثمّ قُطعت الحلقة كاملة في ثلاثة متصفّحات: المسح → المجموعات التأكيدية الصغيرة → الملف → تأكيد المعلّمة → التوصية → التجميع → التفعيل → بطاقات الحاجة المشتركة. التقرير: docs/superpowers/proof-runs/2026-09-24-pilot1-proof-run.md. أُصلح: (١) تخطّي الإحماء من شاشة البداية كان يحبس الطفل؛ (٢) كلّ قراءة كانت تفترض نافذة بداية العام فيظهر طفل الصفّ الأوّل — ومسحه الأوّل في منتصف العام — «غير مُقيَّم» بملف ناقص البيانات (resolveEvidenceWindow: النافذة المفتوحة اليوم → آخر مسح مكتمل → بداية العام)؛ (٣) لم يكن ثمّة مسار يقود الطفل إلى المجموعة التأكيدية — الإجراء التالي صار confirmation قبل مسح جديد وقبل التدريب، والصفحة الرئيسية تعرض «أسئلة صغيرة للتأكّد»؛ (٤) رابط مباشر لصفحة الطالب كان يعرض «الطالب #id»؛ (٥) كلّ مجموعة تأكيدية كانت تترك صفَّي ملف معلّقين — الحلّ الجديد يُلغي الأقدم؛ (٦) «نقاط القوّة» في بطاقة الخطّة كانت تستعير الجسر المرشَّح للحزمة (الاستماع) — الصفوف تحمل الآن الجسر المدعوم بالبيانات؛ (٧) بطاقة المجموعة تسمّي المهارات المستهدفة الفعلية. مفتوح: OQ-23 (فجوة قاعدة PAC لمهارة PA-07)، OQ-24 (≥ ٦ بنود لكلّ صفّ × مهارة × نطاق)، OQ-25 (فهرس قوالب الجلسات).
النشر الصارم لمخطّط التشخيص في واجهة المشرف، وشارة الخلية المؤقتة، وشاشة تعليم قائمة الكلمات (WP-S0 T0.4 FE + T0.6 FE) — 2026-09-24
محرّر مخطّط التشخيص. زرّ «حفظ» يرسل الآن strict: true، فالمهارة التي يقلّ مخزونها القابل للتقديم عن مسح الأسئلة الثلاثة (أو المهارة غير المفعّلة) تُرفض مع تسمية المهارة — كلّ بند من details[] في استجابة 422 يُعرض بالعربية تحت قائمة المهارات («المفردات السياقية (VOCAB-C03): 2 من 3 أسئلة تقييم للصفّ 1 — أقلّ من حجم المسح.»؛ البند غير المعروف يُعرض بنصّ الخادم كما هو) ولا يُنشر شيء. السكربتات والواجهة البرمجية الافتراضية تبقى متساهلة (warnings[]، صار نوعها معلنًا على PutBlueprintResult). الخلية المزروعة التي تحمل notes: "placeholder — partnerPending OQ-1" تظهر بشارة «قائمة مؤقتة» على الشبكة وبتفسير داخل الحوار (دمج T0.5).
تعليم قائمة الكلمات للمعلّمة. بطاقة رابعة «قائمة الكلمات» في صفحة القياس: كلمات حقيقية (DWR-C01) أو غير حقيقية (DWR-C02) لصفّ الطفل نفسه، والكلمات العشرون شرائح قابلة للنقر (نقرة تعلّم الكلمة المقروءة خطأً؛ لون مرجاني وشطب)، وحقل اختياري للزمن بالثواني، و«تسجيل القائمة» → POST /api/word-lists/assessments بمواضع الكلمات الخاطئة → تُقرأ النتيجة صحيحة من مُحاوَلة مع حالة الإسقاط بلغة النموّ (في النافذة · لا نافذة مفتوحة · سيُعاد). النطاق والنسبة المئوية لا يظهران على سطح المعلّمة أبدًا (V-3). غياب قائمة لـ(الصفّ × المهارة) يُقرأ فجوةَ محتوى («المحتوى بانتظار الشريك»)، ولا تُقدَّم قائمة صفّ آخر. لا تغيير في الواجهة البرمجية.
أداة إعادة التشغيل المقارِنة — والثغرة التي كشفتها في قائمة السماح (WP-S9) — 2026-09-24
pnpm --filter server replay:profiles -- --org <id> --window BOY [--allowlist rows.json] [--required-domains rows.json] [--out file.csv] يحلّ ملف كلّ طالب له لقطات مجال في النافذة بالفهرس الفعّال وبصفوف قائمة السماح / المجالات المطلوبة المقترحة، ويطبع مَن يتغيّر (ملف CSV لكلّ طالب بالمعرّفات فقط + ملخّص توزيع). لا كتابة إطلاقًا بحكم البناء — المحرّك نقي والقارئ للقراءة فقط؛ والاختبارات تؤكّد أنّ عدد التعيينات لم يتغيّر. كشفت أوّل إعادة تشغيل ثغرةً حقيقية: تحت قائمة سماح المرحلة الأولى كان بإمكان صفّ منع التداخل (AO) أن يفرض ملفًّا أساسيًّا خارج القائمة — نمط الدقّة انتخب ACCURACY_GAP عبر AO-02 مع أنّ الصفّ الأوّل لا يقبل إلّا ON_TRACK / MONITORING_PROFILE / FOUNDATIONAL_DECODING_GAP — لأنّ القائمة كانت تصفّي مرشّحي CDP فقط. صار كاسر التعادل لا يقبل إلّا ملفّ قرار مسموحًا (وتبقى مطابقة AO مسجّلة لإعادة التشغيل)، فيتراجع النمط كما يتراجع مرشّح مُصفًّى؛ اختبار انحدار مُثبَت من الأحمر إلى الأخضر. لا تغيير في الواجهة البرمجية.
الجرعة إرشادًا (مستوى الدعم × شريحة الصفّ × مجال المهارة)، وجدولة المعلّمة منفصلة عنها، ومستوى الدعم عند كلّ محاولة تدريب (WP-S8، جولة الشريك الثانية §2.5 + الجولة الرابعة C4؛ مواصفة 2026-09-23 §23–24) — 2026-09-24
الجرعة. نطاقات الشريك الثلاثة صارت صفّ إعداد لا ثوابت: dosage_recommendation (٤ صفوف — المستوى العام × الصفّان ١–٢ × أساسيات القراءة ٢–٥ دقائق × ٤–٥ أسبوعيًّا · العام ٥–١٠ × ٢–٣ · الموجّه ١٠–١٥ × ٣–٤ · المكثّف ٢٠–٣٠ × ٣–٤؛ OQ-11 قابلة للضبط) ويُختار الصفّ الأكثر تحديدًا (مجال المهارة > شريحة الصفّ > أيّ). عند التفعيل يخزّن كاتب التعيين الوحيد الإرشاد المستخلَص في bundle_assignment.recommendedDosage (مع صفّه المصدري لإعادة التشغيل)؛ وجدولة المعلّمة (PATCH /api/assignments/{id}/schedule، OVR_SCHEDULE بسبب من الفهرس) تُحفَظ في scheduledDosage — بالصيغة العددية المغلقة (جلسات/أسبوع · دقائق · مجموع الجلسات) — ولا يُدمج الاثنان أبدًا. صفوف التوصيات تكسب dosageAr («١٠–١٥ دقيقة × ٣–٤ مرّات أسبوعيًّا»، مستخلَصة لكلّ طفل من مستوى الدعم × الصفّ × العائلة) وتغذية متابعة التنفيذ تكسب dosageAr + scheduledDosageAr. واجهة المعلّمة: «الجدولة المقترحة» في بطاقة الخطّة تقرأ الإرشاد؛ وبطاقة التنفيذ في صفحة الخطّة تعرض جدولة المعلّمة أوّلًا و«(الموصى به: …)» بجانبها حين تختلفان. مستوى الدعم عند الإجابة. يسجّل practice_response عند كلّ محاولة scaffoldLevelAtResponse (none · hint:LOW|MID|HIGH · reveal محجوز) وhintCount وindependenceLevel (independent → reduced → supported)، تُستخلَص تحت قفل التدريب من المحاولات السابقة على البند نفسه (الإجابة الخاطئة قدّمت تلميح SOLO)، وصار attemptN يزيد فعلًا عند التصحيح (كان ثابتًا ١). لا شيء يستهلكها لقراءة إتقان في المرحلة الأولى (OQ-20: جمع فقط). T8.3 (مستويات الصعوبة المؤلَّفة ١–٤) تبقى محجوزة على OQ-16 — تبقى سلسلة النطاق هي المستوى. لا عملية جديدة؛ amal-api.yaml يبقى ٣٨٥ مسارًا. الترحيلان 20260925160000_s8_dosage و20260925161000_s8_scaffold_at_response. تحقّقنا في ثلاثة متصفّحات أمام الخادم الوهمي.
الفحص الأعمق للأساسيات — المحفّزان A/B، وموافقة المعلّمة، وجلسة موجَّهة، وقراءة نقطة البدء (WP-S7، جولة الشريك الثانية §1 + §3.3؛ الجولة الرابعة A3/B6/B7/C7) — 2026-09-24
للمرحلة التجريبية الأولى مسارٌ واحد للتقييم الأعمق: الرجوع إلى أساسيات القراءة (الصوت → الحرف والصوت → المقاطع → الكلمة). وحدة جديدة backtrack (٣ عمليات؛ amal-api.yaml صار ٣٨٥ مسارًا). المحفّزات تُقيَّم بعد كلّ إعادة حساب للملف (الخطوة G في جسر التشخيص؛ مقياس القراءة الجهرية يقود السلسلة نفسها) فوق رموز أنتجها المحرّك أصلًا — لا خطًّا رقميًّا أبدًا: A = بلاطة الدقّة والطلاقة دون المستوى/بحاجة مكثّفة مع مؤشّر على فكّ الرموز (نطاق الدقّة دون المتوقّع، أو «دقيق لكن بطيء بوضوح» = نطاق السرعة markedly_below من S4، البديل عن انحرافين معياريين حتى OQ-15؛ قاعدة ٢٥٪ أُلغيت)؛ B = مجال فهم المقروء ضعيف على نحو واسع (coherent_domain_weakness / broad_related_domain_concern، لا مهارة معزولة) مع وصول ليس سليمًا بوضوح. الفهم وحده لا يحفّز؛ و«مجالان دون المستوى» ليست قاعدة. المحفّز يكتب صفًّا واحدًا في backtrack_recommendation لكلّ (طالب، نافذة، سنة دراسية) — ولا يُكرَّر صفّ قائم بأيّ حالة، فقرار المعلّمة يبقى. GET /api/backtrack/students/{studentId} يعيده مع سبب بلغة النموّ والخطوات الأربع (بأسماء المهارات العربية). POST /api/backtrack/{id}/approve (معلّمة الطالب) يفتح جلسة d_triggered الموجَّهة للطفل أوّلًا (قد يرفضها حدّ ١٤ يومًا / حارس الجلسة الواحدة → 409 والصفّ لا يُمسّ)، ثم ينقل recommended → approved → sitting_open بصفّي تاريخ؛ الجلسة تحمل نقاط الفحص الرقمية فقط (قوائم العشرين كلمة يصحّحها المعلّم ولا تُعرض على شاشة)، ويجد الطفل الجلسة في مساره اليومي — كلمة «الرجوع» لا تصل إلى الطالب أبدًا. POST /api/backtrack/{id}/decline {reasonCode} يشترط رمزًا أساسيًّا من الفهرس (applicableScope = all؛ 400 وإلّا) ولا يفتح شيئًا. عند انتهاء الجلسة تقرأ قراءة نقطة البدء نتائج نقاط الفحص الخاصّة بالجلسة (كلّها صحيحة → ضمن المتوقّع · النصف فأكثر → متابعة · وإلّا → ضعيفة؛ أدلّة الرجوع لا تُسقَط على لقطات المسح أبدًا) وتسمّي أوّل خطوة ضعيفة فقط حين قِيست كلّ الخطوات السابقة — وثغرة قبلها تُنتج «تعذّر تحديد نقطة البدء — خطوات غير مقيسة: …» (صدق OQ-3) لا تخمينًا. الإعداد backtrack_sequence (FOUNDATIONAL_READING v1؛ خطوتا الحرف/الصوت والكلمة بانتظار محتوى الشريك، OQ-3)؛ وقت التشغيل backtrack_recommendation (قابل للتعديل عبر كاتب واحد بجدول انتقالات مسموحة) + backtrack_recommendation_history (بالإلحاق فقط، مدرج في الفاحص)؛ مفاتيح أجنبية مقيّدة إلى فهرس الأسباب. الترحيل 20260925150000_s7_backtrack. واجهة المعلّمة: صفحة الطالب تكسب بطاقة الفحص الأعمق للأساسيات — السبب، والخطوات الأربع، والموافقة / عدم الاعتماد (سبب من الفهرس، لا نصّ حرّ)، وحالة الجلسة المفتوحة، وعند الاكتمال سطر القراءة وقراءات الخطوات ونقرة واحدة إلى التدريب على مهارة نقطة البدء. تحقّقنا في ثلاثة متصفّحات أمام الخادم الوهمي؛ وطُبّق تدقيق RTL.
رصد الحاجة المشتركة في الصفّ وبطاقتها (WP-S6، جولة الشريك الثانية §1 + مواصفة المطوّر 2026-09-23 §25–26) — 2026-09-24
الدعم على مستوى الصفّ كلّه هدفُ تعيين لا كيانَ خطّة، لذا صار ملخّص الصفّ يقول أين توجد حاجة مشتركة. GET /api/reports/classes/{id}/class-summary (وملخّص مجموعة الدعم) يحمل classWideNeeds {skillNeeds[], domainConcerns[], thresholds} للجمهورين — أعداد ونسب من الطلاب فقط، لا درجة ولا هويّة طالب. حاجة مهارة تظهر حين يكون ≥ ٤٠٪ من الطلاب الذين قِيسوا على المهارة نفسها ضعافًا (الضعاف ÷ المقيسون؛ طفل قيد المراجعة أو do_not_decide_yet خارج العدّين — صفوف perSkill تحمل الآن doNotDecideYetCount؛ وطفل الدعم المكثّف داخلهما، OQ-4) وهي قابلة للتنفيذ: تحمل عبارة المهارة المستهدفة (focusAr من skill_focus_phrase) وpriority — high لمهارة بوّابة في الصفّين الأوّل والثاني (وزن للترتيب لا تجاوزًا). قلق مجال يظهر حين يكون ≥ ٥٠٪ من المقيسين على بلاطة كلّية دون المستوى/بحاجة مكثّفة وهو إخباري (actionable: false) مع مهارات البلاطة التي تُراجَع أوّلًا — قاعدة الشريك «افحص المهارات أوّلًا»؛ لا يُقترح تدخّل على مستوى المجال أبدًا. «الضعف» هو مجموعة الحالات التي يوجّهها موجِّه التدريب إلى التدريب العلاجي (practice_experience_map) فلا يختلف الرصد عن بذر التدريب. العتبات صفّ إعداد (class_need_threshold: skillShare 0.40 · domainShare 0.50 · gatewayBoostGrades [1,2] · countIntensiveInDenominator true؛ رقم الإصدار يعود في الاستجابة). واجهة المعلّمة: لوحة الصفّ تعرض بطاقة الحاجة المشتركة — «{النسبة}٪ من الصفّ يحتاج دعمًا في: {المهارة المستهدفة}» بنقرة واحدة إلى مركز الجلسات مصفًّى بتلك المهارة (?subSkillId=) و«عرض الطلاب»؛ وقلق المجال يعدّد المهارات التي تُراجَع من دون زرّ تعيين؛ والبطاقة بلا أسماء وتختفي حين لا شيء يُقال. خرج من فحص المتصفّح حارسان: مركز الجلسات يستخلص الاسم العربي لمهارة مرتبطة من خارج قائمة صفّ الفصل، وSelect المشترك يعرض عنصره النائب — لا الرمز الخام — لقيمة بلا خيار مطابق. لا عملية جديدة؛ amal-api.yaml يبقى ٣٨٢ مسارًا / ٥٧ شريحة. الترحيل 20260925140000_s6_class_need_threshold. تحقّقنا في ثلاثة متصفّحات أمام الخادم الوهمي.
طبقة المعلّمة: ست عائلات دعم، وسطر المهارة المستهدفة، ومستوى دعم ظاهر، وبطاقة الخطّة، ومراجعة بسؤال واحد، والتقديم نطاقًا × وسيطًا (WP-S5، جولة الشريك الثانية §2 + مواصفة المطوّر 2026-09-23 §4–6 / §11.3 / §17) — 2026-09-24
صارت المعلّمة تقرّر من سطر واحد لكلّ طفل — «المجال» (إحدى عائلات الدعم الستّ، بالنصّ نفسه على البلاطة والتقرير) و**«المهارة المستهدفة»** (عبارة المهارة المستهدفة) و**«مستوى الدعم»** (دعم عام / دعم موجّه / دعم مكثّف — تراكمي، منفصل عن حالة الأداء؛ ولا يظهر «المستوى ١/٢/٣» أبدًا) — بدل اسم حزمة ورمز مستوى. صفوف GET /api/workflow/recommendations/{classId} تحمل الآن familyNameAr وfocusAr وsupportLevelAr. خانة «المرساة» في التوصية تحمل محدِّد الحزمة (D-006..009)، لذا تُستخلَص المهارة المستهدفة من أضعف حالة للطفل نفسه داخل العائلة المعروضة (bundle/engine/target-skill.ts؛ حتمي: الشدّة ثم معرّف المهارة)؛ وخطّة القراءة الجهرية تحدّد هدفها من ملف المقياسين — الدقّة / السرعة / كلاهما (المواصفة §11.3) — لا من عبارة مهارة واحدة. GET /api/students/{id}/tier يحمل supportLevelAr (الخادم يملك النصوص الثلاثة في rti/support-level.ts؛ الواجهة تعكسها واختبار في كلّ جهة يؤكّد تطابقها؛ ورقاقات المدير تقرأ الكلمات نفسها). GET /api/profile/{id} يحمل oralReadingProfile (on_track · accuracy_need · rate_need · accuracy_and_rate_need · insufficient — مقياس واحد سليم لا يدّعي «على المسار»، GSR-05) + oralReadingProfileAr + oralReadingFocusAr. GET /api/bundles/{id}/definition يحمل family {familyId, nameAr, successStatementAr} — سؤال بطاقة المراجعة الوحيد. إعداد عامّ جديد: bundle_family (٦ صفوف — خريطة 18→6؛ الخطّة العابرة للمجالات تعرض عائلة مجال مهارتها المرساة، ولا عائلة سابعة) وskill_focus_phrase (٨٠ صفًّا فعّالًا = ٢٥ عبارة من الشريك + عبارتا القراءة الجهرية من مواصفة المطوّر على FL-C01 / FL-D01 بانتظار OQ-22 + ٥٣ بديلًا من التصنيف؛ الدفعات اللاحقة عبر pnpm --filter server import:focus-phrases --file <json> [--dry-run] الذي يرفض مصطلحًا محظورًا أو عبارة تتجاوز ستّ كلمات؛ وتبقى COMP-A03/A05/C09 على البديل، OQ-2). التقديم صار نطاقًا × وسيطًا فوق خيارات التقديم التسعة (bundle/engine/delivery-axes.ts، يفشل مغلقًا عند معرّف غير مُخرَّط؛ ويعود الزوج إلى الخيار المخزَّن ضمن المجموعة المتوافقة مع الحزمة). واجهة المعلّمة: لوحة التوصيات تصفّي بالعائلة وتُعنوِن بالأسطر الثلاثة (اسم الحزمة تفصيل تحت السبب)؛ صفحة الطالب تفرد سطرًا لمستوى الدعم؛ مراجعة التفعيل تعرض بطاقة الخطّة (نقاط القوّة · الحاجة الحالية · العائلة + المهارة المستهدفة · الأنشطة · النطاق · الوسيط · مستوى الدعم · الجدولة · المتابعة) وتبقي الوصفة الداخلية — الحزمة والمرساة والخيوط الداعمة والجسر وتوزيع الجرعة وسلسلة القواعد — خلف «التفاصيل» وخارج الصفحة افتراضيًّا؛ صفحة الخطّة تكسب بطاقة المراجعة (عبارة نجاح العائلة؛ حكم المحرّك يختار مسبقًا نعم / جزئيًا / لا؛ التغيير يحتاج سببًا من الفهرس؛ do_not_decide_yet لا يؤكَّد؛ وacute_regression يقفلها)؛ ومجال الاستماع غير المفعَّل يُعرض «غير مُقيَّم في هذه المرحلة» على كلّ الواجهات، ولا يُعرض نتيجةً أبدًا حتى مع وجود صفّ. لا عملية جديدة؛ amal-api.yaml يبقى ٣٨٢ مسارًا / ٥٧ شريحة. الترحيلان 20260925120000_s5_bundle_family و20260925130000_s5_skill_focus_phrase. تحقّقنا في ثلاثة متصفّحات (المدمج، Playwright، Chrome DevTools) أمام الخادم الوهمي؛ وطُبّق تدقيق RTL (أرقام مشرقية للمدى، ومطابقة عربية للعدد، وتهجئة واحدة لـ«موجّه»).
قوائم الكلمات العشرين المصحَّحة من المعلّم تدخل المحرّك مقياسَ مجموعة بنود (WP-S0 T0.6، مواصفة الشريك 2026-09-23 §9) — 2026-09-23
مقياسا الكلمات الحقيقية (DWR-C01) والكلمات الزائفة (DWR-C02) في المسح الشامل هما قائمتان من عشرين كلمة يقرؤها الطفل جهرًا ويصحّحها المعلّم، لا ثلاثة أسئلة رقمية — وكان المحرّك يطوي أي نتيجة متعدّدة البنود إلى نمط n/3 (18 من 20 = ٩٠٪ كانت تُقرأ «2/3» أي حدّية وتفتح فحصًا تأكيديًا). وحدة جديدة word-list-measure: GET /api/word-lists (قوائم الصفّ) و**POST /api/word-lists/assessments** (مجموعة الكلمات المقروءة خطأ → صحيح / محاوَل / نسبة → نطاق قياسًا إلى توقّع الصفّ → صفّ أدلّة screening_score واحد بـvalue.kind = ITEM_SET_MEASURE → السلسلة نفسها التي يسلكها التقييم: المهارة → مجال DWR → المجال الكلّي → الملف). جلسة الطفل الرقمية صارت تتخطّى المهارات المصحَّحة من المعلّم الواردة في خليّة المخطّط (تبقى في الخليّة، فيُقرأ المجال «جزئيًا» حتى يسجّل المعلّم القائمة)، ولم يعد نشر المخطّط يشترط لها مخزونًا رقميًا. لا تُقدَّم قائمة إلا لصفّ الطفل نفسه (٤٢٢)؛ وقائمة مفقودة ثغرة محتوى (٤٠٤)؛ ولا نافذة مفتوحة → تُسجَّل ولا تُسقَط. النطاقان ٩٠ / ٧٥ بديل هندسي حتى تصل نقاط قطع الشريك (OQ-19)؛ كل صفّ يحمل standIn. إعداد word_list_measure_config (صفّان)؛ محتوى word_list (على الشريك)؛ وقت التشغيل word_list_assessment (بالإلحاق فقط، سنة دراسية، مفاتيح أجنبية حقيقية — درسا مراجعة قاعدة البيانات ١ / ٩). المحرّك: رموز نطاق set_* + ADR-SET-01..03 + PAC-SET-01؛ تعداد النطاقات صار مشتركًا (MeasureBand). عمليتان جديدتان؛ amal-api.yaml صار ٣٨٢ مسارًا / ٥٧ شريحة. الترحيل 20260925110000_s0_6_word_list_measures (ونُقل ترحيل S4 إلى 20260925100000 ليتأخّرا عن ترحيلات فرع مراجعة قاعدة البيانات — ملاحظات التوفيق في docs/superpowers/seams/db-review-sync-2026-09-23.md).
القراءة الجهرية تدخل محرّك حالة المهارة (WP-S4، جولة الشريك الرابعة B5/B6) — 2026-09-23
عند إنهاء جلسة قراءة جهرية (POST /api/orf/assessments/{id}/stop) يُسقَط الآن مقياسان — دقّة القراءة وطلاقة/سرعة القراءة — كلٌّ منهما حالةَ مهارة مستقلّة، لا يُجمعان بمتوسّط ولا يُحوَّلان إلى نمط n/3. يُصنَّف كل مقياس في نطاق قياسًا إلى معيار الصفّ (expected · below_expected · markedly_below) ويُكتب صفَّ أدلّة oral_reading_benchmark_probe على مهارته الحاملة (الدقّة → FL-C01، السرعة → FL-D01)، ثم يسلك السلسلة نفسها التي يسلكها التقييم التشخيصي: لقطات المهارة → مجال FL_ACC مرّة واحدة (قراءة التركيبات الأربع: كلاهما ضمن المدى → مناسب؛ مقياس واحد دون المتوقَّع → هو محلّ الاهتمام؛ كلاهما دون المتوقَّع → الأسرة كلّها؛ أيّ مقياس دون المتوقَّع بوضوح → قلق تقوده مهارة بوّابة) → مربّع المجال الكلّي → الملف (بانتظار مراجعة المعلّم). حتى وصول جدول معايير الشريك (OQ-15) يقوم حكم المعيار المزروع وعتبتا الدقّة ٩٥ / ٩٠ مقامَ النطاقات — إعداد عامّ orf_measure_band_rule (٧ صفوف) تُثبَّت نسخته على كل صفّ. Not_Assessed (لا معيار، نافذة غير منطبقة، جلسة غير مربوطة) لا يكتب شيئًا؛ وإعادة القياس في النافذة نفسها تَجُبّ السابق (لقطات المهارة تكتسب basisRevision، بالإلحاق فقط). تكتسب استجابة الإنهاء projection {written, window, accuracyBand, rateBand, skippedReason}؛ وما يراه المعلّم يبقى الكلمات الصحيحة في الدقيقة. خطآن أُصلحا: صفوف المعيار الفلسطينية (ORF_WITH_DIACRITICS) كانت غير قابلة للوصول — فكل حكم فلسطيني كان Not_Assessed؛ وgradeBand يُشتقّ الآن من ملف الطالب حين يغفله العميل (صفحة القراءة الجهرية لا ترسله)، على مسار البدء ومسار القياس. تغيير سياسة: صار Accuracy_Fluency مجالًا مطلوبًا للصفوف ٢–٤ — ملف طالب في هذه الصفوف بلا نتيجة قراءة جهرية في النافذة يكون DATA_INCOMPLETE. لا عملية جديدة؛ amal-api.yaml يبقى ٣٨٠ مسارًا / ٥٦ شريحة. الترحيل 20260923130000_s4_orf_measure_bands. المحرّك: ٣ صفوف ADR-ORF + صفّ PAC-ORF + صفّا DDR-FL؛ وصار تمرير المجال المؤجَّل يحمل نمطًا مشتقًّا (كانت DDR-04/05/06/07 غير قابلة للوصول من التقييم التشخيصي).
طلبات التواصل بدل التسجيل التجريبي (التقاط طلبات الموقع) — 2026-09-23
نماذج «اطلب عرضاً» في الموقع التسويقي (نافذة الرأس/البطل، و/signup، و/summit، ومفاهيم الصفحة الرئيسية) صارت ترسل إلى POST /api/contact-requests — مجهول الهوية، خلف Turnstile، ومحدود المعدّل (٥ لكل IP في الساعة، ٣ لكل بريد؛ يُحفظ IP كتجزئة مملّحة فقط). لا يُزوَّد أي شيء: يُخزَّن الطلب في contact_request أولًا، ثم يصل إشعار إلى بريد الفريق (CONTACT_INBOX، وإلا عنوان MAIL_FROM، وإلا SMTP_USER) وتأكيد عربي أولًا إلى صاحب الطلب — وفشل البريد يُسجَّل ولا يُعرض للعميل. GET /api/admin/contact-requests (المشرف الأعلى الحقيقي) يعرض أحدث الطلبات. عمليتان جديدتان؛ amal-api.yaml صار ٣٨٠ مسارًا / ٥٦ شريحة. ترحيل 20260923120000_contact_requests. على العميل صار المسار: نموذج → «استلمنا طلبك» (بلا استطلاع حالة ولا كشف بيانات دخول)، وأُزيل lib/demo-site.ts وفروع النشر الثاني، وأُعيدت تسمية المكوّنات إلى contact-request/*.
سحب بيئة العرض التجريبية (WP-S10) — 2026-09-23
أُزيل منتج العرض التجريبي الذاتي بالكامل: وحدتا demo وdemo-admin (التسجيل، التزويد، بوّابة الموافقة، مسح الانتهاء، انتحال الشخصيات، المراقبة)، وشخصية DEMO_ADMIN ودورها ذو الـ١٦ صلاحية، ووسائط الحماية الخاصة بالبيئة التجريبية على كل مسار كانت عليه، وحقل impersonatedBy في GET /api/auth/me، ومصدر impersonation في سجل النشاط، وأكواد الخطأ DEMO_*، ورسائل الترحيب واستلام الطلب، وseed:demo، ونشر app-demo المنفصل (خدمة Cloud Run، خدمات compose، مضيفات Caddy، قاعدة growamal_demo). حُذفت ١٢ عملية؛ amal-api.yaml صار ٣٧٨ مسارًا / ٥٥ شريحة. الترحيل 20260923110000_s10_retire_demo_tenant يحذف جداول العرض التجريبي وعمود session.impersonatedByUserId وorganization.isDemo وصفّ الدور وقيمة التعداد DEMO_ADMIN — ويرفض التنفيذ ما دامت صفوف تجريبية موجودة: يُشغَّل أولًا pnpm --filter server purge:demo-tenants --confirm (تجربة جافة افتراضيًا) على كل قاعدة بيانات. على العميل أُزيلت /demo و/demo-login و/demo-admin و/admin/demo-tenants وشريط الانتحال وخصائص demoMode وملف تعريف الارتباط amal_demo. نماذج «اطلب عرضًا» في الموقع التسويقي ما زالت ترسل إلى /api/demo/register المحذوف — وهي القرار التالي (التقاط طلبات التواصل أو الإزالة).
تبسيط المرحلة التجريبية الأولى (WP-S0 · S1 · S2): إعداد اليوم الأول، وبوّابات المحرّك، وإغلاق سلسلة التقييم → الملف → الدعم — 2026-09-23
كل ما تحتاجه المدرسة الأولى لمسار «تقييم → حالة المهارة → ملف مبسّط → دعم»، مبنيًّا بحيث يُفعَّل نموذج V5 الكامل لاحقًا بالإعداد لا بالبرمجة. عملية واحدة جديدة؛ المجموع ٣٩٣ مسارًا / ٤٢٨ عملية. ترحيلات: 20260922100000_s1_coverage_basis، 20260922101000_s1_required_domains_by_grade، 20260922102000_s1_pilot_profile_allowlist، 20260922103000_s2_snapshot_basis_revision.
- إعداد اليوم الأول (S0).
pnpm seed:pilot-configينشر نوافذ التقييم الثلاث ومخطّط الصف الأول (١١ مهارة وعي صوتي × BOY/MOY/EOY) على مستوى المؤسّسة.PUT /api/admin/diagnostic-blueprintصار يرفض المهارة غير المفعّلة (422) ويُبلّغ عن ضعف بنك الأسئلة فيwarnings[]مع الاستجابة 200 — أو 422 عندما يحمل الطلبstrict: true. - التغطية نسبةً إلى المخطّط (S1). كان مقام «تغطية المجال» كل مهارات المجال النشطة، فيبقى طفل الصف الأول «جزئيًّا» إلى الأبد. الآن هو خليّة المخطّط المنشورة لصفّه ونافذته (مدرسة → مؤسّسة → عام)، ثم نطاق الصف، ثم المجال كاملًا؛ ويُحفَظ الاختيار في
domain_status_snapshot.coverageBasis. - المجالات المطلوبة حسب الصف + قائمة ملفّات المرحلة الأولى (S1). جدولا إعداد عامّان (
required_domain_by_grade،pilot_profile_allowlist). مجال مطلوب غائب هذه النافذة يوقف الملف عند «بيانات غير مكتملة» (كان يمرّ بصمت كـ«على المسار»). المرحلة الأولى تُظهر فقط: على المسار · متابعة · فجوة أساسيات فكّ الشيفرة (+ معدِّلان)؛ وغياب صفّ في الجدول يعني فتحًا كاملًا، فيبقى محرّك V5 كاملًا قابلًا للوصول ومختبَرًا. - إغلاق السلسلة (S2). بعد انتهاء التقييم: المهارات → كل مجال متأثّر مرة واحدة بعد استقرار كل المهارات الشقيقة (كان صفّ المجال يتجمّد عند تغطية المهارة الأولى ١/ن) → المجال الكلي →
recomputeProfile(بانتظار مراجعة المعلّمة). تأكيد الملف عبرreview-resolutionيُحتسب بعدهrecommendBundleويعيدbundle {written, bundleId, objectType, actionCode, idempotent}. مسار جديدPOST /api/profile/{studentId}/recomputeلإعادة الحساب يدويًا (مقيّد بمعلّمة الصف). - مراجعات أساس اللقطة (S2).
domain_status_snapshotوmacro_domain_status_snapshotيكتسبانbasisRevisionضمن المفتاح الفريد. حين تتغيّر مجموعة اللقطات المغذّية عند نسخة القواعد نفسها — مجموعة تأكيدية تحسم مهارة بوّابية موقوفة — يُلحِق الكاتب مراجعة جديدة بدل تجاهلها، ويبقى الصف الأقدم تاريخًا (B.7). ثم يُعاد حساب الملف بعد اكتمال المجموعة التأكيدية، فتنتقل الطالبة من «بيانات غير مكتملة» إلى «فجوة أساسيات» دون خطوة يدوية. - خلايا «لا تقييم» الصريحة (T0.5، الجولة 4 A1 — الصف الأول لا يجلس لتقييم بداية العام).
PUT /api/admin/diagnostic-blueprint/{grade}/{cycle}يقبل الآنsubSkillIds: []كخلية صريحة تعني «لا تقييم شامل لهذا الصف في هذه النافذة».GET /api/student/today-planيكتسبscreeningState: "not_screened": تُتخطّى النافذة المفتوحة بهدوء لهذا الصف (تعرض الصفحة الرئيسية «لا يوجد تقييم مفتوح الآن»، لا «لا توجد أسئلة جاهزة»)، ولا يُطلق أي تنبيه نقص محتوى. الخلية المفقودة لم تتغيّر — تبقى على مسار QA_040 الصاخب حتى لا تُقرأ خلية منسيّة على أنها قرار.seed:pilot-configينشر خلية BOY الفارغة للصف الأول دائمًا، أمّا قائمتا MOY/EOY المؤقتتان فلا تُنشران إلا لمؤسّسة تجريبية أو مع--allow-placeholder. - التدريب من المهارات المُقاسة (WP-S3، الجولة 4 B3/B4). صار بذر التدريب موجِّهًا من الحالة إلى نوع التجربة (
remedial · reinforcement · maintenance · enrichment · collect_evidence) عبر جدول إعداد عام جديدpractice_experience_map— الطالب على المسار يحصل على قائمة تثبيت/إثراء بدل الرفض، وضعف المهارة البوّابية يتقدّم، وdo_not_decide_yetلا يولّد شيئًا.practice_queue.experienceTypeيسجّل ما فتحته المهارة المحورية. التقديم على مستوى الصف فقط في كل مكان (القياس والتدريب وعدّ بنك المخطّط): لا رجوع إلى صف آخر — مهارة مؤهّلة بلا عنصر تدريب في صف الطالب تُطلق الفحص الجديد QA_041 (سجل تنبيهات المنصة، مرة واحدة لكل صف × مهارة يوميًا؛ السجل صار ٤١ فحصًا) وينتقل البذر إلى المهارة المؤهّلة التالية في الصف نفسه. جلسة يوزّعها المعلّم تحلّ محلّ قائمة التدريب المبذورة من التقييم (supersededByQueueId) بدل تخطّيها؛ جلسة معلّم فوق جلسة معلّم تبقى تخطّيًا. تقديم التدريب يجري تحت حزمة الدعم الفعّالة عند وجود صف مستوى سقالة للمهارة، وبلا مستوى خلاف ذلك. ترحيل20260923100000_s3_practice_experience_map. لا تغيير في المسارات. - الثوابت. لا نموذج لغوي في أي خطوة قياس (V-5)؛ لا نسبة مئوية واحدة للطالب (V-3)؛ جداول القياس تُلحَق فقط (B.7)؛ المعلّمة تقرّر في النقطة نفسها (V-12).
تجربة المدير (WP-MGR) الشريحة BE-4: نموذج الاجتماع، وملخص الصف، وتصدير قائمة الطلاب، والكتالوجان المنتظران من الشريك — 2026-09-19
المستندات التي يُدار بها اجتماع مراجعة البيانات فعليًا، مع عقود الكتالوجات للمحتوى الذي ما زال على الشريك. ٦ عمليات جديدة؛ المجموع ٣٩٢ مسارًا. لا ترحيل قاعدة بيانات — كل جدول تكتب فيه هذه الشريحة وصل في BE-0 وBE-3.
GET /api/principal/students/{studentId}/meeting-form.pdfيطبع «نموذج مناقشة الحالات الطلابية» معبّأً ببيانات الطالب على مستوى الحالة: المجالات الخمسة، ومهارات المجال المحدّد، وخطة الدعم النشطة، وآخر نتائج المتابعة، والطلبات المفتوحة — ثم مساحات مسطّرة فارغة. المناقشة والقرارات تُكتب على الورق ولا تعود إلى المنصة: لا يوجد حقل نص حر في هذه الواجهة لاستقبالها، والنموذج الورقي هو ما يغني عنه.GET /api/principal/classes/{classId}/summary.pdfصفحة «حالة الصف» في ورقة واحدة: معلومات الصف، وبطاقة النمط الأبرز، وجدول المهارات بتوزيعه الكامل، وأسئلة المناقشة. تجميعي فقط — لا يذكر اسم أي طالب.GET /api/principal/classes/{classId}/students/exportيصدّر الصفوف نفسها التي يعرضها الجدول بالمرشّح نفسه، بصيغة CSV (بترميز UTF-8 مع علامة BOM حتى لا تظهر الأسماء العربية مشوّهة في Excel) أو PDF أفقي. يستدعي الدالة نفسها التي تبني الشاشة، لا استعلامًا ثانيًا. وفوق الحدّ الأقصى (٥٠٠ صفًّا افتراضيًا) يُطلب تضييق المرشّح مع ذكر الرقمين — ولا تُقتطع القائمة بصمت أبدًا.GET /api/principal/classes/{classId}/discussion-promptsيقرأ «أسئلة للمناقشة» من كتالوج مغلق يؤلّفه الشريك، مفهرس بـ(المجال × نوع النمط). لا تُولَّد آليًا إطلاقًا. الكتالوج يصل فارغًا بانتظار Q-MGR-10، فتعيد الخدمة قائمة فارغة وتعرض الواجهة «قريبًا» — وهذا هو العقد، لا خطأ.GET /api/principal/meeting-templatesيسرد النماذج الأربعة الثابتة ويتيح تنزيلها (Q-MGR-9). يُفحص وجود الملف على القرص عند كل طلب، فيكفي وضع الملفات ليتحوّل الكارت إلى تنزيل حقيقي دون تعديل برمجي؛ وحتى ذلك الحين تُعرض جميعها بحالة «قريبًا». ولا يُسجَّل أي سجل اطلاع لهما — فالنموذج الفارغ لا يذكر طالبًا، بينما النموذج نفسه معبّأً يُسجِّل سجلًّا واحدًا.- سياسة النسب على الورق. كل نسبة مطبوعة تحمل عدديها: «١٢ من ٢٣ (٥٢٪)»، وإذا لم يُقيَّم أحد تُطبع «—» لا «٠٪» — فـ«لم يُقَس أحد» و«لم يبلغ أحد المستوى» ليسا الشيء نفسه.
- توسيع فحص المصطلحات الدولية (Q15) ليغطي واجهات المدير وكلا مولّدَي ملفات PDF بعد أن كان محصورًا بوحدة واحدة.
- بيانات العرض التوضيحي. أصبح
seed:demoيملأ واجهة المدير: أربع شعب دراسية بصفّين لكل منها، وقائمتا غرفة البيانات، ومجموعتا دعم، ومعلمة نشطة وأخرى غير نشطة، واجتماع قادم بجدول أعماله واجتماع سابق، وطلب لكل حالة، والحالات الحديّة التي يجب أن تثبتها الشاشات.
تجربة مدير المدرسة (WP-MGR) الشرائح BE-1 · BE-2 · BE-3 · FE-2 · FE-7: الشاشات التجميعية الخمس، وقراءات مستوى الطالب، وطلبات المدير واجتماعاته، ولوحة البدائل، 2026-09-19
بقية إعادة تصميم تجربة مدير المدرسة فوق أساس BE-0/FE-0/FE-1 أدناه. ٢٨ عملية جديدة. أصبح amal-api.yaml ٣٨٦ مسارًا / ٤٢١ عملية (من ٣٥٩ / ٣٩٢ على main). الترحيلان 20260918124000_wp_mgr_be_meetings_and_requests و20260919120000_wp_mgr_be_student_visibility.
- BE-1 — القراءات التجميعية. أربعة عشر مسارًا خلف شاشات المدير: طيّات الشعبة والصف وفئة الدعم، وإشارات الانتباه، وطوابير غرفة البيانات، ومؤشرات استخدام المنصة، والبحث ضمن النطاق. كل نسبة تحمل الأعداد التي حُسبت منها وتسمّي مقامها؛ والعدد الذي لم يُقَس يُبلَّغ عنه بـ
nullلا بـ0. - BE-2 — قراءات مستوى الطالب (القرار D-1). ثمانية مسارات مُدقَّقة تضع اسم الطالب وحالته أمام المشرف لأول مرة، إضافةً إلى الأجزاء الخاصة بالطلاب من البحث وقائمة الانتباه وطوابير غرفة البيانات. شكل الاستجابة قائمة سماح مبنية صراحةً لا طرحًا من شكل أوسع: θ والخطأ المعياري وδ_prior وإجابات الأسئلة وصفوف الأدلة وتفاصيل حزمة القرار ومستوى السقالة الفردي ونقاط التحفيز وتاريخ الميلاد وبيانات ولي الأمر ورمز الدخول كلها غائبة بحكم البناء. يُكتب سجل
StudentDataAccessLogواحد لكل استجابة على مستوى الطالب، قبل إرسالها؛ والطلب خارج النطاق يُعيد 404 دون كتابة أي سجل. وOrganization.studentLevelVisibilityمفتاح إيقاف، مفعَّل افتراضيًا. - BE-3 — أول عمليات كتابة للمدير. رمز صلاحية سادس وعشرون (
CREATE_PRINCIPAL_REQUEST)، وجدولprincipal_requestمع سجل حالاته غير القابل للتعديل، واجتماعات مراجعة البيانات بلقطة جدول أعمال مجمَّدة، وثلاثة أنواع إشعارات، ووصلة تفتح مراجعة المستوى داخليًا. لا يمسّ أي مسار للمدير جدولstudent_tier_status— فتغيير المستوى طلب لا كتابة (B.20). - FE-2 — الشاشات التجميعية الخمس. لوحة المدرسة، ولوحة الشعبة، والنصف العلوي من لوحة الصف، ومجموعات الدعم، واستخدام المنصة، بتخطيط الشريك وألوانه.
- FE-7 — لوحة البدائل. أربع معالجات لمدرسة تجريبية واحدة على
/principal/storyboard/*لمراجعة الشريك. بيانات تجريبية فقط؛ لا يُقرأ أي مسار وكل أدوات الإجراء معطّلة.
تجربة مدير المدرسة (WP-MGR) الشرائح BE-0 · FE-0 · FE-1: وحدة principal-views ولوحة المدرسة المجمَّعة، وسجلّ الوصول إلى بيانات الطلاب، وإعدادات المدرسة المُصدَّرة، وشريط الشريك الجانبي وترويسته، وبوّابة النسب المئوية، 2026-09-18
خادم + هيكل واجهة مدير المدرسة ومدير المدارس. الشرائح الثلاث الأولى من إعادة تصميم تجربة المدير (المتطلّبات prds-v2/40-teacher-experience/45-manager-experience-redesign.md؛ التصميم docs/design/wp-mgr-be/ + docs/design/wp-mgr-fe/). لا شاشة ذات محتوى لمدير المدرسة بعد: BE-0 قراءة الأساس، وFE-0 مكوّنات العرض وفحوصه، وFE-1 الهيكل. عملية جديدة واحدة. يبلغ amal-api.yaml الآن 360 مسارًا / 393 عملية. الترحيلات 20260918120000_wp_mgr_be_config_and_catalog و20260918122000_wp_mgr_be_access_log و20260918123000_wp_mgr_be_read_indexes.
GET /api/principal/schools/{schoolId}/dashboard(principalSchoolDashboard، الوسمprincipal-views؛VIEW_SCHOOL/VIEW_ORG/RUN_BACKOFFICE) هو طيّ مجمَّع واحد للمدرسة لكل(schoolId, window, period)، يُطوى في الذاكرة من مجموعة قراءة واحدة: لا حلقة على الصفوف، وحارس عدد الاستعلامات أدناه يثبت ذلك. يحمل المتن المجالات الكبرى الخمسة للموجة الأولى، ولكل منهاcountsعلى ستّ فئات عرض (meetsوapproachingوbelowوsevereوunder_reviewوnot_assessed) وmeetsShareوbandالخاصّة بالمجال (الأسوأ يغلب)؛ وenrolledCount/assessedCount؛ ومؤشّرات الاستخدام الثلاثة المختصرة (teachersActiveوstudentsActiveوplansOnPlanمعperiodFrom/periodToوpartialPeriod)؛ وحكم كفاية البياناتdataSufficiency(sufficientوweeksElapsedوrequiredWeeksوstudentCoverageوblockingReasons)؛ وattention(أعداد لكل عائلة تنبيه، وهو[]حتى BE-1)؛ وqueueCounts(nullحتى BE-1 ومفتاحdataRoomOverviewStrip)؛ وwave2Tiles(يظهر فقط معshowWave2Tiles). الاستعلام:window(BOY|MOY|EOY؛ إغفاله = نافذة المدرسة الحالية من تقويم التقييم) وperiod(this_month|last_30_days|last_90_days، بسقف أفق القياس البالغ 90 يومًا).Cache-Control: private, max-age=60. لا يخرج أيّ معرّف طالب من هذه الاستجابة، فلا تكتب صفًّا في سجلّ الوصول.- غلاف
metaعلى كل استجابة من الوحدة:{ assessmentWindow, computedAt, ruleVersion, configVersion, stale, languageRuleSetVersion }. يُشتقّstaleمن حداثة البيانات (أحدث لقطة مساهمة أقدم منsnapshotStaleMinutes، افتراضيًّا 60) لا من ساعة تحديث؛ وإذا لم يوجد صفّ مساهم أصلًا فـstale: trueمعcomputedAtعند لحظة الطلب. يُثبَّتruleVersion(قواعد الطيّ) وconfigVersion(العتبات؛0= الافتراضيات في الشيفرة) منفصلَين ليميّز الاسترجاع بين «تغيّرت القواعد» و«أعادت المدرسة ضبط مفتاح» (V-6). وlanguageRuleSetVersionهوnullفي القراءات المجمَّعة. - شكل
Shareهو النسبة المئوية الوحيدة على واجهة المدير:{ numerator, denominator, value, shareOf }، وvalueفي[0, 1]و**nullكلّما كان المقام 0** (يُعرض «—» لا 0%)؛ وshareOf∈assessed_students|enrolled_students|measured_skills|active_plans|active_teachers|enrolled_students_active. تُعرضNot_AssessedوPartialوContextualفئاتٍ مستقلّة وتُستبعد من كل مقام، ولا تُطوى في 0 أبدًا. ولا حقل «مستوى قرائي عامّ» في أيّ موضع من الاستجابة (V-3). - الأخطاء، اقرأ هذا قبل الربط.
403هو بوّابة الصلاحية فقط. كل نتيجة نطاق هي404: المدرسة من مؤسسة أخرى، أو مدرسة أخرى، أو خارجscopedSchoolIdsلمدير المدارس، أو غير الموجودة أصلًا، كلها متطابقة على السلك (عدم الإفصاح عن الوجود)، ولا يكتب404صفًّا في السجلّ. لا تقرأ403بمعنى «موجود لكن ممنوع» على أيّ مسار/api/principal/**. و422لقيمةwindow/periodغير صالحة. - ثلاثة جداول جديدة.
student_data_access_logهو سجلّ التدقيق خلف القرار D-1 (يرى مدير المدرسة أسماء الطلاب وحالاتهم للقراءة فقط): صفّ واحد لكل استجابة HTTP على مستوى الطالب (كشف من 25 صفًّا = صفّ واحد بـsubjectStudentCount = 25؛ وتبديل التبويب طلب مستقلّ فصفّ مستقلّ)، يُكتب قبل إرسال الاستجابة (تعذُّر الكتابة يُسقط الطلب، فلا يُقدَّم متن على مستوى الطالب بلا تدقيق أبدًا)؛ وsubjectStudentUserIdهوUser.id؛ وfiltersمجموعة مفاتيح مغلقة ويُرفض المفتاح المجهول؛ ولا يُخزَّن نصّ البحث أبدًا بلqueryLengthفقط؛ ويربطrequestIdالصفّ بأثر الطلب. إضافة فقط بفحص CI (lint:no-update-on-audit-tables) ومسار كتابة واحد (lint:principal-views-single-write-path←repository/access-log-writer.ts)، وهو فحص واصطلاح لا ضمانة من قاعدة البيانات. تشحن BE-0 الكاتب وتختبره؛ أمّا مسارات الطالب التي تستدعيه فتصل في BE-2.school_literacy_index_configيحمل عتبات واجهة المدير، 17 مفتاحًا (minimumWeeksوstudentCoverageThresholdوgaugeBandCutsوclassConcernShareوclassMinAssessedوclassPacketCountوdataIncompleteDaysوpartialVerdictStreakوusageInactiveDaysوgroupSlowShareوminComparablePointsوsnapshotStaleMinutesوexportMaxRowsوpersistQueueSnapshotsوshowWave2TilesوdataRoomOverviewStripوprivacyFooterKey)، نشر ثم تجميد: التعديل يُدرجversion + 1ويعطّل الصفّ السابق، وفهرس فريد جزئي يضمن صفًّا نشطًا واحدًا بالضبط لكل(organizationId, schoolId)؛ والحلّ: صفّ المدرسة ← صفّ المؤسسة ← افتراضيات الشيفرة التي تعيد إنتاجPRN_CONFIGالمُثبَّت سابقًا بايتًا ببايت، فـconfigVersion = 0يعني «سلوك لم يتغيّر». ينشئ البذر صفًّا افتراضيًّا نشطًا واحدًا على مستوى المؤسسة لكل مؤسسة ليس لها صفّ. كل عتبة مملوكة للشريك (Q-MGR-4 / Q-MGR-5)؛ والافتراضيات هي قيم العمل الواردة في المتطلّبات.discussion_prompt_catalogإعداد عامّ يؤلّفه الشريك، نشر ثم تجميد، بصفر صفوف في الموجة الأولى (Q-MGR-10)؛ يثبّت البذر العدد عند 0 فيصير تسليم الشريك تغييرًا مرئيًّا مقصودًا؛ وتعرض الواجهة «قريبًا» ولا يُولَّد شيء (V-5). - تصحيحات تصميم تستحقّ انتباه المُدمِج. جدول
runtime_audit_logالمذكور في المتطلّبات غير موجود:runtime_audit_rowهو عمود القرار (بلا عمودstudentId) وليس سجلّ التدقيق؛ السجلّ هوstudent_data_access_log. والعرضschool_dashboard_snapshotالذي تسمّيه 44 FR-PRN-11 لم يُبنَ قطّ ولا يُبنى هنا: يطوي R0 عمودmacro_domain_status_snapshotالحيّ عبر فهرس تغطية جزئي جديد واحد (DISTINCT ONوالعرض المادّي هما سلّم التصعيد المقيس، الموجة الثانية). وجملة «403 لخارج النطاق» في 44 مُعدَّلة إلى قاعدة 404 أعلاه. ويبقىlib/scope.ts::resolveStudentScopeمجمَّدًا (يُرجعforbiddenلمدير المدرسة، ويعتمد عليه 29 موضع كتابة)؛ أمّاresolveSupervisorStudentScopeالمحلّي في الوحدة فيفوّض القرار إلىcanReachStudentالمشحون، ويفرضlint:principal-scope-isolationهذا الحدّ. - CI. وظيفة جديدة
wp-mgr-beبخدمة Postgres 16 خاصّة بها تشغّل ثلاث خطوات حاجبة:lint:mgr(مسار الكتابة الواحد · عزل النطاق · مُنشئShare، حيث يرفضlint:principal-share-constructorأيّ نسبة خام خارجengine/shares.ts· جداول التدقيق إضافة فقط · معرّف الطلب على جداول النشاط · مسار الكتابة الواحد لحالة المستوى · لا نموذج لغويّ، مع إضافةprincipal-viewsإلى المجموعة التي يغطّيها ذلك الفحص)، وحارس عدد الاستعلامات لكل مسار (test:mgr:query-count: عدد استعلامات R0، المثبَّت عند 21، يجب أن يتطابق على تركيبة من 4 صفوف وأخرى من 30، لأنّ N+1 سريعًا على تركيبة صغيرة يبدو أخضر لفحص زمن الاستجابة)، وحزمة اختبارات الوحدة (test:principal-views). وأُلحقت الأوامر الثلاثة نفسها بـtest:qa. قيس عند خروج BE-0 على تركيبة من 750 طالبًا (منصّةPERF=1عند الطلب، ليست في CI): p95 لـR0 هو 202 مللي ثانية مقابل بوّابة 2000 مللي ثانية. - ثغرات معروفة.
attentionهو[]وqueueCountsهوnullحتى تشحن BE-1 عائلات التنبيه ومحرّك الطوابير (تُحذف العائلة ذات العدد صفر بموجب العقد، فـ«لم يُبنَ بعد» و«لا يُطلق» يُعرضان سواء). يتلقّىDEMO_ADMINالردّ404على R0 (لا فرع لـDEMO_ADMIN فيcanReachSchoolالمشحون: إغلاق آمن، مثبَّت باختبار، ويُحلّ مع بذر العرض التجريبي في BE-4)، فلا يمكن لمستأجر العرض إظهار اللوحة الجديدة بعد. ولا تسرد صفحة تدقيق المشرف وصولَ مدير المدرسة بعد (BE-4). وما زالpnpm test:tenant-isolationليس خطوة في CI؛ يصير خطوة حاجبة قبل دمج BE-2. - الواجهة، المكوّنات والفحوص (FE-0).
ShareValue(components/viz/share-value.tsx) هو المكوّن الوحيد الذي يطبع%على واجهة مدير المدرسة أو مدير المدارس: يُصدرdata-share-of="<numerator>/<denominator>"(أوdata-rate-of="<key>"لرقم بلا زوج أعداد، كتنفيذ الخطط) مع عبارة مخفيّة بصريًّا «n من d …»، ويعرض «—» بلا سمة لمقام صفري. يعمل فحصان جديدان داخلpnpm --filter web lintالذي تشغّله وظيفةbuild:lint:no-global-percentage(قائم على شجرة الشيفرة: يحكم على مواضع النصّ المعروض ونداءات مُنسِّقات النسب، لا قيم CSS ولا عامل باقي القسمة ولا التعليقات؛ ومخرج الطوارئ// eslint-percent-allow: <reason>) وlint:no-inline-arabic(يجب أن يأتي أيّ نصّ عربيّ داخل شجرة المدير منlib/manager-copy.tsأوlib/status-display.tsأوlib/arabic-count.ts؛ والملفّات السابقة في خطّ أساس مؤرَّخ). الوكيل الجذريpnpm test:render:no-global-percentage. وتحلّ مفردات D-5 على مستوى المنصّة كلّها فيstatus-display.ts: صارت رقاقةApproachingتقرأ «تحت المتابعة» وLISTEN_COMPيقرأ «الفهم المسموع» (بما في ذلك واجهات المعلّمة). - الواجهة، الهيكل (FE-1). الشريط الجانبي لمدير المدرسة هو ستّة الشريك + ثلاثة:
/principal·/principal/grades·/principal/students·/principal/support-groups·/principal/usage·/principal/data-room، ثم «الإعدادات» · «مركز المساعدة» · «تسجيل الخروج» (والأخير صفّ تنقّل جديد من نوعkind: "action"يفتح حوار الحساب بدل رابط) وكتلة شعار واحدة. ويحتفظ شريط مدير المدارس بـ«لوحة المؤسسة» (/manager) ويضيف اختصارات بنطاق المدرسة على/manager/orgs/:orgId/schools/:schoolId/{grades,students,support-groups,usage}(تُحلّ من المسار أو من آخر مدرسة زارها) إضافة إلى/manager/data-roomعلى مستوى المؤسسة. تعرض الترويسة على كل شاشة لمدير المدرسة أو مدير المدارس المدرسةَ + العام الدراسي، والبحث المحدود بالنطاق (يُرسَل بتأخير قصير إلىGET /api/principal/search، وهو مسار من BE-1، فيتراجع اليوم إلى «البحث غير متاح حاليًا.»)، والجرس بعدد غير المقروء، ورقاقة المستخدم بسهم القائمة؛ وتحمل الصفحات تحت الرئيسية مسار تنقّل بأيقونة الرئيسية، ورابط رجوع حيث يرسمه التصميم. و/principal/implementation←/principal/usage#implementationو/principal/review←/principal/data-roomتحويلان307منnext.config.ts(مع حفظ الاستعلام، لإصدار واحد)؛ ويحتفظ/principal/growthو/principal/leaderboardبصفحتيهما ويغادران الشريط الجانبي فقط (D-8). تعرض اثنتا عشرة صفحة لمدير المدرسة وخمس لمدير المدارس عنصرًا نائبًا صريحًا «قيد الإنشاء — يصل مع الشريحة التالية» بالعنوان الحقيقي ومسار التنقّل؛ وتبقى صفحة/principalالرئيسية هي اللوحة الحالية حتى تعرض FE-2 تخطيط الشريك على R0. وتعرض الصفحة خارج النطاق بطاقة 404 («هذه الصفحة غير متاحة ضمن نطاقك»)، لا 403 أبدًا.
راجع مدير المدرسة ومدير المؤسسة للشاشات الحالية، والمنسقون والمدراء للأدوار والنطاقات، ومرجع الواجهة البرمجية لأشكال MgrSchoolDashboard وMgrShare وMgrMeta الكاملة.
إدارة المستخدمين للمسؤول: مراجعة متدرّجة، وعمليات كاملة، وإعادة تعيين كلمة المرور مع الإرسال بالبريد، 2026-09-16 (مُوفَّق؛ صدر أصلًا في 2026-09-07)
صار amal-api.yaml يضمّ 352 مسارًا و385 عملية.
أُعيدت صياغة هذا القيد ليصف الواجهة بعد توفيق تصميم 2026-09-07 مع #138 (“استقبال أول عميل”، 2026-09-09). السجلّ المرجعي: docs/superpowers/specs/2026-09-16-admin-user-management-reconciliation.md.
GET /api/users(listUsers) تصفية متدرّجة: بالمؤسسة (لمشرف المنصّة فقط)، فالمدرسة، فالدور، فالصفّ، فالحالة، فالبحث، مع ترقيم بالإزاحة وحقلtotal.GET /api/users/{id}و**PATCH /api/users/{id}** (getUser/patchUser) صارا شكلًا واحدًا مدموجًا. تحمل التفاصيل والتحرير معًا حقول الهويّة من #138: أجزاء الاسم العربي الأربعة التي يركّبها الخادم اسمًا كاملًا (fullNameAr)، إضافة إلى البريد الإلكتروني (وهو معرّف دخول البالغ) والهاتف واسم المستخدم، إلى جانب الحالة (إيقاف/إعادة تفعيل) وحقل خاصّ بدور المستخدم: نقل صفّ للطالب، أو استبدال صفوف المعلّمة وربطها بمدرسة، أو إعادة تعيين مدرسة لمدير المدرسة، أو نطاق مدارس للمشرف، أو مقعد اختصاصي للمسؤول.DELETE /api/users/{id}(deleteUser) حذف ناعم: تُنهى الجلسات والرموز، ويجري تسلسل الإلغاء حسب الدور، ويُعلَّم البريد الإلكتروني كمحذوف داخليًّا فيمكن إعادة استخدامه، ولا يمكن أبدًا إزالة آخر مسؤول عام نشط.POST /api/users/{id}/password/reset(resetUserPassword) هو إجراء الضبط أو إعادة التعيين لكلّ مستخدم على حدة: توليد بيانات دخول أو كتابتها يدويًّا، مع كشف لمرّة واحدة وإرسال اختياري إلى العنوان المسجّل أو عنوان آخر. بيانات دخول الطالب رمز واحد من 4 أرقام، هو نفسه رمز دخول الصفّ وكلمة مرور المنزل، فإعادة تعيينه تُدوِّر الاثنين معًا.- الإرسال الجماعي لم يتغيّر ويبقى
POST /api/users/credentials/sendالخاصّ بـ #138: يختار المسؤول عدّة حسابات فيرسل إليها بيانات الدخول، تلقائيًّا (إعادة إرسال للطلاب، وإعادة تعيين للبالغين) أو بإعادة تعيين للجميع. يتعايش مساران للإرسال بقصد: إجراء الصفّ هو إعادة التعيين الفردية أعلاه، وإجراء الشريط العلوي هو هذا الإرسال الجماعي. - يحمل
AuthEventLogالآنactorUserIdوحقلauditMetaبمفاتيح مغلقة في كلّ كتابة بمبادرة من مسؤول، إلى جانب حقلdetailالخاصّ بـ #138. سبعة أنواع أحداث تعود لهذا التوفيق (admin_password_resetوcredential_email_failedوuser_createdوuser_updatedوuser_suspendedوuser_reactivatedوuser_deleted)؛ أمّاcredential_emailedفمن #138 ويحمل الآنactorUserIdأيضًا.
راجع مرجع الواجهة البرمجية لأشكال الطلب والاستجابة الكاملة.
مركز جلسات المعلّمة: قائمة واحدة لكل أنواع الجلسات، وكشوف الإنجاز، ومراجعة إجابات كل طفل، وإعادة الإرسال، وكشف للطباعة، 2026-09-11
خادم + معلّمة. كانت المعلّمة تنشئ جلساتها وتتابعها في أربعة أماكن منفصلة، ولا مكان منها يجيب عن سؤال «من أنهى؟ وبماذا أجاب كل طفل؟». صارت /teacher/sessions قائمة واحدة تغطّي صفوفها كلّها بأربعة تبويبات (تدريب = جلسة مولَّدة، تقييم = تقييم صفّ أو إعادة قياس واحدة، قراءة = دفعة قراءة مخطّطة، حصّة مباشرة = حصّة مباشرة)، ويفتح كل صفّ كشفًا. وكل ما يُعرض كان محفوظًا أصلًا، فلا جدول جديد ولا ترحيل. 7 عمليات جديدة. يبلغ amal-api.yaml الآن 355 مسارًا / 386 عملية (بعد دمج إصدار تفصيل أخطاء القراءة).
GET /api/teacher/sessions?kind=training|screening|reading|live&classId&cursor&limitيُرجع نوعًا واحدًا في كل نداء، من الأحدث إلى الأقدم، بمؤشّر صفحات مبهم(createdAt, id)وكتلة أعداد لكل صفحة{ total, completed, inProgress, notStarted, other }. وهي أعداد لا نسب مئوية. وإغفالclassIdيعني كل صفوف المستدعية؛ أمّا صفّ لا تدرّسه فيردّ403. وتحمل الحصّة المباشرة الجاريةcounts: null، لأنّ تفصيل كل طالب لا يوجد إلّا بعد انتهائها. ومؤشّر لم تُصدره هذه النقطة يردّ400بدل العودة الصامتة إلى الصفحة الأولى.GET /api/sessions/{id}/progressهو كشف المستلمين لجلسة مولَّدة مُسلَّمة:completedأوin_progressأوnot_startedأوstoppedأوskippedأوexcluded، معitemsAnsweredوitemsCorrectوitemsTotalوlastActivityAt. وتُشتقّ الصفوف الرقمية من قائمة التمرين ومن سجلّ الإجابات الذي لا يُعدَّل (تفوز المحاولة الأخيرة لكل سؤال، والصفّ الذي أخفق في تحميل وسائطه ليس إجابة)، وتُشتقّ الصفوف الورقية ممّا أدخلته المعلّمة من علامات. و409قبل التسليم، و404خارج مؤسسة المستدعية.GET /api/sessions/{id}/recipients/{studentId}/responsesيُرجع إجابات طفل واحد سؤالًا سؤالًا: نصّ السؤال والخيارات وما اختاره وما هو المفتاح ونوع الخطأ المخزَّن. ويعود المختار والصحيح قوائمَ من معرّفات الخيارات (chosenOptionIdsوcorrectOptionIds) محلولةً عبر مطابقة الخيارات التي صحّحت الإجابة نفسها، فيحمل السؤال متعدّد الاختيار أو المرتَّب كل قيمه، وتصل الإجابة القديمة المخزَّنة بنصّ الخيار إلى المعرّف نفسه. ويقولorderSensitiveإنّ الترتيب هو المهارة. ويُعلّمreviewable: falseأنواع التفاعل التي تُصحَّح بمفتاح على الخادم (الإملاء الكتابي، ودمج البطاقات، وتقطيع المقاطع، والفراغات متعدّدة المواضع، وترتيب الكلمات)، فتعرضها الواجهة بعبارة «لا يمكن مراجعتها هنا» بدل صفّ فارغ.GET /api/classes/{classId}/screening-triggers/{id}/progressيقابل القائمة النشطة للصفّ بالجلسات التي فُتحت تحت تقييم واحد. وتفوز آخر جلسة لكل طفل، ويُستثنى الطفل الذي ترك الصفّ من الكشف ومن أعداد التبويب معًا. وcompletedAtهو وقت إنهاء الجلسة فقط، ولا يُستعاض عنه بوقت البدء أبدًا.POST /api/sessions/{id}/resend(المتن{ studentIds }، حتى 200) يعيد تسليم جلسة مُسلَّمة لمستلمين مُسمَّين عبر المسار نفسه الذي سلّم أوّل مرّة. ويعود كل معرّف مطلوب في سلّة واحدة بالضبط:queued، أوstillBlocked(ما زال لدى الطفل تدريب آخر مفتوح)، أوalreadyWaiting(يحمل هذه الجلسة أصلًا)، أوnotResendable(قائمة منتهية أو متروكة، أو معرّف ليس مستلمًا مؤهَّلًا، أو نسخة ورقية بلا ملف بعد). ويستعيد المستلمون الورقيون ملفّهم القائم لإعادة التنزيل، دون إعادة توليد أي شيء. والعملية مُكرَّرة الأثر، وليست تجاوزًا: تعيد محاولة التسليم ولا تغيّر قرارًا.GET /api/sessions/{id}/progress.pdfو**GET /api/classes/{classId}/screening-triggers/{id}/progress.pdf** يطبعان الكشف (A4 من اليمين إلى اليسار: الاسم، وكلمة الحالة، والصحيح/الكلّ). والخلايا على سطر واحد، فيتبع عدد الصفحات عددَ الصفوف، وما تجاوز 500 كيلوبايت يردّ503بدل متن بلا حدّ.- وأيضًا: تحمل صفوف
GET /api/reading-assessments/batches/{id}الآنwcpmوaccuracyإلى جانبadministeredAtالموجود أصلًا. ويبقى كلاهما فارغًا حتى تُوقَف القراءة وتُصحَّح، فالصفّ الذي أُجريت قراءته ولم تُوقَف بعدُ يبقى فارغًا. ويكتسب سجلّ جلسات الطفل نوعًا جديدًا هوgenerated، أي جلسة طبعتها له معلّمته؛ ولا تُدرَج الجلسة الرقمية مرّتين لأنّها تظهر أصلًا بوصفها تدريبًا. - صفحات المعلّمة: مركز الجلسات بتبويبات الأنواع ورقائق الصفوف، وكشوف تفصيل التقييم والقراءة والحصّة المباشرة، وكشف إنجاز على الجلسة المُسلَّمة (تصفية، واختيار من لم يُكمل، وإعادة إرسال، وطباعة)، ومراجعة إجابات لكل طفل تُعلّم ما اختاره والخيار الصحيح جنبًا إلى جنب. أعداد فقط، ولغة نموّ في كل مكان: «توقّف مؤقتًا» للجلسة المتوقّفة، و«لديه تدريب جارٍ» لمن كان لديه تدريب مفتوح.
خطوط الهدف حسب النمط، وحارس أهليّة القياس، وصفحة «لم نجد هذه الصفحة» بالعربية، 2026-09-11
خادم + واجهة. خمس متابعات من مراجعة «تفصيل». لا عملية جديدة؛ يبقى amal-api.yaml عند 348 مسارًا / 379 عملية. الترحيل 20260911120000_orf_sub_skill_and_aim_line_cbm_type.
- صار
aim_lineلكلّ نمط قياس — المفتاح(الطالب، المهارة، cbmType، الإصدار). كان منحنى التقدّم لكلّ نمط بينما خطّ الهدف المقارَن به ليس كذلك، والتفعيل للأسبق، فكانت ثلاث قياسات دقّة (نسبة مئوية) قد تُنشئ الأساس الذي يقرؤه منحنى الكلمات في الدقيقة هدفًا له، فيبقى ذلك المنحنى دون الهدف دائمًا. تُملأ الصفوف القائمة من نمط مجموعة الأساس الخاصّة بها. ويقبلPOST /api/cbm/aim-linesالآنcbmType(افتراضيًّاORF_WCPM). - لا يُسجَّل قياس طلاقة إلّا تحت مهارة مؤهَّلة للقياس (صفوف FL-ACC الأربعة،
skills_master_table.cbmEligible). يردّPOST /api/orf/assessments/startوPOST /api/cbm/probesبـ400 cbm_skill_not_eligibleفيما عدا ذلك. قبل هذا كان رابط مُركَّب يدويًّا يسجّل قياس قراءة جهرية تحت مهارة فهم، فيدخل بصمت في تجميع طلاقة المدرسة ويزيح الوسيط. ولا يتأثّر القياس غير المرتبط (subSkillId: null). - صار
oral_reading_assessment.subSkillIdعمودًا حقيقيًّا — كان يعيش داخلbenchmarkValuesSnapshot.__subSkillIdفقط، غير مرئيّ لـSQL ولا لأيّ قارئ سوى معالج الإنهاء. مُلئ بأثر رجعيّ، ويبقى التثبيت في اللقطة قراءةً احتياطيّة للجلسات الأقدم. - صفحات «لم نجد هذه الصفحة» بالعربية للجذر ولواجهة الكبار ولعالم الطالب. كانت كلّ مواضع
notFound()الـ63 تسقط إلى صفحة Next الإنجليزية المدمجة. - إتاحة النوافذ على سفاري/WebKit — تُصيَّر حرّاس تركيز Base UI هناك كأوامر ARIA بلا اسم (مخالفة
aria-command-nameفي كلّ نافذة مفتوحة)، ولأنّ WebKit لا يُركّز الزرّ عند اللمس كان إغلاق النافذة يعيد التركيز إلى أوّل عنصر في الصفحة بدل الزرّ الذي فتحها. أُصلح الأمران في المكوّن المشترك، فاستفادت مواضع النوافذ الخمسون كلّها.
تفصيل الخطأ في كلمة: أيّ حرف أو حركة قُرئت خطأً، 2026-09-09
خادم + معلّمة. أثناء تسجيل قياس القراءة الجهرية تفتح المعلّمة «تفصيل» على كلمة مميَّزة وتختار الحرف أو الحركة التي أخطأ فيها الطفل؛ يُحفَظ الاختيار مع القياس ويظهر في نتيجة التقييم، وفي صفحة للقراءة فقط لكلّ قياس سابق، وفي عمود الطلاقة بملفّ الطالب. توثيق للملاحظة فقط — لا تتغيّر الكلمات الصحيحة في الدقيقة ولا الدقّة ولا بطاقات المؤشرات ولا المنحنى ولا قرارات الدعم. عملية جديدة واحدة. يبلغ amal-api.yaml الآن 348 مسارًا / 379 عملية.
POST /api/orf/assessments/{id}/stopيقبل اختياريًّاerror_details[]({ word_index, group_index, part: "letter" | "mark", mark_index?, char }) إلى جانبerror_word_indices. يجب أن يُشتقّ كلّ قيد من كلمة النصّ بمقسِّم مجموعات الحروف نفسه المستخدم في استيراد الأسئلة (graphemeSplitVersionv1)؛ أيّ اختلاف، أو كلمة خارج المجموعة النهائية، أو تفاصيل بلا مجموعة نهائية ←422ولا يُكتب شيء. تُحفَظ الصفوف في الجدول الجديدoral_reading_error_detail(إضافة فقط؛ الترحيل20260909120000_orf_error_detail).GET /api/orf/assessments/{id}يُرجع قياسًا واحدًا للقراءة فقط: كلمات النصّ، وerrorWordIndices(المجموعة المحتسبة؛ الصفوف القديمة تعود إلى نقرات السجلّ بلا تكرار)، وerrorDetails، وأرقامًا فارغة حتى الإنهاء. نطاق المعلّمة ←403؛ مؤسسة أخرى ←404.- إصلاح: صار
GET /api/reports/students/{id}/sessions?kind=orf(وتفصيلorf) يعرض قياسات القراءة للطلاب الحقيقيين — كان يقرؤها بمعرّف الملفّ بينما يكتبها القياس بمعرّف المستخدم. - واجهة المعلّمة: زرّ «تفصيل» بجانب الكلمات المميَّزة (أثناء القراءة وفي خطوة آخر كلمة)؛ النافذة؛ بطاقة «الكلمات المقروءة خطأً» في النتيجة؛ الصفحة
/teacher/students/{id}/orf/{assessmentId}من «قياسات القراءة الأخيرة»؛ كتلة «آخر قياس» في عمود الطلاقة بالملفّ. - تصحيح الاحتساب (مراجعة ما قبل الدمج): صار حاسب الطلاقة يحتسب على شبكة الكلمات الصفرية الأساس التي تستخدمها كلّ النصوص المزروعة —
words_attempted = last_word_index + 1والفهرس 0 (الكلمة الأولى) خطأ مشروع. سابقًا لم تكن الكلمة الأولى المقروءة خطأً تُحتسب، وكانت القراءة الكاملة تنقص كلمة. صارstopمعاملة واحدة (صفّ الجلسة + صفوف الأجزاء + صفّاcbm_scores)؛ يخزّنresult.scoredErrorWordIndicesمجموعة المحرّك ضمن المدى؛ ويُسقَط تفصيلٌ على كلمة مميَّزة بعد آخر كلمة وصل إليها الطالب مع علامتها (لا422أبدًا)؛ ويقبل حملorf_probe_eventالمفتاحينdetailCountوadministered.
نوافذ التقييم: تقويم المشرف حسب المؤسسة/المدرسة وفتح المعلّمة للتقييم لصفّها، 2026-09-09
خادم + مشرف + معلّمة + طالب. يُعرض التقييم على الطفل — ويمكنه بدؤه — فقط داخل نافذة تقييم مفتوحة (بداية العام / منتصفه / نهايته). تأتي النافذة من فتحٍ قامت به معلّمة الصف، وإلّا فمن التقويم الذي ضبطه المشرف (المدرسة ← المؤسسة ← العامّ، لكل نافذة). لا شيء مفتوح = لا تقييم. لم يعد التطبيق يقرأ ملفّ تعريف amal_cycle (يقرؤه فقط مكدّس Playwright الوهمي خلف E2E_MOCK_SEAM=1). 6 عمليات جديدة. يبلغ amal-api.yaml الآن 347 مسارًا / 378 عملية.
GET /api/admin/screening-windows?organizationId&schoolIdيُرجع النوافذ الثلاث الفعلية في نطاق ما (startsOn/endsOnتواريخ،source،inherited؛ تواريخ null = غير مُفعَّلة).PUT /api/admin/screening-windows/{window}ينشر مدى تواريخ في نطاق الجسم (نشر مع إصدار،409 concurrent_publish؛422إذا كانت البداية بعد النهاية، أو تداخل المدى مع نافذة شقيقة في النطاق نفسه، أو نطاق غير صالح).DELETE /api/admin/screening-windows/{window}?…يزيل التخصيص. مشرف المنصّة الفعلي، كمسارات المخطّط. يكتسب سجلّ تدقيق المخطّطwindows(سجلّ التواريخ).GET /api/classes/{classId}/screening-triggersو**POST …/screening-triggers** ({ window, startsOn, endsOn }، 31 يومًا كحدّ أقصى، فتحٌ واحد لكل نافذة ←409 trigger_already_open) و**POST …/screening-triggers/{id}/close** — أيّ معلّمة نشطة في الصف تفتح أو تغلق تقييمًا لصفّها؛ المدير والمشرف يقرأان فقط. يحمل ردّ الفتحcalendarWindowليحذّر الواجهة عند مخالفة التقويم.GET /api/student/today-planيكتسبscreening: { window, source } | null؛ ويكونnextActionهو"diagnostic"فقط عندما تكون نافذة مفتوحة لم يكملها الطفل هذه السنة الدراسية (1 آب ← 31 تموز)، أو عند وجود جلسة جارية.POST /api/diagnostic-sessions/start: صارscreeningCycleاختياريًّا. عند إغفاله يحدّد الخادم النافذة المفتوحة (فتح الصف أوّلًا ثم التقويم بحسب النطاق). لا يجوز للطالب تسمية نافذة غير مفتوحة له اليوم (409 window_mismatch)؛ ولا شيء مفتوح ←409 no_open_window(لا تُنشأ جلسة). يجوز للمعلّمين والمشرفين تسمية النافذة صراحةً؛ وd_triggeredصريح دائمًا. يسجّل صفّ الجلسةscreeningSource(class_trigger|calendar|explicit).- صفحة المشرف: شريط «مواعيد التقييم» فوق شبكة المخطّط — ثلاث بطاقات بالتواريخ ورقائق الوراثة ومحرّر مدى التواريخ. صفحة صفّ المعلّمة: لوحة «التقييم المفتوح» مع «افتح تقييمًا» (النافذة + التواريخ، افتراضيًّا اليوم ← +6 أيام) و«إغلاق». الطالب: شاشة هادئة «لا يوجد تقييم مفتوح الآن» عندما لا شيء مفتوح.
- الطرح: لا نافذة مفتوحة في أيّ مكان حتى يضبط المشرف التواريخ أو تفتح المعلّمة تقييمًا — اضبط التواريخ لمؤسّساتك فور النشر. يزرع مُجهِّز العرض التجريبي نافذة بداية عام مفتوحة في مؤسسة العرض. الترحيل
20260909100000_screening_windows.
تثبيت نطاق المؤسسة في قائمتي المدارس والصفوف؛ وقائمة المستخدمين عبر المؤسسات؛ وسجلّ التدقيق يسمّي الناشر؛ وتوحيد تسميات الأدوار، 2026-09-09
إصلاح واحد في عزل المستأجرين مع متابعات صفحات المشرف من مصفوفة الاختبار الشامل. لا عملية جديدة؛ يبقى amal-api.yaml عند 341 مسارًا / 370 عملية.
-
GET /api/schools?organizationId=وGET /api/classes?organizationId=لم يعودا يسمحان لمستدعٍ مقيّد بمؤسسة بقراءة مؤسسة أخرى: يُحترم المُعامل لمشرف المنصّة فقط (مع تسجيل التجاوز)، ويبقى المستدعي داخل مؤسسته ويُتجاهل المُعامل. قبل هذا الإصلاح كانت المؤسسة المُمرَّرة تطغى على تثبيت المستأجر، فيستطيع مسؤول مؤسسة سرد مدارس وصفوف مؤسسة أخرى بما فيها رموز دخول الصفوف. تمرّ كل معالجات القوائم الآن عبر سياسة واحدةtenantWhere(c, { organizationId }). -
GET /api/users?organizationId=يحصر قائمة مشرف المنصّة العابرة للمؤسسات في مؤسسة واحدة (مع تسجيل التجاوز)؛ ويبقى المستدعي داخل المؤسسة محصورًا بمؤسسته ويُتجاهل المُعامل. تعرض/admin/usersعمود المؤسسة ومرشّحها لمشرف المنصّة (بحسب هويّته لا بعدد المؤسسات)، ويُتجاهل?org=غير الصالح بدل أن تفشل الصفحة. -
GET /api/admin/diagnostic-blueprint/audit-logتحمل صفوفهpublishedByName(اسم الناشرfullNameArوقت القراءة، وnullفقط إذا زال صفّ المستخدم)؛ وتعرضه صفحة السجلّ إلى جانب معرّفpublishedByالثابت. -
تسجيل الخروج وكل مسارات الدخول تمسح ملفّ تعريف
amal_cycle(كلمة المرور، الطالب، الرابط السحري، Google، التقمّص، الخروج من العرض التجريبي)، فلا يمرّر جهاز الصفّ المشترك مُحدِّد نافذة التقييم من طفل إلى الطفل التالي. أي كاتب مستقبلي يجب أن يضبطه بـpath=/(lib/cycle-cookie.ts). -
تسمية عربية واحدة لكل دور في هيكل التطبيق وصفحة الأدوار وحوار الإنشاء والمرشّحات وعروض النشاط وبوّابة التوثيق العربية (كانت أربع نسخ متباينة؛ مدير المؤسسة يُقرأ «مدير المؤسسة» في كل مكان). ويستخدم هيكل التطبيق الآن الصيغ النكرة نفسها المستخدمة في صفحات المشرف (مثل «معلّم» بدل «المعلّم» في الإعدادات وشريط التقمّص)؛ وتحتاج لقطات الانحدار البصري لـ
/admin/usersو/admin/rolesإلى تحديث (pnpm --filter web visual:update).
متابعات دورة اختبار التقييم: حقل reason عند البدء، وتنبيه QA_040، وعدّاد أسئلة التقييم للمشرف، وإحصاء المحتوى، 2026-09-08
خادم + شبكة المشرف + محتوى. متابعات دورة اختبار تفعيل/تعطيل مهارات المخطّط بتاريخ 2026-09-08. لا نقاط وصول جديدة؛ يبقى amal-api.yaml عند 341 مسارًا و370 عملية (حقلا استجابة إضافيان).
POST /api/diagnostic-sessions/startيكتسب حقلreasonإلى جانبfirstItemId:no_blueprint(لم تُحلّ أي خلية لصفّ الطالب ونافذته في أي نطاق)، أوno_eligible_item(توجد خلية لكن لا عنصر تقييم قابلًا للتقديم لمهاراتها)، أوnullعندما يُقدَّم عنصر. تجربة الطفل لا تتغيّر (تُترك الجلسة عند البدء وتظهر شاشة «لا توجد أسئلة جاهزة» الهادئة)؛ الحقل للمشغّلين ولتشخيص العميل.- QA_040 — بدء تقييم بلا ما يُقدَّم. فحص جديد في السجلّ (من 39 إلى 40 فحصًا، الشدّة
high): البدء الفارغ يكتب صفًّا فيplatform_alert_logيسمّي المؤسسة والطالب والجلسة والصفّ والنافذة ونطاق المدرسة ومصدر المخطّط وحجمه وreason، ويُنبّه الهندسة — صفّ واحد لكل (نطاق المدرسة × الصفّ × النافذة × السبب) في اليوم، فصفٌّ كامل يعيد الضغط على «ابدأ» على خلية واحدة غير مُهيّأة يساوي تنبيهًا واحدًا؛ ولا يُعرض على لوحة المعلّم أبدًا. يظهر فيGET /api/qa/runtime-alerts?qaCheckId=QA_040لمشرفي المؤسسة.pnpm test:qa:040. GET /api/admin/diagnostic-blueprintيكتسبskillTaqyeemCount(لكل مهارة نشطة، عدد عناصرquick_checkالتشغيلية غير التدريبية — المخزون الذي تسحب منه الشاشة الأولى) و**skillTaqyeemCountAudio** (المخزون نفسه مقصورًا على العناصر ذات الصوت، قاعدة الصوت أولًا للصفّ الأول) و**taqyeemScreenSize** (حجم الشاشة لكل مهارة كما يقرّره الخادم، 3). تُعلّم نافذة المشرف المهارة التي دون حجم الشاشة بشارة «n من 3 أسئلة تقييم»، وتستخدم عدّاد الصوت لخلايا الصفّ الأول (كانت شارة «لا يوجد محتوى بعد» تعدّ أي عنصر تشغيلي، فلم تحذّر قطّ من مهارة لها عناصر تدريب فقط).pnpm --filter server content:censusيطبع لكل مهارة أعداد التقييم (quick_check) والتدريب (practice) والمتابعة (progress_monitoring_probe) مصنّفةً بحسب شاشة الأسئلة الثلاثة (--jsonللآلات). لقطة 2026-09-08 فيdocs/product/taqyeem-content-census-2026-09-08.md.- المحتوى. عناصر الصور الخمسة عشر من دفعات الشريك التجريبية (DWR-D01 وصور خيارات PA-13 ومشاهد SENT-A01) التي كانت تشير إلى ملفات بديلة فارغة صارت تحمل رسومًا حقيقية على المسارات نفسها؛ لا تغيير في البيانات.
بدء تقييم بلا سؤال قابل للعرض يُترك ولا يُكمَل؛ وإصلاحات في تجهيز الحسابات، 2026-09-07
خادم + صفحات المشرف، من مصفوفة الاختبار الشامل التي مرّرت مخطّط النطاقات عبر الواجهة الفعلية. لا عملية جديدة؛ يبقى amal-api.yaml عند 341 مسارًا و370 عملية.
POST /api/diagnostic-sessions/startيترك الآن الجلسة التي لا يحمل مخطّطها المحلول أي سؤال قابل للعرض (فجوة صوتية في الصف الأول، أو خلية تسمّي مهارات بلا محتوى مؤلَّف): يحمل الردّnoEligibleItem: trueمعfirstItemId: nullوstate.status: "abandoned"؛ ويُكتب الصف بالقيمة الجديدةno_eligible_itemفيsessionEndReason(الترحيل20260907070000_session_end_reason_no_eligible_item). ويُرجعPOST /api/diagnostic-sessions/{id}/finishعلى جلسة متروكة404، فلا يستطيع العميل تحويل بداية بلا أي دليل إلى فحص مكتمل. ولا يمنع الصف المتروك بدءًا لاحقًا للطالب نفسه في النافذة نفسها. ويعرض تطبيق الطالب حالة هادئة «لا توجد أسئلة جاهزة الآن» بدل الاحتفال.POST /api/usersمن حوار المشرف: يمكن إنشاء طالب بلا بريد ولا كلمة مرور؛ فيُنشئ الخادم اسم المستخدم والرمز السرّي من 4 أرقام ويعرضهما الحوار مرّة واحدة. و«مسؤول النظام» مع مؤسسة يُنشأ مشرفًا على تلك المؤسسة (scope: ORG)؛ وترك المؤسسة فارغة هو الاختيار الصريح لمسؤول عامّ على المنصّة.- صفحات المشرف: تُعاد تهيئة حوارات الإنشاء (مستخدم، مدرسة، صفّ، مؤسسة) عند فتحها من جديد؛ وتعرض قائمة الصفوف رمز الدخول المكوّن من 6 أرقام لكل صفّ. ولقائمة المؤسسة عند اختيار «مسؤول النظام» خيار صريح «بلا مؤسسة — مسؤول عامّ»، ويردّ
POST /api/usersبـ422عندما لا يتّفقscopeالمسؤول مع ربط المؤسسة (SUPERمع مؤسسة، أوORG/SCHOOLبلا مؤسسة). PUT /api/admin/diagnostic-blueprint/{grade}/{cycle}يردّ الآن بـ409(reason: concurrent_publish) عندما يسبقه نشرٌ آخر للخلية نفسها: صفٌّ نشط واحد لكل نطاق × صفّ دراسي × نافذة تفرضه قاعدة البيانات (فهرس فريد جزئيdiagnostic_blueprint_active_cell، الترحيل20260907080000_diagnostic_blueprint_active_cell_unique).POST /api/diagnostic-sessions/start/re-diagnosticيفتح الجلسة قبل أرشفة قوائم تمرين الطالب؛ وحين لا يوجد عنصر قابل للعرض تُترك الجلسة (no_eligible_item) ويحمل الردّnoEligibleItem: trueمعarchivedQueueCount: 0، وتبقى خطّة التمرين كما هي.
مخطّط التقييم الأوّلي حسب المؤسسة والمدرسة؛ وبوّابة مشرف النظام الفعلي على لوحة الإدارة، 2026-09-07
خادم + شبكة للمشرف. صار مخطّط مهارات التقييم الأوّلي — أي المهارات الفرعية التي تغطّيها الجلسة الأولى لكل صفّ × نافذة فحص — قابلًا للضبط على مستوى المنصّة كلّها، أو مؤسسة واحدة، أو مدرسة واحدة. عملية جديدة واحدة. صار amal-api.yaml يضمّ 341 مسارًا و370 عملية.
- النطاق على كل مسارات المخطّط. يُرجع
GET /api/admin/diagnostic-blueprint?organizationId&schoolIdالشبكة الفعلية لذلك النطاق؛ وتحمل كل خليةsource(globalأوorgأوschool) وinherited. ويقبلPUT /api/admin/diagnostic-blueprint/{grade}/{cycle}حقليorganizationIdوschoolIdفي المتن وينشر على ذلك النطاق (لكل نطاق سلسلة إصداراته الخاصة). ويقبلGET /api/admin/diagnostic-blueprint/audit-logالمرشّحات نفسها، ويحمل كل صفّorganizationIdوschoolIdوscopeLevel. يتطلّبschoolIdوجودorganizationId، ويجب أن تكون المؤسسة موجودة وأن تتبعها المدرسة (وإلا422). - جديد:
DELETE /api/admin/diagnostic-blueprint/{grade}/{cycle}?organizationId&schoolIdيزيل التخصيص على ذلك النطاق (يصير الصفّ النشط غير نشط بلا خَلَف؛ ويُحفَظ السجل) ويُرجعeffective— الخلية كما يحلّها ذلك النطاق الآن من نطاقه الأعلى، أوnullإن لم تُضبط في أي مستوى. ويُرجع404عندما لا يوجد شيء نشط على ذلك النطاق. - الحلّ عند
POST /api/diagnostic-sessions/start: مدرسة تسجيل الطالب النشط ← مؤسسة الطالب ← العامّ. يفوز أول صفّ نشط ويستبدل الخلية كاملة (لا دمج). وما زالت القائمة المحلولة تُنسخ على صفّ الجلسة، فلا يغيّر تعديلٌ لاحق للمخطّط جلسةً بدأت فعلًا. - بوّابة مشرف النظام الفعلي. صارت مسارات المخطّط ومسارات إدارة ملفات المعايير الأربعة تحت
/api/admin/benchmark-profilesتتطلّب مشرف نظام على مستوى المنصّة (حسابًا خارج أي مؤسسة). يحمل كل مشرف مؤسسة رمز الصلاحيةSUPER_ADMIN، فلم يكن الرمز وحده فحصًا كافيًا قطّ؛ ويتلقّى مشرف المؤسسة الآن403، وتعرض صفحات الويب بطاقة «لمشرفي النظام فقط». - المخطّط البياني. يكتسب
diagnostic_blueprintحقلين اختياريينorganizationIdوschoolIdوحقلًا مشتقًّاscopeKey؛ والتفرّد على(scopeKey, gradeLevel, screeningCycle, version). تُبقي الترحيلة20260907001000_r14_diagnostic_blueprint_scopeكل الصفوف الموجودة على النطاق العامّ. وصار مزوّد العرض التجريبي يزرع خلاياه الافتراضية على نطاق مؤسسة العرض، لا على النطاق العامّ أبدًا. - لم يتغيّر: حدّ التغطية الأدنى لكل مجال في المحرّك. يتحقّق النشر من معرّفات المهارات والنطاق فقط، فقد تظلّ خلية ضيّقة على مستوى مدرسة تحلّ الطالب إلى ملفّ البيانات غير المكتملة في ذلك المجال (مقام التغطية قرار شريك معلّق).
متابعات مجموعات الدعم: صلاحية الخطط، وربط المعلّمة بمدرستها، وتوصيات المجموعة، 2026-09-07
عملية جديدة واحدة. صار amal-api.yaml يضمّ 341 مسارًا و369 عملية.
GET /api/support-groups/{id}/recommendationsيُرجع صفوف توصيات TAW_01 (بالشكل نفسه لـ/api/workflow/recommendations/{classId}؛ ويحملclassIdمعرّف المجموعة) لأعضاء المجموعة؛ ويُعلَّم الصفreview_requiredعند وجود تنبيه تراجع حاد مفتوح في أيّ صف للعضو.- صلاحية الخطط. يقبل
POST /api/workflow/activate(mode=individual) حقلgroupIdبدلclassId(واحد منهما فقط): يجب أن تملك المستدعية المجموعة غير المؤرشفة، وأن يكون الطالب عضوًا نشطًا فيها، وتُربط الخطة بصفّ الطالب نفسه (عضو بلا صفّ ← 422). وتصل المعلّمة المسؤولة أيضًا إلىPOST /api/students/{id}/activate-bundleوإلى مراجعة/إنهاء الخطة لأعضائها (القرار: تدير معلّمة الدعم أعضاءها كمعلّمة صف). ويبقى التفعيل الجماعي في معالج الصف ومسوّداته مرتبطًا بالصف. - الضابط الثاني صار على الخادم في كل مسارات التفعيل: أيّ تنبيه تراجع حاد مفتوح (لم يُراجَع بعد) للطالب، أيًّا كان الصف أو النافذة التي رُفع فيها، ←
409منPOST /api/workflow/activate(الفردي والجماعي لأعضائه المؤكَّدين) ومنPOST /api/cluster/bulk-activateومنPOST /api/students/{id}/activate-bundle(FR-TDS-18) — للخطة الجديدة فقط؛ ولا يُحجب مسار توجيهي (توصية بلا حزمة) أبدًا. وتقرأ صفوفreview_requiredللصف والمجموعة المجموعة نفسها. ويسجّل المسار الفرديdeliveryModeالمختار في سجل القرار. ولا يمسّ التفعيل عبر المجموعة مسوّدة معالج الصف المحفوظة للمعلّمة. DELETE /api/schools/{id}يُرجع409عند وجود معلّمة مرتبطة بالمدرسة عبرTeacherProfile.schoolId(القيد صار RESTRICT).GET /api/users/me(TEACHER) يحملprofile.schoolId(قد يكون فارغًا).POST /api/users(TEACHER) يقبلschoolId(يجب أن تكون في المؤسسة؛ وتُشتق من الصف الأول فيclassIdsعند إغفالها) ويخزّنها فيTeacherProfile.schoolId؛ ويضبطها أيضًا حقلschool_refفي ملف الكادر، وجرى تعبئتها للمعلّمات ذوات المدرسة الواحدة. ويعتمد عليهاGET /api/support-groups/owners?schoolId=أولًا.- داخليًا: بديل مشترك واحد لنطاق الطالب (
resolveStudentScope) يحلّ محلّ ستّ نسخ خاصة بالوحدات؛ ولم يعد مدخل الحاوية يطبع عنوان قاعدة البيانات.
مجموعات الدعم: مجموعة خاصة بمعلّمة من عدّة صفوف، 2026-09-06
خادم + صفحات للمعلّمة ولمدير المدرسة ولمشرف المؤسسة (يُنشئ المشرف المعلّمة من «المستخدمون» ثم مجموعتها من /admin/support-groups). 11 عمليات جديدة. صار amal-api.yaml يضمّ 340 مسارًا و368 عملية.
GET/POST /api/support-groupsيسرد المجموعات التي يصل إليها المستدعي (?includeArchived=true، ويُتجاهَل للمعلّمات) ويُنشئ مجموعة؛ ويسردGET /api/support-groups/owners?schoolId=المعلّمات المؤهَّلات لتولّي مجموعة في تلك المدرسة (مقيَّد بالمدرسة: مرتبطات بها أو غير مرتبطات بأيّ مدرسة بعد؛ أسماء وعدد الصفوف فقط، دون بريد). لا تُنشئ المعلّمة إلا مجموعة تملكها في مدرسة تدرّس فيها؛ ويسمّي مدير المدرسة / المدير / المشرف المعلّمة المسؤولة، ويجب أن تكون من تلك المدرسة (403وإلا).GET/PATCH /api/support-groups/{id}يُرجعان التفاصيل مع الأعضاء النشطين (معرّف المستخدم + معرّف ملف الطالب + الصف) وتغيير الاسم؛ أمّاarchivedفللإدارة فقط (403للمعلّمة المسؤولة)، والمجموعة المؤرشفة خارج متناول معلّمتها كليًّا. ويضيفPOST /api/support-groups/{id}/membersأعضاء بـstudentUserIds: يجب أن يكون كل طالب في متناول المنفّذ عبر التسجيل في الصف (المعلّمة من صفوفها، ومدير المدرسة من مدرسته؛ لا عبر مجموعة أخرى تملكها)؛ على دفعات، و409على مجموعة مؤرشفة. ويُزيلDELETE /api/support-groups/{id}/members/{studentUserId}العضو إزالة ناعمة.GET /api/support-groups/{id}/summaryو**/domain-trend** و**/alerts** تُرجع كائنات الصف نفسها (ClassSummaryDTOوDomainTrendDTOوClassAlertsResponse) محسوبة على الأعضاء، فتُعيد لوحة المجموعة استخدام لوحة الصف دون تغيير.- الوصول. تصل المعلّمة إلى الطالب عبر التسجيل في الصف أو العضوية النشطة في مجموعة غير مؤرشفة تملكها، وتحترم كل وحدات الطالب هذا المسار البديل (بما فيها مراجعة/إنهاء خطة الدعم وعرض التجميع). الوصول عبر المجموعة تربويٌّ فقط: تبقى كتابات حساب الطالب (
PATCH /api/students/{id}، وإعادة إصدار رمز الدخول، وإعادة تعيين كلمة المرور) لمعلّمة الصف والإدارة. وصار صندوقاGET /api/monitoring/alertsو**GET /api/cbm/alerts** يشملان الصفوف ∪ أعضاء المجموعات المملوكة. لا يتغيّر التسجيل في الصفوف ولا لوحات معلّمات الصفوف.
استيراد بيانات المدارس من ملفات CSV: المدارس والصفوف والكادر والطلبة من أربعة ملفات، 2026-09-02
خادم + معالج للمشرف لمسار تهيئة أول عميل. 6 عمليات جديدة. صار amal-api.yaml يضمّ 332 مسارًا و357 عملية.
POST /api/roster-import/batches(رفع متعدّد الأجزاء: ملفات CSV باسمschoolsوclassesوstaffوstudents؛ الطلبة إلزامي) يقرأ الملفات ويتحقّق منها ويطابقها ثم يُعيد دفعة مرحليّة — إمّاstatus: invalidمع أخطاء عربية مرقّمة بالسطر (لا يُكتب شيء)، أوstatus: previewedمع إجراءcreateأوupdateأوconflictلكل سطر. ويسردGET /api/roster-import/batchesالدفعات؛ ويُرجعGET /api/roster-import/batches/{id}كل الأسطر؛ ويُنزّلGET /api/roster-import/batches/{id}/report.csvتقرير الأخطاء (UTF-8 مع BOM).PATCH /api/roster-import/batches/{id}/rows/{rowId}يسجّل قرار التعارض (accept_csvأوkeep_amalأوskip_row) — التعارض مطابقة بالاسم العربي المعياري فقط، ولا يُدمج تلقائيًا أبدًا.POST /api/roster-import/batches/{id}/commitينفّذ الدفعة في معاملة واحدة ويُعيد بيانات دخول تُعرض مرة واحدة (كلمات مرور مؤقتة للكادر، ورموز من 4 أرقام للطلبة).409 stale_previewعندما تكون دفعة أخرى قد أنشأت المعرّفات نفسها أولًا؛ و410بعد انقضاء 24 ساعة؛ و422للحالاتbatch_invalidوunresolved_conflictsوschool_principal_conflict.- نموذج الهوية. صار
User.emailقابلًا للفراغ (لا بريد للطلبة؛ ويبقى إلزاميًا للبالغين)، ويحمل كل منUserوSchoolوClassمعرّفًاexternalRefعلى مستوى المؤسسة — معرّف المدرسة نفسها ومفتاح عدم التكرار عند إعادة الاستيراد. وتُركّب أربعة أعمدة للاسم العربي (firstNameAr…familyNameAr) قيمةfullNameAr. ويقبلPOST /api/usersطالبًا دونemail. - بيانات الدخول. صارت رموز الطلبة ذات الأربعة أرقام تُشفَّر بكلفة
AUTH_STUDENT_PIN_BCRYPT_COST(الافتراضي 8)؛ وتبقى كلمات مرور البالغين علىAUTH_BCRYPT_COST.
استوديو الأسئلة P2: إدارة النصوص، والإسناد الجماعي للقوالب، وتسميات المشتّتات، 2026-07-15
خادم الشريحة الثانية من استوديو الأسئلة. 5 عمليات جديدة. صار amal-api.yaml يضمّ 326 مسارًا و351 عملية.
- تأليف النصوص. ينشئ
POST /api/passagesمسودة نصّ؛ ويحسب الخادمwordCountوsentenceCountمن متن النص ويترك مقاييس المقروئية فارغة (يحسبها خطّ الإنتاج غير المتصل لاحقًا). يُرجعGET /api/passages/{id}الحقول القابلة للتحرير، والمقاييس للقراءة فقط، وقائمة الأسئلة المرتبطة مع مقتطفات قصيرة من نصّ السؤال (يُرجع 404 لنصّ خارج نطاق قراءة المستدعي). وPATCH /api/passages/{id}هو نقطة تحرير محتوى النص: يتحقّقIf-MatchعلىupdatedAtويعيد412عند شرط قديم، ويكتب كل حفظ صفًّا فيpassage_revisionللإلحاق فقط ضمن المعاملة نفسها. ويسردGET /api/passages/{id}/revisionsسجل التعديلات. لا يوجد حذف؛ يُتقاعَد النص عبر حالتهstatus. - نتائج تعديل المتن. يعيد تعديل نصّ المتن حساب العددين، ويضع علامة قِدَم على مقاييس المقروئية (
metricsStaleAt)، ويضع علامة قِدَم على معايرة كل سؤال مرتبط تشغيليّ أو مُعايَر. - إنشاء سؤال فهم فارغ. صار
POST /api/itemsمع هيكلblankيقبلpassageIdاختياريًا، فيبدأ سؤال الفهم من مسودة فارغة على نصّ مختار. ويُتحقَّق من ربط النص بالسؤال ضمن نطاق قراءة المستدعي، فيظهر نصّ من مستأجر آخر كأنه غير معروف. - الإسناد الجماعي للقوالب. يُسند
POST /api/items/bulk-templateقالبًا واحدًا (أو يزيله بقيمةnull) عبر 1..200 سؤال. ويُبلّغ كل سؤال عن نتيجة مستقلّة (updatedأوunchangedأوincompatibleأوnot_foundأوconflict)؛ ولا يُوقِف فشلٌ واحد البقيةَ. - تسميات المشتّتات. صار
GET /api/item-types/{code}/distractor-compatيُرجع كل نوع مشتّت مسموح ككائن يحمل تسمية عربية وعائلة، بدل نصّ رمز مجرّد.
معالجة فجوة محتوى التحقّق: حقل reason، وتنبيه QA_039، ومسح الطلبات المتوقّفة، 2026-07-12
خادم فقط؛ حقل إضافي واحد في الاستجابة، ولا نقاط وصول جديدة. عندما تكون مجموعة تحقّق مستحقة للطالب لكن مخزون العناصر بمستوى الصعوبة نفسه فارغ، لا تستبدل المنصة عنصرًا مختلفًا أبدًا. وكانت هذه الحالة سابقًا لا تُميَّز على الواجهة البرمجية عن اكتمال المجموعة، فيبقى طلب التحقّق مفتوحًا بصمت.
- استجابة
GET /api/confirmation/next-itemتكتسب حقلًا اختياريًاreasonيُضبط كلما كانتdone: true:no_open_request(لا شيء مستحق)، أوcomplete(اكتملت المجموعة الحالية للتو)، أوno_eligible_item(يوجد تحقّق مستحق لكن لا يتوفر عنصر مناسب بعد). تجربة الطالب لا تتغير في الحالتين؛ الحقل مخصّص للاستهلاك التشغيلي وواجهات المعلّم. كما يتجاوز التقديم الآن طلب التحقّق المحجوب بنقص المحتوى إلى الطلب التالي القابل للتقديم، فلا يعطّل مخزونٌ ناقص واحد بقية قائمة الطالب. - فحص جديد في السجل QA_039 (خطورة عالية): عند مصادفة المخزون الفارغ يُكتب سطر في
platform_alert_logيسمّي المؤسسة والطالب والمهارة والنافذة والطلب (مرة واحدة لكل طلب)، ويُخطَر فريق الهندسة. يظهر عبرGET /api/qa/runtime-alerts. - أمر صيانة جديد
confirmation:sweepيحوّل طلبات التحقّق المفتوحة لأكثر من 45 يومًا إلىabandoned(قيدٌ دفتريّ فقط؛ لا يُشتق أي قرار مهارة من مجموعة تحقّق غير مكتملة أبدًا).
سلسلة قواعد القرار R13: فحص من 3 عناصر، وعائلات المهارات المرتبطة، ومجموعة التحقّق، ومراجعة الصلاحية، 2026-07-12
خادم + نقطتا وصول جديدتان موجَّهتان للطالب. يُطبّق محرّك قرار المهارة الآن إجابات الشريكة المُقفَلة على أسئلة تغطية قواعد القرار الخمسة. يقدّم التشخيص الآن 3 عناصر بالضبط لكل مهارة فرعية (نطاقات نظيفة 0/3..3/3؛ وعتبة الكفاية تنتقل من 5 إلى 3). تُقرأ مهارات الطالب الشقيقة ضمن العائلة لتفسير الضعف بوصفه معزولًا/غير منسجم/واسعًا، لكن فقط عند وجود مهارتين مقيستين على الأقل (وإلا يبقى قرار المهارة الواحدة)، وهي دائمًا استرشادية — لا تغيّر أبدًا نتيجة المهارة نفسها. يفتح ضعف مهارة البوّابة الكامل (0/3) مجموعة تحقّق بالمستوى نفسه من الصعوبة، بينما يُوجَّه الضعف المصحوب بإشارة سلوكية مؤثِّرة إلى مراجعة صلاحية قصيرة بدل تأكيد الضعف.
GET /api/confirmation/next-itemيقدّم عنصر مجموعة التحقّق التالي لأقدم تحقّق مستحَق للطالب (بنطاق الصعوبة نفسه للفحص الأولي؛ ويعيدdone: trueحين لا يوجد مستحَق أو تكتمل المجموعة).POST /api/confirmation/responsesيُرسل استجابة تحقّق واحدة (تُصحَّح في الخادم). يحمل الردّ فقط الحقلneedMore— دون أيّ درجة أو حالة (لا يرى الطفل أيّ نتيجة داخلية). وعند اكتمال المجموعة (2–3 عناصر) يسجّل المحرّك النتيجة، ويحسم المهارة، ويغلق التحقّق.- ترحيلات جديدة:
related_skill_familyوconfirmation_requestوskill_validity_review. لم يتغيّر شكل أيّ مسار قائم؛ والمساران الجديدان موصوفان ذاتيًّا في مرجع الـ API (المُولَّد آليًّا منamal-api.yaml).
لوحات المدير الإشرافية للمدير والمشرف: قراءات التنفيذ والطلاقة ومصفوفة المراجعة، 2026-07-11
خادم إضافةً إلى واجهة المدير والمشرف. أربع نقاط قراءة تجميعية جديدة تُشغّل لوحات الإشراف المُعاد تشكيلها، ومحور اتجاهات المؤسسة ينتقل إلى نوافذ التقييم، ويتوسّع تقرير المجلس بصيغة PDF إلى تقرير مدرسي من سبعة أقسام. كلّ نقطة جديدة للقراءة فقط، محكومة لمدير المدرسة أو المشرف أو المسؤول، وتُعيد أسماء الصفوف أو المدارس مع أعداد فقط. لا يخرج اسم طالب أو معرّفه أو صفّ لكلّ طالب من هذه الأسطح أبدًا.
GET /api/schools/{schoolId}/implementation-summaryوGET /api/orgs/{orgId}/implementation-summaryتُعيدان تجميع تنفيذ خطط الدعم (المطابقة): أعداد الخطط النشطة موزّعةً فيadequateوinsufficientوunknown، ونسبةimplementationRate، وأعلى ثلاثة رموز عوائق، وتفصيلًا لكلّ صفّ (مسار المدرسة) أو لكلّ مدرسة (مسار المؤسسة). النسبة مقياس مطابقة على الخطط لا النسبة العامة الواحدة المحظورة لمحو الأمية، وتكونnullعندما يكون المقام صفرًا كي لا تظهر مدرسة كلّ خططها مجهولة بنسبة صفر بالمئة. مسار المدرسة محكوم بـVIEW_SCHOOL؛ ومسار المؤسسة بـVIEW_ORG.GET /api/schools/{schoolId}/fluency-summaryتُعيد أرقام القراءة الجهرية للمدرسة ولكلّ صفّ للنافذة المُحلّلة: عدد الطلاب المُقيَّمين، ووسيط الكلمات الصحيحة في الدقيقة، ووسيط الدقّة، وعدد من هم دون المرجع. الطالب الذي يكون حدّ صفّه قيمةً حارسةً من الشريك (NOT_APPLICABLEأوOPTIONAL_BASELINE_NO_CUT) أو غير مُحلَّل يُستبعد من عدد من هم دون المرجع، وهوnullعندما لا يُحلّ أيّ حدّ عبر المجموعة. يُبلّغbenchmarkNoteعن قابلية حلّ الحدّ. محكوم بـVIEW_SCHOOL.GET /api/principal/schools/{schoolId}/review-matrixتُصنّف كلّ صفّ في واحدٍ من خمسة أرباع مغلقة (insufficient_evidenceوimplementation_gapوgood_impl_low_growthوgood_impl_good_growthوneeds_monitoring) مع إجراء مُقترح مرافق بواحدٍ لواحد. تسبق الأدلّة غير الكافية أولًا (الصفّ الذي لا زوج نوافذ قابلًا للمقارنة له لا يُحكَم عليه أبدًا)، ثمّ بوّابة المطابقة (نتائج خطة غير مُنفّذة لا تُقرأ دليلًا على الخطة)، ثمّ الفاعليّة. هذا عون لجدول أعمال الاجتماع لا حُكم. محكوم بـVIEW_SCHOOL.- إعادة تجميع اتجاهات المؤسسة إلى نوافذ التقييم. أصبح
GET /api/orgs/{orgId}/trendsيجمّع محوره السينيّ علىevidenceWindowللّقطة (BOY/MOY/EOY) بدلًا من الشهر التقويميّ. تغيّرت مصفوفةOrgTrendsDTO.windowsمنstring[]إلى{ bucketId, window, yearLabel }[]، وتحمل كلّ نقطة اتجاه الحقول الثلاثة ذاتها؛ ويُرتَّب المحور زمنيًّا (السنة، ثمّ BOY فـMOY فـEOY). على المستهلكين الذين يقرؤون سلاسل النافذة القديمة"YYYY-MM"أن يتكيّفوا. - تقرير المجلس بصيغة PDF أصبح تقريرًا مدرسيًّا من سبعة أقسام. يعرض
GET /api/schools/{schoolId}/board-pdfملخّص المدرسة، والتقييمات الشاملة الثلاثة، وتوزيع المجالات، ودقّة القراءة وطلاقتها، ومقارنة الصفوف، ومتابعة تنفيذ خطط الدعم. يقرأ كلّ قسم وحدته الشقيقة بأمان ليّن: المصدر غير المتاح يتراجع إلى سطر «لم يُقيَّم بعد» هادئ واحد، لا إلى رقم مُلفَّق، وتبقى وضعيّة الإخفاق المغلق للملفّ كاملًا (خطأ العرض أو المهلة أو تجاوز الحجم يُعيد 503) دون تغيير.
يُنفّذ FR-FID (المطابقة وبوّابة تصعيد B.21) وقاعدة الأدلّة غير الكافية GSR-01 ومراجع FR-CBM النافذيّة
وتجميع المجال الكبير (docs/product/prds-v2/30-intervention-and-monitoring/35-fidelity-tracker.md و
33-fluency-measurement.md وdocs/product/prds-v2/60-supporting-features/69-reporting-apis.md). يبقى
قراران للشريك: الصياغة العربيّة لأرباع مصفوفة المراجعة الخمسة وإجراءاتها مسودّة، وعرف عرض النسبة المئويّة
لمعدّل المطابقة بانتظار التأكيد.
عدد العمليات: +4 (اثنتان لملخّص التنفيذ، وواحدة للطلاقة، وواحدة لمصفوفة المراجعة). كان العدّاد المتسلسل
في القيود السابقة قد تخلّف عن العمل المُتداخل؛ والمرجعيّ amal-api.yaml أصبح الآن 305 مسارات و328
عمليّة.
استوديو الأسئلة: محرّكات عرض الطالب + محرّرات مفتاح الإجابة البنيوية (QS-P2/P3)، 2026-07-09
واجهة تأليف للمسؤول إضافةً إلى نوعين جديدين من الأسئلة. أصبح استوديو الأسئلة على /admin/questions
يُعاين الآن أنواعًا أكثر بكثير من الأسئلة تمامًا كما يراها الطالب، ويضيف محرّرات بنيوية لمفتاح الإجابة
لأسئلة التركيب والكتابة والحركات، ويجمع منتقي المهارة حسب الصفّ. لا عمليّات واجهة برمجية جديدة: النوعان
الجديدان صفّان في item_type_catalog يُقدَّمان عبر مسارات العناصر القائمة، وكلّ محرّر مفتاح يكتب عبر
نقطة الاختناق القائمة PATCH /api/items/{id}. سطح الواجهة البرمجية المنشور دون تغيير.
- 9 محرّكات عرض تُرقّى إلى إنتاج الطالب الحيّ.
chip_fill(ملء فراغ داخل السياق)،order_builder←order_all(إعادة ترتيب)،tap_boundary←syllable_cut،tap_tokens←token_flow،letter_hunt←scatter،diacritic_pick←harakat_word،anagram←tile_blend، إضافةً إلى نوعَي التفاعل الجديدين كليًّا أدناه. كلّ منها إسقاط مُقدَّم حقيقي، لا معاينة صوريّة: تعرض معاينة المسؤول المطابقة للواقع مخرجاتservedItem()نفسها التي يتلقّاها الطالب. - نوعان جديدان من الأسئلة + أنواع تفاعل عند التقديم.
TYPED_SPELLING(لوحة مفاتيح عربية على الشاشة، يُصحَّح باستراتيجيةtyped_exactالجديدة) وMULTI_SLOT_CLOZE(ملء فراغات متعدّدة عبر نصّ متّصل، يُصحَّح باستراتيجيةslot_vectorالجديدة). كلاهما من الطرف إلى الطرف: نوع العنصر + استراتيجية التصحيح- إسقاط التقديم + نوع الإجابة + المُصحِّح + العارض + استعادة الذاكرة المؤقتة. تنضمّ أنواع التفاعل الجديدة إلى المجموعة القائمة خلف إسقاط تقديم مُقيَّد بقائمة سماح ولا يُسرِّب المفتاح.
- 7 منافذ نموذج أوليّ للمعاينة فقط.
open_textوmatch_pairsوgroup_sortوstepwiseوpassage_setوtap_regionوtraceتُعرَض داخل معاينة المسؤول مع شارة بيانات عرض تجريبية. هي للمعاينة والتأليف فقط (لا تقديم للطالب ولا مُصحِّح) بانتظار قرارات إنتاج لاحقة. - 5 محرّرات بنيوية لمفتاح الإجابة تحلّ محلّ ملخّص «مفتاح الإجابة» للقراءة فقط في محرّر السؤال:
محرّرا رفّ وتسلسل لـ
tile_blend/word_order، ومحرّر مقصّ لمواضع القطع لـsyllable_cut(يُصلح أيضًا خطأ حقلٍ خاطئ كان يترك صفّ القطع فارغًا)، ومحرّر لوحة مفاتيح وكلمة هدف لـtyped_spelling، ومحرّر حروف أساس وحرف هدف لـharakat_word. ويؤلّف محرّر تجريبي من الطبقة B أشكال منافذ المعاينة الأربعة (أزواج / مجموعات / خطوات / مناطق) ليعرض النموذج الأوليّ بيانات حقيقية بدل العيّنة. كلّ محرّر يكتبinteractionConfig/interactionKeyعبر نقطة الاختناقPATCHنفسها، مع بقاء سجلّ التعديلات للإلحاق فقط والتحقّق المطابق للبوّابة وتقسيم قائمة منع الإعداد/المفتاح (V-12) دون تغيير. - منتقي مهارة واعٍ بالصفّ. أصبحت قائمة «المهارة» في محرّر السؤال مجمّعة حسب صفّ العنصر (تتصدّرها المهارات المستخدَمة أصلًا في ذلك الصفّ) ولا تُخفي أيّ مهارة إخفاءً قسريًّا.
التصميم: docs/design/qs-p2-engine-ports.md + docs/design/qs-p3-key-editors.md. تضيف الهجرات نوعَي
العنصر TYPED_SPELLING / MULTI_SLOT_CLOZE واستراتيجيتَي التصحيح typed_exact / slot_vector.
إدارة المستأجرين التجريبيين لمشرف النظام (WP-DEMO-ADMIN-MGMT)، 2026-06-28
الخادم وواجهة الإدارة. سطح مشرف النظام للإشراف على كل مستأجر تجريبي ذاتي التسجيل. 4 عمليات جديدة.
- مسارات
demo-adminجديدة، جميعها لمشرف النظام الحقيقي فقط (skipTenantFilter): يعرضGET /api/admin/demo-tenantsالمُسجِّل والحالة وتاريخ الانتهاء وآخر استخدام وأعداد الصفوف والطلاب؛ ويقومPOST …/{id}/revokeبحذف المؤسسة حذفًا ناعمًا وتعليق مستخدميها وإنهاء الجلسات ووسم التسجيل ملغى؛ ويمدّدPOST …/{id}/extendمدّة الثلاثين يومًا أو يعيد تفعيل مستأجر انقضت مدّته؛ ويعيدPOST …/{id}/reissueإصدار بيانات الدخول المؤقتة ويعرض حمولة الترحيب مرّة واحدة (لا قراءة لنصّ صريح مخزّن ولا بريد لإعادة الإرسال). - صلاحية
requirePermission("SUPER_ADMIN")ضرورية لكنها غير كافية، لأن كل شخصية ADMIN تحملها. يردّ فحص داخل المعالِج بـ 403 لأي مشرف داخل مؤسسة، ويثبت ذلك اختبار عزل مستأجرين مُسمّى. - كل إجراء يخصّ دورة حياة بيانات الدخول وإدارة النسخة التجريبية مُدوَّن بنمط الإلحاق فقط:
demo_revokeوdemo_extendوtemp_credential_issued. - يؤدّي تسجيل دخول ناجح إلى مؤسسة تجريبية (بكلمة المرور أو بالرمز السريع) إلى تحديث
lastAccessedAtللتسجيل، فيبقى مؤشّر آخر استخدام في قائمة الإدارة حيًّا. - واجهة الإدارة: صفحة لمشرف النظام على
/admin/demo-tenantsفيها لكل صفّ إلغاء وتمديد وعرض بيانات الدخول.
يُنفّذ القسمين 5.7 و5.8 من
docs/superpowers/specs/2026-06-27-in-house-demo-signup-design.md (يحلّ OI-2: السطح تحت admin/). يرتفع
إجمالي سطح الواجهة إلى 278 مسارًا.
شخصية النسخة التجريبية وحارس الصندوق والتقمّص (WP-DEMO-ROLE)، 2026-06-28
الخادم. يجعل المستأجر التجريبي المُجهَّز قابلًا للاستكشاف بالكامل وقابلًا للكتابة بأمان. عملية جديدة واحدة.
- شخصية
DEMO_ADMINجديدة (الشخصية السابعة فيPersonaKey) بمجموعة صلاحيات منتقاة 13 من 25. تحمل كل أكواد القراءة إضافة إلى أكواد الكتابة التربوية داخل المستأجر، ولا تحمل أيًّا من أكواد الإرسال الخارجي أو التزويد أو الإعداد العام أو العابر للمستأجرين. يبقى ثابت الإغلاق على 25 كودًا محفوظًا. - يُستبدل حارس الكتابة الشامل
requireNotDemoبـrequireDemoOutboundBlock. يحجب فقط المسارات الخارجية (LMS) والمسارات الهدّامة بنيويًا (حذف المؤسسة والمدرسة وإنشاء المؤسسة) والكتابات العامة أو العابرة للمستأجرين (استيراد بنك العناصر واعتماده وترقيته وتقاعده، إضافة إلى كتابات ملفات المعايير ومخطط التشخيص). ويرفع الحجب عن كل كتابة تربوية أو تسجيلية داخل المستأجر، بما في ذلك حذف الصف، فهو قابل للاسترجاع ويبقى داخل الصندوق المؤقت. القراءات لا تُحجب أبدًا. POST /api/demo/impersonateهو تقمّص مُقيَّد. يصكّDEMO_ADMINرمزًا حقيقيًا لكل شخصية لأحد المستخدمين المبذورين من الشخصية المطلوبة، محصورًا في مؤسسة العميل التجريبية نفسها (أي هدف خارج المؤسسة غير قابل للوصول ويُعيد 404). يحمل الرمز المصكوك صلاحيات الشخصية الهدف الحقيقية. كل إصدار مُدقَّق بالإلحاق فقط (صفّDemoImpersonationLogإضافة إلى صفّdemo_impersonation_startفيAuthEventLog)، ويُعيدGET /api/auth/meالآنimpersonatedByلشريط «الاستكشاف بصفة شخصية».
يُنفِّذ المواصفة §5.6 من docs/superpowers/specs/2026-06-27-in-house-demo-signup-design.md (يحسم OI-1 وOI-4).
عدد العمليات: +1. أصبح amal-api.yaml الآن 274 مسارًا / 293 عملية.
تسجيل ذاتي للنسخة التجريبية (WP-DEMO-PROVISION-BE)، 2026-06-28
الخادم. تسجيل ذاتي عام للنسخة التجريبية مع تجهيز مستأجر مستقل لكل عميل محتمل. عمليتان جديدتان.
POST /api/demo/registerتسجيل محمي بالكابتشا ومحدود المعدّل. يُنشئ صفّDemoRegistrationقيد الانتظار ويُدرج تجهيز مستأجر تجريبي معزول وكامل البيانات في الخلفية، ثم يُعيد{ registrationId }.GET /api/demo/register/{id}/statusيستعلم عن حالة التجهيز. يُعيد حمولة الترحيب لمرة واحدة (رابط الدخول مع بيانات الاعتماد التجريبية لكل شخصية، بما في ذلكquickCodeوclassIdللطالب التجريبي) فقط عندما تكون الحالةreadyولم تُستهلك الحمولة بعد.
يُعيد التجهيز استخدام خط بذر النسخة التجريبية (نُقلت مكتبة البذر إلى src/modules/demo/seed/) على مؤسسة جديدة
مع عزل نطاق البريد لكل مستأجر، ثم يصكّ بيانات اعتماد مؤقتة إلزامية التغيير. وهو غير حسّاس للتكرار وآمن لإعادة
المحاولة. يتولّى أمر demo:sweep انتهاء الصلاحية بعد 30 يومًا. يُنفِّذ المواصفة §5.3/§5.4/§5.5/§5.8 من
docs/superpowers/specs/2026-06-27-in-house-demo-signup-design.md.
عدد العمليات: +2. أصبح amal-api.yaml الآن 273 مسارًا / 292 عملية.
طبقة التحقق من الكابتشا (WP-CAPTCHA)، 2026-06-28
بنية تحتية. أُضيفت طبقة التحقق من الكابتشا على جانب الخادم باستخدام Cloudflare Turnstile. لا عمليات API
جديدة. متغير البيئة TURNSTILE_SECRET اختياري في بيئة التطوير (المُدقِّق الوهمي يقبل جميع الرموز) ومطلوب
في الإنتاج (يفشل الخادم عند الإطلاق بصوت عالٍ إذا لم يُضبَط، لمنع اختفاء البوابة بصمت). نقطة الاستدعاء
الإلزامية قبل الكتابة ستصل مع WP-DEMO-PROVISION-BE.
يُنفِّذ المواصفة §5.2 / القرار D7 من docs/superpowers/specs/2026-06-27-in-house-demo-signup-design.md.
عدد العمليات بدون تغيير: 285 عملية في amal-api.yaml (لم تُضَف أي مسارات).
إعدادات إمكانية الوصول لكل طالب (WP-PSA-BE)، 2026-06-27
الخادم. يصبح مسار إمكانية الوصول الخاص بكل طالب فعّالًا وآمنًا من ناحية القياس. عمليّتان جديدتان
(مسار جديد واحد فيه PATCH وGET) ترفعان الإجمالي المنشور إلى 285 عمليّة في amal-api.yaml.
PATCH /api/students/me/accessibility-configمسار جديد. يضبط الطالب بنفسه حقوله الخمسة الخاصة بالعرض فقط (dyslexiaFontوhighContrastوlargerTextوaudioFirstوreducedMotion). لا يحمل المسار/meأي معرّف للطالب، فلا شيء يمكن العبث به (آمن من ثغرة IDOR)؛ ويُحَل ملف الطالب من الجلسة على الخادم. يكتب دورSTUDENTوحده، ويُفرَض ذلك بفحص داخل المعالِج لأن صلاحيةVIEW_OWN_PROFILEيملكها كل دور، فبوّابة الصلاحية وحدها ليست هي القيد.GET /api/students/me/accessibility-configمصدر التحميل المبدئي للطالب: الإعدادات الحالية مع رقم نسختها.PATCH /api/students/{id}/accessibility-config، مسار المعلّم والوليّ الحالي، صار يدعم الدمج على مستوى الحقل والتزامن المتفائل والتدقيق.
معلومات مهمة لمستهلكي الواجهة البرمجية:
- استجابة ثلاثية الحالة. كل حقل من الحقول الخمسة هو
trueأوfalseأوnull. القيمةnullتعني “غير مضبوط”، فيحلّها العميل إلى الإعداد الافتراضي لنظام التشغيل؛ أماfalseفهو “إيقاف” صريح. لا تعامل الحقل الغائب على أنهfalse. - التزامن المتفائل. أرسِل قيمة
accessibilityConfigVersionالتي قرأتها أخيرًا في ترويسةIf-Match. تُعيد أي كتابة متزامنة سبق أن رفعت النسخة الرمز409، فأعِد الطلبGETثم حاول مجددًا. احذفIf-Matchلتطبيق مبدأ آخر كتابة تفوز (آمن لإعادة الإرسال دون اتصال). - الدمج على مستوى الحقل. يغيّر جسم الطلب
PATCHالمفاتيح التي يحملها فقط، وتُحفَظ بقية المفاتيح دون استبدال الكائن كاملًا. الكتابة بقيمة مطابقة لا تُحدِث أثرًا (لا رفع للنسخة ولا صفّ تدقيق). - التدقيق. تُلحِق كل كتابة فعليّة صفًّا في
student_accessibility_config_logيسجّل من ومتى وأي حقول والنسخة الناتجة. الجدول للإلحاق فقط. - للعرض فقط. لا تقرأ أي وحدة قياس أو قرار الحقل
accessibilityConfig، فلا يمكن لحقل يضبطه الطالب أن يؤثّر في اختيار البنود أو تقديرات القدرة.
تظهر المسارات الجديدة في مرجع الواجهة البرمجية بعد openapi:generate.
واجهة برمجة التجربة التشخيصية التفاعلية (WP-11-BE) — 2026-06-25
الخادم. ثلاثة مسارات جديدة مجهولة (لا تتطلّب تسجيل دخول أو حساب) ضمن /api/teaser/* تُفعِّل ميزة “جرِّب التشخيص” الترويجية. 3 عمليّات جديدة ترفع الإجمالي المنشور إلى 262 عمليّة وقت هذا القيد. أضافت حزم العمل اللاحقة مسارات إضافية؛ الإجمالي الحالي 283 عمليّة (مُتحقَّق منه في amal-api.yaml).
POST /api/teaser/sessionsيبدأ تجربة تشخيصية للصف المحدّد (1-4). محدَّد بـ 3 جلسات لكل عنوان IP في الساعة. يُعيد رمز الجلسة و10 بنود مُنقّاة مع حذف مفاتيح الإجابة. يُعيد 503 إن لم يكن ثمة مجموعة بنود فعّالة للصف المطلوب.POST /api/teaser/sessions/{id}/finishيُصحِّح الإجابات المُرسَلة باستخدام مُقدِّر راش الحقيقي ويُعيد نطاق تمركّز لمهارة فرعية واحدة (meets/approaching/below/severe) مع تسميات ميزان العربية ونصّ إخلاء مسؤولية باللغة العربية.POST /api/teaser/leadsيُسجِّل بريد إلكتروني أو رقم واتساب اختياريًّا. صفّ واحد لكل جلسة (upsert) فلا يُغرَق الجدول بطلبات متكرّرة.
معلومات مهمة لمستهلكي الواجهة البرمجية:
- تحمل الأوراق الثلاثة
security: []في مواصفة OpenAPI. لا يُطلَب أي ترويسةAuthorization. - يجب إرسال رمز الجلسة الصادر عند البدء إلى مساري
finishوleads. رمز خاطئ يُعيد 401؛ إعادة الإرسال إلىfinishيُعيد 409. - يُحسَب النطاق بناءً على عتبات لوجيتية ثابتة محايدة (لا تعتمد على ملفات المعايير لكل دولة) لأن الزائر المجهول لا دولة له. التجربة مصرَّح عنها صراحةً بوصفها عيّنة.
- لا كتابة في أي جدول قياس أو إتقان أو أدلة طوال مسار التجربة. التجربة معزولة تحليليًّا عن خطّ الإنتاج التشخيصي.
- يُخزَّن عنوان IP فقط كقيمة هاش مُملَّحة لأغراض تحديد معدل الطلبات والتحليل. لا يُحفَظ العنوان الخام أبدًا.
- تحمل الجداول الثلاثة الجديدة (
teaser_sessionوteaser_leadوteaser_item_set) القيمةorganizationId = null(الاصطلاح العالمي نفسه المستخدَم في بنك الأسئلة).
تظهر المسارات الجديدة في مرجع الواجهة البرمجية بعد تشغيل openapi:generate.
بنود مفتوحة: يُعيد الصفّان 1 و3 حاليًّا 503 لغياب مهارة فرعية تحوي 10 بنود مؤهَّلة في الذخيرة الحالية. يجب أن تتعامل الواجهة الأمامية (WP-11-FE) مع هذا الخطأ بشكل سلس.
المواصفة: docs/superpowers/specs/2026-06-25-wp11-teaser-design.md (FR-6.3). الهجرات: wp11_teaser + wp11_teaser_lead_unique.
جولة المستأجر التجريبي (WP-12-FE) — 2026-06-25
عملية واحدة جديدة — GET /api/demo/access (عامة، لا تتطلب مصادقة) — تُشحن مع الواجهة الأمامية. تُسلِّم هذه الحزمة مدخل العرض التجريبي العام بنقرة واحدة، فوق المستأجر التجريبي الذي بنته WP-12-BE.
ما الذي تغيّر:
- صفحة
/demoلاختيار الشخصية. مكوّن خادمي يقرأGET /api/demo/accessوقت الطلب (يقرأ الخادم مؤسسةisDemo=trueفقط) ويعرض بطاقة لكل شخصية بالغة، إضافةً إلى بطاقة الطالب مع منتقي رمز سريع لكل صف. “ادخل كـ…” يُدخل الزائر مباشرةً إلى المستأجر التجريبي — دون تسجيل. - علامة الكوكي
amal_demo. تضبط إجراءات الدخول التجريبيamal_demo=1مع كوكيز الجلسة. شريطDemoBannerمُركَّب في كلا القالبين (قالب البالغين + عالم الطالب) يقرؤها ويعرض شريطًا دائمًا “أنت في الوضع التجريبي” مع زرّي “تبديل الشخصية” (العودة إلى/demo) و”خروج” (مسح الجلسة). لا يراه المستخدمون الحقيقيون (يُعيد الشريطnullدون العلامة). - لوحة بيانات الدخول. لوحة قابلة للطيّ تُدرج كلمة المرور المشتركة للبالغين، والبريد لكل شخصية، ورموز الطلاب السريعة لكل صف مع نسخ بنقرة — ليتمكّن المقدّم من نسخها على جهاز ثانٍ.
- زرّ البطل + حالتا عدم التوفّر والخطأ. يكتسب بطل التسويق زرّ “جرّب العرض التجريبي”. عند عدم تهيئة مستأجر تجريبي تعرض الصفحة لوحة “غير متاح” هادئة مع زرّ الحجز؛ ويُعيد الدخول الفاشل التوجيه إلى
/demo?error=1بإشعار قابل للإغلاق.
يظهر المسار الجديد في مرجع الواجهة البرمجية بعد تشغيل openapi:generate. دليل التشغيل: wp-12-fe.md. اختبار E2E: apps/web/e2e/demo-flow.spec.ts. إمكانية الوصول: accessibility.spec.ts (“demo page: WCAG 2.1 AA”).
بنية المستأجر التجريبي (WP-12-BE) — 2026-06-25
الخادم فقط — لا مسارات API جديدة (حارس العرض التوضيحي هو وسيط، ليس مسارًا). تُسلِّم هذه الحزمة مستأجرًا تجريبيًا مكتفيًا بذاته يستطيع أي شخص مرور عبر جميع الشخصيات الست دون أن يتمكن من إتلافه بصفة دائمة. مرجع API دون تغيير.
ما الذي تغيّر:
- علامة
Organization.isDemo. عمود منطقي يُميّز المستأجر التجريبي. يضعه البذّار علىtrueللمؤسسة التجريبية؛ تبقى كل المؤسسات الأخرى علىfalseافتراضيًا. - حارس
DEMO_READ_ONLY. وسيطrequireNotDemoالجديد مُركَّب على ما يقارب 29 مجموعة من المسارات التدميرية وإدارة الموارد (إنشاء/تعديل/حذف المستخدمين، إنشاء/تعديل/حذف بنية المستأجر، ربط LMS وإجراء التزامن، إعادة توليد الرمز السريع، إرسال بريد إعادة كلمة المرور، إرسال إشعارات الوالدين). يُعيد 403DEMO_READ_ONLYلأي مؤسسةisDemo=true. حلقة التفاعل الكاملة — التشخيص والتدريب والتسخين الذهني وقرارات المعلم وأدلة المراقبة وعلامات السياق وجميع عمليات القراءة — غير محجوبة. يمكن للزوار قيادة الحلقة بالكامل. - بذّار تجريبي متسامٍ. يُنشئ
pnpm --filter server seed:demoمؤسسة تجريبية واحدة (الأردن) بمدرسة واحدة وثلاث فصول و60 طالبًا موزّعين على الصفوف 1–4، إضافةً إلى جميع الشخصيات البالغة الست ببيانات اعتماد محددة مسبقًا (*@amal-demo.jo/AmalDemo!2026). معلّم بطل مُعيَّن في فصلين لعرض منتقي الفصول المتعددة. - حالة حلقة حقيقية. يُشغّل البذّار خط أنابيب RTI الفعلي لمجموعة فرعية تمثيلية من الطلاب — إنهاء التشخيص ← محرك حالة المهارة ← اللقطات الكلية ← ترجمة الملف التعليمي ← توصيات الحزم. تعرض لوحات المعلومات بيانات حقيقية في الحركة، لا أرقامًا مصنّعة.
- التسامي وإعادة الضبط. يمسح إعادة التشغيل حالة التشغيل المتراكمة (الجلسات، اللقطات، الملفات التعليمية، الحزم، صفوف المراقبة، علامات السياق، الإشعارات) ويُعيد اشتقاق الأساس. تُعدَّل صفوف الأشخاص على المفاتيح الطبيعية فتظل بيانات الاعتماد مستقرة عبر عمليات إعادة الضبط.
DEMO-GUIDE.mdمُرسَل إلىdocs/demo/عند كل تشغيل للبذّار: جدول بيانات الاعتماد، جولة صفحات لكل شخصية، رمز الانضمام للفصل المتزامن.
مؤجَّل: ربط المجدول الليلي (موثَّق في دليل التشغيل، غير مُوصَّل)؛ صفحة /demo العامة وخطاف إعادة البذر داخل التطبيق (WP-12-FE، مرحلة لاحقة).
المواصفة: 2026-06-25-wp-12-be-demo-tenant-design.md. خطة البناء: §WP-12-BE FR-5.1/5.2. خطة الاختبار: wp-12-be.test-plan.md. دليل التشغيل: wp-12-be.md. الهجرة: Organization.isDemo. لا مسارات جديدة.
مُسجِّل المتصفّح وإرسال السجلّات بالدُفعات إلى الخادم (WP-LOG-FE) — 2026-06-25
الواجهة الأمامية. أصبح لتطبيق الويب الآن مُسجِّل متصفّح موحّد يطابق عقد مُسجِّل الخادم، إضافةً إلى عامل دُفعات يُرسل سجلّات التحذير والخطأ من العميل إلى نقطة النهاية القائمة POST /api/logs/client. لا توجد مسارات API جديدة (شُحنت نقطة النهاية مع WP-LOG-BE)، لذا مرجع API دون تغيير.
ما الذي تغيّر:
- غلاف
getLogger(module)بالمستويات الأربعة نفسها (debugوinfoوwarnوerror) وبالبنية الموحّدة نفسها لمُسجِّل الخادم. في وضع التطوير تُطبع كل المستويات إلى الـ console فقط. في بناءات الإنتاج يبقى DEBUG وINFO على الـ console فقط بينما يُرسَل WARN وERROR أيضًا إلى الخادم (FR-LOG-6). - عامل الدُفعات. تتجمّع صفوف WARN وERROR وتُرسَل عند بلوغ الذاكرة المؤقتة 50 صفًّا أو بعد 5 ثوانٍ، أيّهما أسبق. ردّ تجاوز الحدّ 429 يتراجع ثلاث مرات (500 و1000 و2000 مللي ثانية) ثم يُسقط الدُفعة مع أثر محلّي واحد. يحفظ فشلُ الشبكة الصفوفَ لإعادة محاولة لاحقة. كما تُرسَل الصفوف المؤقتة عند إخفاء التبويب أو إغلاقه.
- التنقيح في جانب العميل. القائمة المغلقة لمفاتيح الأسرار والبيانات الشخصية في الخادم مُطابَقة في العميل وتُطبَّق على تفاصيل السجلّ قبل وصول أي شيء إلى الـ console أو الشبكة، فلا يغادر أيُّ سرٍّ المتصفّح. يُقنَّع البريد ويُحجَب الهاتف وسائر الأسرار.
lint:no-consoleلـapps/web. يُرفَض استخدامconsole.*المباشر خارج مَصرف المُسجِّل. استخدِمgetLoggerبدلًا منه.
المواصفة: 81-logging-and-observability.md (FR-LOG-6). خطة الاختبار: wp-log-fe.test-plan.md. لا توجد هجرة قاعدة بيانات.
محرّك نمط المؤشرات الثمانية الزمني (R12 Q4) — 2026-06-23
الخادم + المواصفة. أصبحت المؤشرات الثمانية لمهارات القراءة العربية تعمل الآن عبر محرّك ثنائي المرحلة بآلية حالة تتبُّع ديناميكية لكل (طالب × نمط خطأ).
ما الذي تغيّر:
- نموذج ثنائي المرحلة. مرحلة التقييم بدون تغيير — تنتقل الضعف المُثبَت مباشرةً إلى الملف التعليمي والحزمة دون تنبيه لعدد الأخطاء. مرحلة التدريب (جديدة) تُشغّل سلّم حالات لكل (طالب ×
micro_pattern_id): المستوى 1 (حدوث صالح واحد →candidate، صامت)؛ المستوى 2 (حدوثان+ مرتبطان في جلسة واحدة + بندان مستقلّان →automatic_support_active، بلا تنبيه للمعلّم)؛ المستوى 3 (3 حدوثات+ عبر جلستين+ بعد دعم تلقائي مُسلَّم والنمط يستمر → تنبيه معلوماتي خفيف للمعلّم؛ لا ينتظر أربع جلسات). - قاعدة ترابط الأخطاء (5 شروط جميعها مطلوبة). يُعدّ خطآن نفس النمط فقط إذا: المهارة ذاتها أو مهارة مرتبطة رسميًا (خريطة Q7) + نفس
micro_pattern_idأوerror_family+ بندان مستقلّان صالحان للتحليل + صُمِّم البندان لكشف هذا النمط + يكشف الخيار المُختار نوع الخطأ. الانتماء لنفس المجال وحده غير كافٍ. - ضمان V-12 — المستوى 3 معلوماتي فقط. لا يُغيّر تنبيه المستوى 3 الدرجةَ /
skill_status/domain_status/ الملف / مستوى RTI / درجة التدخّل (scoreImpact = "none"). يكتب فقط فيsub_flag_indicator_state+sub_flag_indicator_occurrence+platform_alert_log. مُطبَّق بـlint:subflag-alert-no-mutation. AR_LETTER_CONFUSION_FLAGمُعاد تسميته →AR_ORTHOGRAPHIC_CONFUSION_FLAG. يوضّح أن هذا المؤشر يغطّي التشابه البصري/الإملائي للحروف فقط (DWR-D04/D05)، لا التشابه الصوتي (PA-07).AR_SHADDA_FLAGمعطَّل في هذه المرحلة (enabled=false).- جداول كتالوج عالمية جديدة:
error_category(13 صفًّا)،error_micro_pattern(8 صفوف)،distractor_error_map(6 صفوف)،evidence_error_rule(EV01..EV06). - جداول تشغيل جديدة (بمستوى المؤسسة):
sub_flag_indicator_state(سلّم قابل للتحديث عبر مسار كتابة وحيد) +sub_flag_indicator_occurrence(سجل إضافة-فقط لكل حدوث). - 5 حقول اختيارية جديدة في
item_bank:microPatternId / errorFamilyId / confusionFamilyId / distractorErrorCode / designedToDetectPatternId(تُملأ فقط في بنود الكشف عن الأنماط).
بنود معلّقة (شريك): عتبة الإجابة السريعة في evidence_validity (EV06 — 300 ms مبدئية حتى يُحدَّد رقم RBM-08)؛ أثر الدعم التلقائي الملموس في المستوى 2؛ صفوف الأنماط المخصّصة لـ AR_SHORT_VOWEL_FLAG / VOCAB_ALERT / WR_SP_ALERT (تعمل حاليًا عند مستوى الفئة).
المواصفة: 23-student-profiles.md §4b + FR-SPR-4. الهجرة: r12_q4_subflag_engine. المصدر: إجابات الشريك Q4 (السطور 728-943) + File-2 v2 §14/15/17/23.
إعادة هيكلة حزم التدخّل — 14 حزمة + 7 كائنات مساندة (R12 Tier-D / Q11) — 2026-06-22
تغيير كاسر. يُعيد ملفّ الشريك Q11 النهائي (Q11_Arabic_Intervention_Bundles_Comprehensive_Audit_v1.0.0_2026-06-20) هيكلة الكتالوج المغلق للحزم. تتأثّر وحدة الحزم ومحرّك TAW وجميع المستهلكين الذين يقرؤون recommended_bundle_id.
ما الذي تغيّر:
- 14 حزمة تدخّلية + 7 كائنات مُعاد تصنيفها غير تدخّلية (كانت 19 حزمة). تُصنَّف الكائنات السبعة الآن عبر الحقل الجديد
BundleObjectType(9 قيم:INTERVENTION_BUNDLE / COMPOSITE_SEQUENCE_PLAN / COMPOSITE_INTERVENTION_BUNDLE / SUPPORT_MODULE / DECISION_CLARIFICATION_PROCESS / NON_INTERVENTION_OPTION / LIGHT_SUPPORT_ACTION / ROUTING_GUARD / FUTURE_INACTIVE_SUPPORT_OBJECT). recommended_bundle_idأصبح قابلًا للإهمال (nullable). تحمل 7 صفوف MAP غير التدخّلية (MAP-000/001/002/003/018/019/020) القيمةَNULLفي هذا الحقل مضافًا إليهاobject_typeورمزrouting_state_or_action_code(قرار الشريك D-015: الكائنات غير التدخّلية لا يجوز أن تشغلrecommended_bundle_id). صفّ الحارسNO_BUNDLE_SYSTEM_GUARDكحزمة وهميّة متقاعَد؛ يحلّ محلّه رمزROUTING_GUARDمعrouting_state = BLOCKED_MISSING_EVIDENCE.- نطاقات التوزيع التراكمية عبر الدورة تحلّ محلّ النسب الثابتة لكل جلسة (D-003). أُلغي الشرط القديم
sum==100 per session + anchor strictly largest CHECK. يُوصَف الجرعة الآن بنطاقات تخصيص عبر دورة التدخّل. وصفتان رئيسيتان معتمدتان (ورقة Q11 رقم 07):FLUENCY_WITH_MEANING(10–15% تهيئة ونمذجة / 60–70% قراءة موجّهة/متكرّرة مع تغذية راجعة للدقة مدمجة / 15–25% فحص معنى وانتقال)، وLANGUAGE_MEANING_BUILDING(45–55% محور لغوي مؤكَّد / 20–30% دعم ديناميكي واحد / 20–30% تطبيق سياقي وانتقال قريب). VOCAB_SYNTAX_MORPH_BUNDLEيُقسَّم إلى 3 متغيّرات (VOCAB_DOMINANT / SYNTAX_DOMINANT / MORPH_DOMINANT) تحتbundle_family_id = LINGUISTIC_FEATURE_FAMILY.TEXT_ACCESS_INTEGRATED_BUNDLE+COMPREHENSION_STRATEGY_BUNDLEمُعادان تصنيفهما إلىCOMPOSITE_SEQUENCE_PLAN؛MIXED_READING_LANGUAGE_BUNDLEإلىCOMPOSITE_INTERVENTION_BUNDLE.- يتعامل TAW مع 4 مسارات غير تدخّلية (
NON_INTERVENTION_OPTION / LIGHT_SUPPORT_ACTION / DECISION_CLARIFICATION_PROCESS / ROUTING_GUARD) عبر تسجيل رمز توجيه/إجراء — لا يُنشأ صفّbundle_assignmentلهذه المسارات. - أعمدة جديدة في
bundle_definition:object_type, bundle_family_id, variant_code, runtime_status, anchor_selector, max_supporting_skills, asset_bridge_rule, grade_target_bridge_rule, immediate_progression_target, cycle_allocation_model. - حقول جديدة في
bundle_assignment:object_type, family, variant, cycle_id, session_role, selected_anchor_skill_id, immediate_progression_target, grade_target_skill_id, relationship_map_version. تسعة أدوار جلسات مُعرَّفة:EXPLICIT_TEACHING / GUIDED_PRACTICE / RETRIEVAL_REVIEW / CONTEXT_APPLICATION / GRADE_TARGET_BRIDGE / SCAFFOLD_FADING / NEAR_TRANSFER / PROGRESS_CHECK / MAINTENANCE. - ISC-015 (
ARABIC_FEATURE) مُتقاعَد. تُضاف التصنيفات الثلاثية للانتقال (proximal/near/far) إلى صفوف ISC المتبقّية (V5-012). - 6 فحوصات جودة جديدة QA_033–038: حزمة أساسية واحدة لكل دورة، المرحلة الفعّالة فقط، لا توجيه عبر حزمة وهميّة، لا استنتاج نوع الخطأ من ORF، لا توجيه عبر خاصيّة غير مفعّلة، ملاءمة المحتوى.
الهجرات: r12_d1_bundle_object_types + r12_d2_isc_transfer_split. المواصفة: 31-intervention-bundles.md (FR-IBC-1/2/3/4/9). المصدر: أوراق Q11 رقم 02/03/04/07/09/12 + القرارات D-001..D-015.
كتالوج مخطّطات الجلسات (WP-SBC-BE) — 2026-06-22
الخادم + المواصفة. كتالوج مخطّطات الجلسات المُؤلَّفة دون اتصال، من طرفه إلى طرفه، دون أي نموذج لغوي
كبير. 17 عمليّة جديدة ضمن وسم session-catalog (يصبح الإجمالي المنشور 240 عمليّة).
- المكتب الخلفي —
POST/GET /api/session-blueprints/import(و/{batchId}) لاستيراد دفعة مخطّطات عبر بوّابة التحقّق (الاكتمال ← صحّة المفاتيح الأجنبية ← حدّ تغطية بنك الأسئلة ← سلامة اللغة ← منع التكرار؛ مسار كتابة وحيد، خامل عند تكرار البصمة)؛POST /api/session-blueprints/{batchId}/approveيحوّل الصفوف المقبولة إلى تشغيليّة؛GET /api/session-blueprints/{id}لجلب مخطّط واحد. - كتالوج المعلّم —
GET /api/sessions/catalogلتصفّح الكتالوج التشغيلي والبحث فيه؛GET /api/sessions/catalog/recommendedيرتّب المخطّطات وفق إشارة حاجة RTI (مقروءة من الصفوف المخزّنة ذاتها التي يخصّص منها مسار الطالب؛ الأوزان من إعدادٍ مثبّت الإصدار؛ طلابdo_not_decide_yetيساهمون بصفر). - المُرشد (Wizard) —
POST /api/sessions/from-blueprintوPATCH /api/sessions/{id}/editوPOST /api/sessions/{id}/accept(توزيع ISM لكلّ طالب على قائمة الصف) وPOST /api/sessions/{id}/cancelوPOST /api/sessions/{id}/recipients/{studentId}/include(إعادة إدراج طالبٍ تخطّاه التوزيع — طلاب توقّف المحرّك يُتخطّون مع تدقيق، ولا يُسقطون أبدًا). - التسليم —
POST /api/sessions/{id}/distribute-onlineيدفع جلسات كلّ طالب إلى قائمة التمرين؛POST /api/sessions/{id}/generate-pdfsيولّد ملفّات PDF قابلة للطباعة لكلّ طالب مع رمز QR (كلّ رمز = رمز ربط لمثيل المهمّة المُقدَّمة)؛GET /api/sessions/recently-generatedوGET /api/sessions/{id}وGET /api/sessions/{id}/auditلقراءة الجلسات المولَّدة وسجلّ التدقيق.
يُنفّذ FR-SBC-1/2/3 و FR-SGE-5/6/7/12/13/14/15/16/17. تمّ التحقّق: فحوصات منع النماذج اللغوية ومسار الكتابة
الوحيد والإلحاق فقط خضراء؛ openapi:check وopenapi:lint خضراء؛ بذرة المخطّطات النموذجية تُنتج 4 مخطّطات
تشغيليّة، 0 مرفوض. الواجهة الأمامية تُشحن منفصلةً (WP-SGE-FE).
واجهة معالج مراجعة الاستيراد للمسؤول (WP-LMS-FE) — 2026-06-22
واجهة أمامية فقط — لا عمليّات واجهة برمجية جديدة (جميع المسارات شُحنت مع WP-LMS-BE). يُقدّم معالج الويب الإداري RTL من 5 مراحل (/admin/lms-import): ربط ← ربط المقرّرات ← مراجعة ← تأكيد ← منتهٍ. يُنفَّذ FR-LMS-13 (سير المعالج الكامل مع استعادة الحالة خلال 24 ساعة عند إعادة التحميل) وFR-LMS-14 (قائمة دور قابلة للتعديل — أساسي / مشارك / داعم — لكل معلّم في المقرّرات متعدّدة المعلّمين). يشمل قائمة الاتصالات وزرّ المزامنة الآن وجدول سجلّ عمليّات المزامنة وقطع الاتصال وإعادة الاتصال عند الإلغاء.
استيراد قوائم الطلاب — Google Classroom وOneRoster (WP-LMS-BE) — 2026-06-22
11 عملية جديدة تحت /api/lms/* ترفع الإجمالي المنشور إلى 221.
POST /api/lms/connections/:provider/oauth-start— بدء مصادقة Google Classroom عبر OAuth؛ يُعيد رابط إعادة التوجيه لمتصفّح المسؤول.GET /api/lms/connections/:provider/oauth-callback— استقبال رمز التفويض من Google، والتحقّق من حالة الطلب، وتخزين الرمز المميّز، وإعادة التوجيه إلى معالج الاستيراد.POST /api/lms/connections/:provider/token— رفع مجموعة ملفات OneRoster بتنسيق CSV أو بيانات اعتماد REST لإنشاء اتصال نشط مباشرةً.GET /api/lms/connections— سرد جميع الاتصالات الخاصة بالمؤسسة مع الحالة وآخر وقت مزامنة.DELETE /api/lms/connections/:id— قطع الاتصال وإيقاف المزامنة المجدوَلة.GET /api/lms/:provider/courses— سرد المقرّرات المتاحة عبر الاتصال (مُخبَّرة 5 دقائق؛?cache=bypassلتجديدها). يتطلّبMANAGE_ROSTER.POST /api/lms/:provider/mappings— حفظ ربط المقرّرات بصفوف أمل. يتطلّبMANAGE_ROSTER.POST /api/lms/preview— إنشاء معاينة قراءة فقط للفروقات: مطابقة الهويّة بالمعرّف الخارجي أو البريد الإلكتروني المُحقَّق؛ يُعيد إجراءً لكل سجلّcreate | update | conflict | skipمع ملخّص إجمالي. لا تُكتَب أي بيانات في جداول المستخدمين. صلاحية المعاينة 24 ساعة.PATCH /api/lms/preview/:previewId/rows/:rowId— حفظ قرار حلّ التعارض (accept_lms | keep_amal | skip_row) لسجلّ واحد.POST /api/lms/commit/:previewId— تأكيد المعاينة في معاملة Postgres واحدة: إنشاء المستخدمين، وتسجيلهم في الصفوف، وتعيين أدوار المعلّمين، وإنشاء رموز الدخول، وإضافة سجلّاتUserExternalIdentity(source=roster_import)(لتفعيل تسجيل الدخول عبر Google تلقائيًّا). تُعيد{ created, updated, skipped, conflicts_remaining }. ملغاة الأثر عند الإرسال المتكرّر. تُعيد 422 إذا وُجد تعارض غير مُحلول.GET /api/lms/sync-runs— سجلّ المزامنة مرقَّم الصفحات للمؤسسة.POST /api/lms/connections/:id/sync-now— تشغيل مزامنة فورية؛ يُعيد202 { syncRunId }.
تتطلّب جميع المسارات requireAuth. مسارات إدارة الاتصال تتطلّب MANAGE_LMS_CONNECTIONS؛ مسارات قوائم الطلاب تتطلّب MANAGE_ROSTER. المورد غير المرتبط بالمؤسسة أو المستخدم يُعيد 404 دون الإفصاح عن وجوده.
دعم تعدّد المعلّمين (B.4). عند وجود أكثر من معلّم في مقرّر لنظام التعلّم، يُنشئ التأكيد سجلّ ClassTeacher واحدًا لكل معلّم (الأوّل أساسي، وسواه مشارك). لا يُعدَّل Class.teacherId أبدًا.
إلغاء رمز المصادقة. أي استجابة 401 أو 403 من مزوّد الخدمة تضبط connectionStatus=revoked وتوقف المزامنة المجدوَلة وتُرسل إشعار lms_connection_revoked لجميع مسؤولي المؤسسة وتُضيف سجلّ LmsSyncRun{status:error}. يُعيد المسؤول الاتصال من صفحة الاتصالات.
بوّابة بيانات أولياء الأمور (Q-LMS-5 🔴). استيراد بريد أولياء الأمور من Google Classroom مُغلَق افتراضيًّا (LMS_GUARDIAN_IMPORT_ENABLED=false) حتى اجتياز المراجعة القانونية للاحتفاظ بالبيانات. لا يدعم OneRoster استيراد بيانات أولياء الأمور في الموجة الأولى.
تسجيل الدخول عبر Google — الدخول الموحّد (WP-SSO-BE) — 2026-06-22
أصبح تسجيل الدخول باستخدام بروتوكول OAuth 2.0 من Google (تدفّق رمز التفويض + PKCE) متاحًا للمستخدمين البالغين (المعلّمين، والمسؤولين، ومديري المدارس) والطلاب المرتبطين بسجلّ الحضور. 3 عمليات جديدة ترفع الإجمالي المنشور إلى 206.
GET /api/auth/google/start— تُعيد رابط إعادة توجيه OAuth إلى Google. تُنشئ صفًّا واحدًا للاستخدام المرّة الواحدةGoogleOAuthState(صالح 10 دقائق) يحمل حالة CSRF ومُحقَّق PKCE.GET /api/auth/google/callback— تستقبل رمز التفويض من Google، وتتحقّق من الحالة، وتُحقَّق من رمز الهويّة، وتُحلّ الهويّة عبر سلسلة أولويّة ثنائية (المعرّف الفرعي ← البريد الإلكتروني المُحقَّق)، ثم تُعيد توجيه المتصفّح إلى الواجهة الأماميّة بـ?code=صالح لمدة 60 ثانية للاستخدام المرّة الواحدة. لا تظهر الرموز المميّزة أبدًا في رابط إعادة التوجيه.POST /api/auth/google/exchange— يستبدل رمز الجسر بزوج رموز قياسي{ accessToken, refreshToken, tokenType }. يُعلَّم الرمز مُستهلَكًا عند أول استخدام؛ الرموز المُعادة أو المنتهية الصلاحية تُعيد 401.
يتمكّن الطلاب من تسجيل الدخول عبر Google فقط عند وجود رابط UserExternalIdentity من نوع roster_import أنشأه المسؤول مسبقًا (لا يُسمح بالتسجيل الذاتي). يتحكّم حقل Organization.allowedGoogleDomains بنطاقات Google Workspace المقبولة؛ إذا كانت القائمة فارغة يُقبل أيّ حساب Google. تتجاوز حسابات المسؤولين العامّين (null-org SUPER) هذه البوّابة تلقائيًا.
إعادة تسمية مؤشّر الالتباس — AR_LETTER_CONFUSION_FLAG ← AR_ORTHOGRAPHIC_CONFUSION_FLAG (R12 / Q4) — 2026-06-22
أُعيدت تسمية مؤشّر التباس الحروف العربية ليُطابق اسمُ القيمة دلالتَه المعتمدة سابقًا (تأكيد الشريك 2026-06-19 حصره في الالتباس البصري/الإملائي فقط — لا السمعي). ترحيلٌ يحفظ البيانات عبر ALTER TYPE "SubFlag" RENAME VALUE (r12_rename_orthographic_flag)؛ تحتفظ الصفوف القائمة بقيمتها تحت الاسم الجديد. لا تغيير في السلوك — اشتقاق المؤشّر ونطاقه وتوجيه البروفايل لاحقًا دون تغيير. (محرّك المؤشّرات متعدّد المراحل الأوسع في Q4 يبقى بندَ عملٍ منفصلًا مجدولًا.)
خريطة العلاقات بين المهارات (R12 Tier-E / Q7) — 2026-06-21
الخادم + المواصفة. تُشحَن خريطة علاقات المهارات (الشريك Q7) بوصفها مخطّطًا فرعيًا عالميًّا استشاريًّا فقط. تُبذَر 195 علاقة + 413 رابط تشغيل عبر 11 جدول إعداد عالمي جديد (skill_rel_type / subtype / runtime_use / trigger / type_runtime_map / applicability / group / skill_relationship / runtime_link / skill_coverage / qa_rule)، خلف بوّابة استيراد من 22 قاعدة وقت البذر.
- NO_BLOCK / measurement_effect = NONE. الخريطة توثيقيّة فقط — غير مربوطة باختيار البنود أو التقييم أو أي مسار قرار. يُفشِل الحارس
lint:skill-rel-not-wiredالبناءَ إذا استوردتها أي وحدة قرار. - المواصفة:
docs/product/prds-v2/10-skills-and-standards/12-skill-relationship-map.md. المصدر: الشريك Q7. الهجرة:r12_e_skill_relationship_map.
المهارات — MORPH-C01 وأهليّة CBM (R12 Tier-A / Q9) — 2026-06-21
الخادم + المواصفة. يرتفع جدول المهارات الرئيسي من 79 → 80 مهارة: تُضاف MORPH-C01 تمييز المفرد والجمع وفق مذكّرة الشريك Q9. أصبحت أهليّة CBM خاصيّةً صريحةً لكل مهارة — محصورة بـنص ORF فقط، فلا تكون DWR-A03 / DWR-A05 مؤهَّلتَين لـ CBM.
- تؤكّد البذرة
skills_master_table = 80(76 فعّالة = 80 − LISTEN×3 − WR-SP-F03). المواصفة:11-skills-taxonomy.md. المصدر: مذكّرة الشريك Q9 بتاريخ 2026-06-21.
المعايير — معايير ORF حسب النافذة (R12 Tier-A / Q8) — 2026-06-21
الخادم + المواصفة. تكتسب طبقة المعايير بُعدَ نافذة التقييم الاختياري في الحلّ، وعلاماتٍ مرجعيّة لقابليّة تطبيق ORF.
AssessmentWindow {BOY/MOY/EOY}+ 5 أعمدة بيانات وصفيّة جديدة علىBenchmarkProfile(benchmarkStatus,sourceStrength,requiresRecalibration,minimumAccuracyPct,orfApplicability). استُخرجت قِيَم قطع ORF الحقيقية من الشريك: الأردن 46 / فلسطين 33. تُنتج البذرة الآن 55 صفًّا معياريًّا (18 صفًّا مستقلًّا عن النافذة من الشريك + 24 صفّ ORF حسب النافذة + 13 صفّ احتياطي__GLOBAL__).- حلّ احتياطي تمثيليّ لنافذة EOY (
findWithWindowFallback)؛ مسار HTTP…/resolveأعمى عن النافذة حاليًّا (متابعة Tier B) ويحلّ بصرف النظر عن النافذة. تُعيد علامتا NOT_APPLICABLE / OPTIONAL_BASELINE_NO_CUT (الصف الأول + الصف الثاني BOY = غير قابل للتطبيق) علامةً مُحدَّدة النوع — لا حُكم Meets/Below أبدًا. - المواصفة:
12-benchmarks-and-country-config.md§FR-STD-7/8. الهجرة:r12_a_windowed_orf_benchmarks.
المعايير — قاموس مؤشّرات المنهج لكل صفّ، للمواءمة فقط (R12 Tier-A / Q9) — 2026-06-21
الخادم + المواصفة. تُبذَر 51 مؤشّر منهج لكل صفّ (الأول:12 / الثاني:13 / الثالث:13 / الرابع:13) في 3 جداول عالمية جديدة (curriculum_kpi_dictionary, curriculum_kpi_to_skill_map, curriculum_kpi_country_map).
- ضمان حوكمة المواءمة-فقط. يحمل كل صفّ
decisionWeight = 0(قيد DB CHECK) +runtimeRole = ALIGNMENT_ONLY. يمنع الحارس الجديدlint:kpi-alignment-onlyأي وحدة محرّك قرار من قراءة الجداول الثلاثة (V-3). تُتخطّى المهارات غير الفعّالة ومهارات LISTEN من خريطة المهارات. - المواصفة:
12-benchmarks-and-country-config.md§FR-STD-9/10. الهجرة:r12_a_curriculum_kpi_dictionary.
محرّك القرار — تصعيد العجز إلى Severe عبر المسار B (R12 Tier-B / Q3) — 2026-06-21
الخادم + المواصفة. يكتسب تجميع المجالات الكبرى (L5 DSM) مسارَ تصعيدٍ ثانيًا إلى Severe. لا تكون Severe إطلاقةً مباشرةً من DSM، ولا قائمةً على العدّ، ولا على المئينيّات — تُنتَج فقط عبر مسارَي تصعيد:
- المسار A (قائم) — شدّة البوّابة ≥
DTH-SEV-01(DSM-04). - المسار B (جديد) — مغذٍّ من
coherent_domain_weakness/broad_related_domain_concern/gateway_driven_domain_concernمعدّل عجزه المرجَّح الخامweightedDeficitRate ≥ DTH-DEF-03(50%) بأدلّة صالحة يتصعّد إلى Severe. إعادة ضبطDTH-DEF-03تُزيح الآن حدّ Below↔Severe، لا تصنيف القلق الواسع وحده. - المواصفة:
21-skill-status-engine.mdFR-SSE-11 +22-macro-domain-rollup.md§4. المصدر: الشريك Q3 R12.
التزام التدخّل — دورة حياة خارج المسار + حظر التخفيض (R12 Tier-B / Q2) — 2026-06-21
الخادم + المواصفة. تكتسب طبقة الالتزام دورةَ حياة «خارج المسار» وتُحكِم بوّابة الحركة.
- دورة حياة خارج المسار. الخطّة التي تمرّ بها 3 أسابيع تعليمية دون تسليم تدخل حالة «خارج المسار» المتتبَّعة على
intervention_track_statusالجديد. الالتزام دون 80% يُنتج حُكمinvalid_due_to_implementation_gap. - TM_BLOCK_01 يحظر أيضًا التخفيض (لا التصعيد وحده) عند الالتزام المنخفض/المجهول — «الخطّة غير المُنفَّذة» لم تعد تُحرّك درجة الطفل في أيّ اتجاه.
- المواصفة:
35-fidelity-tracker.md+34-rti-alerts.md. الهجرة:r12_b_intervention_track_status.
CBM — أرضية اتجاه من 3 نقاط قابلة للمقارنة + بيانات قابليّة المقارنة (R12 Tier-B / Q5) — 2026-06-21
تغيير كاسر نهائي من الشريك. تنخفض أرضية اتجاه CBM من 4 → 3 نقاط قابلة للمقارنة (GrowthTrendRule.minimumComparablePointsForStrongTrend، الافتراضي 3، مدفوعة بالإعداد ومثبّتة V-6) — وهذا يُلغي قاعدة v5 ذات الأربع نقاط. دون الأرضية → insufficient_points.
- بيانات قابليّة المقارنة (§6) مُضافة لكل اختبار على
cbm_scores(comparabilityGroupId,probeType,assessmentWindow,difficultyBand,diacriticsLevel,timingSeconds= 60,administrationMode= TEACHER_LED). مفتاح قابليّة المقارنة GSR-04 يمنع الآن خطّ اتجاه واحد يجمع قائمة كلمات بنصّ متّصل، أو نصًّا مشكولًا بغير مشكول. - ضمانات محفوظة: لا قرار من نقطة واحدة؛ 3 نقاط وحدها لا تُفشل خطّة ولا تُحرّك درجة تلقائيًّا (بوّابات GSR + خارج-المسار/الالتزام). يُبذَر صفّ الإعداد الجديد
growth_trend_rule(القيمة=3) مع الكتالوج. - المواصفة:
33-fluency-measurement.mdFR-CBM-4 + §6. الهجرة:r12_b_cbm_trend_floor.
الإحماء الذهني — للتدريب فقط، دقيقة واحدة (R12 Tier-C / Q10) — 2026-06-21
تغيير نهائي من الشريك يمسّ وحدة الإحماء الذهني (61-cognitive-warmup.md). ثلاثة تغييرات في سلوك واجهة warmup:
POST /api/warmup/sessionsيتطلّب الآنsessionType—TRAININGأوINTERVENTION_PRACTICEفقط. أي قيمة أخرى (مثل سياق تقييمي) تُرفض422(فشل آمن). لا يعمل الإحماء قبل أي تقييم (BOY/MOY/EOY/Screening/ORF/CBM/confirmatory).- مدة ثابتة 60 ثانية — تُستبدل خطة الـ 3–5 دقائق متعددة المراحل بوحدة واحدة محدودة بـ 60 ثانية؛ يُنهي المحرّك الجلسة تلقائيًا عند بلوغ الحد (
MAX_WARMUP_MS = 60_000). لا يظهر أي عدّاد تنازلي للطفل. - تسليم الإعدادات النهائية لـ COG-05 (المطابقة) + COG-06 (التتبّع البصري) وتفعيلها — 8 صفوف جديدة في
WarmupGradeConfigتحمل أعداد العناصر القابلة للقراءة آليًا (numberOfVisualElements,pairCount,movingObjectsCount,targetCount,distractorCount,pathNodesCount,crossingCount,occlusionCount,speedChangeCount) إضافةً إلىtemplateContractId(TPL-COG05-*/TPL-COG06-*). يَبذُر الكتالوج الآن 32 إعدادًا فعّالًا (بدلًا من 24 فعّالًا + 8 غير فعّالة).
دون تغيير: لا يزال الإحماء لا يُغذّي θ / الإتقان / XP (G-ISO)؛ scored=false / decision_weight=0 ولا يُحتسب ضمن جرعة التدريب اللغوي. تُضيف الهجرة r12_c_warmup_60s نوع WarmupSessionType، وعمود sessionType على warmup_session، وأعمدة أعداد عناصر COG-05/06 على warmup_grade_config.
واجهة التحفيز التعليمي (WP-14-FE) — 2026-06-21
واجهة أمامية فقط، لا مسارات جديدة في الخادم. تستهلك واجهتَي WP-14-BE المشحونتين (gamification وleaderboard). تُطلق ستّة أسطح عبر أربع شخصيّات.
- ملفّ الطالب الذاتي (S1) (
/student/me): يرى الطالب رصيد نقاط النموّ ومستوى الشخصية والسلسلة اليومية (الحالية والأطول) وجدار الشارات المؤلَّف من 15 خانة (المكتسَبة بالألوان، والمقفلة كظلال مع تلميح). ملفّ الطالب لا يحمل بيانات أقران، ولا توجد صفحة لوحة صدارة تحت تطبيق الطالب، فلا مجال لظهور أيّ مقارنة أو ترتيب. - احتفال فتح الشارة (S2): طبقة غير معيقة تُعلن فتح كلّ شارة جديدة (اسمها بالعربية وأيقونة جائزة متحرّكة). تُقارَن رموز الشارات المجلوبة حديثًا بآخر مجموعة محفوظة في ذاكرة المتصفّح، فتظهر الطبقة مرّةً واحدة لكلّ شارة ولا تتكرّر بعد إعادة التحميل (Q-SYNC-10).
- لوحة نموّ الصفّ (T1) (
/teacher/class/[classId]/leaderboard): يرى المعلّم أعداد أحداث الإتقان وتقدّم المستوى لكلّ طالب في صفّه، مرتّبةً حسب النموّ، مع تفصيل لكل نوع حدث. تأتي عناوين الأعلى والمرشّحين للدعم من الخادم (framing.topLabelAr/framing.bottomLabelAr)؛ الواجهة لا تخترع مصطلحات الترتيب. أدوات التحكّم بالعرض (بأحداث الإتقان / بتقدّم المستوى) والنافذة الزمنية (7 / 14 / 30 يومًا) تُحفَظ في حالة الرابط. - لوحة نموّ جميع الصفوف (T2) (
/teacher/leaderboard): نفس جدول النموّ مجمَّعًا عبر جميع صفوف المعلّم، مع رقائق تجميعيّة لكل صفّ تُوصِل إلى T1. - لوحة نموّ المدرسة (P1) (
/principal/leaderboard): نفس السطح بنطاق جميع صفوف المدرسة، متاحٌ لشخصية مدير المدرسة فقط (يُعيد 403 لأي دور آخر). - إلغاء الشارة (T3): يُطلَق من قائمة شارات الطالب داخل صفحة تفاصيل الطالب للمعلّم. يختار المعلّم الرمز المضبوط الوحيد (
Gam_Award_Invalid_05)؛ لا يوجد حقل نصّ حرّ. تبقى الشارات الملغاة ظاهرةً بشريطة «أُلغيت» (مرئيّة للمراجعة، لا تُخفى، V-6). - لوحة مراجعة المسؤول وإعادة التشغيل (A1) (
/admin/gamification): استعلام بمعرّف الطالب والنطاق الزمني لاستعراض تدفّقات أحداث الإتقان ومعاملات النقاط والشارات، ثمّ تشغيل فحص انجراف إعادة التشغيل (V-6) الذي يُعيد اشتقاق الأرصدة والشارات من السجلّ الثابت ويُبلّغ عن أيّ حقل يختلف عن القيمة الحالية. - حقل BE إضافيّ (تمّ حلّ OQ-RESCIND-ID). يحمل
BadgeDtoالآن الحقلَينstudentBadgeIdوstatusلمستدعي المعلّم ومدير المدرسة والمسؤول؛ يُحذفان من استجابة الطالب والوالد. يعكسهماamal-api.yaml(يُعرَض تلقائيًا في مرجع الواجهة البرمجية للبوّابة). عدد العمليات ثابت: 202.
التحقّق: Playwright e2e عبر أجهزة الهاتف واللوح والحاسوب والعارض، مع تأكيد لغة النموّ في كلّ مكان وغياب نصوص ترتيب الأقران على أسطح الطلاب وبوّابة رمز الإلغاء وفحص انجراف إعادة التشغيل. فحص رسم الاستيراد AC-GAM-2 واختبارات لقطة الرموز النصية جميعها خضراء.
إعدادات المعلّم والمشرف (WP-SETTINGS-FE) — 2026-06-21
واجهة أمامية فقط — دون أي تغيير في الخادم أو المواصفة. تُغلق مسارَي التنقّل المعطّلَين الإعدادات
(/teacher/settings و/manager/settings) بصفحتَي حساب وتفضيلات بسيطتَين لكن حقيقيّتَين على الواجهة
الموحَّدة للبالغين. كلّ قسم مدعوم بواجهة مشحونة أو بتفضيل محفوظ على الجهاز؛ لا شيء مُختلَق.
- الحساب (للقراءة فقط): الاسم والدور والبريد والمؤسسة وعدد الصفوف (للمعلّمين) من
GET /api/auth/me. لا إدخال لكلمة المرور أو بيانات الاعتماد، ولا إجراءات حذف للحساب — بل توجيه «تواصل مع مسؤول النظام في مؤسستك» بدلًا من ذلك. - إمكانية الوصول: مفتاحا التباين العالي والخطّ المناسب لعسر القراءة نفساهما المتاحان في الترويسة، معروضَين كقسم في الإعدادات. يقود السطحان تفضيلًا واحدًا محفوظًا على الجهاز، فيبقى التبديل في أيّهما متّسقًا.
- الإشعارات: عدد الإشعارات غير المقروءة للقراءة فقط من
GET /api/notifications/unread-count، مع تنويه بأن الإشعارات تظهر من جرس الترويسة. لا توجد نقطة كتابة لتفضيلات الإشعارات، لذا لم تُختلَق أي تفضيلات — القسم حالة للقراءة فقط. - تسجيل الخروج:
POST /api/auth/logout، ثم العودة إلى صفحة الدخول العامّة — أوّل سطح لتسجيل الخروج في التطبيق. - ملاحظات (نواقص الخادم): لا نقطة كتابة لتفضيلات الإشعارات؛ ولا آلية تبديل لغة التطبيق (لذا لم يُبنَ قسم اللغة)؛ ولا تحمل حمولة الهويّة حقل رمز دخول.
تم التحقّق: فحص الأنواع والـ lint والبناء الإنتاجي كلّها نظيفة (المساران موجودان)؛ وPlaywright e2e 4/4 على الحاسوب واللوح، مع تأكيد ظهور أقسام الحساب وإمكانية الوصول والإشعارات، وعمل مفتاح إمكانية الوصول من الإعدادات، وصفر أخطاء في الطرفيّة. واجهة عربية أوّلًا من اليمين إلى اليسار، وسمة فاتحة.
مسارات المعلّم الثانوية (WP-TEACHSEC) — 2026-06-21
واجهة أمامية فقط — دون أي تغيير في الخادم أو المواصفة. تُغلق مسارات تنقّل المعلّم الثلاثة المعطّلة بإضافة نقاط الدخول العابرة للصفوف: عدسة «كلّ صفوفي دفعةً واحدة» التي تعجز عنها الشاشات المرتكزة على صفّ واحد. وكلّها تستهلك واجهات مشحونة ومحصورة بصفوف المعلّم (ClassTeacher).
- طلابي (
/teacher/students): كلّ طلاب المعلّم عبر جميع صفوفه في قائمة واحدة قابلة للمسح السريع — الاسم، والصفّ، وكلمة حالة أضعف مجال، وشارة كثافة الدعم، وعلامة التنبيه المفتوح — مرتّبة بحيث يظهر مَن يحتاج الانتباه أوّلًا، مع مُرشِّح حسب الصفّ. يفتح كلّ صفّ ملفّ الطالب الموجود. - متابعة التقدّم (
/teacher/progress): إشارات المتابعة المفتوحة عبر صفوف المعلّم — تنبيهات التراجع المفاجئ (مصاغة للمراجعة، لا بوصفها إخفاقًا) وإشارات اتجاه طلاقة القراءة — مربوطة بكلّ طالب وموصِّلة مباشرةً إلى مراجعة الخطّة. - خطط الدعم (
/teacher/plans): كلّ خطط الدعم المُفعَّلة عبر صفوف المعلّم، مع تقدير الالتزام والتوصية وشارة بوّابة «أكملي الجرعة أوّلًا»، وتفتح تفاصيل الخطّة الموجودة. - الالتزام بضوابط المعلّم. لا نسبة مئوية إجماليّة واحدة في أيّ مكان (كلمات حالة وأعداد فقط)؛ ولغة نموّ في كلّ النصوص؛ ولا تظهر سوى صفوف المعلّم وطلابه. مُركَّبة في الواجهة الأماميّة عبر استدعاء القراءات المشحونة لكلّ صفّ (لا توجد نقطة تجميع بعد).
تم التحقّق: Playwright e2e 6/6 على الحاسوب واللوح، مع تأكيد التجميع العابر للصفوف، وغياب النسبة المئويّة، ولغة المراجعة، وبوّابة الالتزام، وصفر أخطاء في الطرفيّة لكلّ مسار؛ ولم تتأثّر اختبارات المعلّم القائمة.
واجهة التزويد الإداري (WP-ADMINFE) — 2026-06-21
واجهة أمامية فقط، دون أي تغيير في الخادم أو المواصفة. تستهلك واجهتَي WP-A2 (البنية المؤسسية) و WP-A3 (المستخدمين) المشحونتين. تَنزِل ثلاثة أسطح إدارية على واجهة الكبار، تمنح المسؤول كل ما يلزم لتأسيس بنية المؤسسة وأفرادها.
- المؤسسات (
/admin/organizations): صفحة تنقّل تدريجي واحدة — المؤسسات → المدارس → الصفوف — عبر الكشف داخل الصفحة. يجري الإنشاء والتحرير في نوافذ حوارية في كل مستوى. تُحذف المؤسسات حذفًا مؤقّتًا؛ أمّا المدارس والصفوف فلا تُحذف إلّا وهي فارغة، ويعرض حذفُ غير الفارغ إرشادًا واضحًا بنقل الأعضاء أوّلًا بدل الحذف المتسلسل المُتلِف. - المستخدمون (
/admin/users): قائمة مستخدمين قابلة للتصفية (حسب الدور) مع الإنشاء، ويتكيّف النموذج مع الدور المختار (طالب، معلّم، ولي أمر، مدير مدرسة، مشرف، مسؤول). يكشف إنشاء طالبٍ عن رمز دخوله لمرّة واحدة فقط. يمكن إسناد صفوف المعلّمين عبر جدول الربط متعدّد الصفوف. - الصلاحيات (
/admin/roles): مصفوفة الأدوار × الصلاحيات للعرض فقط، منسوخة من تعريفات الأدوار في المنصّة للرجوع إليها. وهي ثابتة في الموجة الأولى وغير قابلة للتعديل من الواجهة. - العربية أوّلًا في كل مكان. كلّ اختيار يجب أن يكون من مجموعة محدّدة (البلد، الصفّ، الدور، الرتبة، اللهجة) هو قائمة منسدلة مغلقة، لا نصًّا حرًّا. سمة فاتحة، ونوافذ حوارية بدل الألواح المنزلقة.
تم التحقّق: Playwright e2e (تنقّل المؤسسات والإنشاء، قائمة المستخدمين وتصفيتها وإنشاؤها، مصفوفة الصلاحيات) على عرضَي الحاسوب واللوح، دون أيّ أخطاء في الطرفية.
إعدادات إمكانية الوصول — تباين عالٍ وخط لعسر القراءة (WP-A11YTOG) — 2026-06-21
واجهة أمامية فقط، دون أي تغيير في الخادم. إعدادان لإمكانية الوصول محفوظان على الجهاز يُلبّيان البندين FR-ACC-4 (التباين العالي) وFR-ACC-9 (خط مناسب لعسر القراءة)، يظهران من قائمة إمكانية الوصول في ترويسة واجهة البالغين.
- وضع التباين العالي يبدّل سمة واحدة على المستند (
<html data-contrast="high">) تُعيد تعريف ألوان رقاقات الحالة إلى أزواج تباين بنسبة ≥7:1 — فتتغيّر ألوان كل الرقاقات والشارات والحدود والنصوص الباهتة دفعةً واحدة، دون عمل على مستوى كل مكوّن. ويمكن إضافة ترميز بالأنماط (تظليل مائل / نقاط / تقاطع) بلا اعتماد على اللون وحده لمن لديهم عمى ألوان. - الخط المناسب لعسر القراءة يبدّل وجه الخط العربي ويزيد التباعد بين الكلمات وارتفاع السطر. ولا يضيف تباعدًا بين الحروف عمدًا، لأن ذلك يكسر اتّصال الحروف في الخط العربي المتّصل. أمّا الوجه المعتمَد من الشريك فما زال بانتظار قراره (🚩 OQ-ACC-5) ويُبدَّل عبر متغيّر CSS واحد دون تغيير في الشيفرة.
- الحفظ دون ومضة. يُحفظ الإعدادان على الجهاز ويُستعادان عبر نص تمهيدي متزامن قبل رسم الصفحة، فيبقيان بعد إعادة التحميل دون ومضة للمظهر الافتراضي. وعلى الجهاز المشترك في الصف تُفعّلهما المعلّمة أو ولي الأمر مرّة واحدة، فترثهما واجهة الطالب الغامرة تلقائيًا (وأُجِّلت قائمة مخصّصة داخل واجهة الطالب).
التحقّق: اختبارات Playwright الشاملة — تفعيل التباين العالي يعيد تلوين رقاقة حالة ويجتاز فحص axe-core بصفر مخالفات WCAG-AA؛ ومفتاح عسر القراءة يغيّر الخط والتباعد؛ ويبقى الإعدادان بعد إعادة التحميل. مجموعة إمكانية الوصول كاملةً (75 اختبارًا) ناجحة عبر الهاتف واللوح والحاسوب والعارض دون تراجع.
عارض سجلّ التدقيق الإداري (WP-AUDITLOG) — 2026-06-21
عمليّة واحدة جديدة تحت وسم audit الجديد، ليرتفع إجمالي العمليّات المنشورة إلى 203 عمليّات.
GET /api/admin/audit-log— قائمة موحَّدة للقراءة فقط لأحداث أمان المنصة، مرتَّبة زمنيًا عكسيًا ومقسَّمة على صفحات. للمسؤول فقط (VIEW_QA_REGISTRY)؛ محدودة بنطاق المستأجر لكل جدول. تحمل الاستجابة نوع الحدث ومعرّف المنفّذ والطابع الزمني ومؤشر طول القيمة فقط؛ لا عناوين IP ولا وكلاء المستخدم ولا القيم المُحاوَل إرسالها. قابلة للتصفية حسب نوع الحدث والمنفّذ والنطاق الزمني؛ مقسَّمة بـlimit/offset. يرى المسؤول فائق الصلاحية (null-org) جميع المؤسسات. قراءة المسؤول فائق الصلاحية تُلحق صفًّا واحدًا فيSuperAdminBypassLog(القراءة ذاتها مُدقَّقة)؛ قراءة المسؤول العادي لا تُلحق شيئًا.
تُضيف صفحة عارض الويب الإدارية (/admin/audit-log) شريط تصفية وحوار تفصيلي وتقسيمًا على صفحات.
إحصاءات نطاقات مدير المدرسة ومتابعة النموّ (WP-PRN-COMPLETE) — 2026-06-21
لا مسارات جديدة؛ المسارات الثلاثة التي كانت بيانات مؤقتة باتت ترجع بيانات حقيقية. عدد العمليّات ثابت: 203 عمليّات.
GET /api/principal/schools/{id}/overview— مؤشرات المنهج من صفوفdomain_status_snapshotالفعلية: أعداد الطلاب بكل حالة لكل نطاق، ومؤشر صحة محو الأمية المدرسي المشتقّ من تلك الأعداد. لا معرّفات طلاب ولا أسماء في الاستجابة؛ ولا نسب مئوية (V-3).GET /api/principal/schools/{id}/heatmap— مصفوفة الصف مقابل المؤشر بأعمدة عربية فقط؛ الإدخالات غير المقيَّمة مستثناة من الأعداد.GET /api/principal/schools/{id}/growth— أعداد الحالات بحسب النافذة الزمنية مع حركة النافذة مقابل النافذة (تحسّن / تراجع / ثبات). النطاق غير المصنَّف مستثنى من الحركة. الاستجابة متطابقة عند التكرار (V-6).
واجهة سير عمل تفعيل المعلّم (WP-TAW-FE) — 2026-06-21
واجهة أمامية فقط، دون أي تغيير في الخادم أو المواصفة. معالج «القرار ثم التدخّل» الذي يُتيح واجهة WP-TAW-BE لسير العمل للمعلّمين. خمس مراحل تنقل المعلّمة من قراءة التوصيات لكل طالب حتى تأكيد الخطط المُفعَّلة؛ ثم تتبع كل تعيين نشط شاشةُ مراقبة.
- معالج التفعيل (
/teacher/class/[classId]/activate): خمس مراحل متتالية: لوحة التوصيات (توصية حزمة لكل طالب مع سبب مكتوب وفق القواعد ونقطة قوة موثّقة)، ثم التجميع الذكي (تجميع الطلاب الذين يمكنهم مشاركة خطة واحدة)، ثم معاينة السقالات (مزيج مستوى الدعم، قابل للتعديل من المعلّمة لكل طالب)، ثم مراجعة التفعيل (أسلوب التسليم والجرعة ونوع المهمة مع شرح لمرّة واحدة عن سبب التوصية)، ثم التأكيد (مجمّع أو فردي). تُحفظ حالة المسودة عبر الجلسات (TTL 7 أيام على الخادم). - مراجعة الخطة والمراقبة (
/teacher/class/[classId]/plans/[assignmentId]): بطاقة الالتزام وأداة المراقبة وتدفقات قرار ما بعد التفعيل (الإبقاء / التخفيض / التصعيد / الحظر على ضعف الالتزام). - ثلاثة ضمانات غير قابلة للتجاوز. عدم كفاية الأدلّة: يُعطَّل التفعيل ولا يُتاح سوى خيار «طلب مزيد من البيانات». رصد تراجع مفاجئ: تُفتح نافذة مراجعة؛ لا تُوقَف الخطة تلقائيًا ولا تُفشَل. غياب ملفّ مستقرّ: يُستبعَد الطالب من التجميع. كل ضمانة تستلزم إجراءً صريحًا من المعلّمة قبل أن يتابع المعالج.
- المعلّمة تتّخذ كل قرار (V-12). المعلّمة تقرّر في كل خطوة. تستخدم حقول الأسباب القائمة المضبوطة ذات التسعة رموز، لا نصًا حرًا. لا تظهر التسميات الداخلية أو معرّفات المستوى أو الدرجات على أي سطح مرئي للطالب.
تم التحقّق: Playwright e2e 16/16 على عروض الهاتف واللوح والحاسوب وعارض الصفّ، مع تغطية المراحل الخمس للمعالج والمسارات الثلاثة للضمانات.
واجهة الحصّة المباشرة (WP-18-FE) — 2026-06-21
واجهة أمامية فقط — دون أي تغيير في الخادم أو المواصفة. تستهلك واجهة sync المشحونة من WP-18-BE. تَنزِل
ثلاثة أسطح مباشرة على أصداف WP-RBL.
- لوحة قيادة المعلّم على المسار
/teacher/sync(واجهة الكبار): ينشئ المعلّم حصّةً مسوّدةً لصفّ → يحصل على رمز صفّ رقمي يقرؤه بصوتٍ عالٍ → يبدأ (بوّابة سلامة اللغة) → يقود قائمة الأنشطة بأوامر تحكّم مُتسامحة مع التكرار (تقديم / إيقاف مؤقّت / استئناف / تخطّي / إنهاء). يعرض العرضُ المباشر أعدادًا إجماليّةً فقط (المنضمّون / المُجيبون / المنتظرون) — لا تفاصيل لكلّ طالب (FR-SYNC-9). - شاشة استجابة الطالب على المسار
/student/sync(عالم الطالب الغامر): ينضمّ عبر رمز الصفّ الرقمي (للمسجَّلين فقط)، يرى الخطوة الحالية، يُجيب على جهازه. تُعيد استعادةُ التخزين المحلّي (Q-SYNC-10) الطالبَ إلى الخطوة المباشرة ذاتها بعد التحديث / القفل / تبديل التطبيق / انقطاع الشبكة. - شاشة العرض المشتركة على المسار
/projector/sync(ملء الشاشة، دون بوّابة شخصية): النصّ المشترك، ورمز الانضمام الكبير، والأعداد الإجمالية فقط — دون أي تفاصيل داخلية لكلّ طالب (FR-CLIENT-10). - نمط المجموعات: إرسال توافقي يقوده القائد فقط؛ يتابع غيرُ القادة (الإرسال مُعطَّل).
- استطلاع REST فقط (Q-SYNC-1 / B.8) — دون WebSocket / SSE / WebRTC. يضاعف التراجعُ لتوفير الطاقة الفترةَ عند الاستطلاعات الفارغة (بحدٍّ أقصى 10ث) ويستطلع فورًا عند العودة إلى التبويب.
- مؤجَّل: شاشة العرض المخصّصة (FR-SYNC-PRJ-1..5) وملاحظة القراءة الجهرية (FR-SYNC-12) — في مرحلةٍ لاحقة؛ تُرجِع منافذ الإعداد/الالتزام لديها 503 حتى تُشحَن خدمتا توليد الجلسات والمسح.
جسر إسقاط لقطات محرّك حالة المهارة (WP-SSE-SNAPSHOT-BRIDGE) بتاريخ 2026-06-21
لا مسارات جديدة. صار إنهاءُ التشخيص يُغذّي خطَّ القرار، فتوقّفت أسطح الحالة الكبرى عن قراءة جدول فارغ.
- يكتب التشخيصُ المُنهى أدلةَ الفرز لكل مهارة فرعية، ويُشغّل محرّك حالة المهارة، ويكتب البلاطات الكبرى الست مع صفّ GLOBAL العام. تُرجع أسطحُ التقارير وملف المدرسة وتعدّد المدارس وولي الأمر بلاطاتِ الطالب الحقيقية.
- كل لقطة مُلحقة فقط، وغير قابلة للتكرار عبر مفتاح مثبَّت بالإصدار، ومُجمَّدة على وقت إنهاء الجلسة لإعادة تشغيل حتمية. وإعادةُ الإنهاء لا تكتب شيئًا جديدًا.
- كل لقطات الحالة الكبرى وحالة المهارة وحالة المجال تُفهرَس على معرّف ملف الطالب. وتمّت مواءمةُ قُرّاء التقارير وملف المدرسة وتعدّد المدارس وولي الأمر والملف على ذلك المعرّف.
- يُبقي جدولُ اللقطات الكبرى على أسماء أعمدته المُطبَّقة. والتغيير الوحيد في المخطّط هو مفتاح تفرُّد مثبَّت بالإصدار لكل نافذة.
لوحة مدير المدرسة (WP-PRN-FE) — 2026-06-21
واجهة أمامية فقط — دون أي تغيير في الخادم أو المواصفة. صار لشخصية «مدير المدرسة» لوحةُ صحّةٍ مدرسيّةٍ على
المسار /principal، ضمن واجهة الكبار. تُركَّب من واجهات تجميعٍ مشحونةٍ سابقاً؛ ولمّا لم تُشحَن واجهة تجميعٍ
موحَّدة بعد، تَربط الواجهة الأماميةُ قراءتين مباشرةً.
- اكتشاف المدارس عبر
GET /api/schools، التي تَحصُر مدير المدرسة بمدرسته وحدها (TENANCY-C2). مدرسةٌ واحدة ← الهبوط مباشرةً على اللوحة؛ عدّةُ مدارس (بمستوى المشرف) ← مُنتقي المدارس على/principal/schools. - بيانات حيّة من
GET /api/schools/{schoolId}/overview(WP-10-BE) — أعدادُ المجالات الحقيقية لكلّ صفّ، وتوزُّع المجالات على مستوى المدرسة، وإجمالي الطلاب، وحداثة اللقطة. ومخطَّط البيانات تجميعيٌّ فقط (الصفّ هو أدقّ مستوى، ومعلومات الطالب محجوبة على مستوى المخطَّط)؛ فلا تَصِل أيّ صفوفٍ على مستوى الطالب إلى الصفحة. - مقاييس المنهاج تَعرض مسمّيات المنهاج العربية الحقيقية من
GET /api/principal/schools/{id}/overview(WP-STD-BE). في الموجة الأولى لم يُربَط التجميع لكلّ مقياسٍ بعد، فتَصِل الأعدادُ صفريّةً ويَعرض كلُّ مقياسٍ حالةَ انتظارٍ هادئةً «بانتظار تراكم البيانات» — مكتملٌ بنيويًّا، دون أيّ أرقامٍ مُختلَقة. - لا نسبةَ مئويّةً عامّةً واحدة (V-3) — كلُّ سطحٍ هو كلمةُ حالةٍ مع عدٍّ صحيح. أمّا الخريطة الحرارية ومؤشّر صحّة القراءة في المدرسة ومقياس كفاية البيانات فمُعلَّمةٌ «قريبًا» بانتظار تمريرة التجميع في WP-PRN-BE. ولا يَظهر تقرير الوزارة.
لوحة المشرف متعدّد المدارس (WP-MSA-FE) — 2026-06-21
واجهة أمامية فقط — دون أي تغيير في الخادم أو المواصفة. صار لشخصية المشرف متعدّد المدارس لوحةٌ على مستوى المؤسسة ضمن واجهة الكبار، تستهلك مسارات المؤسسة المشحونة في WP-MSA-BE.
- ثلاثة عروض تحت
/manager/orgs/[orgId]: نظرة عامة (بطاقات تجميعية لكل مدرسة + إجماليّات المؤسسة)، والمقارنة (مصفوفة حالات: المجال × المدرسة بالأعداد)، والتغيّر عبر الزمن (رسم بياني لعدد الطلاب بحاجة إلى متابعة لكل مدرسة عبر فترات القياس). ويُحوِّل/managerإلى مؤسسة المستخدم. - بيانات تجميعية فقط — تظهر أسماء المدارس والأعداد فقط؛ ولا يظهر أيّ اسم طالب أو معلّم أو صفّ فرديّ على أيّ سطح (تُسقِط واجهات الخادم بيانات الطلاب على مستوى المخطّط).
- عرضٌ محايد — المقارنة جنبًا إلى جنب بالأعداد مع ترتيب المدارس أبجديًّا، دون أيّ ترتيب تفضيليّ أو لوحة صدارة ودون درجة مركّبة.
- أعدادٌ فقط (لا نِسَب مئوية، V-3)؛ وتُعاد كلمات الحالة من خرائط العرض المشحونة؛ وصفرٌ من مصطلحات الأطر الدولية (Q15). والرسم البياني SVG داخليّ قائم بذاته (دون أيّ اعتمادية جديدة)؛ وألوان الخطوط تدلّ على هويّة المدرسة لا على شدّة الحالة.
لوحة إدارة معايير القياس (WP-STD-ADMIN) — 2026-06-20
لا مسارات جديدة — أُضيفت مُرشِّحات اختيارية إلى قراءتين قائمتين لمدير النظام؛ والتبديل مُعاد استخدامه كما هو. لوحة خلفية لمدير النظام/الشريك من أجل استعراض معايير القياس وتفعيلها ومراجعة سجلّها، ضمن واجهة الكبار.
- صار
GET /api/admin/benchmark-profilesيقبل مُرشِّحات اختيارية:countryوskillIdوassessmentTypeوgradeBandوisActive(تُدمَج بـ«و»؛ والاستعلام الفارغ يُعيد كلّ الصفوف كالسابق). - صار
GET /api/admin/benchmark-profile-changelogيقبلbenchmarkProfileIdاختياريًا لقراءة سجلّ مراجعة معيار واحد (وعند غيابه يُعيد السجلّ الكامل كالسابق). - يُعيد التبديل استخدام مسار الكتابة المُقفَل القائم — دون إضافة كاتب ثانٍ، فيبقى فحص مسار الكتابة الواحد أخضر.
- تبقى كلّ المسارات محصورة بمدير النظام الأعلى. تعرض اللوحة مسمّيات المنهاج العربية فقط؛ ولا تظهر أيّ مقاييس داخلية في الواجهة (Q15).
واجهة الإحماء الذهني للطالب (WP-WARM-FE) — 2026-06-20
واجهة أمامية فقط — دون أي تغيير في الخادم أو المواصفة. صار للإحماء الذهني غير اللغوي (٣–٥ دقائق) شاشةُ
طالبٍ على المسار /student/warmup، مبنيّةٌ على هيكل «عالم الطالب». وهي تستهلك واجهة warmup المشحونة
سابقاً في WP-WARM-BE.
- عارضٌ مُوجَّهٌ بالبيانات. سجلٌّ واحد يختار العارض المناسب من بيانات التمرين
(
select/positions/buckets/go_nogo) — دون شاشةٍ منفصلةٍ لكلّ نوع تمرين. - هادئٌ بالتصميم. أشكالٌ بلا كلمات، دون عدّاد تنازليّ، ومسارُ «تخطٍّ إلى المهمة» بلا عقوبة، وبلا درجةٍ أو ترتيب. ولا يغذّي الإحماء محرّك القياس إطلاقاً.
- يستأنف عند الانقطاع. التحديث أو القفل أو تبديل التطبيق يُعيد الطفل إلى خطوة التمرين نفسها من ذاكرة المتصفّح.
ملخّص الصفّ للمعلّم + إعادة القياس (WP-07-FE / WP-08-FE) — 2026-06-20
لا مسارات جديدة في الخادم — كلاهما واجهتان أماميّتان تستهلكان واجهات مشحونة مسبقًا (قراءات التقارير WP-06-BE + إعادة القياس WP-08-BE).
- ملخّص الصفّ (
/teacher/class/[classId]/summary) — المكمّل التقريري للوحة الصفّ التشغيليّة. يعرض توزيع مستويات الدعم، وشبكة المجالات السداسيّة المعاد استخدامها، وجدول توزيع حالات المهارات (أعداد بحاجة لتدخّل لكلّ مهارة)، وقائمة المقترَحين لإعادة القياس. كلّ رقم هو كلمة حالة × عدد — لا نسبة مئويّة عامّة واحدة أبدًا (V-3). - إعادة القياس — يفتح زرّ المعلّم في ملفّ الطالب جلسة إعادة قياس
(
POST /api/diagnostic-sessions/start/re-diagnostic؛ مهلة الأربعة عشر يومًا مفروضة في الخادم)، وتعرض صفحة المقارنة (GET /api/reports/students/{id}/re-diagnostic-comparison/{sessionId}) حالة كلّ مهارة فرعيّة قبل ← بعد مع اتجاه النموّ. لغة نموّ فقط — لا تصل أيّ درجة قدرة خام إلى أيّ طرف؛ والتراجع يُؤطَّر للمراجعة لا للإخفاق (V-12).
معايرة راش الحقيقية (WP-CAL) — 2026-06-20
لا مسارات جديدة. صار تقدير قدرة المتعلّم (θ) في محرّك التشخيص يُنتَج عبر مُقدِّر راش 1PL حتميّ حقيقي
(EAP) بدل النموذج المغلق الصوري. والقيمة rasch_1pl_v1 في EngineImplementation هي الافتراضية؛
ويبقى النموذج الصوري قابلاً للاختيار لإعادة تشغيل الجلسات الأقدم.
- صعوبة بمسارين. يستخدم السؤال صعوبته المقيسة بمجرّد بلوغه 300 استجابة حقيقية أو أكثر، ويستخدم
التقدير الحتميّ (
delta_prior) قبل ذلك. وتُثبّت الجلسات إصدار معايرة مُجمّداً، فلا تتزحزح صعوبةٌ في منتصف الجلسة (V-6). - خطّ معايرة غير متصل (
services/calibration/، بايثون + girth) يُلائم صعوبات 1PL لكلّ مهارة فرعية ويسكّ لقطة مُرقّمة جديدة في كلّ تشغيل؛ وقد جرى التحقّق من استعادته صعوبات معلومة على بيانات تركيبية. ولا توجد بعد استجابات تجريبية حقيقية، فهو يُشحَن مبنيّاً وجاهزاً، دون تشغيل فعليّ بعد. - دليل جديد: دليل تشغيل المعايرة يغطّي فحص جاهزية البيانات، والتشغيل التجريبي، والتشغيل الحقيقي، وقراءة إحصائيّات الملاءمة، وإعادة ضبط الصعوبة كلّما هبطت استجابات أكثر.
مركز الإشعارات الموحّد (WP-NOTIF-BE) — 2026-06-20
خمسة مسارات جديدة (وسم notifications). صندوق الإشعارات الموحّد عبر جميع الأدوار، يحلّ محلّ أكثر من ستّة
أسطح تنبيه متفرّقة كان يواجهها المعلّم في يومه الأول. داخل التطبيق فقط في الموجة الأولى؛ قناة البريد والاشتراك
لكلّ نوع تنتقل إلى WP-NOTIF-EMAIL.
- مقصور على المُستلِم، بلا ثغرة وصول مباشر. المسارات:
GET /api/notifications،GET /api/notifications/unread-count،POST /api/notifications/{id}/read،POST /api/notifications/{id}/dismiss،POST /api/notifications/mark-all-read. يستمدّ كلّ مسار هويّة المُستلِم من رمز الدخول (لا يوجد مُعاملuserIdفي المسار). يقرأ المستخدم ويُعدّل صفوفه فقط؛ ومعرّف لا يملكه يُعيد 404 لا 403، فلا يُكشف وجود معرّف في صندوق آخر. - عزل المستأجر والأدوار. يُخزَّن
organizationIdعلى كلّ صفّ؛ فلا يقرأ معلّم إشعارات مدرسة أخرى ولا إشعارات وليّ أمر. - بوّابة
notifications.dispatch()الداخلية (بلا واجهة HTTP) هي مسار الكتابة الوحيد: تحقّق Zod لكلّ نوع (Q18 بلا نصّ حرّ)، ثمّ تكوين القالب العربي، ثمّ مرشّح سلامة اللغة على العنوان والنصّ المُكوَّنين (حجب صارم بلا نصّ بديل)، ثمّ تحديد المؤسسة والدور، ثمّ الإدراج. بلا نماذج لغوية كبيرة (V-5). - تسعة أنواع في الموجة الأولى. الصفوف غير قابلة للتعديل بعد الإنشاء (يتغيّر حقل حالة التسليم فقط)؛ والإشعار المُستبعَد لا يظهر مجدّدًا في أيّ قائمة.
- تتبنّى الوحدات المُنتِجة البوّابة ضمن تغييرها الخاص؛ هذا الإصدار يقدّم البوّابة والاختبارات. عدد العمليات أصبح 202.
خادم واعٍ بالجهاز (WP-CLIENT-CTX-BE) — 2026-06-20
لا مسارات جديدة — وسيط واحد + مُحدِّد طبقة أصول نقيّ + حقل قياس + فحص العزل
(83-client-and-device-support المتطلّبان FR-CLIENT-8/9، القاعدة الصارمة B.27).
- عقد ترويسة
X-Client. ترسل الواجهة ترويسة قدرات واحدة مُتحقَّقة بـ zod —X-Client: {"class":"phone|tablet|desktop|projector","standalone":bool,"bandwidth":"slow|normal|fast|unknown","reducedData":bool,"viewport":"xs..xl","appVersion":"…"}. يحوّلها وسيطclient-contextإلىc.var.client. قدرات فقط، بلا أي بيانات تعريف شخصية (تُرفض المفاتيح الزائدة/المجهولة). آمن عند الفشل — الترويسة الغائبة أو المشوَّهة ترجع إلى قيم افتراضية آمنة (desktop/unknown)، ولا تُنتج خطأً أبداً. - القياس. تحمل سجلّات الطلبات الآن حقل صنف الجهاز
client(اختياري، إضافي، متوافق مع السابق). - طبقات أصول متكيّفة (FR-CLIENT-9). يُرفق تقديم المهمة الحقل
presentation.assetTier({ audio: lo|hi, image: 1x|2x }) المختار من قدرات العميل — والطبقة الخفيفة هي الافتراض. يغيّر هذا حجم البايتات المُقدَّمة، لا العنصر نفسه: العنصر نفسه وخياراته وإجابته الصحيحة وصفّ التدقيق متطابقة مهما كان الجهاز. - حارس الحتمية (B.27 / V-6). فحص CI،
lint:client-context-isolation، يُفشِل البناء إذا قُرئ سياق الجهاز/العميل داخل أي مسار قياس أو قرار أو تخويل. ويُثبت اختبارُ حتمية عبر الأجهزة أن المدخل ذاته على صنفَي جهاز يُنتج قياساً متطابقاً بايتاً ببايت. - 🚩 بانتظار الشريك (25 يونيو): عناوين الأصول الحقيقية لكل طبقة وعتبات معدّل البِت/الدقّة الدقيقة تأتي مع خطّ إنتاج الصوت/الرسوم (OQ-CLIENT-2)؛ تُعلَّم الطبقة المختارة الآن لتستهلكها الواجهة/شبكة التوزيع.
إعادة القياس التشخيصي (WP-08-BE) — 2026-06-20
مسارَان جديدان (وسم re-diagnostic). تستطيع المنصة الآن فتح تشخيص إعادة قياس مركّز بعد دورة تدخّل،
ومقارنة النتائج بالجلسة التشخيصية السابقة.
- بوّابة 14 يوماً.
POST /api/diagnostic-sessions/start/re-diagnosticيفتح جلسة إعادة قياس. يُرجع 409 إذا كان التشخيص المكتمل السابق أقل من 14 يوماً. - أرشفة قائمة الانتظار. يؤدّي فتح إعادة التشخيص إلى أرشفة قائمة التدريب النشطة للطالب، حتى يبدأ من جديد بعد إعادة القياس بدل الاستمرار في المنتصف.
- مقارنة جنباً إلى جنب.
GET /api/reports/students/:id/re-diagnostic-comparison/:sessionIdيقرن إعادة التشخيص بأحدث جلسة تشخيصية مكتملة سابقة، ويُرجع لكل مهارة فرعية{ priorStatus, currentStatus, statusTransition, growth }. قيمةgrowthواحدة منimproved، أوdeclined، أوsame، أوindeterminate. لا يغادر θ الخام الخادمَ أبداً (FR-RPT-3/9 no-leak). - التخويل: المعلّمة (ClassTeacher للصف الخاص) أو المسؤول أو
RUN_BACKOFFICE؛ الطلب خارج المؤسسة يُرجع 404.
بنية الأجهزة والعملاء — تطبيق ويب تقدّمي + طبقة القدرات (WP-CLIENT-INFRA-FE) — 2026-06-20
النصف الأمامي من عقد دعم الأجهزة والعملاء (القاعدة الصارمة B.27 · المواصفة
83-client-and-device-support). يُحَلّ مرة واحدة على مستوى المنصّة لترث كل الشاشات — الحالية
والمستقبلية — السلوك المتجاوب والعمل دون اتصال عبر فئات أجهزة المدارس الأربع (الهاتف، اللوحي/آيباد،
الحاسوب المكتبي/المحمول، عارض الصفّ).
- طبقة قدرات واحدة، لا اعتماد على سلسلة المتصفّح. مزوّد واحد يحدّد فئة الجهاز من حجم الشاشة وقدراتها
(نوع المؤشّر، توفير البيانات، وضع التطبيق المثبّت، سرعة الشبكة) ويتيحها عبر
useClient(). التخطيط يبقى مدفوعًا بنقاط الكسر في CSS؛ ولا تُقرأ سلسلة المتصفّح (User-Agent) لاتخاذ قرار تخطيط أبدًا. - نقاط كسر معيارية مُعرّفة مرة واحدة (
sm 480 / md 600 / lg 1024 / xl 1280)، فتصبح مصفوفة الأجهزة المرجع الوحيد للعروض. يطوي هيكل البالغين الشريط الجانبي إلى شريط سفلي دونmd؛ وعالم الطالب يملأ الشاشة؛ وعارض الصفّ لا يُظهر أي تفاصيل خاصّة بطالب بعينه (عدم التسريب). - تطبيق ويب قابل للتثبيت. بيان تطبيق (“أمل”، أيقونات قابلة للقَنْع، اتجاه من اليمين، سمة فاتحة) مع عامل خدمة يخزّن هيكل التطبيق مسبقًا ويقدّمه دون اتصال، مع إشعار غير صامت بوجود تحديث (لا إعادة تحميل مفاجئة). لا يخزّن العامل سوى الأصول الثابتة، ولا يمسّ ذاكرة جلسة الطالب الجارية.
- إجابات الطالب لا تضيع دون اتصال. يواصل الطالب الذي انقطع اتصاله أثناء التدريب الإجابة؛ تُحفظ الإجابات محليًّا وتُرسَل عند عودة الشبكة بمفتاح عدم التكرار، فيسجّلها الخادم مرة واحدة (دون ازدواج). أمّا قرارات المعلّم وأي كتابة قياس فتبقى متّصلة فقط مع حالة هادئة “لا يوجد اتصال” — دون نجاح زائف. الخادم هو المرجع دائمًا.
- ترويسة
X-Clientوميزانيات الأداء. يحمل كل طلب واصفًا للقدرات فقط (دون بيانات تعريف شخصية) لأغراض القياس والأصول المتكيّفة مستقبلًا؛ ولا يؤثّر في أي قياس (الحتمية، V-6). يفرض Lighthouse-CI سقفًا لحجم جافاسكربت وزمن التفاعل على ملف تعريف منخفض الموارد (جهاز المدرسة هو المعيار). وتعمل مصفوفة أجهزة من أربع عروض في كل حزمة عمل أمامية. - 🚩 بانتظار الشريك (25 يونيو): الحدّ الأدنى لمواصفات أجهزة المدارس (يحدّد أرضية الأداء الحقيقية وقيود تطبيق الويب على متصفّح iOS) وعتبات مستويات الأصول.
محرّك تجميع الجلسة (WP-ISM) — 2026-06-20
ثلاثة مسارات جديدة (وسم ism). نموذج السقالات المتكامل (“المايسترو”) — المنسّق الذي يبني جلسة تدريب
متماسكة الموضوع من بنك العناصر التشغيلي المتوفّر: موضوع واحد، وسلّم وحدة نموّ الجملة، ومهارات متشابكة على
عائلة كلمات واحدة، فلا ينتقل الطفل بين تدريبات غير مترابطة.
- يختار ولا يولّد. يختار ISM عناصر بنك كاملة ومعايَرة ومعتمَدة من خبير المحتوى فقط — لا توليد وقت التشغيل ولا نموذج لغوي (V-5). التشخيص لا يستدعيه أبداً (V-3)؛ يبقى اختباراً تكيّفياً صرفاً.
- حتمي (V-6). الطالب + الموضوع + البذرة + لقطة بنك العناصر نفسها ⇐ جلسة متطابقة بايتاً ببايت ومعرّف تشغيل نفسه. أي تغيّر في البنك يُنشئ تشغيلاً جديداً؛ لا يُعدَّل التاريخ أبداً.
- وضعان، نقطة وصول واحدة. تدريب عام (قائمة مهارات فرعية) أو سياق حزمة (مرساة + داعمتان كحدّ أقصى + جسر أصول، موزونة بنموذج المسار المتشابك مع كون حصّة المرساة دائماً الأكبر).
- آمن عند الفشل. سلّم تخفيف من أربع خطوات (توسيع النطاق ← الحقل الدلالي ← إسقاط تسلسل النموّ ← فشل ليّن) يَسِم الجلسة القصيرة بأنها ناقصة بدل حشوها. كل جلسة رابعة تُفسح المجال لفحص CBM.
- لا يُحجب الوصول إلى التدريب أبداً. تُقيَّد جلسات RTI القائمة على الحزمة فقط (409) عند عدم كفاية الأدلة أو التراجع الحاد؛ ويرى المعلّم/الوليّ نصّ لغة نموّ، لا رمز الخطأ.
- جدولان جديدان:
assembly_run(تدقيق/إعادة اشتقاق إضافة فقط) +assembly_rule_set(إعداد مُصدَّر). مزيج FSRS ومعالجة اللهجة وإدراج الفحص مُعلَّمة بانتظار قرار الشريك (25 يونيو).
وضع الدرس التزامني (WP-18-BE) — 2026-06-20
سبعة عشر مساراً جديداً (وسم sync). الواجهة الخلفية لدروس المعلّم التزامنية، حيث يعرض المعلّم جلسة حية
ويُجيب الطلاب على أجهزتهم عبر الاستقصاء الدوري REST بلا WebSocket أو SSE (قيد Q-SYNC-1 LOCK لأجهزة المدارس
التجريبية ذات الموارد المحدودة).
- دورة حياة الجلسة.
POST /api/sync/sessionsتنشئ مسودة جلسة برمز انضمام رقمي؛POST …/startتُفعّلها؛GET …/summaryتُرجع النتائج المجمّعة أو لكل طالب بعد انتهاء الجلسة. - ثلاثة أوضاع. الفصل الكامل، والاستجابة الجماعية، وعارض الشاشة الشخصي. في وضع العارض الشخصي
يُرسَل عنصر مختلف لجهاز كل طالب بينما تبقى شريحة مشتركة على الشاشة المعروضة.
المسارات:
…/personalized-projector/setup,…/answer-key,…/mark,…/commit. - المجموعات بقيادة المحدَّد.
POST …/groupsينشئ مجموعات الطلاب بقائد محدَّد؛PATCH …/groups/:groupId/leaderينقل القيادة. - الاستقصاء الدوري REST. يستقصي الطلاب والمعلّمة
GET …/pollوGET …/eventsللتغييرات في الحالة. تُرسَل الإجابات إلىPOST …/responses؛POST …/observationيسجّل ملاحظة المعلّمة. - القائمة والتحكّم.
POST …/playlistيحمّل تسلسل العناصر؛POST …/controlيتحكّم في التشغيل، والإيقاف المؤقت، والانتقال، والإنهاء. تستطيع الجلسات الارتباط بتشغيل ISM عبرPOST …/ism-run.
خادم التحفيز (WP-14-BE) — 2026-06-20
سبعة مسارات جديدة (وسما gamification + leaderboard). محرك التحفيز المرتبط بالتعلّم: سجلّ أحداث
الإتقان (ثمانية أنواع مصدر مغلقة)، ونقاط الخبرة المشتقّة، والأوسمة، وصورة رمزية تجميلية، وسلاسل لطيفة،
ولوحات صدارة المعلّم والمدير، ومسار إلغاء الوسام، وتدقيق المسؤول وإعادة الاشتقاق.
- كل مكافأة تعود إلى حدث إتقان مقاس (V-8). لا تُمنح النقاط/الأوسمة إلا من أحد أنواع المصدر الثمانية — عدد الجلسات، والوقت على التطبيق، وسلاسل تسجيل الدخول لا تمنح شيئاً أبداً. يتحقّق فحص آلي من أن كل قاعدة منح وسام تستند إلى مصدر مقاس.
- لا لوحة صدارة للطالب أبداً. لوحات الصدارة للمعلّم (عدّة صفوف) وللمدير (المدرسة) فقط؛ رمز الطالب يُرفض (403) على كل مسار صدارة. صفحة نقاط الطالب تعرض بياناته وحده — لا مقارنة بالأقران ولا ترتيب.
- عديم التكرار وقابل لإعادة الاشتقاق. الإصدار عديم التكرار على المفتاح الطبيعي؛ رصيد النقاط مشتقّ من السجلّ المُلحَق فقط (لا يُخزَّن)؛ إعادة اشتقاق المسؤول تعيد حساب الرصيد/الأوسمة/الصورة وتقارن بصفر انحراف.
- الإلغاء = رمز مضبوط واحد، بلا نص حرّ. يُلغي المعلّم عبر الرمز التاسع الوحيد
Gam_Award_Invalid_05؛ تُلحَق حركة تعويض معاكسة؛ ويُحفَظ صفّ المنح الأصلي. - القيم الافتراضية العاملة (قيم النقاط، وسقف 200/جلسة، وعتبات الصورة/السلسلة، وكتالوج الأوسمة الخمسة عشر بالعربية) مزروعة ومُصدَّرة ومُعلَّمة بانتظار الشريك لجلسة 25 حزيران — لم يُختلق شيء.
أدلة حلقة القرار — الأمانة وحزم القرار وغرفة البيانات — 2026-06-20
لا تغيير في الواجهة. ثلاثة أدلة مطوّرين جديدة تحت الأدلة، مبنية على
شيفرة الوحدات المشحونة، تمنح موجة قرارات الاستجابة للتدخل تغطيتها على مستوى الواجهة:
متتبّع أمانة تنفيذ التدخل (بوابة التصعيد: النسبة والتصنيف والحكم
وescalationBlocked)، وحزم القرار (سير عمل التجميع ثم الاعتماد أو الرفض
الذي يستدعي محرك RTI لنقل المستوى)، وغرفة بيانات الطالب (الملفّ + فهرس
الأدلة + هيكل الحزمة). يوثّق كلٌّ مساراته الحقيقية وصلاحياته وأشكال حقوله، مع ثوابت الفشل المغلق
والإلحاق فقط وتثبيت الإصدار والسبب المضبوط وعدم الظهور للطالب أبداً. تطابق إنجليزي + عربي.
دليل المنصة — بوّابة التوثيق الخارجي — 2026-06-20
لا تغيير في الواجهة. نكهة توثيق ثانية لجمهور غير تقني، تُقدَّم تحت بادئة المسار /external. يحمل
الشريط العلوي تبويبَين، وثائق المطوّرين ودليل المنصة، وتعرض كل بوّابة قائمتها وحدها (تتبدّل
القائمة الجانبية حسب البوّابة). ولم تتغيّر مسارات وثائق المطوّرين.
- 27 صفحة معمّقة بالإنجليزية والعربية، مبنية على شيفرة الوحدات الفعلية، منظّمة في ستة أقسام: القياس والقرارات، والتدخل والتدريس، والمراقبة والاستجابة، والتقارير ولوحات المعلومات، وأسس المنصة، إضافةً إلى نظرة عامة، والثقة والخصوصية، وخارطة الطريق، والأسئلة الشائعة. تشرح كل صفحة قدرةً حقيقية من طرفها إلى طرفها بقواعدها وعتباتها الحقيقية، بلغة منتج واضحة (بلا نقاط نهاية أو مخطّطات أو معرّفات داخلية).
- مكتوبة بلغة النموّ فقط: لا تسميات سريرية أو برامجية، ولا نتيجة إجمالية واحدة، وفصلٌ صادق بين المتاح الآن والمخطّط له.
- يتشارك البوّابتان التطبيق والسمة والبحث؛ ويثبت تطابق الإنجليزية/العربية (60/60).
البوّابة — أدلة شاملة للمرحلة الأولى — 2026-06-20
لا تغيير في الواجهة. مرور توثيقي فقط يجعل البوّابة مواكبةً لنحو 21 حزمة عمل لمحرّك الاستجابة للتدخّل شُحنت منذ بناء البوّابة أوّل مرّة. كانت أدلة التزويد قائمةً بمفردها؛ أمّا حلقة الاستجابة للتدخّل القائمة على القياس فلها الآن تغطية مفاهيمية كاملة.
- قسم مفاهيمي جديد “كيف تعمل المرحلة الأولى” — حلقة الاستجابة للتدخل، القياس والحتمية، محرك القرار، تصميم التدخل، وقواعد السلامة.
- 16 دليلًا جديدًا للأنظمة الفرعية تحت الأدلة — التشخيص والتدريب، وتصنيف المهارات، ومحرك حالة المهارة، وملفات الطلاب، وحزم التدخل، والتجميع الذكي، وتفعيل المعلم، ومراقبة التقدم، والقياس المنهجي وطلاقة القراءة، وقرارات الاستجابة للتدخل (معاينة)، والمعايير والمحكات، وتسليم المهام، والتقارير وملف ولي الأمر، والإحماء الذهني، وسلامة اللغة، وفحوصات جودة النظام.
- مصطلحات جديدة وثلاثة إصلاحات لصفحات قديمة (نظرة عامة، نتائج «التوقّف الآمن» في الأخطاء، وتجميع المنسقين والمدراء الذي صار مأهولًا).
- كل صفحة تُشحن بـ الإنجليزية + العربية (تطابق 33/33)؛ وكل الروابط الداخلية صالحة.
بوّابة وليّ الأمر — 2026-06-20
أربع عمليات قراءة جديدة تحت وسم parent-portal جديد (يصبح العدد 171) — عرضُ وليّ أمرٍ موثَّق لأبنائه.
GET /api/parent/children(الأبناء المرتبطون)،…/:childId/diagnostics(سجلّ بالحالة فقط)،…/:childId/growth(مسار حالة المجالات، تسميات عربية فقط)،…/:childId/recommendations(≤5 اقتراحات منزلية من سرد D2 المولّد مسبقًا — لا نموذج لغوي وقت التشغيل).- الأبناء المرتبطون فقط. وليّ الأمر هو المستخدم الموثَّق (لا
:parentIdفي أيّ مسار ← لا IDOR)؛ ويُفحَص كل:childIdمقابل رابطParentStudent— ابنٌ غير مرتبط داخل المؤسسة ← 403، وابنٌ عبر المؤسسات/غير موجود ← 404. ويرى وليّ الأمر متعدّد الأبناء جميع أبنائه المرتبطين. - آمن من التسريب بالتصميم (حِزامان). DTO بقائمة سماح مكتوبة + مرشّح الصرامة-لوليّ-الأمر النصّي — لا θ ولا أرقام ولا نِسَب ولا تسميات داخلية تصل إلى وليّ الأمر (طفلٌ ببيانات θ/ملفّ/نسبة حقيقية لا يُظهَر منها شيء). يفشل مغلقًا (503) إن غابت قواعد المرشّح.
- لا ملخّص واتساب، لا تخزين هاتف (D1) — كل المسارات GET للقراءة فقط؛ لا تخزّن البوّابة شيئًا عن وليّ الأمر.
نظرة إدارية متعدّدة المدارس — 2026-06-20
ثلاث عمليات جديدة تحت وسم multi-school جديد (يصبح العدد 167) — تجميعٌ على مستوى المؤسسة لمدير الشبكة،
مبنيٌّ فوق عرض المدرسة الواحدة.
GET /api/orgs/:orgId/overview— بطاقة تجميع لكلّ مدرسة (الاسم + إجمالي الطلاب + عدد الصفوف + كم منهم يحتاج دعمًا).GET /api/orgs/:orgId/comparisons— مجالات القراءة الستّة × N مدرسة جنبًا إلى جنب، كأعداد حالة.GET /api/orgs/:orgId/trends— سلسلة زمنية للمؤسسة، خطٌّ لكلّ مدرسة × مجال، عبر نوافذ شهرية.- المقارنة تجميع حالة محايد، وليست ترتيبًا — لا ترتيب أفضل/أسوأ، ولا لوحة صدارة للمدارس. ويظهر المجال الجامع كبطاقة “قريبًا”.
- تجميعيٌّ بالتصميم. يُظهر أسماء الصفوف لكنه لا يُظهر أبدًا اسم طالب أو معرّفه في أيٍّ من الاستجابات
الثلاث — نفس حارس الـ lint (مُوسَّعًا على هذا الوحدة) + اختبارات تزرع اسمًا مميَّزًا وتؤكّد غيابه. لا θ، ولا
نسبة عامّة واحدة (V-3)؛ ويُستثنى
Not_Assessedمن أيّ تجميع. - يرى المدير كلّ مدارس مؤسسته افتراضيًّا (لا واجهة تحديد جزئي في الموجة الأولى)؛ ويُعيد المعرّفُ خارجَ المؤسسة 404. للمدير/المشرف فقط — لا للمعلّم ولا للطالب.
- يعيد استخدام محرّك تجميع المدرسة وقُرّائه المُسلَّمين (لا جداول جديدة، لا منطق قياس). قراءاتٌ مُجمَّعة تفي بميزانية ≤5 ثوانٍ لمؤسسة من 10 مدارس.
تغطية سرد وليّ الأمر (مولّد بالذكاء الاصطناعي، مبدئي) — 2026-06-20
عملية إدارية واحدة جديدة (يصبح العدد 164) + تغيير محتوى وبيانات بحيث يُظهر تقرير وليّ الأمر وبوّابته شرحًا مكتوبًا للنموّ لـ كلّ ملفّ، لا للملفّين المكتوبين من الشريك فقط.
- 56 سردًا عربيًّا لوليّ الأمر (12 أساسيًّا + 5 معدِّلة × نطاقات الصفوف) مولّدة من مواصفات الملفّات ومزروعة
كطبقة مبدئية. كلٌّ موسوم
ai_generated+needs_sme_reviewويجتاز مرشّح الصرامة-لوليّ-الأمر دون تغيير — لا أرقام، لا θ، لا تسميات داخلية، لغة نموّ فقط (نفس انضباط V-12/V-3). - تُعرض حيّة، موسومة (قرار محمد): يرى وليّ الأمر الشرح الآن؛ ويراجعها الشريك ويستبدلها في جلسة 25 يونيو. يُستبدَل عرض وليّ الأمر فقط — تبقى سرود المعلّم والمشرف والطالب من تأليف الشريك. وتبقى صفحة “نحتاج بيانات إضافية” الآمنة لحالات غياب الملفّ الحقيقية، لا لـ”لم يُكتب السرد بعد”.
GET /api/admin/profile-narratives/pending-reviewيسرد الصفوف المبدئية لطابور مراجعة الخبير (RUN_BACKOFFICE فقط).
نظرة عامة على المدرسة + تقرير المجلس (PDF) — 2026-06-20
عمليتان جديدتان تحت وسم board-pdf جديد (يصبح العدد 163) — عرضٌ على مستوى المدرسة للمديرين ومديري الشبكات.
- نظرة عامة (JSON) + تقرير مجلس بصفحة واحدة A4 عربي RTL لاجتماع مجلس/إدارة: أعداد حالة المجالات لكل صفّ + التوزيع على مستوى المدرسة عبر مجالات القراءة الستّة (+ بطاقة “قريبًا” للمجال الجامع).
- تجميعيٌّ بالتصميم. يُظهر أسماء الصفوف (ليتصرّف المدير) لكن لا يُظهر أبدًا اسم طالب أو معرّفه — يحرس كل مسار قراءة فحصٌ مخصّص، ويزرع اختبارٌ اسمًا معروفًا ويؤكّد غيابه من بايتات التقرير ومن الـ JSON. لا θ، لا نسبة إجمالية واحدة (V-3).
- يعيد استخدام قارئات التقارير المشحونة + أساس
lib/pdfالمشترك (خط عربي مضمَّن، حتمية بايتات V-6) الذي صار تقرير وليّ الأمر يُبنى عليه أيضًا — وصفة PDF واحدة، تخطيطان. - للمدير/مدير الشبكة/المشرف فقط (المدير يرى مدرسته؛ مدير الشبكة يرى مدارس مؤسسته)؛ غير ظاهر للمعلّم أو الطالب أبدًا. ≤500 كيلوبايت، ≤30 ثانية، يفشل-مغلقًا.
مواءمة مفردات v5 — 2026-06-20
لا تغيير في السلوك. أصبحت طبقة قرارات الاستجابة للتدخّل تُخزّن أسماء رموز الحالة القياسية للشريك (v5)
مباشرةً، مع إزالة طبقة ترجمة وسيطة. كفاية البيانات تُقرأ sufficient / insufficient / contextual؛ وقرارات
المستوى escalate / de_escalate / maintain / defer؛ وتنبيهات RTI كتالوجها الخماسي Skill_Alert / Student_Alert / Intensive_Review / acute_regression_review / tier_review_due؛ وتُضاف specialist إلى أدوار الاعتماد؛ وحزمة القرار
تُقرأ draft / under_review / approved / rejected / deferred. تغيّرت تهجئة الرموز المُخزّنة فقط — أمّا منطق
القرار والضمانات والحتميّة (V-6) فلم تُمَسّ، ومخطّطات OpenAPI تعكس أسماء v5.
مسار حزمة القرار — 2026-06-20
أربع عمليات جديدة تحت الوسم الجديد decision-packet (يصبح العدد 161). القطعة الختامية في موجة قرارات
الاستجابة للتدخّل: مسار المراجعة والاعتماد الذي يحوّل توصية انتقال المستوى إلى قرار موثّق ومدقّق — وعندئذٍ
فقط يُنقَل مستوى الطفل.
- التجميع.
POST /api/decision-packet-workflows/assembleيفتح حزمة قرار غنيّة (الأدلّة مُلتقطة بالإحالة لا بالنسخ، وكلّ إصدار قاعدة/إعداد مُثبَّت لإعادة التشغيل)، ويحسب توصية المستوى الحتميّة، ويسجّل صفّ مسارٍ بانتظار المراجعة. - المراجعة والاعتماد.
GET /api/decision-packet-workflows/{id}هو واجهة المراجِع؛ وPOST …/{id}/approveيمرّر التوصية عبر بوّابة الاعتماد — وانتقالٌ إلى المستوى الثالث يتطلّب الأخصّائي عالي الكثافة (مُقعَد إداريًّا في الموجة الأولى) — وعند الاعتماد يُنفَّذ انتقال المستوى عبر مسار الكتابة الوحيد للمستوى في محرّك RTI، ثم تُغلَق الحزمة. وPOST …/{id}/rejectيسجّل رفضًا بسبب مضبوط؛ دون أي انتقال. - لا انتقال دون اعتماد؛ وسبب القرار رمزٌ مضبوط لا نصٌّ حرّ. أي إيقاف «نحتاج مزيدًا من الأدلّة»، أو انتقالٌ غير معتمَد إلى المستوى الثالث، أو ملفّ ناقص — كلّها تحجب الانتقال (فشل آمن). والحزمة المُغلَقة والقرار المُطبَّق غير قابلين للتعديل أبدًا (وإعادة التشغيل تُعيد إنتاجهما).
- هذا المسار لا يضيف أيّ كتابةٍ للمستوى من تلقاء نفسه — بل يستدعي محرّك RTI لنقل المستوى وغرفة البيانات لفتح/إغلاق الحزمة. مُلحَق فقط، معزول حسب المؤسّسة، مُثبَّت الإصدار (V-6)، ولا يُعرَض للطالب أبدًا.
متتبّع أمانة تنفيذ التدخّل — 2026-06-20
خمس عمليات جديدة تحت الوسم الجديد fidelity (يصبح العدد 152). البوّابة التي تميّز بين «الخطّة لم تنجح»
و«الخطّة لم تُنفَّذ»، حتى لا تُصعِّد المنصّة أبدًا حالة طفلٍ لم يُنفَّذ تدخّله فعليًّا.
- بوّابة التصعيد.
GET /api/fidelity/{bundleAssignmentId}/checkيُرجع الحكم المتزامن الذي يستدعيه محرّك RTI قبل أي انتقال من المستوى الثاني إلى الثالث: نسبة الالتزام (الجلسات المُنفَّذة ÷ المخطّطة)، تصنيف من خمس قيم، حكم من أربع حالات، وescalationBlocked. التنفيذ الأمين (≥80٪) مع نموٍّ ضعيف قد يُصعِّد؛ ودون 80٪ مع نموٍّ ضعيف يُحظر؛ وغياب بيانات الجلسات يعني «لا يمكن التقييم بعد» — لا تمرير بالتخمين أبدًا. - إعادة الحساب + المتتبّع + الفئة.
POST …/recomputeيُلحق لقطة جديدة غير قابلة للتعديل (مع قفل احترازي، ثابتة الناتج)؛ وGET …/{bundleAssignmentId}يقرأ الأحدث؛ وGET /api/students/{id}/fidelity-trackerيغذّي تبويب الالتزام لدى المعلّمة؛ وGET /api/fidelity/admin/low-fidelity-cohortيسرد الخطط المُعرَّضة (للمدير). - فقرة بلغة النمو. كل حكم يُصيغ تلقائيًّا فقرة عربية قصيرة لاجتماع المراجعة — مكتوبة بالقواعد لا بالذكاء الاصطناعي — ومُرشَّحة من اللغة السريرية وأطر القياس الدولية ولغة العجز.
- غير قابل للتعديل ومثبَّت بالإصدار (V-6)؛ مُقيَّد بالمعلّمة (B.4)؛ معزول بين المؤسّسات؛ لا يُعرض للطالب أبدًا. الحكم المُخزَّن هو ما تقرؤه الآن بوّابة الالتزام في RTI — فلا انتقالٌ تصاعديٌّ بالتخمين يمرّ عن خطّةٍ لم تُنفَّذ.
غرفة بيانات الطالب — 2026-06-20
خمس عمليات جديدة تحت الوسم الجديد data-room. غرفة البيانات هي طبقة توثيق القرار: تجمع أدلّة الطفل في
ملفّ قابل للمراجعة بحيث تكون القرارات الكبرى موثَّقة ومستندة إلى الأدلّة وقابلة لإعادة التشغيل بعد سنوات.
هي لا تقرّر — القواعد تبقى هي صاحبة القرار؛ وغرفة البيانات تجعل كل قرار حسّاس يُظهر شواهده.
- ملفّ واحد لكل طفل.
GET …/data-roomيعيد ملخّصات الأدلّة الثمانية (المعيار، اتجاه القياس CBM، التدريب، الفحوص الورقية، الصيانة، أنماط الخطأ، الالتزام، إشارات السلوك) + حالة كفاية البيانات. الملخّصات تجميعات يولّدها النظام من أدلّة مُشار إليها — لا نصّ حرّ أبدًا، ولا مُدخَل لأي قاعدة. - الأدلّة مُفهرسة لا منسوخة.
GET …/data-room/evidenceيصفّح فهرس الأدلّة؛ كل صفّ يشير إلى سجلّه الأصلي. أدلّة التطبيق غير الصالحة تبقى مُفهرسة (لا يُحذف شيء) لكنها تُستبعَد من حساب الكفاية. - هيكل حزمة القرار.
POST …/decision-packetsيفتح حزمة، ويلتقط الأدلّة بالإشارة، ويثبّت إصدارات القواعد التي قرأها — فتُعاد الحزمة حرفًا بحرف بعد سنوات. فتح ثانٍ لنفس نوع المراجعة يعيد 409؛ والحزمة المغلقة غير قابلة للتعديل إلى الأبد. - البيانات الضعيفة تمنع القرار القوي. عندما تكون مهارة في حالة
do_not_decide_yet، أو الأدلّة دون العتبة القابلة للمقارنة، يُبلِّغ الملفّ عنinsufficientويوصي بـإجراء البيانات التالي — لا حركة أبدًا. - لا حركة مستوى هنا. غرفة البيانات تقرأ سجلّ قرار المستوى وتؤلّفه؛ لكنها لا تكتبه أبدًا. مسار كتابة المستوى الوحيد يبقى في محرّك RTI.
- لا يرى الطلّاب أيًّا من هذا — لا توجد نقطة وصول للطالب؛ المعلّمة (صفوفها فقط) والمشرف فقط.
محرّك قرارات الاستجابة للتدخّل RTI — 2026-06-20
عشر عمليات جديدة تحت الوسم الجديد rti. هذه هي طبقة القرار المركزية: ترفع التنبيه المناسب على لوحة
المعلّمة، وهي البوّابة الوحيدة التي يمرّ منها أي تغيير في مستوى التدخّل RTI.
- طبقتا تنبيه. الطبقة A هي حالة المهارة الواحدة (
on_track/monitoring/maintenance، محسوبة من محرّك حالة المهارة)؛ الطبقة B هي تنبيه الطالب —Skill_Alert(تنبيه مهارة واحدة)،Student_Alert(يحتاج هذا الطالب خطّة دعم موجَّهة)،Intensive_Review(المراجعة الأعمق). يبقى تنبيه واحد مفتوحًا لكل طالب؛ ويُغلق التنبيه الأشدّ تلقائيًا التنبيهَ الأخفّ. - قواعد حركة المستوى الأربع. كل تغيير في المستوى يمرّ عبر
TM_ESC_01(تصعيد) /TM_MAINT_01(إبقاء) /TM_DEC_01(تخفيض) /TM_BLOCK_01(حظر عند ضعف الالتزام). المحرّك يقترح؛ المعلّمة توافق؛ والأخصّائي (المُجلَس على مقعد المدير في الموجة الأولى) يضبط بوّابة المستوى الثالث.GET …/recommendationيُرجع الحكم الحتمي؛ وPOST …/decisionيُثبّته عبر مسار الكتابة الوحيد المُدقَّق. - الالتزام قبل التصعيد.
TM_BLOCK_01يسبقTM_ESC_01: «الخطّة لم تنجح» و«الخطّة لم تُنفَّذ» حكمان مختلفان. وحتى يصل متتبّع الالتزام، يفشل التصعيد بأمان (محظور) — لا تصعيد بالتخمين أبدًا. do_not_decide_yetيحظر كل شيء. عند عدم كفاية البيانات، لا يُفتح تنبيه ولا يتحرّك مستوى — لأي دور، دون تجاوز. ترى المعلّمة رسالة هادئة «نحتاج بيانات أكثر»، لا إنذارًا أحمر.- لا ضبط مباشر للمستوى أبدًا. يتغيّر المستوى فقط عبر مسار القرار المُبوَّب الذي يكتب سجلّ قرار غير قابل للتعديل في المعاملة نفسها. تستخدم عمليات الصرف رمز سبب مُتحكَّمًا فيه — لا نصّ حرّ. والطلاب لا يرون أيًّا من هذا.
محرّك متابعة الطلاقة CBM / ORF — 2026-06-20
عشر عمليات جديدة تحت وسمين جديدين — orf + cbm (يصبح العدد 129). تقيس المنصّة الآن طلاقة القراءة
وتتابع تحسّنها عبر الزمن.
- تقييم شفوي بتسجيل المعلّمة، بلا ذكاء اصطناعي. تُسجّل
POST /api/orf/assessments/{start, :id/mark, :id/stop}قراءةً شفويّة مدّتها 60 ثانية عبر نقر المعلّمة على الأخطاء (لا تعرّف على الكلام، ولا نموذج لغوي؛ والصوت للأرشفة فقط) ← الكلمات الصحيحة في الدقيقة + الدقّة ← صفّcbm_scoresإلحاقي. - خط الهدف وقاعدة النقاط الأربع. تكتب
POST /api/cbm/probesعيّنةً؛ ويُفعَّل خط الهدف بعد ثلاث عيّنات أساس (الوسيط)، وتُنتِج آخرُ أربع نقاط متماثلة اتجاهًا مُصنَّفًا (trend_above_goal/trend_below_goal/trend_mixed/insufficient_points). تُعيدGET /api/cbm/trend/...السلسلة + خط الهدف؛ وGET /api/cbm/alertsالتنبيهات المفتوحة. - إصدار فقط (V-12). يُصدِر المحرّك الإشارة + تنبيهًا خامًا؛ ولا يطبّق بوّابة الالتزام ولا يكتب رسالة المعلّمة (تلك لـ WP-RTI-BE + متتبّع الالتزام، اللذين يقرآن التنبيه خلف بوّابة ≥80%). والتراجع الحاد يرفع الإشارة دون إخفاقٍ تلقائي. ويستخدم الرفض رمز سببٍ مضبوط — لا نصّ حر.
- النواقص في المعايير صريحة. الصفوف التي لا معيار لها بعد (الأول/الرابع مملوكان للشريك؛ الثاني–الثالث مزروعان) تُسجَّل وتُتابَع على WCPM الخام لكن تُوسَم “غير مُقيَّمة” بدل الحكم عليها بحدٍّ مُختلَق.
محرّك الإحماء الذهني — 2026-06-20
سبع عمليات جديدة تحت الوسم الجديد warmup؛ يصبح العدد 119. هذا هو خادم الإحماء الذهني الذي يستغرق
٣–٥ دقائق قبل جلسة الطالب — إحماء قائم على قواعد، حتميّ، غير لغويّ تمامًا (أشكال وألوان ومسارات — لا كلمات
ولا حروف ولا أرقام إطلاقًا).
- توليد حتميّ ببذرة. عشرة قوالب نشاط من الطبقة الأولى + ٢٤ إعدادًا حسب الصف عبر مولّد مركزيّ واحد؛ النتيجة
لنفس
(القالب، الصف، الصعوبة، البذرة)تمرين متطابق دائمًا (قابل لإعادة التشغيل V-6 عبرPOST /api/admin/warmup/dry-run-replay). - قابل للاستئناف ومحدود.
POST /api/warmup/sessions←…/events←…/complete، مع…/resumeالذي يعيد الطفل إلى نفس خطوة التمرين بالضبط. سقف صامت ٥ دقائق؛ التخطّي بلا عقوبة (لا إعادة محاولة ولا أيّ علامةwarmup_abandoned). - معزول عن القياس — بالتصميم. الإحماء لا يمسّ θ أبدًا، ولا يصدر حدث إتقان، ولا يمنح نقاطًا، ولا يملك أيّ مفتاح خارجيّ إلى أيّ جدول قياس/قرار. حارس رسم بيانيّ للاستيراد + اختبار مفاتيح المخطّط يُثبتان ذلك؛ القياسات إشارة جاهزيّة تُخزَّن في جداول الإحماء وحدها.
- مُتاح للمعلّم/المشرف ومقيَّد بـ ClassTeacher؛ لا توجد واجهة للطالب (يُسلَّم التمرين إلى العارض).
- بانتظار الشريك (٢٥ يونيو): إعدادات COG-05 (المطابقة) + COG-06 (التتبّع البصري) حسب الصف تُشحَن مُعطَّلة؛ حدود الصفوف ومكتبة الأصول SVG قيم عمل افتراضية منقولة.
واجهات تشخيص الطالب والتدريب — 2026-06-20
عشر عمليات جديدة تحت وسمين جديدين — diagnostic-session (٦) + practice (٤)؛ يصبح العدد 112. هذا هو
جانب الطالب من حلقة الاستجابة للتدخّل: يخضع الطفل لتشخيص ثم يتدرّب تكيّفيًّا.
- التشخيص (WP-04).
POST /api/diagnostic-sessions/start← تقديم عنصر ←…/responses←…/finish، حسب الصف (الصف الأول صوت-أولًا، مرتبطًا بصف الطالب نفسه — لا بصف الفصل). حفظ/استئناف لمدة ٢٤ ساعة (رمز حالة موقَّع جذر الثقة فيه هو إعادة تحقّق الملكية من الخادم)، وسقف وقت نشط ١٥ دقيقة (لا تُحتسب التوقّفات وإعادة تشغيل الصوت). يصحّح الخادم كل إجابة ويسلسل θ بنفسه — فلا يستطيع الطالب تزييف الصواب أو توجيه درجته. يجري التقدير عبر المحرّك، وتقديم العناصر عبر خدمة التسليم. - التدريب والاختبار التكيّفي (WP-05). تبني
POST /api/practice/queues/seed/:diagnosticSessionIdطابورًا من التشخيص؛ وتختار…/current/next-itemالعنصر الأكثر إفادة عند θ±0.5؛ وتُقدّر…/submit-responseالإجابة. ضبط الصعوبة لكل كتلة (80/60) مفعَّل، ويعدّل نطاق صعوبة دائمًا لكل (طالب × مهارة فرعية) يُحمَل عبر الجلسات (يستأنف الطالب عند المستوى الذي بلغه). تلميح SOLO عند الخطأ. - آمن للطالب بالتصميم. كل ردّ يظهر للطالب يُسلسَل بقائمة سماح — لا تصل θ / تسمية حالة / ملف / حزمة / مستوى سقالة / دقة إلى الطالب أبدًا. محصور بطالبه (لا يمسّ إلا جلسته)؛ والمعلّمة تقرأ ملخّصات جلسات صفّها فقط.
- ذاكرة المتصفّح واستعادة الاضطرابات الخمسة تغييرٌ أمامي لاحق؛ والخادم يشحن عقد الاستئناف ويختبره. مفردات فئات الأخطاء وأرقام عتبات 80/60 الدقيقة مملوكة للشريك (٢٥ يونيو)، مبنيّة خلف افتراضات عمل موثّقة.
خدمة PDF لولي الأمر — 2026-06-20
عملية واحدة جديدة تحت وسم parent-pdf الجديد (يصبح العدد 113). تستطيع المعلّمة الآن تصدير تقرير نموّ
موجّه لولي الأمر كملفّ PDF عربي بحجم A4 ومن اليمين إلى اليسار — تركيب للقراءة فقط، دون أي منطق قياس أو
قرار، ودون كتابة، ودون جدول جديد.
- النقطة. تُعيد
POST /api/parent/pdf/:childIdملفّ الـPDF مباشرةً (A4، عربي RTL، خطّ المتن ≥ 12 نقطة، ≤ 500 كيلوبايت، وأقلّ بكثير من حدّ الـ30 ثانية). تُطلَق من المعلّمة أو المشرف؛ ولا تُعرض للطالب أبدًا. - أصرم طبقة سلامة في المنصّة. كل نصّ يمرّ عبر مرشّح أولياء الأمور الأكثر صرامة + تجريد حقول مُمَوْضَع: لا يرى وليّ الأمر أي أرقام أو نسب مئوية أو درجات أو رموز داخلية — لغة نموّ فقط (V-3/V-12).
- الفشل المغلق. الطالب بلا تقرير مُحلَّل ← صفحة “نحتاج بيانات إضافية” صريحة، لا ملفّ مُلفَّق أبدًا. وعند
تعذّر مجموعة قواعد السلامة ←
503بدل إخراج نصّ غير مُرشَّح. - عربية تُسافر. الخطّ العربي (Noto Naskh، مضمَّن) يُشحَن داخل الملفّ، فيُعرَض الـPDF بشكل صحيح عند المشاركة (عبر واتساب مثلًا) أيًّا كانت خطوط جهاز المستلِم. محتوى حتمي (V-6)؛ ولا نموذج لغوي (V-5).
واجهات تقرير المهارات الفرعية — 2026-06-20
ثلاث عمليات قراءة فقط تحت وسم reporting الجديد (يصبح العدد 112). هذه طبقة القراءة التي تحوّل
أحكام المحرّكات المُخزَّنة إلى تقارير موجّهة للمعلّم والمدير — لا تضيف أيّ منطق قياس أو قرار، ولا تكتب شيئًا.
- تقرير الطالب. تُعيد
GET /api/reports/students/:id/sub-skill-reportحمولة واحدة بخمسة أقسام: الملف التعليمي (مع السرد الجاهز للمعلّم)، بلاطات المجالات الكبرى، حالات المهارات الفرعية مرتَّبة “يحتاج تدخّل” أوّلًا، خطة التدخّل النشطة، وأي تنبيهات مفتوحة. الطالب بلا بيانات يُعيد ملفًّا بحالةdataIncomplete(استجابة 200، لا تقرير مُلفَّق أبدًا). - ملخّص الصف. تُعطي
GET /api/reports/classes/:id/class-summaryللمعلّم عدد الطلاب لكل حالة لكل مهارة فرعية + تجميع المجال الكبير للصف (الأسوأ يَغلِب) + صفوفًا لكل طالب في صفوفه هو (عبر وصلة ClassTeacher). مع?audience=managerتتحوّل إلى عرض تجميعي فقط بلا أسماء أو معرّفات طلاب. - مرجع النطاقات. تُعيد
GET /api/reports/band-descriptionsكتالوج “ميزان” بخمسة نطاقات، مُخزَّن 24 ساعة (التسميات قيم افتراضية بانتظار اعتماد الشريك). - السلامة. لا نسبة مئوية إجمالية (V-3)؛ كل نصّ يمرّ عبر مُرشِّح سلامة اللغة (V-12)؛ كل استعلام محصور بالمؤسسة (عبر المؤسسات ← 404)؛ لا نموذج لغوي (V-5). للمعلّم (عبر ClassTeacher) والمدير فقط.
محرّك التشخيص (تقدير القدرة θ) — 2026-06-20
أربع عمليات جديدة تحت وسم engine الجديد (يصبح العدد 96). هذا هو قلب القياس: يحوّل إجابات الطالب
التشخيصية إلى تقدير للقدرة (θ) ويختار السؤال الأنسب التالي.
- التقدير. تأخذ
POST /api/engine/scoreإجابات الطالب + θ سابقة وتُعيد{newTheta, newSE, calibrationVersion, nextItemId, calibrationProvisional}. كل عملية تقدير تُسجَّل كصفّDiagnosticSessionإلحاقي فقط. القراءات/الكتابات محصورة بالمؤسسة؛ وتتطلّب صلاحيةUSE_DIAGNOSTIC_ENGINE، ولا يمكن لرمز الطالب أن يُقدِّر إلا إجاباته هو. - حتمي وقابل لإعادة التشغيل (V-6). المدخلات نفسها ← θ متطابقة حرفيًا إلى 4 منازل عشرية. كل جلسة تُجمِّد
صعوبات الأسئلة المستخدمة فعليًا (
resolvedDeltas)، فتُعيدPOST /api/engine/replay/:sessionIdإنتاج التقدير الأصلي دائمًا — حتى بعد أن يُحدِّث خطُّ المعايرة تلك الصعوبات لاحقًا. - صعوبة بمسارين. تُعتمَد الصعوبة المقيسة للسؤال متى بلغ ≥300 إجابة حقيقية (وطابق إصدار المعايرة المثبَّت للجلسة)؛ وإلا تُستخدم الصعوبة المقدَّرة الحتمية ويُوسَم الصفّ مبدئيًا.
- لا نموذج لغوي إطلاقًا (V-5). مسار التقدير بأكمله دالة حتمية صرفة — يغطّيه فحص CI لمنع النماذج اللغوية +
تجسّس تكاملي. عند نقص البيانات ←
newTheta:null(استجابة 200، أي «لا تقرّر بعد»). - القراءات:
GET /api/engine/sessions/:id+GET /api/engine/sessions/by-student/:studentId. تقدير الموجة الأولى بديل حتمي مؤقّت، لا إحصاء راش الحقيقي — يحلّ المحرّك الإحصائي الحقيقي لاحقًا (خطّ المعايرة) دون أي تغيير في العقد.
سجلّ فحوصات الجودة في النظام — 2026-06-20
أربع عمليات تحت وسم qa الجديد (يصبح العدد 92). يسجّل سجلٌّ من 32 فحصًا الثوابتَ الأمانية الشاملة
التي تفرضها محرّكات القرار والتدخّل والمحتوى فعلًا — تتولّى هذه الطبقة التسجيل والتوجيه فقط؛ لا تضيف أي
منطق فحص جديد.
- مراقبة للمشرفين/الهندسة فقط. تُعيد
GET /api/qa/checksسجلّ الـ32 فحصًا؛ وتُدرجGET /api/qa/runtime-alertsالتنبيهاتِ الموجَّهة في وقت التشغيل لمؤسستك (بترشيح حسبseverityأو النافذة الزمنية أوqaCheckId)؛ وتُلخّصهاGET /api/admin/qa/audit-summaryحسب الفحص والخطورة. وتتطلّب جميعها صلاحيةVIEW_QA_REGISTRY(أو المشرف الأعلى/الواجهة الخلفية) — ولا يصل إليها رمز معلّمة أو طالب أبدًا. - توجيه حتمي. يُوجَّه فشلُ فحصٍ في وقت التشغيل وفق خطورته المسجَّلة فقط — الحرِج يظهر على لوحة المعلّمة وينبّه قناة التنبيه، والعالي ينبّه الهندسة، والمتوسّط يسجّل التنبيه، والمنخفض يسجّل فقط. ويُثبَّت على كل تنبيه موجَّه نسخةُ السجلّ والقاعدة لإعادة التشغيل.
- لا حوض تنبيهات جديد. تُلحَق التنبيهات الموجَّهة بسجلّ تنبيهات المنصّة القائم (إلحاق فقط)؛ ولا تُعيد قراءةُ الـQA أي صفوف تنبيه غير خاصة بالـQA.
- جديد —
POST /api/admin/qa/checks-set(نشر نسخة جديدة من السجلّ). للمشرف الأعلى/الواجهة الخلفية فقط. يماثل نشر إعدادات الحزمة ومحرّك القرار: يأخذ مجموعة فحوص مرشَّحة مع موافقة الشريك وإقرار الفروقات، ويُجري بوّابة اكتمال (وجود الفحوص الـ32 جميعها، وقابلية كل أمر للتشغيل، وأمان كل رسالة عربية)، ثم يُعيد النسخة المرتقَبة — رافضًا النقصَ أو غياب الموافقة أو عدم إقرار الفروقات. - جديد — حارس الإفراط في القياس QA_032. تنبيهٌ متوسّط الخطورة (وليس حجبًا أبدًا) يُطلَق عندما يُقاس الطالب مرّاتٍ كثيرة في فترة قصيرة — تُسجَّل جلسة القياس دائمًا، ويكتفي التنبيه بتذكير المعلّمة بالتدريس قبل قياسٍ إضافي. عتبةُ الإفراط ونافذتُه قابلتان للضبط من الشريك (قيمٌ افتراضية مؤقتة بانتظار جلسة الشريك في يونيو).
طبقة سلامة اللغة — 2026-06-20
ستّ عمليات جديدة تحت وسم language-safety الجديد (يصبح العدد 102). طبقةُ إعادة الصياغة الحتميّة القائمة على
القواعد، توضَع أمام كل نصٍّ يعرضه النظام أو يحفظه أو يطبعه — تحوّل العبارات السريريّة/عبارات العجز إلى لغة نموّ،
وتحذف مسمّيات الأطر الدوليّة، وتطبّق مرشّحًا أكثر صرامةً لجمهور أولياء الأمور. هي ليست نموذجًا لغويًا (V-5)
ولا تغيّر أي قيمة قياس — بل تغيّر طريقة وصفها فقط (V-3/V-12).
- تحقّقي من أي نص. تُشغّل
POST /api/language-rules/validateالدالّةsanitize(text, appliesTo, profileKey?)وتعيد النصّ الآمن + القواعد التي طُبّقت + رقم نسخة مجموعة القواعد (إعادة تدقيق V-6). المستويات:ui / reports / parent / parent_stricter / teacher_note / student / admin. ويمنع مستوى parent_stricter الدرجاتِ الرقميّة والمعرّفاتِ الداخليّة؛ وتُطبَّق طبقةdo_not_sayالخاصّة بكل ملف عند العرض. - إدارة القواعد للمشرف. تُعيد
GET /api/language-rulesمجموعة القواعد الفعّالة (تُستهلك عند تحميل النصوص في التطبيق ومولّد PDF)؛ وتُدرِجPOST /api/language-rulesنسخةً جديدة (إلحاق فقط — يُعطَّل الصفّ السابق ولا يُعدَّل في مكانه)؛ وتُحيلPATCH /api/language-rules/{id}/deactivateصفًّا إلى التقاعد. - أعلام سياق مضبوطة فقط. تُرفِق
POST /api/students/{id}/context-flagعلمًا مضبوطًا من قاموسٍ مغلق — لا يوجد حقل نصّ حرّ في الجسم؛ والعلم المحظور/الممنوع يُعيد422 context_flag_blockedويُسجّل قيدَ تدقيقٍ أمنيًّا يحفظ الطولَ فقط (لا يُخزَّن أي نصّ عن الطفل أبدًا). وتُعيدGET /api/students/{id}/context-flagsالأعلامَ المسجّلة بمسمّياتها الآمنة (للمعلّمة/المشرف فقط). - الفشل المغلق. أي عرضٍ يتعذّر فيه تحميل مجموعة قواعد فعّالة يرفض بدلًا من إخراج نصٍّ غير مُرشَّح.
العمود الفقري للمعايير + الإدارة الديناميكية لمستويات الكفاية — 2026-06-20
ثماني عمليات جديدة تحت وسم standards الجديد (يبلغ عدد العمليات الآن 110). هكذا تتحوّل الدرجة الخام إلى
«ضمن المسار / يقترب / دون المستوى / حرِج» — وكيف تُدار هذه العتبات دون تعديل الشيفرة.
- مفردات حُكمٍ واحدة، ولا درجة إجمالية أبدًا (V-3). كل مقياس يُحَلّ إلى إحدى القيم
meets / approaching / below / severe / not_assessed. القيمةnot_assessedلا تُعامَل كصفر أبدًا وتُستبعَد من أي تجميع. لا توجد «درجة قراءة إجمالية» في أي مكان. - العتبات تعيش في البيانات، مُصدَّرة، وقابلة للتبديل. يسير
GET /api/standards/benchmark-profiles/resolveعبر سلسلةٍ حتميّةٍ من ثلاث خطوات (مطابقة دقيقة ← افتراضي للدولة ← احتياطي عالمي) ولا يُعيد قيمةً فارغةً أبدًا — فصفٌّ عالميٌّ مزروعٌ يضمن الحلّ. يدير المشرفون العامّون الصفوف تحت/api/admin/benchmark-profiles؛ والتفعيل تبديلٌ ذرّيٌّ (تُعطَّل النسخة القديمة وتُفعَّل الجديدة، وكلاهما مُدقَّق). - التاريخ لا يتبدّل أبدًا (V-6). تثبّت الجلسةُ نسخَ معاييرها عند البدء؛ والتبديل اللاحق لا يغيّر أحكام الجلسات الجارية، وكل نتيجةٍ مخزَّنةٍ تُعيد اشتقاق حالتها الأصلية إلى الأبد.
- صفر تسميات أُطُر دولية (FR-STD-1). المعايير الدولية (المستخدَمة فقط لمعايرة عتبات العربية) تُجرَّد عند طبقة التسلسل — لا تصل أبدًا إلى واجهة معلّمٍ أو مديرٍ أو وليٍّ أو طالب. لوحة المدير تتحدّث بمسمّيات مؤشّرات المنهاج العربية فقط.
- قراءات المدير + نموذج تقرير الوزارة. يُعيد
GET /api/principal/schools/:id/{overview,heatmap}مقاييس مؤشّرات المنهاج + مؤشّر صحّة القرائية للمدرسة المحسوب (دون بيانات شخصية). تقرير الوزارة بنقرةٍ واحدةٍ مُسجَّلٌ كنموذج عقدٍ للموجة الأولى (501)؛ ويصل ملفّ PDF في الموجة الثانية.
أرقام مستويات الكفاية مملوكةٌ للشريك (مستخرَجة من مصنّف v3.3 — الأردن وفلسطين)؛ وصفوف الاحتياطي العالمي +
صياغة مسمّيات مؤشّرات المنهاج مُعلَّمةٌ كقيمٍ افتراضيةٍ مؤقّتةٍ بانتظار جلسة الشريك في 25 يونيو. الترحيل:
20260620150000_wp_std_be. وثيقة المتطلّبات: 12-benchmarks-and-country-config (FR-STD-1..6).
سير عمل تفعيل المعلّمة — 2026-06-20
سبع عمليات جديدة تحت وسم workflow الجديد (يصبح العدد 88). يقود سيرُ عملٍ من 17 خطوة المعلّمةَ عبر
المراجعة ← التجميع ← التفعيل ← المتابعة ← القرار، مُركّبًا محرّكات الحزمة والتجميع والمتابعة في تدفّقٍ موجَّه
واحد.
- المعلّمة تقرّر، والنظام يمنع الخطوات غير الآمنة (V-12). لا تُفعّل
POST /api/workflow/activateخطّةً حالتهاdo_not_decide_yet، وتُرفض أي نقلة حياة غير صالحة (409). ولا يُغيَّر مستوى RTI بأي إجراء سير عمل. - حواجز الأمان عند الحدود. الأدلة غير الكافية ← مطالبة، لا تفعيل؛ وتنبيه التراجع الحاد المفتوح يفرض مسار
المراجعة (تحلّه
POST /api/workflow/reviewبتصرّفٍ صريح من المعلّمة)؛ والطالبDATA_INCOMPLETEيُستبعد من التفعيل المجمّع. - التعديلات لكل عضو مقصودة. أي تغيير لمستوى السقالة / التسليم / الجدولة عن التوصية يتطلّب تأكيدًا صريحًا (وإلا 409) ورمز سببٍ مضبوط — لا نصّ حر.
- لا مسار بيانات جديد. تمرّ آثار سير العمل عبر مسارات الكتابة القائمة (التفعيل/التجميع/المتابعة)؛ وتُختم
خطوة سير العمل المُطلِقة على تاريخ الإسناد. وتحفظ
POST /api/workflow/save-draftسير عملٍ قيد التقدّم (7 أيام)، يُستعاد عبرGET /api/workflow/draft/:teacherId/:classId. - أيضًا: لم يعد ردّ تنبيه التراجع الحاد يتضمّن
contextFlagId— يُسجَّل علم سياق الرفض في سجلّ أعلام السياق فقط (الموطن المعتمد الوحيد).
السجلّات والرصد — 2026-06-20
عمليتان جديدتان تحت وسم logging الجديد (يصبح العدد 81). تُكمل عقد السجلّات في المنصّة فوق نواة
المُسجِّل وربط المعرّفات الذي شُحن سابقًا.
POST /api/logs/client— يُرسل المتصفّح سجلّات التحذير والخطأ إلى الخادم (تحذير/خطأ فقط؛ بحدّ دفعة واحدة لكل مستخدم كل 5 ثوانٍ). يَختم الخادمuserId/orgId/tsمن الهويّة الموثّقة — لا من جسم الطلب أبدًا — فلا يستطيع العميل تزييف صاحب السطر أو مؤسّسته. ونقطة الاستقبال لا تُسجّل نفسها عمدًا (حارس الحلقة اللانهائية).GET /api/health/log-level— فحص تشغيلي بلا مصادقة يُعيد مستوى السجلّ العام الفعّال وأي تجاوزات لكل وحدة، ليتأكّد المشغّلون ممّا يعمل به النشر دون إعادة نشر.- لا تغيير في المخطّط. السجلّات شأن تشغيلي؛ وحفظ سجلّات العميل سؤال للموجة الثانية.
خدمة تسليم المهام — 2026-06-20
أربع عمليات جديدة تحت وسم delivery الجديد (يصبح العدد 79). هذا ما يحدث وقت الطالب: تختار المنصّة العنصر
المُؤلَّف مسبقًا المناسب وتقدّمه كما هو مخزَّن تمامًا — ولا تُركّب المحتوى أثناء التشغيل أبدًا.
- الاختيار والتقديم. تُرشّح
POST /api/delivery/taskبنك العناصر التشغيلي وفق(المهارة الفرعية × مستوى السقالة × نمط المهمة × الصعوبة × اللهجة)، وتختار حتميًا، وتُعيد العنصر المخزَّن. وهي نقطة التقديم الوحيدة التي يستدعيها كل مستهلك (التشخيص، التدريب، عيّنات المتابعة، نموذج السقالة المتكامل) لكل مهمة. - لا ارتجال. المجموعة الفارغة من المرشَّحين تُعيد
200 { served: null, log.reason: "no_eligible_item" }— لا خطأ ولا بديل صامت أبدًا. المُستدعي يقرّر تجربة الاستخدام؛ وتتجمّع الفجوة فيGET /api/admin/delivery/gap-summary(حسب المهارة الفرعية × المستوى × النمط) لتخطيط حجم المحتوى. - المستوى والنمط مُرشِّحات، لا مفاتيح عرض. متغيّرات كل مستوى صفوف مخزَّنة مستقلة؛ وعيّنات المتابعة تتجاهل المستوى ولا تُظهر تلميحات أو تغذية راجعة أثناء العيّنة (سلامة العيّنة). ولا يرى الطالب أبدًا تسمية ملف أو حزمة أو مستوى.
- حتمي وقابل للتدقيق. كل تقديم يكتب صفًّا إلحاقيًا في
served_task_instanceمفتاحهtaskInstanceIdمن نوع UUID (رمز ربط ورقة العمل عبر QR)، يُثبِّت مدخلات اختياره؛ وتُعيدPOST /api/admin/delivery/dry-run-replayالتأكيد على الاختيار نفسه (V-6) دون أن تكتب شيئًا. ولا نموذج لغوي على مسار التقديم (V-5). - نافذة “المُقدَّم حديثًا” (الافتراضي للموجة الأولى 7 أيام) ونصوص التغذية الراجعة لكل نمط مملوكة للشريك
(25 يونيو)؛ واستبدال المعلّمة بمستوى أدنى مؤجَّل (الافتراضي
no_eligible_item).
قواعد متابعة التقدّم — 2026-06-20
ثلاث عمليات جديدة تحت وسم monitoring الجديد (يصبح العدد 75). تتابع المنصّة الآن ما إذا كان التدخّل
ناجعًا وتطلق مراجعةً عند تراجع الطالب.
مواءمة المواصفات وإصلاحات — 2026-06-20
جولة صيانة — دون عمليات جديدة (يبقى العدد 75). تغييران ظاهران لمستهلك الواجهة، إضافةً إلى تصحيحاتٍ في مجموعة المواصفات وفي الاختبارات.
-
المؤسّسات تُعيد الآن
createdBy. يتضمّن كل ردٍّ منGET /api/organizations/…/{id}حقلcreatedBy(مُعرّف المستخدم للمشرف الأعلى الذي أنشأ المؤسّسة) — القيمة كانت مُخزّنة أصلًا عند الإنشاء، وأصبحت الآن مكشوفة (FR-TEN-1). وحُدِّث مخطّطOrgResponseفي مرجع الواجهة وفقًا لذلك. -
تصحيح إشارة حالة المجال. تُعيد
GET /api/sse/students/{id}/domain-statusالآن إشارةdoNotDecideYetالمُخزَّنة بدل اشتقاقها وقت القراءة، التزامًا بعقد المستهلك FR-SSE-16 «مُخزَّنة لا تُشتَقّ» (وهو ما كان يحدث أصلًا في نقطة حالة المهارة). وعلى المستهلكين ما زال يلزم التحقّق منdoNotDecideYetقبل التصرّف. -
مسارات التصنيف توثّق
401. أصبحت مسارات القراءة الأربعة (GET /api/sub-skillsو…/{id}و/api/domainsو/api/skill-dependencies) تُصرّح بردّ401(غير موثَّق) الذي كانت تُعيده أصلًا. -
داخلي فقط. يكتسب
gateway_priority_configعمود تدقيقpublished_at(ترحيل20260620120000)؛ ومواءمات في مجموعة المواصفات داخل11-skills-taxonomy(15 نوع عنصر نشط، سطح واجهة التصنيف بأربعة مسارات، عدد SENT/SYN 12، تعريف العرض العادي)، وتصحيح مرجعَي FR-ID متقاطعَين، وتغطية اختبارية إضافية لفروع فشل فحوص request-id والإلحاق-فقط / context-flag. -
تسجيل أدلة التقدّم. تُسجّل
POST /api/monitoring/evidenceأنواع الأدلة غير-CBM (فحص سريع، روبرِك، ملاحظة المعلّمة، ورقة عمل، اتجاه رقمي) مع ظروف التطبيق؛ السجلّ إلحاقي فقط ويُطلق إعادة حسابٍ حتمية مثبَّتة على إصدار القاعدة (V-6). -
خمس قواعد سلامة تحكم كل قرار. الأدلة غير الكافية أو غير القابلة للمقارنة ←
do_not_decide_yet؛ لا قرارات من نقطة واحدة؛ لا تُقارَن إلا الفحوص المتماثلة. التراجع الحاد (هبوط ≥20% عبر جلستين متماثلتين) يطلق مراجعةً فوريّة — دون إخفاقٍ تلقائي أو خروجٍ تلقائي أو تغيير مستوى RTI (المعلّمة هي من تقرّر). -
الحالة والتنبيهات. تُعيد
GET /api/monitoring/status/{bundleAssignmentId}الحكم الحالي + إصدارات القواعد المثبَّتة؛ وتسردGET /api/monitoring/alertsتنبيهات التراجع الحاد المفتوحة. ولا يُغلَق التنبيه إلا بتصرّفٍ صريح من المعلّمة عبر رمز سببٍ مضبوط — لا نصّ حر. -
إغلاق جسر سلامة التجميع الذكي. يقرأ التجميع الآن تنبيه التراجع الحاد الحقيقي (كان يفشل-مفتوحًا)، فيُوجَّه الطالب المتراجع إلى مراجعة فردية ويُبقى خارج المجموعات.
التجميع الذكي والتفعيل المجمّع — 2026-06-19
ثلاث عمليات جديدة تحت وسم cluster الجديد (يصبح العدد 72). تجمّع المعلّمة الطلاب الذين يحتاجون الدعم
نفسه في مجموعات صغيرة وتفعّل المجموعة كاملةً بإجراءٍ مؤكَّد واحد.
- تجميع حتمي. تجمّع
POST /api/cluster/recompute/:classIdالصف بمطابقة من 5 مفاتيح (الحزمة + المرساة + مستوى السقالة + نمط التسليم المتوافق + كفاية البيانات)؛ ويندمج المستوى 1 + المستوى 2 للتسليم بقيادة المعلّمة فقط؛ الحد الأدنى لحجم المجموعة 2 (مفتاح المدرسة 3–5). النتائج إلحاقية فقط ومثبَّتة على إصدار قاعدة التسلسل (حتمية V-6)، مع احتفاظ 60 يومًا. - استثناءات السلامة صارمة. الطالب
DATA_INCOMPLETE/do_not_decide_yet← قائمة “بيانات إضافية مطلوبة”؛ والطالب ذو التراجع الحاد ← مراجعة فردية. ولا يُجمَّع أيٌّ منهما أو يُفعَّل ضمن مجموعة أبدًا. - التفعيل المجمّع (V-12، يعيد استخدام مسار الكتابة الوحيد). تتطلّب
POST /api/cluster/bulk-activateتأكيد المعلّمة الصريح، وتنشئ إسناد كل عضو عبر الكاتب نفسه الذي يستخدمه التفعيل الفردي (مختومًا بمعرّف المجموعة)؛ الكل-أو-لا-شيء (عضو مستثنى ← 422)، وعديم التأثير عند التكرار، و409 عند مجموعة قديمة. ويبقى التمايز في إسناد السقالة لكل طالب فقط. - معاينة. تُعيد
GET /api/cluster/student/:studentId/previewالمجموعة الحالية للطالب + توزيع السقالة لكل مستوى؛ دون أي تفاصيل تظهر للطالب. - يقرأ استثناء
acute_regressionجسرًا يفشل-مفتوحًا حتى تنتج WP-PROG-MON-BE الإشارة؛ ومُجدوِل إعادة الحساب الليلي جسرٌ (تُشحن دالة إعادة الحساب عديمة-التأثير الآن).
فهرس حزم التدخّل — 2026-06-19
يصل مُوصِّي الحزم. إحدى عشرة عملية جديدة تحت /api/bundles و/api/assignments و/api/students/:id
و/api/admin/bundle-* (يصبح العدد 69). يحوّل ملف الطالب إلى حزمة تدخّل واحدة موصى بها من فهرس مغلق
يضم 20 حزمة، ويُسنِد دعم السقالة، ويسلّم المعلّمة تفعيلًا بنقرة واحدة.
- توصية حتمية. تربط
POST /api/bundles/recommendالملف النشط (الرمز الأساسي + المحرّك/المعدّل) عبر خريطة الملف↔الحزمة المكوّنة من 21 صفًّا إلى حزمة واحدة بالضبط — مهارة مرساة + 1–2 خيط داعم + جسر أصول مدعوم بالبيانات، مع بقاء المرساة دائمًا أكبر حصة جرعة. - الحزمة توصية لا تفعيل تلقائي (V-12). تتطلّب
POST /api/students/:id/activate-bundleالمعلّمة؛ ودورة حياة الإسناد ذات الـ14 حالة إلحاقية فقط ومُظلَّلة بالتاريخ. تستخدم التعديلات (PATCH …/scaffold-assignment | …/delivery | …/scheduleوPOST …/context-flag) رموز أسباب مضبوطة فقط — لا نصّ حر — ولا يمكن لأي تعديل تغيير مستوى RTI إطلاقًا. - توقّف آمن. لا ملف نشط / DATA_INCOMPLETE /
do_not_decide_yet⇒blocked_insufficient_evidenceمع إجراء بيانات تالٍ موصى به، لا حزمة. ولا يمكن لأي دور التجاوز. - لا يرى الطالب أبدًا معرّف الحزمة أو اسمها أو رمز الملف أو وسم مستوى السقالة — يُحذف عند التسلسل.
- المشرف.
POST /api/admin/bundle-config-sets(نشر + بوابة اكتمال)؛ وPOST /api/admin/bundle-replay(تشغيل تجريبي للفرق V-6 دون كتابة). تصل نقاط التجميع الذكي والتفعيل المجمّع مع WP-CLUSTER-BE.
تحديد ملف الطالب التعليمي — 2026-06-19
يصل محرّك الملفات التعليمية. ست عمليات جديدة تحت /api/profile و/api/admin/profile-* (يصبح العدد
58). يركّب مخرجات محرّك حالة المهارة في ملف تعليمي واحد مُسمّى لكل طالب لكل نافذة قياس، مع سرديات
عربية مكتوبة بالقواعد لكل جمهور.
- قراءة ملف الطالب. ترجع
GET /api/profile/{studentId}?window=الإسناد النشط أو المعلّق — الرمز الأساسي والمحرّكات والمعدّلات والثقة وتثبيتات إصدارات القواعد وassignmentStatus(ليعرض العميل مسار «معلّق ← تأكيد»). وعند نقص الأدلة تُرجِع حارس DATA_INCOMPLETE المنظَّم (200)، لا ملفًا. - السرديات لكل جمهور وآمنة. ترجع
GET /api/profile/{studentId}/narrative?audience=teacher|parent|adminالنصّ المُصفّى مسبقًا بفلتر سلامة اللغة.audience=studentمرفوض (422) — لا يتلقّى الطالب أبدًا رمز ملف أو أي درجة رقمية؛ ولا تحمل سردية ولي الأمر أي معرّفات داخلية. - المعلّمة تقرّر (V-12). يبدأ كل تحديد جديد بحالة
pending_teacher_review؛ وتقومPOST /api/profile/{studentId}/review-resolutionمع{ outcome: confirm }بترقيته إلىactive. ملف أساسي واحد نشط لكل نافذة؛ وكل تغيير صفّ جديد لا يُعدَّل. - توقّف آمن. إذا كانت أي مهارة مساهِمة
do_not_decide_yetأو نقصت تغطية مجال مطلوب، لا يُكتب ملف — ولا يمكن لأي دور تجاوز ذلك. - المشرف. تُشغّل
POST /api/admin/profile-catalog/publishبوابة اكتمال الفهرس (لكل رمز أساسي تغطية CDP/PGA/SPOT)؛ وPOST /api/admin/profile-replayتشغيل تجريبي للفرق (V-6) دون أي كتابة.
تصنيف المهارات: إضافة VOCAB-C06 (79 مهارة) — 2026-06-19
اعتماد الشريك لربط معرّفات المهارات الفرعية. يرتفع فهرس المهارات من 78 إلى 79: تُرجِع
GET /api/sub-skills الآن المهارة VOCAB-C06 (فهم المرادفات) ضمن مجال المفردات VOCAB. لا عمليات
جديدة (يبقى العدد 52).
- مهارة جديدة
VOCAB-C06فهم المرادفات. يغطّي مفهومVOC_RELالآن الأضداد (VOCAB-C05) والمرادفات (VOCAB-C06) معًا. - توحيد أسماء المؤشرات. مؤشر الكتابة/الإملاء أصبح
WR_SP_ALERT(بدلWRITING_SPELLING_ALERT)؛ وAR_LETTER_CONFUSION_FLAGيقتصر على الخلط البصري/الإملائي فقط. - نطاق الميزات العربية (المرحلة الحالية). تأتي إشارات المدّ/الحركات القصيرة من بنود مكتوبة/بصرية فقط (لا من نوع خطأ القراءة الجهرية)؛ ولا تفتح الهمزة/الشدة/التنوين أي حزمة أو تنبيه في هذه المرحلة.
محرّك حالة المهارة — 2026-06-19
يصل محرّك القرار. سبع عمليات جديدة تحت /api/sse (يصبح العدد 52): خمس نقاط قراءة فقط للمستهلكين
ونقطتان للمشرف.
- قراءة الحالة التفسيرية للطالب. ترجع
GET /api/sse/students/{id}/skill-statusو/domain-statusأحدث لقطة لكل(مهارة فرعية|مجال، نافذة قياس)، وتحمل كل منها معرّفات وإصدارات القواعد المطابِقة (لإعادة التشغيل) وإشارةdoNotDecideYet. وتغذّي/pattern-classificationsو/behavior-logشرح «لماذا هذه الحالة» وشاشة مراجعة المعلّمة. جميعها محصورة بالمستأجِر، للقراءة فقط، بصلاحيةVIEW_STUDENT_PROGRESS— ولا تُعرض أي قيمة حالة للطالب إطلاقًا. do_not_decide_yetتوقّف صارم. حين تكون الأدلة قليلة أو متضاربة أو متدنّية الجودة يرفض المحرّك الحسم ويُصدر الإشارة؛ على المستهلكين التوقّف فورًا (لا ملف، لا حزمة، لا تنبيه، لا حدث إتقان) — ولا يمكن لأي دور تجاوزها.- تُحسب الحالة في الخادم لا عند الطلب. لا توجد نقطة «احسب الآن» للعميل؛ تُعاد الحالة عند وصول دليل جديد. تُرجع القراءات اللقطة المخزّنة — ولا يعيد المستهلكون اشتقاقها.
- المشرف (نشر القواعد).
POST /api/sse/admin/rules/{layer}/publish(تحقّق من المخطّط + استثناء الدقّة العربية + كشف الصفوف المتداخلة + فرق التشغيل التجريبي، بحاجة موافقة الشريك) وPOST /api/sse/admin/dry-run-replay. نشر إصدار قاعدة جديد لا يغيّر اللقطات القائمة بأثر رجعي — تبقى مثبّتة على إصدار وقت حسابها.
مُعرِّف ربط الطلب — 2026-06-19
صارت كل استجابة تحمل مُعرِّف ربط X-Request-Id، ويقبل الخادم مُعرِّفًا واردًا. لا عمليات جديدة؛ العدد
كما هو (45).
- صار
X-Request-Idمقبولًا واردًا. إذا أرسلت ترويسةX-Request-Idمطابقة للنمط^[A-Za-z0-9_-]{8,128}$، يعتمدها الخادم حرفيًا في الاستجابة؛ وإلا يولِّد واحدًا (req_<hex>). أرسِل مُعرِّفك الخاص لربط أثر العميل بسجلات الخادم لذلك الطلب. X-Request-Idمكشوف عبر CORS. صار بإمكان عملاء المتصفح على أصل مسموح قراءة الترويسة من الاستجابة (Access-Control-Expose-Headers: X-Request-Id) — سجِّلها في جهة العميل واذكرها في بلاغ الخطأ.- داخليًا (دون تغيير في العقد): يُربط المُعرِّف تلقائيًا بكل سطر سجل في الخادم ويُحفظ على صفوف النشاط/التدقيق التي ينتجها الطلب (أحداث المصادقة، تجاوز المشرف الأعلى، سجلات استيراد العناصر وδ_prior)، فيتمكّن الدعم من الانتقال من مُعرِّف مُبلَّغ ← سجلات الخادم ← تغييرات قاعدة البيانات لطلب واحد.
المحتوى — 2026-06-19
إضافات على محتوى بنك العناصر ومخططه تمهيدًا للتجربة الميدانية. لا عمليات منشورة جديدة؛ العدد كما هو (45) — إذ تبقى واجهات بنك العناصر والاستيراد غير منشورة بعد.
- مجموعة محتوى بذرية مُتحقَّق منها. صار لدينا بنك عناصر مُؤلَّف دون اتصال ومُتحقَّق منه — 645 عنصرًا
- نصّان قرائيّان عبر المجالات الرقمية السبعة، وكل مهارة قابلة للتأهيل ممثَّلة بـ 8–12 عنصرًا، وجميعها
يجتاز بوابة الاستيراد. العناصر بحالة
source='offline_generated'وstatus='draft'(لا تُقدَّم لطالب حتى موافقة خبير المادة). قِيَم صعوبة العناصر (δ_prior) حقيقية بالكامل (معجم SAMER v2 + CAMeL).
- نصّان قرائيّان عبر المجالات الرقمية السبعة، وكل مهارة قابلة للتأهيل ممثَّلة بـ 8–12 عنصرًا، وجميعها
يجتاز بوابة الاستيراد. العناصر بحالة
- إضافات على المخطط (بنك العناصر). حقل استيراد اختياري جديد
image_urlوعمودimageUrlلعناصر مطابقة الصورة، وتوسيع مفرداتdistractor_typeالمضبوطة من 13 إلى 19 (أُضيفagreement_errorوwrong_part_of_speechوwrong_function_wordوin_text_wrong_detailوwrong_syllable_countوwrong_sound_position) مع توسيع مصفوفة توافق الاستيراد لتطابقها. لا تغيير على أيّ مسار منشور أو شكل طلب أو شكل استجابة.
صيانة — 2026-06-18
تمريرة تصحيحية مدفوعة بالمهام الدورية — أُغلقت دفعة من ملاحظات مراجعة الكود وانحراف المواصفة. لا عمليات جديدة؛ العدد كما هو (45).
- حذف الصف أصبح حذفًا ناعمًا (soft-delete). نقطة
DELETE /api/classes/:idلم تتغيّر للمستهلِك (الطلب نفسه والاستجابة{ ok: true }نفسها)، لكن الصف وإسنادات معلّميه وطلابه تُحفَظ الآن للتدقيق بدل إزالتها. لم يَعُد الصف المحذوف يظهر فيGET /api/classesولاGET /api/classes/:id(404) ولا في التجميع المؤسسي ولا في استعلامات القوائم والإسناد. ولا يزال حذف صفٍّ به طلاب نشِطون مرفوضًا (409). ← راجع المفاهيم الأساسية. - تحصين داخلي (لا تغيير في عقد الـ API): إحكام نطاق المدير/المعلّم على الوصول إلى الصفوف والطلاب والمنسقين؛ وصحّة تصعيد قفل محدّد المعدّل؛ وسلامة استيراد العناصر (كتابة ذرّية، تحقّق لكل صف، حماية كتابة العناصر العامة)؛ وحجب حقول السجلّات. رموز الأخطاء وأشكال الطلب والاستجابة لم تتغيّر.
تصنيف المهارات الفرعية — 2026-06-18
يُشحَن تصنيف مهارات محو الأمية العربية كبيانات مرجعية عامة — 4 عمليات قراءة ضمن الوسم الجديد
sub-skills، فيصير المجموع 45 عملية منشورة.
GET /api/sub-skills— قائمة مُقسَّمة لجميع المهارات الـ 78 الفرعية مع مجالها ونطاقها الصفّي ونوع تقييمها وعلامتي البوابة/المهارة الأساسية. (ارتفعت إلى 79 بإضافة VOCAB-C06 المذكورة أعلاه)GET /api/sub-skills/{id}— صف مهارة واحدة بمعرِّف CUID.GET /api/domains— المجالات التسعة لمحو الأمية العربية (الوعي الصوتي، فك الترميز، طلاقة القراءة، الفهم، المفردات، وغيرها).GET /api/skill-dependencies— روابط المتطلّبات السابقة بين المهارات.
تتطلّب النقاط الأربع مصادقة وسياق مستأجِر؛ وصلاحية VIEW_OWN_PROFILE تُمتلَك من قِبَل كل الأدوار
(معلّم، مسؤول، مدير مدرسة، منسّق، ولي أمر، طالب)، فالتصنيف متاح لجميع المستخدمين المصادَق عليهم.
أساس بنك العناصر — 2026-06-18
واجهة بنك العناصر متاحة — 12 عملية ضمن الوسم items. هذه مسارات غير منشورة مقيَّدة بـ
RUN_BACKOFFICE (للمكتب الخلفي/خبير المادة فقط)؛ ولا تؤثّر في عدد العمليات المنشورة (45).
- القراءة —
GET /api/items،GET /api/items/{id}(?view=authoringللصف التأليفي الكامل)،GET /api/item-types،GET /api/item-types/{code}/distractor-compat. - مسار الاستيراد —
POST /api/items/import،GET /api/items/import،GET /api/items/import/{batchId}،POST /api/items/import/{batchId}/approve. - دورة الحياة —
POST /api/items/{id}/sme-approve،POST /api/items/{id}/promote،POST /api/items/{id}/retire. - قِيَم الصعوبة المسبقة —
GET /api/expected-difficulty/log(سجل تدقيق δ_prior الحتمي).
1.0.0-phase0
الموقع الأوّل. يوثّق WP-A1 المصادقة + WP-A2 البنية المستأجِرة + WP-A3 إدارة المستخدمين — 41
عملية عبر الوسوم auth وtenancy وusers وsystem.
- auth — التسجيل (للتمهيد فقط)، الدخول، التجديد (متدوّر)،
me، الخروج، إعادة تعيين كلمة المرور وتأكيدها، دخول الطالب بالرمز السريع. ← راجع المصادقة والبدء السريع والأخطاء. - tenancy — المؤسسات، المدارس، الصفوف (CRUD)، التجميع المؤسسي. ← راجع المفاهيم الأساسية وإدارة الصفوف والقوائم.
- users — التزويد (
POST /api/usersالمُميَّز)، ملفات الأدوار، قوائم الصفوف، إسناد ClassTeacher، المدراء، المنسقون، روابط ولي الأمر بالطالب، إعادة توليد الرمز السريع للطالب. ← راجع تزويد المستخدمين والمدراء والمنسقون وروابط ولي الأمر بالطالب. - system — فحص الجاهزية. ← راجع مرجع الـ API.