تخطَّ إلى المحتوى
kazma.
البحث في كاظمه والتوثيق
EN

الهندسة داخل كاظمه

تستخدم كاظمه LangGraph لحلقة الوكيل، ومكتبات معتادة لما سواها (FastAPI وhttpx وSQLite وPostgres وChroma وPlaywright). هذه الصفحة عن الأجزاء التي تبنيها بنفسها. وجد معظمها لأن شيئًا ما أخطأ في تثبيت حقيقي، لذلك يذكر كل قسم ما كانت المشكلة، وما تفعله كاظمه حيالها، وأين توجد الشيفرة، وأي اختبار يثبت ذلك. ويُشغَّل كل اختبار من هذه أيضًا على السلوك القديم ليُظهر أنه يفشل هناك: فالفحص الذي لم يفشل قط لا يثبت شيئًا.

وللمسار الذي تقطعه رسالة واحدة عبر هذا كله، راجع كيف يجري الدور. وللعمل على العربية، راجع كيف تتعامل كاظمه مع العربية.

1. نظام موافقة واحد، وثلاث طرق للتوقف

Section titled “1. نظام موافقة واحد، وثلاث طرق للتوقف”

المشكلة. يمكن للوكيل أن يتوقف طلبًا للموافقة في ثلاثة مواضع: دور محادثة، وعامل سرب، وخطوة من خط معالجة متعدد الخطوات. وكان لكل منها تصوّره الخاص عن إجابة السؤال. فضغطة «موافقة» مكرَّرة، أُرسلت بعد أن انتقل الوكيل إلى سؤاله التالي، وافقت على سؤال لم يره الشخص قط. وكان يمكن للبطاقة أيضًا أن تعرض «تمت الموافقة» لعمل لم يُستأنف أبدًا.

ما تفعله كاظمه. كل موافقة، على كل مسار، صف واحد في سجل بوابات بآلة حالات صارمة: pending وclaimed وresuming وsettled (ومعها timeout وsuperseded وerror). كل تغيير مقارنة-ومبادلة واحدة؛ والضغطة التي تخسر السباق تتلقى 409 مع الحالة الحقيقية للصف. ويسمّي القرار السؤال الذي يجيب عنه بالضبط (معرّف المقاطعة في LangGraph)، فلا يستأنف إلا ذلك السؤال. يقرّر السجل هل أُجيب السؤال؛ وتقول نقطة الحفظ في LangGraph هل الرسم متوقف فعلًا. وترسم الصفحات ما يقوله هذان؛ ولا تخمّن أبدًا.

والأداة التي لم يصنّفها أحد تُحجب افتراضيًا، والسماح لبرنامج في الصدفة لا يسمح بما يستطيع تشغيله (يُرفض find -exec وgit -c core.fsmonitor=...).

أين. kazma_core/safety/hitl_gates.py (السجل)، وkazma_core/agent/graph_tool_worker.py (توقف المحادثة)، وkazma_core/swarm/shared_approvals.py (قرار واحد مشترك عبر Telegram وDiscord وSlack والويب لعمل السرب)، وkazma_core/safety/hitl.py (الطبقات).

الإثبات. tests/test_hitl_gates.py، وtests/test_hitl_gate_reconciler.py، وtests/test_hitl_wiring.py، وtest_every_registered_tool_has_a_tier في tests/test_static_gates.py.

2. افحص الخطة قبل أن تتصرف

Section titled “2. افحص الخطة قبل أن تتصرف”

المشكلة. نموذج طُلب منه «ذكّرني في اليوم الذي يسبق امتحاني» اخترع تاريخًا وجدوله. ونموذج طُلب منه نشر مجموعة مسودات نشر نصًّا لم يعد المسودة التي وافق عليها المستخدم. تلتقط بطاقات الموافقة بعض هذا، لكن فقط إن قرأ الشخص بتمعّن.

