تصميم Loupe: تعليقات تبقى بعد إعادة النشر
هذه ترجمة آلية لم تُراجَع بعد. الأصل الإنجليزي هو المرجع. اقرأ الأصل الإنجليزي
Loupe أداة ملاحظات مرئية: يثبّت شخص تعليقًا على عنصر في صفحة حية، ويقرؤه وكيل ذكاء اصطناعي عبر MCP. الجزء الصعب في تصميمه أمران. الأول أن يبقى التعليق مثبّتًا بعد إعادة نشر تغيّر الشيفرة. والثاني أن يستطيع الوكيل العمل على التعليق دون أن يقرر أبدًا أن العمل انتهى.
![]()
شكل النظام
| المكوّن | بيئة التشغيل | الدور |
|---|---|---|
@loupekit/sdk |
المتصفح | الأداة، داخل Shadow DOM، على أي صفحة |
@loupekit/server |
Node 24 | واجهة HTTP API، وPostgres مضمّنة (PGlite) أو حقيقية، والملفات على القرص |
@loupekit/dashboard |
المتصفح | اللوحة ذات المراحل الخمس |
@loupekit/mcp |
Node (الإصدار 24 موثّق) | خادم MCP عبر stdio بـ 19 أداة، مع جسر محلي |
@loupekit/extension |
المتصفح، Manifest V3 | نواة SDK نفسها، للمواقع التي لا تستطيع تغييرها |
loupekit/laravel |
PHP 8.2+ | الـ API واللوحة وخادم MCP بأربع أدوات داخل تطبيق Laravel |
محليًا تشغّل عملية Node واحدة الـ API وقاعدة البيانات وتخزين الملفات والاستضافة الثابتة للوحة والعرض التجريبي وحزمة SDK. يمكن لتطبيق Laravel أن يحل محل هذه العملية. أما Loupe Hub فهو خادم منفصل تستضيفه بنفسك، وهو اختياري، ويوجّه التذاكر بين التطبيقات.
رحلة التعليق
- الالتقاط. تسجّل SDK مرساة، وهي HTML الخارجي للعنصر (حتى 6,000 حرف)، وبعض الأنماط المحسوبة، ولقطة شاشة.
- محوّل التخزين. تستدعي الأداة
StorageAdapter. محوّل HTTP يرفع لقطة الشاشة أولًا إلىPOST /v1/blobs، ثم يرسل التعليق مع الرابط المُعاد. إذا فشل الرفع يحتفظ بالبيانات المضمّنة. أما المحوّل دون اتصال فيكتب فيlocalStorageبدلًا من ذلك. - الـ API. يتحقق الخادم من الهوية، ويوحّد صيغة الرابط، ثم يُدرج التعليق أو يحدّثه بمعرّفه الذي ولّده العميل.
- اللوحة وMCP. يفرز الناس التعليقات على اللوحة. ويقرأ الوكيل التعليقات نفسها عبر خادم MCP.
- اقتراح أو طلب دمج. يكتب الوكيل اقتراحًا (HTML وCSS وملاحظات تظهر كمعاينة قبل وبعد) أو سجل طلب دمج.
- المراجعة. ينقل الوكيل المحادثة إلى In Review، فتشير الأداة واللوحة إلى أنها تحتاج إلى شخص.
- الحسم. يحسمها شخص.
ثلاث بيانات اعتماد تُبقي المسارات منفصلة. ترسل الأداة هوية مستخدم موقّعة بـ HMAC (X-Loupe-User وX-Loupe-Hmac). ويستخدم تطبيق Laravel جلسته الخاصة ورمز CSRF. ويستخدم خادم MCP واللوحة سر المشروع في X-Loupe-Admin.
المرساة: بصمة لا محدِّد
يتعطل محدِّد CSS عند أول تغيير في اسم صنف. يخزن Loupe عدة إشارات عن العنصر، تسمى المرساة، ويحلّها من جديد عند كل تحميل وكل تغيير في DOM.
| الحقل | المحتوى |
|---|---|
tag |
اسم الوسم بأحرف صغيرة |
cssPath |
مسار CSS ينطلق من أقرب معرّف ثابت أو معرّف اختبار |
xpath |
مسار XPath إلى العنصر |
testid |
data-testid أو data-test أو id ثابت |
text |
النص بعد توحيده، حتى 120 حرفًا |
attrs |
role وaria-label وname وtype وalt وhref وplaceholder وtitle، كلٌّ حتى 200 حرف |
nthOfType |
الترتيب بين الإخوة من الوسم نفسه |
rect, viewport |
موضع المستند وحجمه، ومنفذ العرض وقت الالتقاط |
حلّ المرساة من جديد
packages/sdk/src/fingerprint.ts.الترتيب مقصود: الإشارات الأقوى أولًا.
- معرّف اختبار أو
idفريد يفوز بدرجة 0.98. - مسار CSS ينطلق من معرّف ثابت، بتطابق واحد ونفس الوسم، يفوز بدرجة 0.9. وهذا يصمد أمام تغيّر النص.
- وإلا فالعناصر التي يحددها مسار CSS ومسار XPath، وكل عنصر بالوسم نفسه، تصبح مرشحة، وتُضاف العناصر ذات النص المطابق حتى يزيد العدد على 4,000. يُقيَّم كلٌّ منها بتشابه موزون: النص 0.34، والخصائص 0.22، ومعرّف الاختبار 0.22، ومسار CSS 0.2، والوسم 0.12، والموضع 0.1.
- إذا بلغت أفضل درجة 0.5 على الأقل، يلتصق التعليق بذلك العنصر. وتحت 0.5 ينفصل التعليق وتعرض القائمة شارة “moved”.
العتبة تعبّر عن قرار في المنتج: تقول الوثائق إن التعليق المنفصل أأمن من تعليق واثق على عنصر خاطئ. التعليق الواثق الخاطئ يرسل المطوّر لإصلاح الشيء الخطأ، أما المنفصل فيطلب من شخص أن ينظر. العتبة تقلل احتمال التثبيت الخاطئ؛ لكن إصابة بدرجة 0.9 أو 0.98، أو درجة فوق 0.5، قد تظل خاطئة.
مرشّحان يُبقيان المرشحين نزيهين. يُتجاهل المعرّف الذي يبدو مولَّدًا من إطار عمل: أطول من 40 حرفًا، أو يبدأ بـ ember أو react أو radix أو headlessui أو :r، أو يحتوي على :. وتُتخطى العناصر المخفية إذا كان المتصفح يدعم checkVisibility.
يرتبط تعليق المنطقة بأصغر عنصر أب يغطي 60% على الأقل من المنطقة، صعودًا من العنصر الواقع تحت مركز المنطقة. ولا يصلح body ولا html أبدًا. وتخزّن المنطقة مستطيلها ككسور من تلك المرساة، فيمكن وضعها من جديد بعد إعادة تدفق التخطيط المتجاوب.
دورة الحياة، ومن يحق له تحريكها
القاعدة سهلة الصياغة: يجوز للوكيل نقل التعليق إلى In Review، والإنسان وحده يحسمه. وأدوات MCP في Node تحملها. الأداة mark_thread_addressed، المصممة للتسليم، ليس لها معامل للحالة وتضبط In Review دائمًا. أما update_status فتذكر القاعدة نفسها في وصفها، ومنذ 0.14.1 ترفض resolved دون تغيير التعليق.
تنبيهان. درس Loupe نفسه يقول إن هذا تعليمات للوكيل، لا فحص صلاحية. وأداة update-status في حزمة Laravel لا ترفض resolved: تقبله وتحفظه. وفي معالج PATCH في خادم Node لم أجد أي قاعدة على الحالة (قرأت الشيفرة ولم أشغّلها).
وتقرر الأداة أيضًا متى يلزم أن يتصرف شخص (needsYou())، بهذا الترتيب:
- المحادثة المحسومة لا تحتاج أحدًا أبدًا.
- فشل تشغيل الوكيل: “The agent’s run failed”.
- آخر رسالة من الوكيل تنتهي بعلامة استفهام: “The agent asked you something”.
- المحادثة في In Review: “Waiting on your review”.
الفشل يتقدم على السؤال، وكلاهما يتقدم على المراجعة الروتينية.
ما الذي يغطيه الحجب
العناصر الموسومة بـ data-loupe-redact تُستبعد من لقطات الشاشة التي يلتقطها الالتقاط المدمج في Loupe. هذا للصور فقط: نص المرساة وHTML الخارجي للعنصر (حتى 6,000 حرف) قد يظلان يحتويان المحتوى، ومن يستبدل الالتقاط عليه أن يجري الحجب بنفسه. وتسجيلات الشاشة تلتقط البكسلات الحقيقية، بما فيها العناصر المحجوبة، وتذكر الوثائق ذلك. أما خادم Node واللوحة فيعملان على جهازك أو على مضيف تختاره، والتعليقات في قاعدة بيانات تتحكم بها.
المقايضات
- أفضل النتائج تحتاج مقبضًا ثابتًا. أعطِ العناصر المهمة
data-testid. من دونه يعتمد التعليق على الوسم ومسار CSS والنص والخصائص والموضع، وتعدّها الوثائق إشارات أضعف. - التعليق المنفصل يكلّف انتباه شخص. هذا ثمن تقليل احتمال التثبيت على العنصر الخطأ.
- قاعدة أن الإنسان وحده يحسم تقع في أدوات MCP في Node، لا في معالج الحالة في خادم Node، ولا في أداة
update-statusفي Laravel.
ما الذي فحصته وما الذي لم أفحصه
قرأت ثوابت المرساة في packages/sdk/src/fingerprint.ts على نسخة مستنسخة من Loupe 0.14.2 في 2026-10-31: درجتي 0.98 و0.9، وعتبة القبول 0.5، وتجربة معرّف الاختبار الفريد ومسار CSS أولًا. ووثيقة البنية تصف 0.14.1، فأسماء الأدوات وقواعد المراحل هنا مأخوذة من تلك الوثيقة. شغّلت الخادم المحلي من تلك النسخة وحمّلت الصفحة التجريبية واللوحة.
قرأت معالج الحالة وأداة Laravel في الشيفرة ولم أشغّلهما. ولم أشغّل المزامنة ثنائية الاتجاه في Hub ولا حزمة Laravel ولا إضافة المتصفح من أجل هذه المقالة، ولم أختبر إعادة المحاذاة على إعادة نشر حقيقية لموقعي. صور قبل وبعد من وثائق Loupe نفسها.
ما الذي كنت سأفعله بشكل مختلف
- فرض قاعدة المراجعة على الخادم أيضًا. اليوم تحملها أدوات Node، ويصفها الدرس بأنها تعليمات للوكيل لا فحص صلاحية. وأداة Laravel تقبل
resolvedاليوم. - إخبار الفرق عن
data-testidقبل أول تعليق. التقييم مصمم ليصمد أمام التغيير، لكن المقبض الثابت أقوى إشارة، وهو يكلّف الفريق خاصية واحدة.
المصادر
- بنية Loupe, جُلب في 2026-10-31
- شيفرة Loupe، بصمة المرساة, جُلب في 2026-10-31
- درس Loupe، ثبّت أول تعليق وسلّمه إلى Claude Code, جُلب في 2026-10-31
- Model Context Protocol، ما هو MCP؟, جُلب في 2026-10-31
