سجل التغييرات
GitHubكل تغيير جدير بالذكر، إصدارًا بعد إصدار. الملف نفسه يأتي مع المستودع ومترجم إلى جميع اللغات الـ19.
[1.201.0] — 2026-08-15
تم الإصلاح — المتتبِّع ذو ترويسات الأعمدة المُترجَمة أو البديلة لم يعد يظهر فارغًا.
تم الإصلاح
- إذا كان
data/applications.mdيستخدم ترويسات غير إنجليزية أو بديلة — الإسبانيةempresa/puesto/estado/fecha/enlace، أوposition/stage/link— كان المتتبِّع يقرؤها بمفاتيح خاطئة ويعرض أعمدة الشركة / الدور / الحالة / التاريخ / الرابط فارغة. الآن تُطوى هذه الترويسات إلى أسماء الحقول القانونية فيُعرض المتتبِّع بشكل صحيح. المتتبِّع الإنجليزي يُعالَج تمامًا كما كان.
ملاحظات
- خريطة
HEADER_ALIASESجديدة وطيّ تطبيع فيparseApplications(server/lib/parsers.mjs)؛ الترويسات غير المعروفة أو القانونية أصلًا تمرّ دون تغيير.tests/tracker-header-aliases.test.mjs. المجموعة: 2563.
[1.200.0] — 2026-08-15
أُضيف — فحص «هل ما زالت متاحة؟» بنقرة واحدة لوظائف منصات ATS في متتبِّعك.
أُضيف
- في #/tracker، أي طلب يكون رابطه إعلانًا على Greenhouse / Lever / Ashby / Workday / SmartRecruiters يعرض الآن زر «هل ما زالت متاحة؟». نقرة واحدة تسأل JSON العام للمنصة نفسها — بدون توكنات، بدون متصفح — وتعرض متاحة / منتهية / غير معروفة، لترصد الإعلانات الميتة دون فتح كل واحد. متحفِّظ بالتصميم: فقط 404/410 القاطع يُقرأ منتهية؛ وأي التباس يبقى غير معروفة (دون منتهية خاطئة).
ملاحظات
- ملفان جديدان
server/lib/liveness-core.mjs+liveness-api.mjsومسار للقراءة فقطGET /api/liveness?url=(بلا كتابة، بلا LLM). آمن ضد SSRF: يمرّ الرابط عبرisValidJobUrl، ثم يُوصل إلى API المنصة فقط عبرsafeGet(المثبِّت لِـ DNS) بمضيف ثابت ومقاطع مسار مُتحقَّق منها.tests/liveness-core.test.mjs+tests/liveness-route.test.mjs. المجموعة: 2557.
[1.199.0] — 2026-08-15
تم الإصلاح — الجداول العريضة تُمرَّر الآن أفقيًا بدل أن تُقتطع.
تم الإصلاح
- في صفحة Scan (وفي كل الجداول الأخرى — المتتبِّع، الإحصاءات، الاستخدام، اللوحة) كان الجدول الأعرض من النافذة يُقتطع دون شريط تمرير، فتتعذّر الوصول إلى الأعمدة اليمنى. الآن تُظهر الجداول العريضة شريط تمرير أفقيًا عند الحاجة، فيبقى كل عمود قابلاً للوصول عند أي عرض.
ملاحظات
- تم تحويل
.table-wrapفيpublic/css/components.cssمنoverflow: hiddenإلىoverflow-x: auto(مثل حاوية.reports-scrollالحالية)؛ مع الحفاظ على الحد المدوَّر.tests/table-wrap-scroll.test.mjs. المجموعة: 2540.
[1.198.0] — 2026-08-15
أُضيف — تستخدم إعادات محاولة المسح الآن تراجعًا أُسّيًا وتشويشًا (jitter) وتحترم Retry-After القادم من مُحدِّد المعدل.
أُضيف
- عندما تُحدِّد لوحة وظائف المعدل مؤقتًا أو تُخطئ (HTTP 429 / 5xx) أثناء المسح، تنتظر إعادة المحاولة الآن بـتراجع أُسّي + تشويش بدلًا من تأخير قصير ثابت — فلا تُطرَق اللوحة المزدحمة بالإيقاع نفسه، ولا تتصادم المحاولات المتزامنة معًا من جديد. ويُحترَم
Retry-Afterالقادم من اللوحة (لكن مع تقييد، حتى لا يوقفRetry-After: 86400عدائي المسح كله). أما الأخطاء الدائمة (404، عمليات إعادة التوجيه المرفوضة) فتفشل فورًا كما كانت — دون تغيير.
ملاحظات
- دالتان جديدتان
parseRetryAfterMs()والدالة النقيةcomputeRetryDelayMs()فيserver/lib/http-json.mjs؛ يلتقطfetchJsonالآن.retryAfterعند استجابة غير ناجحة، ويقبلfetchJsonWithRetryقيمةmaxDelayMsاختيارية (الافتراضي 8000).tests/http-json.test.mjs(+9). المجموعة: 2536.
[1.197.0] — 2026-08-14
أُضيف — تابِع لوحة وظائف صندوق Getro عبر careers_url وحدها؛ ويُحَلّ مُعرّف المجموعة تلقائيًا.
أُضيف
- لم تعد لوحة Getro المُتابَعة (b2venture، Earlybird، Point Nine، …) بحاجة إلى
getro_collectionرقمي يُبحث عنه يدويًا. أعطِهاcareers_urlالخاص باللوحة، فيُحَلّ المُعرّف تلقائيًا من تلك الصفحة عند أول فحص — طلب GET واحد آمن ضد SSRF يقرأnetwork.idالرقمي مباشرةً من بيانات الصفحة المُضمّنة. ولا يزالgetro_collectionالصريح له الأولوية ويتخطّى الجلب بالكامل.
ملاحظات
- دوال جديدة
httpsCareersUrl()وextractCollectionId()وresolveCollectionId()غير المتزامنة فيserver/lib/sources/getro.mjs؛ تُجلَب صفحة اللوحة عبرsafeGet(DNS مُثبَّت، حجم مُقيَّد)، ويظل المُعرّف المُحَلّ مُثبَّتًا على المضيفapi.getro.comبواسطةassertGetroUrl. صار المُحوِّل الآن يطابق مُدخلprovider: getroيحملcareers_urlبروتوكول https حتى بدون مُعرّف.tests/sources-getro.test.mjs(+8). المجموعة: 2527.
[1.196.0] — 2026-08-14
تم الإصلاح (الأمان) — محوّل Workday يتحقق من نقطة api عبر اسم المضيف لا عبر سلسلة فرعية.
تم الإصلاح
- قيمة
api:الخاصة بـ Workday فيportals.ymlتُقبل الآن فقط عندما يكون اسم مضيفها هوmyworkdayjobs.com(أو نطاق فرعي.myworkdayjobs.com). كان الفحص القديم مطابقة سلسلة فرعية، لذا أي رابط يحتوي على السلسلة فحسب — مثلhttps://example.com/?x=myworkdayjobs.com— كان يمر ويُستخدم كنقطة نهاية. نقاط Workday الحقيقية غير متأثرة. (أبلغ عنه CodeQL، #443.)
ملاحظات
isWorkdayApi()الجديد يحلّل الرابط ويتحقق من المضيف (server/lib/portals/adapters/workday.mjs).tests/workday-adapter-endpoint.test.mjs(+1). المجموعة: 2522.
[1.195.0] — 2026-08-14
الأداء (الماسح) — يبقى كشف إعادة النشر سريعًا على سجلات المسح الكبيرة.
الأداء
- لم يعد كشف الإعلانات المكرّرة يتدهور إلى O(N²) على
scan-history.tsvكبير. كان تجميع العناوين لكل شركة حلقة متداخلة تدفعroleFuzzyMatchكاملًا لكل زوج؛ أصبح الآن فهرسًا معكوسًا — تجميع الصفوف حسب العنوان المطابق في مرور واحد، ثم مطابقة ضبابية فقط بين الحاويات المختلفة التي تتشارك رمزًا مميّزًا (غير أساسي). المخرجات متطابقة — نفس مجموعات إعادة النشر — أُثبت باختبار تفاضلي ضد الخوارزمية القديمة على أكثر من 200 سجلّ عشوائي.
ملاحظات
groupRowsByTitleفيserver/lib/detect-reposts.mjs(مُصدَّر للاختبار التفاضلي).tests/detect-reposts-grouping.test.mjs(+2). المجموعة: 2521.
[1.194.0] — 2026-08-14
تم الإصلاح (الماسح) — صفحات وظائف Workday ذات المسار المكوّن من مقطع واحد تُمسح الآن بشكل صحيح.
تم الإصلاح
- محوّل Workday يحلّل الآن روابط الوظائف التي مسارها مقطع واحد — مثل
https://parsons.wd5.myworkdayjobs.com/Searchو.../KBR_Careersو.../Careers. سابقًا كان الموقع يعود إلىExternal، فيصيب المحوّل نقطة CXS الخاطئة وقد يبدو الفحص سليمًا دون إرجاع شيء. الآن يأخذ أول مقطع غير فارغ من المسار كموقع (متجاهلًا بادئة لغة مثلen-US)؛ والحالة الموثّقة/en-US/Externalدون تغيير. (أُبلغ عنه في #255.)
ملاحظات
- تحليل بنيوي للمسار في
server/lib/portals/adapters/workday.mjs.tests/workday-adapter-endpoint.test.mjs(+7). المجموعة: 2519.
[1.193.0] — 2026-08-14
أُضيف (إحصاءات) — تبويب “صمت بعد المقابلة” يُبرز المقابلات التي تستحق تذكيرًا.
أُضيف
- تبويب صمت بعد المقابلة في
#/stats: مقابلات صمتت بعد نافذة مجاملة (30 يومًا افتراضيًا)، يجمع مقابلاتك النشطة والمتتبع — مع مدة صمت كلٍّ منها وتاريخ آخر مقابلة والسبب. قائمة لطيفة للتذكير/الإغلاق؛ اقتراحات فقط، وليست ادعاء رفض أبدًا. بدون رموز.
ملاحظات
- مسار جديد
GET /api/stats/rejection-latency(fail-soft{available:false}).tests/stats-rejection-latency-route.test.mjs(+2). +10 مفتاح i18n ×17؛ help-hint في#/statsمن 7→8 تبويبات. المجموعة: 2510.
[1.192.0] — 2026-08-14
أُضيف (cv-studio) — بوابة “تحقّق من حقائق سيرتك” تلتقط أرقامًا لم تمتلكها قط.
أُضيف
- بطاقة تحقّق من حقائق سيرتك في
#/cv-studio: الصق سيرة أو خطابًا معدّلًا وتحقّق من كل مقياس وحقيقة مقابل سيرتك وملفك وصفحتيك الحقيقية. تحصل على حكم pass / warn / block إضافةً إلى المقاييس المختلقة والحقائق غير المدعومة والعبارات المحظورة / التحذيرية بدقة. بدون LLM؛ لا يُكتب شيء.
ملاحظات
- مسار جديد
POST /api/cv-studio/verify-facts: يكتب النص في ملف مؤقت للاستعمال مرة واحدة ويشغّلverify-cv-facts.mjs، ويثق بحكم JSON رغم خروج السكربت بالرمز 1 عند block.tests/cv-studio-verify-facts-route.test.mjs(+4). +15 مفتاح i18n ×17. المجموعة: 2508.
[1.191.0] — 2026-08-14
أُضيف (إحصاءات) — تبويب “ماذا تتعلم بعد ذلك” يرتّب المهارات الأولى بالتعلم.
أُضيف
- تبويب ماذا تتعلم بعد ذلك في
#/stats: تجميع على مستوى المتتبع بالكامل — المهارات الناقصة التي أغرقت غالبًا تطابقًا منخفضًا، موزونة (بـ 5−درجة التطابق في كل تقرير) ومصنّفة Critical / High / Medium — إضافةً إلى ما تغطيه سيرتك/ملفك بالفعل. للقراءة فقط، اقتراحات فقط، بدون رموز.
ملاحظات
- مسار جديد
GET /api/stats/upskill(حقل{ error }عند قلة البيانات؛ fail-soft{available:false}).tests/stats-upskill-route.test.mjs(+3). +15 مفتاح i18n ×17. المجموعة: 2504.
[1.190.0] — 2026-08-14
أُضيف (المتتبع) — لوحة “سجل الشركة” تخبرك بالشركات التي ترد عليك فعلاً.
أُضيف
- بطاقة سجل الشركة في
#/tracker: اختر شركة واحصل على أدلة للقراءة فقط — مدى تجاوبها معك (صامتة تجاهك / مختلط / استجابت سابقًا) وما إذا كانت الوظيفة نفسها تُعاد نشرها — بدمج متتبعك والمتابعات وسجل المسح. بدون رموز؛ لا يُستدعى الماسح.
ملاحظات
- مسار جديد
GET /api/stats/company-history[?company=](fail-soft{available:false}).tests/stats-company-history-route.test.mjs(+3). +18 مفتاح i18n ×17. المجموعة: 2501.
[1.189.0] — 2026-08-14
تم الإصلاح (الماسح) — مستويات الأقدمية المكتوبة بالأرقام الرومانية أصبحت تُحتسب أيضًا في العناوين غير اللاتينية.
تم الإصلاح
- مصنّف المستوى وراء
skip_tiersأصبح يقرأ لاحقة مستوى بالأرقام الرومانية (I / II / III / IV / V) بعد كلمة الوظيفة في أي نظام كتابة — “Инженер III”، “エンジニア I”، “Ingénieur IV” — وليس فقط بعد الكلمات اللاتينية. سابقًا كان رقم المستوى بعد كلمة غير لاتينية يُتجاهل وتقع الوظيفة في mid، فيفوتskip_tiers: [senior]أو[entry]تلك الإعلانات.
ملاحظات
- lookbehind مستقل عن نظام الكتابة في
server/lib/classify-tier.mjs؛ وحُذف مطابقSr.مكرّر ميت.tests/classify-tier.test.mjs(+1). المجموعة: 2498.
[1.188.0] — 2026-08-14
تم الإصلاح (واجهة) — لم تعد أزرار الإجراء الرئيسية ملتصقة بعنوان الصفحة الفرعي.
تم الإصلاح
- صف الإجراء / التحكم الرئيسي في الملخص الأسبوعي للمقابلات والشركات الممولة والبوابات والخطة المهنية والتوجيه المهني أصبح له الآن هامش علوي مناسب، بحيث يتنفس الزر أسفل العنوان الفرعي بدلاً من الالتصاق به.
ملاحظات
- حارس الانحدار
tests/lead-row-top-margin.test.mjs(+5). المجموعة: 2497.
[1.187.0] — 2026-08-14
تصحيح (الماسح) — إعداد skip_tiers يعمل من جديد: الوظائف التي طلبت تخطّيها حسب المستوى تُستبعد.
تصحيح
- أصبحت قائمة
skip_tiers:فيportals.yml(مثلskip_tiers: [intern, entry]) مُحترَمة في المسح. يُصنَّف عنوان كل وظيفة إلى مستوى (intern / entry / mid / senior) ويُستبعَد إذا كان مستواه في قائمتك. سابقًا كان المسح يطبّق مرشّحات العنوان / الموقع / المحتوى / الثقة لكن بلا مرشّح مستوى، فكانskip_tiersيُتجاهَل بصمت. العناوين بلا كلمة مستوى تقع في mid (فـskip_tiers: [mid]يستبعد أيضًا معظم الوظائف العادية)، ويقرأ المصنِّف كلمة المستوى الأقصى إلى اليسار.
ملاحظات
- وحدة نقية جديدة
server/lib/classify-tier.mjs(classifyTier+buildTierFilter)، موصولة بسلاسل مرشّحات ماسحَي EN و RU.tests/classify-tier.test.mjs(+7). المجموعة: 2492.
[1.186.0] — 2026-08-14
إضافة (استوديو السيرة) — لوحة “فجوة المهارات”: أيّ المهارات المطلوبة في وظيفة يذكرها سيرتك أو يُلمِّح إليها أو تفتقدها.
إضافة
- لوحة فجوة المهارات جديدة في استوديو السيرة. اختر وصفًا وظيفيًا محفوظًا فيصنّف كل مهارة مطلوبة إلى مذكور في سيرتك أو مُلمَّح إليه في سيرتك أو مفقود — مقارنة كلمات بلا نموذج لغوي، ولا يُكتب شيء. تظهر ملاحظة ثقة منخفضة عندما لا يكون للوظيفة قسم متطلبات واضح.
ملاحظات
GET /api/jds/:name/skill-gapجديد (يُطهَّر اسم الوظيفة ويُتأكَّد من وجوده تحتjds/قبل أن يصير وسيطًا؛ تراجع لطيف إلى{available:false}بدون السكربت). +13 مفتاح i18n ×17. الاختبارات:tests/jds-skill-gap-route.test.mjs(+4، بما فيها رفض اجتياز المسار). المجموعة: 2485.
[1.185.0] — 2026-08-14
إضافة (إحصاءات) — علامة تبويب “المسار والسرعة”: كيف يقارَن مسارك بالسوق ومدى سرعة تنقّلك بين المراحل.
إضافة
- تعرض علامة المسار والسرعة الجديدة في الإحصاءات معدّلي الرد والمقابلة بجوار نطاقات مرجعية للسوق (مع تحفّظات العيّنة الصغيرة وتحيّز الاختيار)، وقائمة انتظار للطلبات الجارية التي تجاوزت نافذة الرد الأول المعتادة، ووسيط الأيام لكل مرحلة (تقدّم → رد → مقابلة → عرض) — تُراقَب الصفوف البطيئة من اليمين حتى لا تُحيّز الوسطاء. للقراءة فقط وبلا رموز؛ يقرأ متتبّعك أنت فقط.
ملاحظات
GET /api/stats/funnelجديد (تراجع لطيف إلى{available:false}بدون السكربت). +18 مفتاح i18n ×17. الاختبارات:tests/stats-funnel-route.test.mjs(+2). المجموعة: 2481.
[1.184.0] — 2026-08-14
تصحيح (واجهة) — بلاطات الإجراءات السريعة في لوحة القيادة تصطف الآن في شبكة متساوية.
تصحيح
- في لوحة القيادة (مركز التحكم)، كانت مجموعة من 3 بلاطات تظهر أعرض من مجموعة من 4، فتترك الأقسام بحافة يمنى غير مستوية. تستخدم كل مجموعة الآن أعمدة متساوية العرض (4 على الشاشة العريضة، تنخفض إلى 3 / 2 / 1 كلما ضاقت النافذة)، فتصبح كل البلاطات بالحجم نفسه وتصطف حوافها اليمنى.
ملاحظات
- CSS فقط (
.qa-grid:repeat(N, minmax(0,1fr))ثابت بدلauto-fill). محميّ بـtests/dashboard-grid-align.test.mjs(+2). المجموعة: 2479.
[1.183.0] — 2026-08-14
إضافة (الماسح) — كشف تكرارات أذكى: الوظيفة نفسها المعاد نشرها برابط تتبّع لم تعُد تظهر مرتين.
إضافة
- يتعرّف الماسح الآن على الوظيفة عبر مفتاح URL أساسي، فالوظيفة نفسها المعاد نشرها بمعامل تتبّع (
?utm_…،gclid، …)، أو عبرhttpمقابلhttps، أو بشرطة مائلة نهائية /#جزءتُعامَل كوظيفة واحدة — بلا صف مكرَّر في نتائج المسح أو المسار، وبلا تقييم مُهدَر لوظيفة رأيتها من قبل. الوظائف المختلفة فعلاً (مُعرّف وظيفي مُبقى مثلgh_jid) تُحسب منفصلة كما هي.
ملاحظات
- ملف جديد
server/lib/url-key.mjs، موصول بإزالة التكرار في كلا الماسحين وبكاتب المسار. يُطبِّع بأقل قدر عمدًا — لا يدمج أبدًا وظيفتين مختلفتين. الاختبارات:tests/url-key.test.mjs(+5)،tests/parsers.test.mjs(+1). المجموعة: 2477 (+6).
[1.182.0] — 2026-08-14
تصحيح (الماسح) — نطاقات الراتب تظهر الآن بالشكل نفسه في كل اللغات.
تصحيح
- أرقام الراتب في صفوف المسح والمتابعة تستخدم الرمزين المحايدين ≥ و ≤ (مثل
≥ 120000 EUR،≤ 90000) بدلاً من الكلمتين الإنجليزيتين “from” / “up to” اللتين كانتا تتسربان دون ترجمة إلى الواجهات غير الإنجليزية. ينطبق على كل لوحة تُبلِّغ عن نطاق من جهة واحدة (Getro وRemotli وManfred وAgentic Jobs وJustJoin وJobicy)؛ النطاقات ذات الجهتين (100000–150000 USD) كانت محايدة أصلاً.
ملاحظات
- عرض فقط — يحلّل مرشّح الراتب في العميل الأرقام بصرف النظر عن البادئة، فالتصفية دون تغيير. المجموعة: 2471.
[1.181.0] — 2026-08-14
إضافة (الماسح) — لوحات وظائف Getro تعرض الآن الراتب وجميع المواقع والوظائف عن بُعد.
إضافة
- أصبح ماسح Getro (لوحات شبكات المواهب للصناديق) يعرض الآن راتبًا لكل وظيفة (نطاق سنوي + عملة)، ويسرد جميع المواقع بدلاً من الأول فقط، ويضع علامة على الوظائف عن بُعد. باتت وظيفة Getro في المسح والمتابعة تحمل نفس تفاصيل الراتب والموقع مثل بقية اللوحات.
ملاحظات
- الماسح فقط؛ بلا اعتماد جديد، وبلا تغيير في المسارات / CSP / SSRF. الاختبارات:
tests/sources-getro.test.mjs(+5). المجموعة: 2470 (+5).
[1.180.0] — 2026-08-14
تصحيح (متوسط، التقارير) — قائمة #/reports أصبحت جدولاً، واستُعيدت درجة حقيقية كان عنصر نائب في Machine Summary يخفيها.
تصحيح
- قائمة
#/reportsجدول (التقرير · التاريخ · المصداقية · الدرجة)، لا شبكة من 4 بطاقات. كانت شريحة “لم يتم اكتشاف درجة” الطويلة تضغط عمود العنوان إلى ما يقارب الصفر، ثم يكسرoverflow-wrap: anywhereفي عنوان البطاقة اسم التقرير حرفاً حرفاً. الآن لكل حقل عموده الخاص، وتلتفّ خلية الاسم عند الكلمات، ويتمرر الجدول أفقياً على الشاشة الضيقة (حاوية.reports-scrollجديدة). مفتاح i18n جديدrep.colReport×17. - لم تعُد الدرجة الحقيقية في المتن (
**Итоговый балл:** 1.8 / 5) مخفيّة بعنصر نائب في Machine Summary (score: —). عندما كانت كتلة## Machine Summaryتحمل درجة غير رقمية أو خارج المدى، كانت تشغل خانة الدرجة المُحلَّلة وتمنع بديل صيغة-القيمة بالخط العريض، فيُظهر التقرير “لم يتم اكتشاف درجة” رغم وجودX / 5حقيقي في المتن. أصبحparseReportHeaderيستعيد صيغة-القيمة من المتن كلما لم يبقَ رقم صالح (الخطوة 4.5).
ملاحظات
- العميل + المحلّل فقط؛ لا تغيير في المسارات / CSP / SSRF / الكتابة إلى الأصل. الاختبارات:
tests/reports-table.test.mjs(+5)،tests/report-header-locale.test.mjs(+2). المجموعة: 2465 (+7).
[1.179.0] — 2026-08-13
تغيير (LOW، الماسح) — دمج 20 مفكِّك كِيانات HTML مكرَّرًا في الوحدة المشتركة (متابعة التكافؤ، يُغلق قائمة العمل).
تغيير
- كان لدى 20 مصدر مسح كلٌّ منها
decodeEntities/decodeXmlEntitiesخاص به (+ مساعدfromCodePoint) — نسخ انحرفت (ثلاث كان يمكن أن تُطلقRangeError، أُصلحت في v1.172.0؛ وأخرى تسمح بـ NUL/C0 أو تحلّلa2;خطأً). صارت جميعها تمرّ عبرserver/lib/html-entities.mjsالوحيد (مفكِّك آمن وفق مجموعة Char في XML 1.0)، مع إزالة ~237 سطرًا من التكرار. اكتسبت المصادر الثمانية من نوع RSS فكّ ترميز (كانت تعالج 5 كِيانات فقط)؛ ويُحفَظ فكّ الترميز المزدوج المقصود في cryptocurrencyjobs عبر اسم مستعار. يحتفظhhبمفكِّكه (يعالج—/–، خارج الستة المشتركة). اختبار حارس جديد يفشل إذا أعاد أي مصدر إنشاء مفكِّك محلي.
ملاحظات
- إعادة هيكلة تحافظ على السلوك؛ لا تغيير في المسارات / CSP / SSRF / الكتابة إلى الأصل. الاختبارات:
tests/decoder-consolidation.test.mjs(+2). المجموعة: 2458 (+2).
[1.178.0] — 2026-08-13
أُصلح (LOW، تكافؤ مع الأصل) — تحديث ثابتَين قديمَين ليطابقا المشروع الأصل (PARENT-SYNC GAP #4 + #5).
أُصلح
- User-Agent للمتصفح (GAP #4) — رُفِع
BROWSER_LIKE_USER_AGENT(تُرسله workable/workday/oraclecloud/a16z/eightfold لتجاوز بوابات WAF/الروبوتات) من Chrome 131 إلى 151 ليطابقuser-agent.mjsفي الأصل؛ فالإصدار القديم أكثر عرضة للحجب. محمي باختبارChrome major ≥ 151. - FALLBACK لحالات المتتبِّع (GAP #5) — اكتسب
FALLBACKالاحتياطي فيstates.mjs(يُستخدم فقط عندما يتعذّر قراءةtemplates/states.ymlالحيّ — نسخة جديدة / جذر CI معزول) أسماء الحالات التركية من الأصل (#2615): değerlendirildi، başvuruldu، yanıt verildi، mülakat، teklif، reddedildi، iptal edildi، uygun değil، kabul edildi/işe alındı. في الإنتاج كان الملف الحيّ يوفّرها بالفعل.
ملاحظات
- ثابتان فقط؛ لا تغيير في المسارات / CSP / SSRF / الكتابة إلى الأصل. الاختبارات:
tests/http-json.test.mjs(+1) +tests/states.test.mjs(+1). المجموعة: 2456 (+2).
[1.177.0] — 2026-08-13
أُصلح (MEDIUM، الماسح) — كان csod (Cornerstone) يُرجِع 0 وظيفة لدى المستأجرين الذين يحمون واجهة البحث بكوكيز الجلسة (parent #2769، PARENT-SYNC GAP #1).
أُصلح
- بعض مستأجري Cornerstone يضعون كوكيز جلسة على صفحة البداية لموقع الوظائف ويردّون
401 CSOD Unauthorizedعلى واجهة البحث ما لم تَعُد تلك الكوكيز مع رمز الحامل المجهول. تقرأsources/csod.mjsالآن صفحة البداية عبر مساعد جديدfetchResponse، وتبني ترويسةCookieمن قيمSet-Cookie(cookieHeaderFrom— الاسم=القيمة فقط، دلالة الجرة) وتُعيدها في POST البحث. نفس الأصل فقط (المضيف مثبَّت +redirect:'error')، فلا يمكن أن تصل كوكيز الجلسة إلى طرف ثالث؛ ومستأجر لا يضع كوكيز يتصرف كما كان.
ملاحظات
- جديد
server/lib/http-json.mjs::fetchResponse(إضافي؛ المصادر القائمة غير متأثرة). لا تغيير في المسارات / CSP / SSRF / الكتابة إلى الأصل. الاختبارات:tests/sources-parity-v1118a.test.mjs(+1). المجموعة: 2454 (+1).
[1.176.0] — 2026-08-13
أُصلح (MEDIUM، التقارير) — درجة تحت تسمية عريضة لا تُدرِجها جداول RU ظلّت تُظهر “Score not detected” (FIND-5).
أُصلح
- كتب تقريران بالروسية الدرجة بالصيغة
**Итоговый балл:** 1.8 / 5/**Скор:** 1.8 / 5— وهي تسميات عريضة لا يُعدّدهاREPORT_LABELS.ru(يعرف “Оценка”/“Балл” فقط)، فبقيت الدرجة دون تحليل. وبدلًا من توسيع قائمة المرادفات، يعودparseReportHeaderالآن إلى صيغة القيمة: كسر على مقياس /5 تحت أي تسمية عريضة. إنها مستقلة عن اللغة، ومحصَّنة ضد العناوين (لا**، ولا قيمة/5)، وترفض تاريخًا مثل5/5/2026(استباق سلبي على المقام).
ملاحظات
- محلِّل الخادم فقط؛ لا تغيير في المسارات / CSP / SSRF / الكتابة إلى الأصل. الاختبارات:
tests/report-header-locale.test.mjs(+2). المجموعة: 2453 (+2).
[1.175.0] — 2026-08-13
أُصلح (LOW، تحصين) — حارس انحدار لوصف SEO الخاص بـ FIND-3 + تنظيف مشروعية آمن ضد القيم الفارغة (متابعة لمراجعة الذكاء الاصطناعي).
أُصلح
- حارس تكافؤ وصف SEO — إصلاح v1.174.0 الذي استبدل “~55” المُثبَّت في
meta.descلكل لغة بعنصر نائب{adapters}مشتق من السجل لم يكن له اختبار، فكان يمكن أن ينحدر بصمت عند تحرير اللغة التالي. الاختبار الجديد المعزول عن CItests/site-meta-desc-parity.test.mjsيفشل إذا فقد أي من الـ17site/src/i18n/*.jsonالعنصر النائب أو أعاد تثبيت عدد، أو إذا توقّفLanding.astroعن إدراجه في أوصاف meta الثلاثة. - تنظيف مشروعية آمن ضد الفراغ — تُرجِع
stripEmphasisالقيمة''لمدخل فارغ بدل السلسلة “undefined” (الحقول مُهيَّأة كسلاسل، فهذا دفاع في العمق).
ملاحظات
- اختبار + حارس من سطر واحد في المحلِّل؛ لا تغيير في المسارات / CSP / SSRF / الكتابة إلى الأصل. الاختبارات:
tests/site-meta-desc-parity.test.mjs(+3). المجموعة: 2451 (+3).
[1.174.0] — 2026-08-13
أُصلح (HIGH، التقارير) — كانت التقارير المُترجَمة تُظهر “Score not detected”؛ ووصف SEO قديم.
أُصلح
- تحليل الدرجة (FIND-1) — تقرير غير إنجليزي يحتوي عنوانه H1 على كلمة تسمية الدرجة (
# Оценка вакансии: <العنوان>) لم يَعُد يخلط ذلك العنوان مع الدرجة. صارparseReportHeaderيرتكز على التسمية العريضة المُترجَمة (**Оценка:** 1.5 / 5)، ويتخطى أسطر العناوين، ويشترط أن تكون التسمية ملاصقة لنقطتيها — لذا تعرض تقارير RU التي كانت تُظهر “Score not detected” درجتها الحقيقية. - شارة المشروعية (FIND-2) — يُزال تشديد Markdown من القيمة، فتُظهر الشارة “High Confidence” بدل “** High Confidence”.
- تجاوز الدرجة — سطر درجة مذيَّل بنص حالة (“1.8, Status: Evaluated, …”) يُختصر إلى الدرجة فقط؛ ويكتسب
.score-pillحدًّا بلا التفاف/تجاوز، ويمكن لعمود العنوان أن ينكمش، فلا تتجاوز الشارة الملونة حافة البطاقة. - وصف SEO (FIND-3) — أوصاف meta / OG / Twitter في cvstart.org (بجميع اللغات الـ17) كانت تُثبِّت “Scan ~55 job boards” بينما يَعُدّ المتن السجل الحقيقي (“~75”). صار الوصف يُدرج العدد المُشتق من السجل، فلا ينحرف مجددًا.
ملاحظات
- محلِّل الخادم + عرض/CSS العميل + i18n الموقع؛ لا تغيير في المسارات / CSP / SSRF / الكتابة إلى الأصل. الاختبارات:
tests/report-header-locale.test.mjs(+4). المجموعة: 2448 (+4).
[1.173.0] — 2026-08-13
أُضيف (LOW، الإعداد) — انضمام Hermes إلى قائمة أدوات CLI للذكاء الاصطناعي المكتشَفة (تكافؤ مع career-ops).
أُضيف
- تبويب
#/config← «أدوات CLI للذكاء الاصطناعي» يكتشف الآن Hermes (Nous Research)، وهو بيئة تشغيل الوكيل التي دعمها المشروع الأصل حديثًا (الملف التنفيذيhermes). تنمو القائمة المسموحة الثابتة فيserver/lib/routes/cli-detect.mjsمن 10 إلى 11 أداة؛ ويظل الاكتشاف مسحًا لـ PATH للقراءة فقط (لا يُنفَّذ أي ملف تنفيذي أبدًا).
ملاحظات
- لا تغيير في i18n / المسارات / CSP / SSRF / الكتابة إلى الأصل؛ القائمة ثابتة وليست إدخالًا. المجموعة: 2444 (حُدِّث كناري cli-detect من 10 إلى 11).
[1.172.0] — 2026-08-13
أُصلح (MEDIUM، الماسح) — كِيان HTML مشوَّه كان قد يُعطِّل مصدر مسح (تكافؤ مع career-ops #2150).
أُصلح
- كانت مصادر
oraclecloudوgemوdassaultتفكّ ترميز كِيانات HTML الرقمية بفحصNumber.isFiniteضعيف قبلString.fromCodePoint— أي مرجع أعلى من0x10FFFF(مثل�من تغذية مشوَّهة أو خبيثة) كان يُطلقRangeErrorغير مُلتقَط ويُجهض تحليل ذلك المصدر بأكمله. وحدة مشتركةserver/lib/html-entities.mjs(تعكس_html-entities.mjsفي المشروع الأصل) تُقيّد الآن المراجع الرقمية بمجموعة Char في XML 1.0 §2.2 حتى لا يُطلقString.fromCodePointأبدًا، وتُطابق الست عشري والعشري بشكل منفصل حتى لا يُحلَّلa2;خطأً بعد الآن. المصادر الثلاثة تستوردها.
ملاحظات
- لا تغيير للتغذيات الصحيحة؛ لا تغيير في JS / i18n / المسارات / CSP / SSRF / الكتابة إلى الأصل. يُتابَع دمج نسخ فك الترميز الـ~20 المتبقية في المصادر في
qa/PARENT-SYNC-WORKLIST-v1.26.0.md. - الاختبارات:
tests/html-entities.test.mjs(+7). المجموعة: 2444 (+7).
[1.171.0] — 2026-08-13
تغيير (منخفض، نظام التصميم) — رموز مقياس الخط + طبقات z-index (D-4، الخطوة الأولى). كانت الأحجام والتراص قيمًا حرفية لكل مكوّن.
تغيير
- طبقات z-index — أُدخلت رموز
--z-*(--z-topbar…--z-skiplink) ورُحّل كل قيمة z-index حرفية إليها. القيم محفوظة والتراص متطابق؛ ويمنع اختبار كناري جديد الأرقام السحرية الجديدة. - مقياس الخط — سُلّم
--font-size-*(xs 11…2xl 28، الأساس = Inter 15px)؛ ورُحّلت الأحجام الأساسية (دون تغيير بصري). القيم خارج السلّم تُرحّل تدريجيًا (docs/UX-ROADMAP.md).
ملاحظات
- رمز CSS فقط؛ دون تغيير في السلوك/JS/i18n/المسار/CSP/SSRF/الكتابة. دون تغيير بكسل.
tests/design-tokens-scale.test.mjs(+3). المجموعة: 2437 (+3).
[1.170.0] — 2026-08-13
أُضيف (منخفض) — تلميحات ETA صادقة على عمليات التوليد الطويلة بالذكاء الاصطناعي (P4-ETA). كانت العمليات الثقيلة (خطة المسار ~40 ث، التوجيه / السوق / التواصل ~30 ث، two-pager ~20 ث) تعرض “جارٍ التوليد…” فقط دون تقدير للمدة.
أُضيف
- يظهر الآن بجانب كل زر توليد طويل تلميح خافت
⏱ ~N ثانية(مثل ETA في#/auto). نمط.eta-hintمشترك + مفتاحان عامّان (common.eta~{n}s،common.etaTitle).
ملاحظات
- العميل فقط؛ دون تغيير في المسار/CSP/SSRF/الكتابة. +2 مفتاح i18n ×17 (اللقطة 1219 → 1221).
tests/generation-eta-hint.test.mjs(+2). المجموعة: 2434 (+2).
[1.169.0] — 2026-08-13
أُضيف (منخفض) — معاينة PDF مضمّنة (D-5). كان GET /api/output/pdfs/:name يفرض Content-Disposition: attachment، حتى إن زر “فتح” في #/cv كان يُنزّل الملف بدل عرضه.
أُضيف
?inline=1يقدّم نفس الملف المُعقّم معContent-Disposition: inline، ليعرضه المتصفح في تبويب جديد كـ 👁 معاينة؛ والافتراضي يبقى تنزيلًا. دون مسار جديد؛ ونفس حراسات الاسم.- أصبح أول زر في قائمة PDF بـ
#/cvهو 👁 معاينة بجانب ⬇ تنزيل. أُعيدت صياغةcv.openPdfمن “فتح” إلى “معاينة” ×17.
ملاحظات
- دون تغيير CSP/SSRF — نفس
sanitizePathName. أُعيدت صياغة مفتاح i18n قائم ×17 (اللقطة 1219).tests/output-pdfs.test.mjs(+3). المجموعة: 2432 (+3).
[1.168.0] — 2026-08-13
تم الإصلاح (منخفض، a11y) — أصبحت صفوف مربّعات الاختيار تفي بالحد الأدنى 24×24 من WCAG 2.5.8 (D-2). كانت تسميات مربّع الاختيار/الراديو في #/scan و#/config و#/evaluate و#/cv-studio ضمن شريط ~22 بكسل.
تم الإصلاح
- قاعدة محدّدة
label:has(> input[type="checkbox"/"radio"]) { min-height: 24px }تضمن شريطًا ≥24 بكسل.min-heightفقط — التسميات بالفعل flex فلا شيء يتزحزح؛ و.apply-checklist(32 بكسل) كان متوافقًا مسبقًا.
ملاحظات
- CSS فقط؛ دون تغيير في السلوك/JS/i18n/المسار/CSP/SSRF/الكتابة.
tests/checkbox-target-size.test.mjs(+1). المجموعة: 2429 (+1).
[1.167.0] — 2026-08-13
تم الإصلاح (منخفض، نظام التصميم) — أصبحت الأسطح المرتفعة تنفصل عن الخطوط الفاصلة (D-3). كانت الرموز --panel-2 / --surface-elev1 تُحلّ إلى --slate — نفس قيمة الخطوط --line / --border — دون فصل بصري.
تم الإصلاح
- رمز مخصّص مدرك للسمة
--elev(#eef1f6فاتح /#1e232eداكن، مختلف عن--slateفي السمتين) يدعم الآن الأسطح المرتفعة؛ وتبقى الخطوط على--slate. أما بقية النتائج (D-2، D-4، D-5، P4-ETA) فمسجّلة فيdocs/UX-ROADMAP.md.
ملاحظات
- رمز CSS فقط؛ دون تغيير في السلوك/JS/i18n/المسار/CSP/SSRF/الكتابة.
tests/elevation-token.test.mjs(+2). المجموعة: 2428 (+2).
[1.166.0] — 2026-08-13
تم الإصلاح (منخفض) — أصبحت مصطلحات المعيار تطابق الوثائق المرجعية. تصف career-ops.org/docs “خمسة أبعاد إضافةً إلى تقييم عام شامل”، لكن واجهة الويب وcvstart.org والويكي كانت تقول “معيار من ستة أبعاد” (5 + 1 = 6، لكن الصياغة كانت مختلفة).
تم الإصلاح
- اعتُمدت صياغة الوثائق — “خمسة أبعاد إضافةً إلى تقييم عام شامل” — بشكل متّسق في README ×17، وموقع cvstart.org ×17، ودليل المساعدة ×17، و
docs/career-ops-canonical.md، والويكي (Home ×17 + Features).
ملاحظات
- الوثائق/التسويق فقط؛ دون تغيير في الكود/مفتاح i18n/المسار/CSP/SSRF/الكتابة.
tests/rubric-terminology.test.mjs(+2). المجموعة: 2426 (+2).
[1.165.0] — 2026-08-13
تم الإصلاح (منخفض) — أصبح مصطلح “Two-pager” متّسقًا داخل كل لغة. في العربية كان الشريط الجانبي يعرض “Two-pager” اللاتينية بينما كان <h1> مُترجَمًا بالكامل — وهي السلسلة اللاتينية الوحيدة في تنقّل RTL معكوس بخلاف ذلك.
تم الإصلاح
- قرار مُطبَّق: لكل لغة، يتّفق
nav.twoPagerوtwoPager.titleعلى المصطلح (كلاهما لاتيني أو كلاهما مُترجَم). العربية وحدها كانت منقسمة؛ وأصبح تسمية التنقّل الآن مُترجَمة (“الصفحتان”). يفشل اختبار كناري جديد إذا فصلت أي لغة بينهما مجددًا.
ملاحظات
- نص فقط؛ دون تغيير في المسار/CSP/SSRF/الكتابة. تغيّرت قيمة i18n واحدة (ar)؛ دون مفاتيح جديدة (اللقطة 1219).
tests/two-pager-term-consistency.test.mjs(+2). المجموعة: 2424 (+2).
[1.164.0] — 2026-08-13
تم الإصلاح (منخفض) — لم يعُد نص البحث النائب يفيض في أي لغة. كان “Find a company, role or URL…” يُقتطع (nowrap) عند تقلّص شريط البحث، ولم يكن نصف “…or URL” يظهر أبدًا.
تم الإصلاح
- أصبح
top.search(×17) القصير “ابحث أو ألصق رابطًا” (≤24 حرفًا في كل لغة)، يتّسع حتى في شريط ضيّق ويحافظ على الإشارة إلى الرابط. النص النائب الاحتياطي فيindex.htmlمطابق؛ ويحتفظaria-labelبالتفصيل الكامل.
ملاحظات
- نص فقط؛ دون تغيير في المسار/CSP/SSRF/الكتابة. أُعيدت صياغة مفتاح i18n واحد قائم ×17 (دون جديد؛ اللقطة 1219).
tests/search-placeholder-fit.test.mjs(+2). المجموعة: 2422 (+2).
[1.163.0] — 2026-08-13
تم الإصلاح (منخفض) — أصبح مساعد “اسأل الوثائق” داخل التطبيق يغطّي تصدير تقرير إلى PDF. كان يجيب بأن الدليل لا يغطّي ذلك، رغم وجود زر 📄 Generate PDF يعمل في #/reports/:slug.
تم الإصلاح
- أُضيف عنوان H3 “تصدير تقرير إلى PDF” تحت §10 التقارير في جميع حزم المساعدة الـ17 (مكان الزر، وأن الملف يُكتب في
output/*.pdf، ويتطلّب Playwright، وراجِع قبل الإرسال). أصبح بحث المساعد يُظهر قسم التقارير.
ملاحظات
- الوثائق/المساعدة فقط؛ دون تغيير في الكود/المسار/CSP/SSRF/الكتابة. بوابة المساعدة 112 → 113 H3 (31 H2 دون تغيير).
tests/help-reports-pdf-section.test.mjs(+2). المجموعة: 2420 (+2).
[1.162.0] — 2026-08-13
تم الإصلاح (متوسط) — أصبح “?” المساعدة هدفًا بحجم ≥24×24 (WCAG 2.5.8). كان .help-hint بحجم 18×18 بكسل مع padding:0، دون الحد الأدنى، في كل عنوان.
تم الإصلاح
- صار صندوق
.help-hintالآن 24×24 (الهدف القابل للقياس) بينما تبقى الحلقة المرئية 18 بكسل — تُرسم عبر::beforeمتمركز، فلا يتغيّر المحرف ولا خط أساس<h1>. تتبع حالات التمرير/النشط/التركيز الحلقة؛ الهامش 6→3 بكسل للحفاظ على الفجوة.
ملاحظات
- CSS فقط؛ دون تغيير JS/i18n/المسار/CSP/SSRF/الكتابة.
tests/help-hint-target-size.test.mjs(+2). المجموعة: 2418 (+2).
[1.161.0] — 2026-08-13
تم الإصلاح (متوسط) — يعرض #/reports شارة “لم يُكتشف التقييم” بدل الفراغ. بعد محلّل v1.159.0 المتعدد اللغات، كان التقرير بلا تقييم قابل للتحليل يعرض منطقة فارغة لا تُميَّز عن الفشل.
تم الإصلاح
- تتفرّع خلية التقييم الآن: يوجد تقييم → حبة اللون؛ لا يوجد → شارة
.score-mutedخافتة (“لم يُكتشف التقييم”، ×17) مع تلميح “افتح التقرير…”. تبقى البطاقةrole="link"قابلة للتشغيل بلوحة المفاتيح ويظهر التاريخ. - تعيد استخدام الرمز المحايد القائم؛ دون لون جديد.
ملاحظات
- العميل فقط؛ دون تغيير في المسار/CSP/SSRF/الكتابة. +2 مفتاح i18n ×17 (اللقطة 1217 → 1219). المجموعة: 2416 (+3).
[1.160.0] — 2026-08-13
تم الإصلاح (عالي) — لم يعُد نص المزوّدين يناقض وعد المزوّدين السبعة. كان #/config يقول إن التقييم المباشر “يستخدم مفتاح Anthropic أو Gemini” وإن مفتاح OpenAI “لا تستخدمه واجهة الويب”؛ وكانت لوحة المعلومات تقول “Anthropic-first scoring” — وكلّه خاطئ منذ سلسلة المزوّدين السبعة (v1.157.0).
تم الإصلاح
config.providerModelNote(×17): يذكر الآن أن ⚡ التقييم المباشر يعمل دون واجهة بأيٍّ من مفاتيحك السبعة (Anthropic · Gemini · OpenAI · Qwen · OpenRouter · GitHub Models · Hermes)، مرتّبة تلقائيًا مع الرجوع الاحتياطي. حُذفت جملة OpenAI الخاطئة.dash.quick.evaluateSub(×17): محايد تجاه المزوّد (“تقييم الملاءمة 0–5”).Keys: N / 5←N / 7.
ملاحظات
- نص فقط؛ دون تغيير في المسار/CSP/SSRF/الكتابة. دون مفاتيح i18n جديدة (اللقطة 1217). المجموعة: 2413 (+3).
[1.159.0] — 2026-08-13
تم الإصلاح (عالي) — لم تعُد بيانات التقرير الوصفية مرتبطة باللغة. التقارير المُولَّدة بلغة غير الإنجليزية كانت تعرض شريط بيانات فارغًا في #/reports، لأن parseReportHeader كان يتعرّف على الوسوم الإنجليزية العريضة فقط.
تم الإصلاح
- يحلّل
parseReportHeaderالآن كتلة YAML الثابتة## Machine Summary(score:/legitimacy:/date:— نفس المصدر الذي يقرؤهauto-pipelineبالفعل): الوسوم الإنجليزية → كتلة Machine Summary → الوسوم المحلّية (REPORT_LABELS، 17 لغة). تبقى التقارير الإنجليزية متطابقة بايتًا ببايت. - تحليل رقمي متسامح (
1.5/5،1,5/5،1.5 из 5،4.5 out of 5)؛ ويرجع التاريخ إلى mtime الملف عند غيابه.
ملاحظات
- قراءة/تحليل فقط؛ دون تغيير في المسار أو CSP أو SSRF أو الكتابة في الأب. دون مفاتيح i18n جديدة. المجموعة: 2410 (+8).
[1.158.0] — 2026-08-12
تم الإصلاح — خطآن تجميليان في العرض (علامة «?» تتسرّب إلى عنوان التبويب، وعدد مزوّدين خاطئ في صفحة الهبوط). العرض فقط؛ دون تغيير في السلوك أو الأمان أو تدفّق البيانات.
تم الإصلاح
- لم تعُد «?» الخاصة بـ HelpHint تتسرّب إلى
document.title. كان الراوتر يشتق عنوان التبويب منh1.textContentالخام فيظهر «Vacancy search?» بدلاً من «Vacancy search». الآن يستنسخrouter.js::focusNewViewالعنوان ويزيل.help-hintثم يقرأ النص؛ وتبقى «?» المرئية دون مساس. - كانت cvstart.org تُظهر «17 AI providers» بدلاً من «7». كان المساعد
sub()فيFeatures.astroيستبدل كل{n}بعدد اللغات (17) قبل الاستبدال لكل بطاقة؛ والآن يُحلّ{n}لكل بطاقة (المزوّدون → 7، اللغات → 17).
ملاحظات
- دون تغيير في الخادم أو المسار أو CSP أو SSRF أو مفاتيح i18n. المجموعة: 2402 اختبار (+1).
[1.157.0] — 2026-08-12
تم الإصلاح — تعمل التقييمات المباشرة الآن مع أي مزوّد مُهيّأ، وليس فقط Anthropic/Gemini. كان المستخدم الذي عيّن OPENROUTER_API_KEY فقط يُجبَر خطأً على الوضع اليدوي.
تم الإصلاح
- السبب الجذري: تثبيت
LLM_PROVIDERدون مفتاح (مثلLLM_PROVIDER=claudeمنinit) كان يصل إلى طريق مسدود؛ والآن يتراجع إلى ترتيب auto بين المزوّدين المُهيّئين (فيselectActiveProviderوكِلا سلسلتَي الإرسال). - منطق الواجهة (
#/deepوواجهات mode-page) يستخدم الآنwindow.ProviderStatus(/api/status/providers، السبعة) بدل فحص Anthropic/Gemini المتقادم؛ نصوص مُعاد صياغتها (deep/eval × 17) + شارة «تقييمات مباشرة» في لوحة المعلومات +config.llmProviderHint.
ملاحظات
- لا تغييرات أمنية. المجموعة: 2401 اختبارًا (+5).
[1.156.0] — 2026-08-12
إعادة هيكلة — تقسيم scan.js تحت حدّ الحجم (P-16) + إصلاح CodeQL. كان scan.js بحجم 906 أسطر؛ استُخرج مصنعان يحافظان على السلوك → 648. يُكمل زوج تقسيم الواجهات P-15/P-16.
تم التغيير
- ملفان جديدان
scan/runner.js(محرّك تنفيذ الفحص) وscan/filters.js(آلة حالة المرشّحات) عبر حقائبctx/refs؛ يربطهماscan.js.
تم الإصلاح
- CodeQL
js/useless-assignment-to-local(#428) فيconfig/tab-controller.js:let n = i;→let n;.
ملاحظات
- إعادة هيكلة صرفة دون تغيير سلوك؛ أُعيد توجيه 4 اختبارات تقرأ المصدر. كلتا الواجهتين الكبيرتين أصبحتا تحت 800 (اكتمل P-15/P-16). المجموعة: 2396 اختبارًا.
[1.155.0] — 2026-08-12
إعادة هيكلة — تقسيم config.js تحت حدّ الحجم (P-15). كان config.js بحجم 1030 سطرًا (فوق حدّ 800)؛ استُخرج وحدتان تحافظان على السلوك ليصبح 783.
تم التغيير
- ملفان جديدان
config/field-specs.js(بيانات الحقول + قوائم النماذج) وconfig/tab-controller.js(مصنع شريط التبويبات)؛ يشير إليهماconfig.jsومنطق العرض دون تغيير.
ملاحظات
- إعادة هيكلة صرفة دون تغيير سلوك؛ أُعيد توجيه 6 اختبارات تقرأ المصدر. يبقى
scan.js(906) كما هو (مقسَّم جزئيًا بالفعل؛ نواته مترابطة أكثر من أن يفيدها تقسيم آلي نظيف). المجموعة: 2396 اختبارًا.
[1.154.0] — 2026-08-12
دليل جديد — «تشغيل المنظومة كاملةً في السحابة». لا يملك career-ops سردًا خاصًا للسحابة/الخادم، فأضفنا واحدًا: وصفة خطوة بخطوة لوضع خط الأنابيب الأصل career-ops وهذا العارض career-ops-ui ومحرّك الذكاء الاصطناعي (اشتراك Claude عبر Claude Code، أو Hermes محلي، أو مفاتيح API) على خادم صغير دائم التشغيل. يصل بوصفه المساعدة §31 بـ17 لغة، وقسمًا في README، وصفحة ويكي.
أُضيف
- المساعدة §31 «تشغيل المنظومة كاملةً في السحابة» (× 17) — الأجزاء الثلاثة، التجهيز + التثبيت، اختيار المحرّك، والعرض الآمن (بروكسي عكسي HTTPS + مصادقة + ثوابت CSP/SSRF/XSS/لا-أسرار). تنمو حزمة المساعدة إلى 31 H2 / 112 H3.
- README — قسم «تشغيل المنظومة كاملةً في السحابة» (× 17) + صفحة Cloud-Deployment في الويكي.
ملاحظات
- توثيق فقط — لا مسار ولا خادم ولا تغيير عميل؛ ولا مفتاح i18n جديد. تنتقل اختبارات المساعدة الأربعة إلى عقد 31 H2 / 112 H3. المجموعة: 2396 اختبارًا (دون تغيير).
[1.153.0] — 2026-08-12
نقل ماسح Jobvite إلى موجز XML العام (مزامنة مع الأصل). أوقف المشروع الأصل واجهة JSON الخاصة بـ Jobvite (تعيد صفر وظيفة)؛ وكان source في web-ui يستخدم النقطة الميتة نفسها، فكانت أي شركة Jobvite متتبَّعة تُمسح فارغة بصمت. نقل إصلاح الأصل (#2623): يقرأ الآن موجز XML العام لكل مستأجر بمفتاح companyEId.
تم الإصلاح
- كان source يطلب واجهة JSON الموقوفة ويعيد صفر وظيفة؛ وهو الآن يطلب
https://app.jobvite.com/CompanyJobs/Xml.aspx?c={companyEId}ويحلّل XML<result><job>…(CDATA + كيانات،detail-urlقبلapply-url).
تم التغيير
- حلّ
companyEId: (1)company_eid:في البوابة، (2) معاملc=لـapi:صريح، (3) اكتشاف من صفحة اللوحة. يُرفقfetchText(http-json.mjs) الحقلين.location/.retryAfterبخطأ non-ok (قراءة فقط، متوافق رجعيًا).
ملاحظات
- الأمان — مضيفان (
jobs.jobvite.com،app.jobvite.com) مثبّتان عبرassertJobviteUrl: https فقط، قائمة سماح صارمة، دون اتباع أي تحويل.companyEIdمجرد قيمة?c=؛ وعدد المصادر دون تغيير. - المجموعة: 2396 اختبارًا (+4).
[1.152.0] — 2026-08-12
مزوّد Hermes — اكتمل التوصيل + تحديث الوثائق. كشفت مراجعة كود لتكامل Hermes في v1.151.0 عن ثغرتين حقيقيتين وأربعة بنود اكتمال؛ أُصلحت جميعها هنا، ورُفعت قائمة مزوّدي LLM في التطبيق كله إلى السبعة الكاملة على كل أسطح الوثائق واللغات الـ17.
تم الإصلاح
- تعذّر فرض Hermes من
#/config— كانت قائمةLLM_PROVIDERتُدرج ستة مزوّدين فقط، فيمكن ضبطHERMES_API_KEYدون فرض Hermes من الواجهة. أصبحhermesالخيار الثامن، ويمنع اختبار تكافؤ جديد انحراف القائمة مجددًا عنLLM_PROVIDERS. - كانت المفاتيح المحلية القصيرة تُرفض بصمت — عُيِّر حدّ الـ20 حرفًا في
isUsableKeyلمفاتيح السحابة؛ يستخدمhasHermesKeyالآن حدًا مخففًا قدره 8 (مثال وثائق Hermes نفسه 19 حرفًا).
تم التغيير
- نُظِّمت قائمة المزوّدين إلى السبعة الكاملة في README (× 17) والمساعدة داخل التطبيق (× 17) وقاموس
config.llmProviderHint(× 17) وdocs/sdd؛ ويكملhermesChatUrlمضيفًا بلا مسار؛ ويذكر نص التراجع اليدوي Hermes.
ملاحظات
- الأمان دون تغيير — لا مسار جديد ولا تغيير SSRF/CSP؛ ويكتسب health/doctor صف
HERMES_API_KEY. - المجموعة: 2392 اختبارًا (+2).
[1.151.0] — 2026-08-12
أصبح Hermes الآن مزوّد LLM موصولًا (Phase 5) — أكّد فحص نطاق Phase 5 أن Hermes من Nous Research يضم خادم API Server متوافقًا مع OpenAI (hermes gateway → POST /v1/chat/completions)، لذا يُشغّل career-ops-ui الآن تقييمات مباشرة عبر Hermes محلي تمامًا مثل OpenAI/Qwen. اضبط HERMES_API_KEY في إعدادات التطبيق لينضم إلى ترتيب auto (الأخير). يُغلق آخر بند مفتوح في خارطة الطريق — Phase 5, Shape A.
أُضيف
- مزوّد LLM Hermes (Shape A) —
runHermesفوق العميل المشتركrunOpenAICompatible(server/lib/openai.mjs)، في كلتا السلسلتين (llm-dispatch.mjs+routes/llm.mjs)، في ذيل ترتيب auto + التثبيتLLM_PROVIDER=hermes، و/api/status/providers، وllm-pricing.mjs. يصل إلى base URL محلي قابل للضبط (افتراضيًاhttp://127.0.0.1:8642/v1) بمصادقة Bearer — وهو نقطة نهاية مزوّد مُهيّأة (مثل OpenRouter/Qwen)، وليست عنوان وظيفة يقدّمه المستخدم، لذا لا يمرّ عبر حارس SSRF. - حقول
#/config—HERMES_API_KEY(سرّي) +HERMES_BASE_URL+HERMES_MODEL(افتراضيًاhermes-agent)، مع 6 مفاتيح i18n جديدة × 17 لغة (لقطة 1208 → 1214).
تغيّر
- حُلّ فحص النطاق: ينتقل
docs/integrations/HERMES.mdوالمساعدة المدمجة §30 (× 17) وعرض README (× 14) ومهارةhermes-bridgeوخارطة الطريق من «مخطَّط له / غير موصول بعد» إلى موصول (Shape A). لم يلزم Shape B (relay مخصّص لبيئة تشغيل الوكيل).
ملاحظات
- الأمان: جلب المزوّد هو نقطة نهاية مُهيّأة، من الفئة نفسها لبقية المزوّدين المتوافقين مع OpenAI — لا سطح SSRF جديد، ولا تغيير في CSP/المنقّي.
HERMES_API_KEYهوSECRET_KEY(لا يُعرَض أبدًا). - اختبارات (معزولة في CI، نقل وهمي):
tests/hermes-provider.test.mjs(+5)؛ اختبار الكناري «لا فرع لـ Hermes» من v1.146.0 مقلوب ليؤكّد أنه موصول؛ حُدّثت اختبارات سطح المزوّدين إلى ترتيب 7 مزوّدين. - المجموعة: 2390 اختبارًا (+5).
[1.150.0] — 2026-08-12
حالات فارغة متسقة (صقل Phase 4) — أصبح كل لوح “لا شيء بعد” يُعرَض الآن عبر نمط .empty المشترك الوحيد، بدلاً من أن تعيد بعض العروض إعلان المظهر داخليًا برقم سحري 40px. إصلاح صغير للاتساق البصري؛ الحالات الفارغة في #/activity و#/cv-studio و#/stats و#/usage أصبحت الآن مطابقة لجميع الأخرى (حشوة 48px مرمَّزة + حدّ متقطّع).
تغيّر
#/activityو#/cv-studioو#/statsو#/usageأزالتstyle: { padding: '40px', textAlign: 'center', color: 'var(--foggy)' }المضمَّن على الألواح الفارغة — الخصائص الثلاث تقدّمها فعلاً الفئة المشتركة.empty(--space-7= 48px، توسيط، لون خافت، حدّ متقطّع). وهكذا تُعرَض هذه الأربعة مطابقةً لنحو 25 لوحًا.emptyآخر.- التجاوزات المشروعة لكل عرض (
#/dashboardwidth:100%،#/pipelineborder:none) لم تُمَس — أُزيلت فقط الإعلانات المكرّرة تمامًا.
ملاحظات
- تنظيف استخدام CSS في العميل فقط — دون تغيير في المسار أو الخادم أو مفتاح i18n أو قواعد CSS (فئة
.emptyنفسها دون تغيير)؛ لقطة القاموس 1208. تم التحقق في المتصفّح (لوح#/usageالفارغ يحسب 48px حشوة + حدّ متقطّع، 0 أخطاء وحدة تحكّم). - الاختبار الكناري الجديد
tests/empty-state-consistency.test.mjsيبقي.emptyمصدر الحقيقة الوحيد. تظل Phase 5 (مزوّد Hermes) معطَّلة. - المجموعة: 2385 اختبارًا (+2:
tests/empty-state-consistency.test.mjs).
[1.149.0] — 2026-08-12
نقل البوابات إلى الإعدادات (Phase 4) — أصبح #/portals الآن في مجموعة التنقّل Setup بجوار إعدادات التطبيق، بدلاً من Sourcing. منذ v1.144.0 وهو واجهة إعدادات (تفعيل/تعطيل الشركات المتتبَّعة + فحص حالة ATS)، وليس إجراء sourcing — لذا هذا مكانه الصحيح. تغيير في التنقّل فقط؛ الصفحة ومسارها دون تغيير.
تغيّر
- عنصر التنقّل
#/portals→ مجموعة Setup (فيpublic/index.html)، موضوع مباشرة بعد إعدادات التطبيق. أُزيل من مجموعة Sourcing (التي تحتفظ بـ Scan / Pipeline / Auto-pipeline / الشركات المموَّلة). المسار#/portalsوالعرض والتسميةnav.portalsدون تغيير — تحرّك موضع الشريط الجانبي فقط.
ملاحظات
- ترميز تنقّل فقط — دون تغيير في المسار أو العرض أو مفتاح i18n أو الخادم. تم التحقق في المتصفّح (0 أخطاء وحدة تحكّم)؛ محميّ بـ
tests/portals-nav-placement.test.mjs. - المجموعة: 2383 اختبارًا (+2:
tests/portals-nav-placement.test.mjs).
[1.148.0] — 2026-08-12
مرشّحات فحص أوضح (Phase 4) — لوحة المرشّحات أصبحت الآن شبكة مرتّبة — انتقلت لوحة مرشّحات #/scan من flex-wrap غير منتظم من صناديق صلبة متفاوتة العرض إلى شبكة متجاوبة، وأصبحت إجراءات «تطبيق / إعادة تعيين» الآن في صفّها الخاص المنفصل المحاذى إلى اليمين. المرشّحات نفسها والسلوك نفسه — فقط أسهل قراءة. تحسين تصميمي (دون parent-sync).
تغيّر
- لوحة مرشّحات
#/scan→ شبكة متجاوبة — أصبح.scan-filtersالآنdisplay: gridبأعمدةrepeat(auto-fill, minmax(180px, 1fr))وتباعد منتظم، بحيث تصطفّ المرشّحات الـ11 الموسومة في أعمدة مرتّبة عند أي عرض بدلاً من الالتفاف في صفّ غير منتظم. - إجراءات «تطبيق / إعادة تعيين» تمتدّ عبر الشبكة كاملةً في صفّها الخاص، مفصولةً بخطّ رفيع ومحاذاة إلى اليمين. أُزيلت حيلة التسمية المخفية القديمة + الغلاف flex الداخلي في
scan.js.
ملاحظات
- CSS فقط + تنظيف بسيط للـ DOM — كل معرّف مرشّح (
#scan-filter-*،#scan-apply) وربطSR.render()دون تغيير، لذا يبقى مسار Playwright سليمًا. لا مفاتيح i18n جديدة. - تم التحقق في المتصفّح (0 أخطاء وحدة تحكّم)؛ محميّ بـ
tests/scan-filters-grid.test.mjs. - المجموعة: 2381 اختبارًا (+3:
tests/scan-filters-grid.test.mjs).
[1.147.0] — 2026-08-12
Hermes & Telegram — قسم المساعدة داخل التطبيق + واجهة على cvstart.org (Phase 5b، الجزء 2) — الجزء الثاني والأخير من عمل توثيق Hermes: أصبح الشرح الآن داخل دليل المساعدة الخاص بالتطبيق بجميع اللغات الـ17، ويجيب مساعد التوثيق المدمج عن أسئلة Hermes استنادًا إليه. لا يزال الأمر يقتصر على التوثيق — يبقى مسار موفّر LLM الخاص بـ Hermes مخططًا له / غير موصول بعد (Phase 5).
أُضيف
- مساعدة داخل التطبيق §30 «Hermes & Telegram» × 17 لغة — قسم دليل جديد (ما هو Hermes + شكلا التكامل؛ التشغيل على خادم سحابي؛ Telegram عبر Hermes + قاعدة «ما الذي يجب ألا يُكشَف»)، يمكن الوصول إليه من
#/help. يلتقطه grounding فيdocs-assistant/DocsFabتلقائيًا لأن كليهما يقرأdocs/help/<lang>.md. - cvstart.org — رابط إلى دليل Hermes يشير إلى المستند على GitHub.
تغيّر
- رُفِع حد حزمة المساعدة إلى 29 → 30 H2 / 105 → 108 H3 (
canonical-docs-coverage،help-ui،help-ru-config-section)؛ يضيف §30 ثلاثة عناوين H3.
ملاحظات
- لا شيء يستدعي Hermes حتى الآن. يتحقق الاختبار الكناري الجديد
tests/help-hermes-section.test.mjsمن أن كل لغة تحوي §30 مع مراسيها المستقلة عن اللغة (docs/integrations/HERMES.md،hermes-bridge،#/help،127.0.0.1، Telegram). يظل المزوّد معطَّلًا بانتظار عقد واجهة برمجة التطبيقات في Phase 5. - هذا يُغلق مُخرَج التوثيق + skill لـ Phase 5b؛ ويظل تكامل المزوّد (Phase 5) بندًا منفصلًا ومعطَّلًا.
- المجموعة: 2378 اختبارًا (+2:
tests/help-hermes-section.test.mjs).
[1.146.0] — 2026-08-12
وكيل Hermes + Telegram — دليل التكامل + skill (Phase 5b، الجزء 1) — يمكنك تشغيل career-ops-ui على خادم سحابي وربط أحداثه (فحص منتهٍ، تقرير جديد، متابعة عاجلة) بـ Telegram عبر وكيل Hermes من Nous Research. يقدّم هذا الإصدار وثائق التصميم + النشر و skill بعنوان hermes-bridge؛ ويبقى مسار موفّر LLM الخاص بـ Hermes مخطَّطًا له / غير موصول بعد (معطَّل بسبب spike عقد API لـ Phase 5). الوثائق تسبق الكود بشكل مقصود.
أُضيف
docs/integrations/HERMES.md— الشرح المعمّق: شكلا التكامل (نقطة نهاية متوافقة مع OpenAI مقابل بيئة تشغيل وكيل)، النشر على خادم سحابي (reverse proxy + HTTPS + systemd، وعقد القراءة فقط مع الـ parent على جهاز بلا واجهة)، Telegram عبر Hermes، وقائمة نموذج تهديدات لما «يجب ألا يُعرَض» (لا سيرة ذاتية / راتب / محتوى تقارير / مفاتيح إلى القناة).- عرض
## Hermes agent + Telegramفي README — إشارة مختصرة مع رابط في README الإنجليزي، وتنعكس في نسخ README المترجمة بالكامل لكل لغة. - skill بعنوان
hermes-bridge(.claude/skills/hermes-bridge/) تُفعّل الدليل عمليًا — فحوصات الشروط المسبقة وحدود النطاق (Node ≥ 18، وجود المفاتيح، إمكانية الوصول إلى نقطة النهاية عبر المسار الآمن من SSRF)، لا تكتب الأسرار على القرص/السجلات أبدًا، وترفض اختراع نقطة نهاية لـ Hermes أو الزعم بأن الموفّر متصل. - قسم Integrations في
docs/architecture/OVERVIEW.mdيربط بالدليل.
ملاحظات
- لا شيء يستدعي Hermes حتى الآن. اختبار كناري (
tests/hermes-docs.test.mjs) يتحقق من علامات الصدق «مخطَّط له / غير موصول بعد» ومن أنllm-dispatch.mjsلا يحتوي على أي فرع لـ Hermes/Nous — لذا فإن توصيل الموفّر لاحقًا يجب أن يحدّث الوثائق + خارطة الطريق في نفس التغيير. - مؤجَّل إلى v1.147.0 (Phase 5b، الجزء 2): قسم المساعدة داخل التطبيق «Hermes & Telegram» H2 × 17 لغة، وواجهة تسويق cvstart.org.
- المجموعة: 2376 اختبارًا (+4:
tests/hermes-docs.test.mjs).
[1.145.0] — 2026-08-12
إحصاءات ثاقبة (تابع): رسم بياني قابل لإعادة البناء — أصبحت علامة التبويب «اتجاه الأدوار المستهدفة» في #/stats تحوي أداة إنشاء رسم بياني: اختر مقياسًا × بُعدًا فيُعاد رسمه مباشرة. طلب UX من المستخدم (بدون parent-sync).
أُضيف
- رسم بياني قابل لإعادة البناء بحسب المقياس × البُعد — اختر مقياسًا (الوظائف / الراتب الوسيط / متوسط الراتب) وبُعدًا (حسب البلد / حسب الدور) فيُعاد رسم المخطط الشريطي فورًا. تحترم مقاييس الرواتب العملة ومبدّل سنويًا ⇄ شهريًا؛ أما الوظائف فهي عدّ بسيط.
- 8 مفاتيح i18n جديدة × 17 لغة؛ اللقطة 1200 → 1208.
ملاحظات
- تم التحقق في المتصفح (0 أخطاء وحدة تحكم). المجموعة: 2372 اختبارًا (+2).
[1.144.0] — 2026-08-12
الإعدادات والمرشحات (المرحلة 4، الجزء 1): تفعيل/تعطيل البوابات المتتبَّعة — يمكنك الآن تشغيل أو إيقاف شركة مراقَبة من #/portals، والماسح يحترم ذلك. طلب UX من المستخدم (بدون parent-sync).
أُضيف
- زر تفعيل/تعطيل لكل شركة في
#/portals— نقرة واحدة تُطفئ بوابة (الماسح EN يتخطى بالفعل الشركات ذاتenabled: false، فتخرج البوابة المعطَّلة من كل عمليات الفحص المقبلة) أو تعيد تشغيلها، مع إشعار تفاؤلي. POST /api/portals/toggle— كتابة صريحة من المستخدم تبدّل جراحيًا ومع التحقق من التحليل علامةenabledلشركة فيportals.yml(مع الحفاظ على التعليقات والترتيب وبقية الحقول). 5 مفاتيح i18n جديدة × 17 لغة؛ اللقطة 1195 → 1200.
ملاحظات
- تغيير الماسح كان صفرًا —
en-scanner.mjsيفلتر بالفعلenabled !== false. المجموعة: 2370 اختبارًا (+3).
[1.143.0] — 2026-08-12
سهولة الفهم (تابع): تلميحات ? على شاشات العمل الأساسية — يغطّي ? المساعدة الآن الصفحات التسع الرئيسية للإجراءات، بكل اللغات. تحسين UX مبلَّغ من المستخدم (بدون parent-sync).
أُضيف
- تلميح مساعدة
?على 9 عناوين شاشات إضافية —#/scan,#/evaluate,#/cv-studio,#/tracker,#/config,#/deep,#/batch,#/auto,#/applyتحصل على?مضمّن (عبرHelpHint.title) يفتح نافذة منبثقة مترجمة «ماذا يفعل / كيف تستخدمه / ماذا تتوقع» — نفس المكوّن الآمن لـ CSP من v1.139.0. - 9 مفاتيح i18n جديدة × 17 لغة (
help.hint.scan/…/apply)؛ اللقطة 1186 → 1195.
ملاحظات
- تم التحقق في المتصفح (0 أخطاء وحدة تحكم). المجموعة: 2365 اختبارًا (+1).
[1.142.0] — 2026-08-12
تصحيح: لا مزيد من النمط المهني “Unknown” — أصبحت #/orientation تُصنّف دائمًا من بين ثمانية متجهات مهنية مُسمّاة بدلاً من الإجابة أحيانًا بـ“Unknown” والتوصية بـ«مضاعفة التركيز» عليه. تصحيح مبلَّغ من المستخدم (بدون parent-sync).
أُصلح
#/orientation— يمنع موجّه الذكاء الاصطناعي الآن أي نمط خارج المجموعة. يجب على النموذج ترتيب أفضل ثلاثة من بين الثمانية المُسمّاة تحديدًا، ولا يجوز أبدًا الإجابة بـ“Unknown”/“N/A”/“بيانات غير كافية” أو اختراع تسمية. وإن كانت السيرة ضعيفة، يسمّي الأقرب ثلاثة بثقة أقل ويوضّح الأدلة الناقصة بدل الامتناع.
ملاحظات
- تغيير موجّه الخادم فقط (
buildOrientationPrompt)؛ دون تغيير i18n/المخطط. المجموعة: 2364 اختبارًا (+1).
[1.141.0] — 2026-08-12
إحصاءات ثاقبة (تابع): إثراء الشركات المموَّلة — أصبحت #/funded أكثر بصرية: شعارات الشركات، ورسم بياني حسب مبلغ التمويل، وبطاقات تحوي الجولة / المبلغ / درجة الاكتشاف / الإجراء المقترح. تحسين UX مبلَّغ من المستخدم (بدون parent-sync).
تغيّر
#/funded— جدول مسطّح ← شبكة بطاقات. كل شركة مموَّلة حديثًا صارت بطاقة تحوي شعارًا (مشتقًا من الاسم عبرCompanyLogo، مع صورة حرفية كبديل)، ورقاقتَي الجولة + المبلغ، ودرجة الاكتشاف والإجراء المقترح من المشروع الأصلي، مع رابط الخبر وتاريخه.- تصوير مبلغ التمويل — رسم بياني شريطي أفقي لأكبر الشركات حسب المبلغ المُعلن؛ تُحلَّل المبالغ النصية الحرة (“$120M”/“€1.5B”) إلى مقدار عبر
parseAmountجديد. 3 مفاتيح i18n جديدة × 17 لغة.
ملاحظات
- لا يزال للقراءة فقط عبر
GET /api/company-funded؛ الوصف ونطاق الراتب غير موجودَين في مصدر التمويل. المجموعة: 2363 اختبارًا (+2).
[1.140.0] — 2026-08-12
إحصاءات ثاقبة: أرقام رواتب أغنى — أصبح تفصيل الرواتب في «مساري» على #/stats يعرض الآن المتوسط (وليس الوسيط فقط)، ومبدّل سنويًا ⇄ شهريًا، وجدول الأدنى · المتوسط · الوسيط · الأعلى لكل بلد. أول جزء من المرحلة 3. تحسين UX مبلَّغ من المستخدم (بدون parent-sync).
أُضيف
- متوسط الراتب — أصبح
RoleStats.salaryStatsيُرجعavgUsdإلى جانبminUsd/medianUsd/maxUsd. الوسيط يقاوم القيم الشاذة، والمتوسط يكشف الانحراف، فيُقرآن معًا كتوزيع. - مبدّل سنويًا ⇄ شهريًا وجدول الأدنى · المتوسط · الوسيط · الأعلى لكل بلد في قسم الرواتب، مرتبطان بمحدِّدَي العملة والفترة. 8 مفاتيح i18n جديدة × 17 لغة.
ملاحظات
- الأرقام لا تزال مستمدة فقط من الإعلانات ذات الراتب القابل للقراءة ومُطبَّعة إلى الدولار (استرشادية). المجموعة: 2361 اختبارًا (+1).
[1.139.0] — 2026-08-12
سهولة الفهم: تلميحات ? — زر ? قابل لإعادة الاستخدام وآمن لـ CSP يشرح عند النقر «ماذا يفعل / كيف يعمل / ماذا تتوقع» بلغتك. تحسين UX مبلَّغ من المستخدم (بدون parent-sync).
أُضيف
- نافذة تلميح المساعدة
?(window.HelpHint) — يفتح زر?الدائري بجوار العنوان نافذة منبثقة خفيفة، تتوافق مع السمة ومنعكسة في RTL، وتعرض شرحًا مترجمًا عبرUI.md()؛ متاحة للوصول (role="tooltip"،aria-expanded، الإغلاق بـ Escape/النقر خارجها، استعادة التركيز) وآمنة لـ CSP. - إضافة
?إلى علامات التبويب الخمس في#/statsوإلى 8 عناوين لشاشات الذكاء الاصطناعي/التحليلات (career-plan، التوجيه، two-pager، التواصل، المقابلة التجريبية، الذاكرة، funded، الملخص الأسبوعي) — 14 مفتاح i18n جديدًا × 17 لغة.
ملاحظات
- كانت كل الشاشات تحمل بالفعل عنوانًا فرعيًا من سطر واحد؛ ويضيف
?الشرح الأعمق عند الطلب ويجعل الحالات الفارغة مفهومة ذاتيًا. المجموعة: 2360 اختبارًا (+4).
[1.138.0] — 2026-08-12
التوليد بلغة واجهتك — كل توليد بالذكاء الاصطناعي يردّ الآن باللغة التي اخترتها في الواجهة، إضافةً إلى تعزيزات اختبار ناتجة عن المراجعة. تحسين UX مبلَّغ من المستخدم (بدون parent-sync).
تغيّر
- توليدات الذكاء الاصطناعي تحترم الآن لغة الواجهة. عند ضبط الواجهة على الروسية أو الإسبانية أو اليابانية… يعود النص المولَّد بتلك اللغة بدلاً من الإنجليزية دائماً. مُوجِّه لغة الإخراج ممرَّر عبر كل نقاط التوليد — خطة المسار المهني، التوجيه، تقرير السوق، المقابلة التجريبية، خطة التواصل، «اسأل التوثيق»، اقتراح ملاحظة الذاكرة، ومسودة two-pager. تبقى الشيفرة والمعرّفات بالإنجليزية (مثل مفاتيح YAML في two-pager)؛ ويُترجَم فقط النص والعناوين والنقاط.
أُصلح
- حارس أدوار ألوان CSS (
tests/css-role-tokens.test.mjs) — كناري ثابت يتحقّق أن رموز الأسماء المستعارة للوضع الداكن من v1.137.0 لا تعكس دورها أبداً: رموز النص (--fg/--danger/--ok/…) لا تُستخدم أبداً كـbackground، ورموز الأسطح (--card/--panel/--line/…) لا تُستخدم أبداً كـcolorللنص، عبر كل CSS وأنماط SPA المضمّنة. - الفحص الذاتي لمحمّل XSS في
UI.md()— الاختبار الذي يحمّلmd()منapi.jsصار يفحصmd('<script>…')مباشرة بعد الاستخراج ويرمي خطأً إذا غاب الهروب، فيفشل أي تقطيع خاطئ مستقبلي بصوتٍ عالٍ بدل ترك مجموعة الأمان خضراء على دالة مبتورة. - حارس التمرير في
#/career-plan— يُنفَّذscrollIntoViewبعد التوليد فقط عندما تكون المعاينة ما زالت متصلة بالمستند.
ملاحظات
- حُدِّث
docs/UX-ROADMAP.md: تلميحات المساعدة?+ أوصاف الصفحات + الحالات الفارغة صارت v1.139.0؛ ومزوّد Nous Research / Hermes — مع دليل نشر على خادم سحابي + Telegram ومهارة Hermes — يُتابَع كـ المرحلة 5 / 5b. - المجموعة: 2356 اختباراً (+5).
[1.137.0] — 2026-08-11
إصلاحات قابلية القراءة والعرض — تباين الوضع الليلي، وتسميات الرسوم البيانية، وخطة المسار المهني. مراجعة لتجربة المستخدم (UX) بناءً على بلاغ من مستخدم (بلا تكافؤ مع المشروع الأصل).
أُصلح
- تعارض الألوان في الوضع الليلي (نص أبيض على أبيض / أسود على أسود) في شاشات عديدة — خمس عشرة خاصية CSS مخصَّصة كانت تستخدمها عدة صفحات (
--fg،--panel،--panel-2،--ok،--danger،--card، …) لم تكن مُعرَّفة إطلاقاً، فكانت تعود إلى قيم فاتحة/داكنة ثابتة يدوياً: لا بأس بذلك في الوضع النهاري، لكنها غير قابلة للقراءة في الوضع الليلي (رقائق النظرة العامة في#/pipeline، والتبويب النشط في#/stats، وقسم “Active / Keys” + “✓ set” في#/config، وأقسام#/two-pager، وفقاعة السؤال في#/mock-interview، ونص الخطأ). أصبحت هذه الخاصيات الآن مُستعارة إلى الرموز الحقيقية المُدرِكة للسمة، فتتبع السمة تلقائياً — صفر إخفاقات تباين وفق WCAG-AA عبر جميع الصفحات الـ29، بحسب أداة تدقيق آلية؛ وانتقل التبويب النشط في#/configإلى تصميم شارة مُظلَّلة قابلة للقراءة. حارس انحدار (tests/dark-theme-tokens.test.mjs) يُبقيها مُستعارة. - كانت تسميات الرسوم البيانية في
#/statsتُقطَع في منتصف الكلمة (“Senior Backend Engineer” → “…Enginee”) — أصبحت الآن تُختصَر بعلامة حذف (…) مع الاحتفاظ بالتسمية الكاملة كتلميح يظهر عند التمرير. - كانت
#/career-planتعرض الخطة المُولَّدة كنص Markdown خام — أصبحت تُعرَض تلقائياً الآن كنص مُنسَّق سهل القراءة (يبقى Markdown القابل للتحرير في مربع النص؛ ويُبدِّل زر «معاينة» العرض بينهما).
ملاحظات
- لا تُعَدّ
#/career-plan، و#/two-pager، و#/stats، وموجز المقابلات الأسبوعي معطَّلة — فهي تعرض حالات فارغة إلى أن تُولَّد خطة أو تتوفر بيانات. من المخطَّط توفير توجيه أوضح داخل الصفحة وتلميحات مساعدة بعلامة؟في الإصدار القادم (docs/UX-ROADMAP.md).
[1.136.0] — 2026-08-11
تكافؤ مع المشروع الأصل career-ops v1.26.x (الفرع الرئيسي بعد v1.26.0) — مصدر جديد واحد بلا حاجة إلى مصادقة، إضافة إلى موجة من عمليات نقل الجودة والمتانة إلى نظائر web-ui المُبرمَجة. أصبح السجل الآن 79 مصدراً = 74 إنجليزية + 5 روسية (ALL_ADAPTERS 74).
أُضيف
eightfold(Eightfold AI، #2684) — لوحات استقطاب المواهب عبر واجهةhttps://<tenant>.eightfold.ai/api/apply/v2/jobsبلا حاجة إلى مصادقة، مُثبَّتة المضيف على*.eightfold.ai(يُرفض عمداً اسم CNAME المُعلَّم بالعلامة التجاريةcareers.<company>.com)؛ بترقيم صفحات محدود بسقف أمان، وإطلاق خطأ عند اللوحة الميتة، وإزالة تكرار الروابط. مصدر + مُحوِّل + مجموعة اختبار معزولة عن CI؛ يظهر في مرشِّح المصدر بصفحة#/scanوعلى الصفحة الرئيسية.
أُصلح
- مفاتيح إزالة التكرار ومطابقة الأدوار المُدرِكة لـUnicode (#2569 / #2587 / #2667) — دالة
normalizeTextKeyمشتركة جديدة (NFKC، تحتفظ بالحروف والعلامات والأرقام من أي نظام كتابة) تحل محل المفاتيح المقصورة على ASCII: أصبحتdetect-repostsتُجمِّع الآن متغيرات الشركة المختلفة في العرض/الترقيم (“Acme, Inc.” ≡ “Acme Inc”)، ولا تدمج أبداً أصحاب عمل متمايزين غير لاتينيين، بينما تطويrole-matcherالعناوين ذات العرض الكامل وتحتفظ برموز الأدوار غير اللاتينية بدلاً من محوها. - لم تعد
fetchJsonWithRetryتُعيد المحاولة عند رفض إعادة توجيه (#2657) — عندما يُقابِل حارسredirect:'error'استجابة من فئة 3xx فإن ذلك حتمي، فأصبح غير قابل لإعادة المحاولة الآن، ويفشل بسرعة بدلاً من استهلاك ميزانية إعادة المحاولة. - مجموعات AND في
title_filter.positive(#2552) — الفاصل+المُحدَّد بمسافات داخل إدخال إيجابي يتطلب الآن ظهور كل حد في العنوان، بأي ترتيب. - أصبحت
oraclecloudتقبل نطاقات المستأجرين المُرقَّمةoraclecloud1.com … oraclecloud99.com(#2683) — عائلة محدودة (بلا صفر بادئ، وبحد أقصى رقمين)، وليست نطاقاً عاماً (wildcard) أبداً. - تصليب
workable(#2675) — إعادة محاولة، وترويسات (headers) شبيهة بالمتصفح، وتسلسل الطلبات في مواجهة المضيف المحمي بـCloudflare. - أصبحت
personioتعود إلى استخلاص HTML عندما تكون تغذية XML معطَّلة، بدلاً من أن تُعيد شيئاً فارغاً. - أُعيدت مزامنة أسماء
statesالبديلة (FALLBACK) مع المشروع الأصل (#2615).
ملاحظات
- لم يُنقَل (غير مُعكَس في web-ui، أو خاص بواجهة سطر الأوامر فقط): reply-matcher (#2672)، وjd-similarity (#2661)، وjd-skill-gap (#2686)، ومسار البيئة الخاص بالمسح (#2568) / تحليل
--flag=value(#2589)، وتغييرات خطاب التقديم / قالب السيرة الذاتية / doctor / ollama / إنشاء PDF. أما تحذيرات الأمان عالية الخطورة الخاصة بـjs-yaml/nanoidللويب فقد جرى تصحيحها بالفعل في web-ui الإصدار v1.135.0.
[1.135.0] — 2026-08-11
تكافؤ مع المشروع الأصل career-ops v1.26.0 — خمسة مصادر مسح جديدة بلا حاجة إلى مصادقة، إضافة إلى إصلاحات تصحيح لأربع لوحات تحملها career-ops-ui بالفعل. أصبح السجل الآن 78 مصدراً = 73 إنجليزية + 5 روسية (ALL_ADAPTERS 73).
أُضيف
- خمسة مصادر مسح جديدة (كل مصدر منها بملف مصدر + مُحوِّل + مجموعة اختبار معزولة عن CI؛ تظهر في مرشِّح المصدر بصفحة
#/scanوعلى الصفحة الرئيسية لـcvstart.org):join(JOIN) — لوحة JOIN الخاصة بشركة ما، تُقرأ من__NEXT_DATA__الخاص بـNext.js المُضمَّن فيjoin.com/companies/<slug>(مُثبَّت المضيف، ومحدود عدد الصفحات).getro(Getro) — لوحات محافظ صناديق رأس المال الجريء ذات “شبكة المواهب”، عبر واجهةapi.getro.comالعامة بطلبات POST، بترقيم صفحات تنازلي من الأحدث؛ تُنسب كل وظيفة إلى الشركة المحفظة نفسها لا إلى الصندوق.consider(Consider) — لوحات محافظ صناديق رأس المال الجريء على getconsider.com عبر طلب POST من المصدر نفسه؛ المضيف المُحدَّد عبر الإعداد مُثبَّت بواسطة حارس بنيوي ضد هجمات SSRF (مضيف HTTPS عام فقط).joinup(JOINUP) — اللوحة السويسرية joinup.ch، بقراءة أحدث صفحة مُصيَّرة من جهة الخادم (SSR)؛ تتوقف بأمان عند عطل في أداة الاستخلاص.remotli(Remotli) — remotli.ch، أدوار عمل عن بُعد لدى شركات سويسرية (رواتب بالفرنك السويسري)؛ يُصدِر رابط التقديم الخاص بنظام ATS التابع لصاحب العمل نفسه، بحيث تُزال التكرارات بين الإعلانات المتقاطعة.
أُصلح
- لم تعد a16z Speedrun تُلغي اللوحة بأكملها عند عطل عابر — أصبحت طلبات جلب الصفحات تمر الآن عبر
fetchJsonWithRetryمشتركة (إعادة محاولات محدودة عند أخطاء 429/5xx/انتهاء المهلة العابرة فقط، ولا تُعاد المحاولة أبداً عند خطأ 4xx دائم)، وأُعيد ضبط ميزانية الصفحة لتناسب صفحة الـ50 وظيفة. - انتقلت arbeitsagentur إلى واجهة Jobsuche الإصدار v6 (
/pc/v6/jobs) — أصبحت نقطة النهاية القديمة v4 تُعيد خطأ 404؛ أُعيدت تسمية شكل الاستجابة، وأصبح تصفية العمل عن بُعد تُضيَّق الآن من جهة الخادم. - انتقلت thehub إلى واجهة الإصدار v2
jobsandfeatured— لا تحمل الصفوف تاريخ نشر، وهي مُستثناة من مرشِّح الأقدمية. - أصبحت hackernews تعثر على سلسلة “Who is hiring?” الشهرية بموثوقية — عبر تصفية بحث Algolia إلى وسم حساب
author_whoishiringبدلاً من استعلام نص حر.
ملاحظات
- لم يُنقَل (واجهة career-ops-ui آمنة بالفعل، أو مُمرَّرة للقراءة فقط، أو خاصة بواجهة سطر الأوامر فقط): مفاتيح إزالة تكرار الأدوار / مطابقة الشركات الخاصة بالـUnicode (تجميع إعادة النشر الخاص بـweb-ui يُحدِّد الشركة بالفعل بحرف صغير عادي، بحيث لا تتداخل الشركات غير اللاتينية المتمايزة أبداً)؛ إشارة تأخّر الرفض الخاصة بالمتابعة وتحسينات الشركات الممولة (تُمرَّر للقراءة فقط، مع فشل آمن)؛ مسارات المسح القابلة للتجاوز عبر متغيرات البيئة وتحليل
--flag=value(تُشغِّل web-ui الماسحات داخل العملية نفسها)؛ إعادة هيكلة توحيد وكيل المستخدم (User-Agent) (تُطبِّقها web-ui مركزياً بالفعل)؛ والعناصر الخاصة بواجهة سطر الأوامر فقط (قائمة المحتوى غير الموثوق،oferta/offer-prep،doctor، تغييرات قالب خطاب التقديم/السيرة الذاتية).
[1.134.1] — 2026-08-05
تصليب التحقق من الصحة — إصلاحات كشف عنها تدقيق شامل للمشروع.
أُصلح
- لم يعد
successfactorsيُهدر الوظائف المُجمَّعة عند فشل في منتصف المسح (انحدار في تحويل «إطلاق خطأ اللوحة الميتة» بإصدار v1.134.0) — لم تكن حلقة الترقيم (pagination) الخاصة به تحتوي علىtry/catch، فكان الفشل في الصفحة 2 وما بعدها (بعد نجاح الصفحة الأولى) يُطلِق خطأً ويُهدر كل ما جُمِع مسبقاً؛ وإذا كان ذلك الفشل من نوع404(بقيمةstartrowخارج النطاق)، كانen-scannerيحجر مستأجراً (tenant) حيّاً بوصفه ميتاً لأيام. أصبح الآن يُطابق سلوكphenom/radancy: لا يزال الفشل في الصفحة صفر يُطلِق خطأً (لوحة ميتة)، لكن الفشل في صفحة لاحقة يُبقي على النتائج الجزئية. - أصبحت رقاقات (chips) تصفية
#/scanقابلة للتشغيل عبر لوحة المفاتيح (WCAG 2.1.1) — كانت رقاقات الأوجه (وأيضاً رقاقة «مسح») عناصرspanبمعالج نقر فقط، دونtabindexأو دور (role)، فلم يكن بمقدور مستخدمي لوحة المفاتيح وقارئات الشاشة الوصول إليها أو تبديلها. تحمل الآنrole="button"وtabindex="0"وaria-pressed، وتُفعَّل بمفتاحي Enter/Space. - أصبحت ثلاث سلاسل نصية إنجليزية مُثبَّتة يدوياً (hardcoded) مُترجَمة الآن — كانت تلميحة شارة الثقة (trust-badge tooltip) في
#/scan، وعنوان عمود إعادة التموضع (relocation) في#/scan، وعنوان عمود النتيجة في#/dashboardسلاسل حرفية عارية لا تراها بوابة تكافؤ الترجمة (i18n parity gate) — لأنها لم تكن مفاتيح (keys) قط — فبقيت بالإنجليزية في كل لغة غير الإنجليزية. أصبحت الآنscan.trustTip+scan.col.reloc(مفتاحان جديدان) + إعادة استخدام لـtrack.col.score، مع حارس (guard) ثابت المصدر.
[1.134.0] — 2026-08-05
تكافؤ مع المشروع الأصل career-ops v1.25.0.
أُضيف
- مصدر مسح جديد: getManfred (
manfred) — تغذية على مستوى اللوحة بأكملها لوظائف تقنية في إسبانيا والاتحاد الأوروبي بأجور منشورة، منwww.getmanfred.com/api/v2/public/offers(بلا مصادقة، مثبَّتة المضيف + HTTPS فقط، كتالوج كامل باستدعاء واحد). مصدر + مُحوِّل + مجموعة اختبار معزولة عن CI (tests/sources-manfred.test.mjs)؛ أصبح السجل الآن 73 مصدراً = 68 إنجليزية + 5 روسية (ALL_ADAPTERS68). يظهر في مرشِّح المصدر بصفحة#/scanوعلى الصفحة الرئيسية لـcvstart.org.
أُصلح
- كانت تغذية a16z Speedrun تُقتَطع بصمت إلى 50 وظيفة (#2404) — تُقيِّد التغذية الصفحة الواحدة بـ50 وظيفة، بينما كان المصدر يطلب
PER_PAGE = 100، فتوقّف الترقيم بعد الصفحة الأولى. جرى تصحيحها إلى 50. - أصبحت اللوحات الميتة تُطلِق خطأً بدلاً من أن تُقرأ وكأنها “حيّة لكن فارغة” (#2379) —
cryptocurrencyjobs، وphenom، وradancy، وsuccessfactors: أصبح فشل الجلب الذي لا يُحسَم فيه أي طلب الآن يُطلِق خطأً (بحيث تُسجِّل صحة#/portalsوالمسح فشلاً حقيقياً)، بدلاً من ابتلاعه كقائمة فارغة؛ الفشل في منتصف المسح بعد نجاح واحد على الأقل يُبقي على النتائج الجزئية. - أصبح workable يستخدم الآن واجهة الودجت العامة (#5ab8425) — جرى التحوّل إلى
apply.workable.com/api/v1/widget/accounts/<slug>، التي تُعيد قائمة النشر الكاملة لحساب كبير في طلب واحد، بحيث لم تعد الحسابات الكبيرة تُقتَطع.
ملاحظات
- لم يُنقَل (خاص بواجهة سطر الأوامر فقط أو غير مُعكَس في web-ui): إعادة كتابة أداء تجميع العناوين الخاصة بـdetect-reposts #2389؛ إصلاحات مفتاح الشركة الخاصة بـUnicode (إزالة تكرار المتتبِّع الخاص بـweb-ui آمنة بالفعل للأحرف غير اللاتينية)؛
scan --since؛cv-facts؛ مسار تدقيق قالب السيرة الذاتية / PDF؛doctor؛ توجيه المحتوى غير الموثوق للأوضاع.
[1.133.1] — 2026-08-02
أُصلح
#/funded(الشركات الممولة) يعرض النتائج الآن — خطآن كانا يجعلان الجدول يظهر دائماً “لا توجد شركات ممولة” حتى عندما يُعيد سكربت المشروع الأصلcompany-funded.mjsقائمة كاملة. (1) كان العرض يقرأ النتائج تحتres.candidates، بينما يُصدرها المشروع الأصل تحتcompanies(كل عنصر بالشكل{company, amount, round, funding: { sources: [{ source, url, observed_date }] } })؛ يقرأ العميل الآن المفتاح الصحيح ويُطابق شكل الأدلة الفعلي. (2) كان جدول النتائج يُمرِّر خلاياه إلىUI.el('tr', {}, …)كوسائط متغيرة (varargs)، لكنUI.el(tag, attrs, children)يتوقع أن يكونchildrenعقدة واحدة أو مصفوفة، لذا لم يكن يُعرَض سوى العمود الأول (الشركة) فقط — أصبحت الخلايا الآن تُمرَّر كمصفوفة. جرى التحقّق في متصفح فعلي: تُعرَض 11 شركة عبر التغذيات الأربع بأعمدة الشركة / إشارة التمويل / المصدر / التاريخ، مع روابط أدلة عاملة، ودون أي أخطاء في وحدة التحكم (console). أصبح المرور الفارغ الآن يُظهر أيضاً تشخيصات كل مصدر على حدة، بحيث يمكن تمييز يوم إخباري هادئ عن تغذية محظورة.- ضمانات انحدار جديدة في
tests/parity-routes-v1133.test.mjs: أصبح سكربت المشروع الأصل الوهمي (fake) يُصدر الآن شكل الإخراج الحقيقيcompanies(كانت التركيبة (fixture) الأصلية تعكس شكلcandidatesالخاطئ — وهذا بالضبط سبب انطلاق الخطأ للإنتاج)، إضافة إلى كناري (canaries) ثابتة المصدر تتحقق من أنfunded.jsيقرأres.companies(وليسres.candidatesأبداً) ويبني صفوف الجدول بخلايا كمصفوفة (+1 ← 2144).
career-ops-ui v1.267.1 · page 5/11 · mirror of the project changelog for cvstart.org