ما تفعله كاظمه. تقع طبقة الالتزام بين النموذج وأي شيء دائم. قبل أن تعمل أداة، يحلّ authorize_effect الطلب مقابل ما تعرفه كاظمه. فيربط التاريخ النسبي بالذكرى التي يشير إليها، ويعيد كتابة معاملات الأداة إلى ذلك التاريخ بالمنطقة الزمنية للمشغّل. ويرفض أمر الصدفة الكارثي قبل أن تظهر أي بطاقة موافقة. ويرفض تغييرات الوكيل على الإعدادات المحمية (safety.*، وطبقة الالتزام نفسها). وحين يضبط المشغّل قائمة سماح للوجهات، يسأل عن الوجهة المقصودة إن سمّت رسالة صادرة وجهة مجهولة. ويجب أن يسمّي منشور X مسودة محفوظة، وتستبدل البوابة نص النموذج بالمسودة المخزَّنة، فيُنشر ما تمت الموافقة عليه. ولا يمكن لمصدر أقل ثقة أن يكتب فوق حقيقة قالها المستخدم، كحقيقة استنتجها النموذج.

أين. kazma_core/safety/commitment/authorize.py، وkazma_core/safety/commitment/relative_time.py، وkazma_core/safety/side_effects.py (ما يستطيع كل أداة تغييره)، وkazma_core/memory/provenance.py (سلّم الثقة للحقائق). وفي طبقة الالتزام التصميم الكامل.

الإثبات. tests/test_commitment_authorize.py، وtests/test_x_post_proposal_gate.py، وtests/test_memory_provenance.py.

المشكلة. حين كان استدعاء النموذج يفشل بعد إعادة المحاولات، كانت الخطوة الأخيرة القديمة تطلب من النموذج مع ذلك أن «يلخّص ما حدث»، فيكتب جوابًا مقنعًا فوق دور لم يفعل شيئًا. ورأى المستخدمون ردودًا واثقة على عمل لم يجرِ قط.

ما تفعله كاظمه. يُصنَّف كل فشل للنموذج: أخطاء الشبكة وحدود المعدّل عابرة وتُعاد محاولتها، أما أخطاء المحتوى والمخطط فـدائمة وتفشل فورًا. والدور الذي يفشل استدعاء نموذجه يضبط turn_failed، فتتخطى الخطوة الأخيرة ملخّصها كليًا. ويرى المستخدم رسالة ⚠️ مع تلميح، لا جوابًا مختلقًا أبدًا. وحين تنتقل كاظمه إلى نموذج آخر بديل، تقول ذلك. وحين ينفق نموذج مفكِّر ردّه كله في تفكير مخفي، يسمّي تحذير القطع ذلك، وتوقف استدعاءات X المنظَّمة ذلك التفكير.

أين. kazma_core/llm_provider.py (LLMError مع transient، وتفصيل القطع، ومفتاح التفكير)، وkazma_core/agent/graph_supervisor.py (حلقة إعادة المحاولة)، وkazma_core/agent/graph_respond.py (حارس turn_failed).

الإثبات. tests/test_retry_backoff.py، وtests/test_source_grounding.py (الدور الفاشل يتخطى التلخيص)، وtests/test_x_reasoning_off.py.

4. إيصال لكل تغيير، ولا إعادة تشغيل عمياء

Section titled “4. إيصال لكل تغيير، ولا إعادة تشغيل عمياء”

المشكلة. إن أُعيد تشغيل كاظمه في منتصف استدعاء أداة ترسل بريدًا أو تكتب ملفًا، فإن إعادة المحاولة الساذجة ترسله مرة أخرى. وعدم إعادة المحاولة قد يُضيع العمل. وكلاهما غير مقبول للأفعال خارج كاظمه.

ما تفعله كاظمه. قبل أن تعمل أداة تغيّر شيئًا، يسجّل دفتر الآثار إيصالًا يسمّي المحادثة والدور والاستدعاء وبصمة لمعاملاته. وتُكتب النتيجة قبل أن يتقدم الرسم. وعند الإعادة، يعيد الاستدعاء المنتهي نتيجته المسجَّلة. أما الاستدعاء الذي بدأ ولم ينتهِ فيُحتجز على أنه «أثر مجهول»: يتوقف الدور بتحذير صادق بدل تشغيله من جديد. وتعلّم الأدوات الإخفاقات التي حدثت قبل أن تفعل أي شيء (RefusedBeforeEffect)، فيستطيع النموذج تصحيحها والمحاولة مجددًا. ويقرأ اختبار جسم كل أداة ليتحقق من أن حالات الرفض معلَّمة بهذه الطريقة.

أين. kazma_core/agent/effect_journal.py، وkazma_core/agent/tool_refusal.py.

الإثبات. tests/test_effect_journal.py (عملية فرعية حقيقية تُقتل في منتصف الاستدعاء)، وtests/test_tools_refuse_before_effect.py.

5. ذاكرة لا تجيب إلا حين تعرف

Section titled “5. ذاكرة لا تجيب إلا حين تعرف”

المشكلة. كانت الذاكرة الأولى تحقن دائمًا أعلى خمس ذكريات لديها، أيًّا كان السؤال. وعلى معيار الاسترجاع، كانت ثلاث من كل أربع حقائق تحقنها ضجيجًا، وكانت الأسئلة التي لا جواب لها تتلقى مع ذلك ذكريات «ذات صلة».

ما تفعله كاظمه. يقيّم الاسترجاع كل مرشّح على أمرين: كم هو أقرب في المعنى إلى السؤال من خلفية السؤال، وكم يحمل من كلمات السؤال ذات المحتوى. والخلفية هي متوسط تشابه المرشحين في المراتب من الرابعة إلى الخامسة عشرة، لأن نموذج التضمين يجعل كل شيء تقريبًا متشابهًا قليلًا. وتحت حدّ أدنى لا يُحقن شيء. ولا يُحقن شيء كذلك إن تأخر المرشح عن الأفضل بأكثر من فجوة محددة. ويقارن البحث بالمعنى كل ذكرى مخزَّنة بدقة، دون فهرس جزئي. والحقائق ثنائية الزمن: تسجّل متى صارت الحقيقة صحيحة ومتى كُتبت، فلا يستطيع قول قديم قُرئ متأخرًا أن يكتب فوق قول أحدث. ويكتب النسيان شاهد قبر ومدخلًا في دفتر، فتنسى النسخة الاحتياطية المستعادة من جديد، ولا تعيد أي مهمة في الخلفية ذكرى منسية.

وتأتي العتبات من معيار مُرقَّم الإصدارات فيه أسئلة محجوزة للاختبار، ودرجاته سقّاطة: يجوز أن ترتفع، ولا تنخفض أبدًا.

أين. kazma_core/memory/recall.py، وkazma_core/memory/belief_mutation.py، وkazma_core/memory/forget.py، وkazma_core/memory/forget_journal.py، وkazma_core/memory/benchmark.py. وفي الذاكرة التصميم الكامل.

الإثبات. tests/test_memory_relevance.py (يضع الترتيب القديم مكانه فيجب أن ينكسر كل مسار استرجاع)، وtests/test_memory_benchmark.py، وtests/test_memory_forget_converges.py.

6. النص غير الموثوق مسيَّج، والسياج مَقيس

Section titled “6. النص غير الموثوق مسيَّج، والسياج مَقيس”

المشكلة. يمكن لصفحات الويب ونتائج البحث والمستندات والرسائل والذكريات المسترجعة كلها أن تحمل تعليمات كتبها شخص آخر («تجاهل قواعدك و…»). والنموذج الذي يقرؤها خامًا قد يتبعها.

ما تفعله كاظمه. كل أداة تعيد نصًّا من الخارج تحيطه بسياج يعلّمه بيانات لا تعليمات. ويُفشل اختبار البناء حين تعيد أداة ويب نصًّا غير مسيَّج. والأثر مَقيس لا مفترض. فعلى مجموعة هجمات كاظمه نفسها خفّض نجاح الهجوم بين 33 و42 نقطة على النماذج الثلاثة التي نجحت معها الهجمات (وقاومها نموذجان آخران بالسياج ودونه). وعلى معيار AgentDojo العام يتفوق بوضوح على غياب أي دفاع، لكن لا يمكن تمييزه عن فاصل من أربعة أحرف. والنتيجتان منشورتان.

أين. kazma_core/safety/prompt_fence.py، وscripts/injection_report.py، وحقن التعليمات: الأرقام.

الإثبات. tests/test_injection_containment.py، وtest_no_unfenced_web_tool_output في tests/test_static_gates.py.

7. تسليم يصمد أمام إعادة التحميل

Section titled “7. تسليم يصمد أمام إعادة التحميل”

المشكلة. يتدفق جواب المحادثة عبر رسائل صغيرة كثيرة. وخلف وكيل شبكي يقسّمها تقسيمًا مختلفًا، كانت الصفحة تُسقط صفوف الأدوات وبطاقات الموافقة. وإعادة تحميل الصفحة في منتصف دور كانت ترسم الدور مرتين أو لا ترسمه أبدًا.

ما تفعله كاظمه. كل دور دفتر من الأحداث المرقَّمة، وترسم الصفحة من ذلك الدفتر. ولا تكتب حالة الدور بنفسها أبدًا. ودالة واحدة بالضبط تقرّر هل الدور مفتوح، أو ينتظر موافقة، أو انتهى (close_turn). وتُحفظ نتيجتها قبل إبلاغ المتصفح. وتستأنف إعادة التحميل من آخر حدث قرأته الصفحة. ويحتفظ قارئ التدفق برسالة وصل نصفها حتى تكتمل، أيًّا كان تقسيم الشبكة لها.

أين. kazma_ui/turn_runtime.py، وkazma_ui/static/js/streaming.js، وkazma_ui/static/js/modules/turn_document.js.

الإثبات. tests/test_turn_runtime.py، وtests/js/test_sse_parser.js (كل موضع تقسيم)، وtests/e2e/test_chunked_stream_browser.py (متصفح حقيقي خلف وكيل يقسّم كل رسالة إلى قطع من 1 إلى 40 بايت).

المشكلة. تشغّل كاظمه أعمالًا تمتد إلى ما بعد رسالة واحدة: مهام السرب، والمهام المجدولة، والمستندات، والبحث، والزحف، ومنشورات X، وصيانة الذاكرة. وحين كان أحدها يتوقف، لم يكن شيء يقول ذلك.

ما تفعله كاظمه. مشرف واحد يقرأ كل نوع من العمل من مخزنه الخاص دون أن يكتب فيه. ويحكم على كل منها بتقدّمه، لا بمجرد أن عمليته حية، ويفتح حادثة حين يتوقف أحدها عن التقدم أو يعلق أو يفشل. وتصل الحادثة بطاقةً بأزرار إلى المحادثة التي بدأ منها العمل. وتُسجَّل البطاقة مع حالة تسليمها قبل إرسالها: فإعادة التشغيل لا ترسلها مرتين أبدًا، والبطاقة التي لم تُرسل تخرج عند التشغيل التالي. والقرار الأول هو النافذ على كل واجهة.

أين. kazma_core/runs/ (supervisor.py وkinds.py وincidents.py). وفي الأعمال الجارية ما يراه المستخدم.

الإثبات. tests/test_run_kinds_declared.py (كل مخزن فيه عمود حالة مراقَب أو مصرَّح بسببه)، وtests/test_run_incident_crash.py (عملية حقيقية تُقتل في كل مرحلة)، وtests/test_run_decisions.py.

9. جلب الويب دون أن يُقلب على المضيف

Section titled “9. جلب الويب دون أن يُقلب على المضيف”

المشكلة. يمكن لصفحة تجلبها كاظمه أن تعيد التوجيه إلى عنوان داخلي، أو أن تستخدم جواب DNS يتغير بين فحص الأمان والاتصال، لتصل إلى خدمات على شبكة المضيف نفسه.

ما تفعله كاظمه. يُفحص كل عنوان في عملية حلّ أسماء معزولة بحدود للوقت والذاكرة. ويُثبَّت الاتصال على العنوان المفحوص مع الحفاظ على اسم المضيف الحقيقي، ويُفحص الطرف الآخر مرة أخرى بعد الاتصال. وتُعترض طلبات المتصفح واحدًا واحدًا، بما فيها قفزات إعادة التوجيه، وتُجلب عبر الفحوص نفسها. وتتشارك عمليات الزحف الآلية حدود المعدّل لكل موقع وتتبع قواعد robots الخاصة به.

أين. kazma_core/security/ssrf.py، وkazma_core/security/ssrf_pin.py، وkazma_core/web_acquire/dns_worker.py، وkazma_core/web_acquire/browser_network.py. وفي البحث على الويب التفاصيل.

الإثبات. tests/test_ssrf_pin_authority.py، وtests/test_acquisition_dns.py، وtests/test_browser_acquisition_broker.py.

10. المستندات العدائية تبقى خارج الخادم

Section titled “10. المستندات العدائية تبقى خارج الخادم”

المشكلة. يمكن لملف PDF أو Office أن يحمل نصوصًا برمجية، أو أفعالًا خارجية، أو استغلالًا للمحلّل. وتحليله داخل عملية الخادم يأتمنه على كل ما يستطيع الخادم لمسه.

ما تفعله كاظمه. تُحلَّل المستندات في عامل منفصل بحدود للذاكرة والمعالج. وعند الطلب، تعمل كل مهمة في حاويتها الخاصة بلا شبكة ولا مجلدات مربوطة. ويشغّل الحاوية وسيط، وهو العملية الوحيدة التي تملك صلاحية Docker. وتجوب سياسة PDF رسم كائنات الملف وترفض النصوص البرمجية والأفعال الخارجية والمرفقات والروابط إلى ملفات أو مشاركات شبكية، قبل التحليل وبعد كل تغيير تجريه كاظمه.

أين. kazma_core/documents/pdf_policy.py، وkazma_core/documents/worker_broker.py. وفي أمان المستندات نموذج التهديد.

الإثبات. tests/test_document_pdf_policy.py، وtests/test_document_worker_container.py.

11. الأسرار لا تخرج من باب جانبي

Section titled “11. الأسرار لا تخرج من باب جانبي”

المشكلة. البرنامج الذي تشغّله أداة (مشغّل اختبارات، أو تثبيت حزمة، أو خطّاف git) يرث بيئة الخادم بمفاتيحها، ما لم يمنعه شيء.

ما تفعله كاظمه. تعيش الأسرار في خزنة مشفّرة (AES-256-GCM). وتتلقى البرامج التي تشغّلها الأدوات بيئة منظَّفة بلا متغيرات كاظمه، وبلا ما يُسمّى كبيانات اعتماد، وبلا رابط يحمل كلمة مرور. ويعمل الإخفاء باسم المفتاح وبالقيمة، فتُخفى كلمة المرور داخل رابط قاعدة بيانات أيضًا. ويجد اختبار كل موضع تشغّل فيه أداة أو بيئة التطوير أو مهارة أو تطبيقات المحادثة عملية، ويتحقق من مصدر بيئتها.

أين. kazma_core/security/vault.py، وkazma_core/security/child_env.py.

الإثبات. tests/test_child_env.py (يشغّل pytest حقيقيًا وخطّاف git حقيقيًا)، وtests/test_url_credentials.py.

12. مشرف يميّز إعادة التشغيل من إعادة التحميل

Section titled “12. مشرف يميّز إعادة التشغيل من إعادة التحميل”

المشكلة. يعيد مدير العمليات تشغيل الخادم الذي يتوقف عن الإجابة. لكن الخادم الذي ينتظر انتهاء إعادة تشغيل قاعدة البيانات ليس معطّلًا. وإعادة تشغيله لا تعيد قاعدة البيانات، بل تضيف انقطاعًا فحسب.

ما تفعله كاظمه. يشغّل kazma_guard.py كاظمه ويقرأ إجاباتها عن صحتها. وغياب الإجابة ثلاث مرات متتالية يعني إعادة التشغيل. أما الإجابة التي تقول «غير جاهز: قاعدة البيانات متوقفة» فتعني الانتظار، مع تنبيه واحد للمشغّل، وإعادة التشغيل بعد عشر دقائق فقط. وإعادة التحميل هادئة: يطلب الحارس من كاظمه أن تتوقف، وينتظر انتهاء أدوار المحادثة (--when-idle)، ويشغّل الشيفرة الجديدة. ويكتب نبضة حياة، فتنبّه كاظمه المشغّل إن مات حارسها يومًا، ويحتفظ بآخر كلمات الخادم حين ينهار.

أين. scripts/service/kazma_guard.py.

الإثبات. tests/test_guard_integration.py (الحارس الحقيقي أمام خادم زائف: إعادة تحميل هادئة، وانقطاع قاعدة بيانات يُتجاوز بالانتظار، وآخر أسطر الانهيار محفوظة)، وtests/test_guard_owns_reload.py.

كيف تُجعل الإصلاحات دائمة

Section titled “كيف تُجعل الإصلاحات دائمة”

يُشحن كل إصلاح في هذه القائمة مع ثلاثة أشياء. اختبار يعيد إنتاج الفشل الأصلي. وبوابة فئة تجد كل نظير للشيفرة المعطوبة من المصدر نفسه (كل أداة، وكل مخزن، وكل مسار)، فلا يستطيع التالي تكرار الخطأ. وضابط سلبي يشغّل تلك البوابة على الشيفرة القديمة ليُظهر أنها تفشل هناك. ومن أمثلتها tests/test_store_registry.py وtests/test_static_gates.py وtests/test_child_env.py. والقائمة الكاملة لنقاط الضعف المفتوحة في الفجوات المعروفة، بتواريخها.