
HiddenSteps — منصة ذكاء سير عمل شخصية تعتمد مبدأ "المحلية أولاً"
هذا هو المكمّل الأمين للحالة الراهنة لخريطة الوحدات المستهدفة في docs/design/02-system-architecture.md. إنه يوضح ما هو مبني فعلياً، وما تم التحقق منه مقابل خلفية حقيقية أو نموذج محاكى (mock)، وما لا يزال مفقوداً فعلياً — وليس ما هو مخطط له (ذلك في docs/roadmap/01-implementation-roadmap.md).
شغّل cargo build --workspace && cargo test --workspace && cargo clippy --workspace --all-targets -- -D warnings من جذر المستودع. وقت كتابة هذا: 12 صندوقاً (crate)، 193 اختباراً ناجحاً، صفر تحذيرات clippy، cargo fmt --check نظيف — 183 عبر الصناديق الـ 11 التي لا تحتاج إلى شاشة عرض أو خدمة خارجية، بالإضافة إلى 10 في hiddensteps-observation تحتاج إلى شاشة X11 حية (تم التحقق منها حيثما توجد واحدة؛ انظر ذلك الصف). أربعة اختبارات مؤجَّلة بـ #[ignore] عن قصد (انظر أدناه) ولا تُحتسب كإخفاقات أو ضمن الـ 193.
| الصندوق (Crate) | ما ينفّذه | كيف تم التحقق |
|---|---|---|
hiddensteps-domain | الأنواع الأساسية: PrivacyLevel/PrivacyState، EventSummary/SignalType، Pattern، Recommendation، AuditEntry، وCapturedSignal — وهو نوع لا يمكن استمراره بنيوياً (لا يحتوي Serialize)، ما يفرض قاعدة البيانات الخام الخاصة بـ ADR-0006 على مستوى النوع | اختبارات وحدة: round-trip وترتيب المستويات، وبوابة TTL للوضع العميق |
hiddensteps-security | SecretStore (ADR-0008): تنفيذان — خزنة OS حقيقية (KeyringSecretStore) وخزنة في الذاكرة (للاختبار)؛ توليد مفتاح رئيسي عبر CSPRNG (يُعاد في غلاف zeroize::Zeroizing بحيث يُمسح المفتاح عند الإفلات (drop) بدلاً من أن يبقى في الذاكرة المحررة)؛ اشتقاق مفتاح من عبارة المرور عبر Argon2id للوضع المحمول (PassphraseKey يصفّر مفتاحه المشتق عند الإفلات، مع الإبقاء على الملح (salt) غير السري). بالمثل، يحتفظ hiddensteps-event-store بنص SQL الحامل للمفتاح PRAGMA key/rekey داخل Zeroizing | اختبارات وحدة مقابل مخزن الذاكرة وKDF؛ اختبار round-trip للخزنة الحقيقية مؤجَّل بـ #[ignore] (انظر أدناه) |
hiddensteps-event-store | SqlCipherEventStore (ADR-0003): المخطط الكامل من docs/design/07-database-schema.md، وعمليات CRUD لحالة الخصوصية، والأحداث، وسجل التدقيق، والأنماط، وروابط النمط↔الحدث، وتمثيلات الأنماط (انظر الملاحظة أدناه)، والتوصيات، وإعداد مزوّد LLM، والإعدادات العامة، بالإضافة إلى delete_all_data (معاملاتي؛ ويقوم أيضاً بـ rekey من أجل "حذف كل شيء" يصمد بعد إعادة التشغيل)/export_data/count_rows (تشخيصات)/delete_expired_events (مسح TTL للوضع العميق، يُستدعى من حلقة التوصيات الدورية في apps/desktop/src-tauri — كان ttl_expires_at يُستمر منذ v0.1.0 لكن لم يكن أي شيء يحذف صفاً تجاوزه قبل هذا)؛ فرض المفاتيح الأجنبية (PRAGMA foreign_keys = ON) بحيث يعمل ON DELETE CASCADE في schema.sql على روابط النمط↔الحدث فعلياً | 33 اختباراً مقابل ملف SQLCipher حقيقي: المفتاح الخاطئ يفشل في الفتح، والمفتاح نفسه يعيد الفتح بشكل صحيح، وحذف الكل يمسح كل جدول بما فيها الأحدث، وround-trip لـ rekey، ومسح TTL يترك الأحداث غير المنتهية دون مساس، والحذف المتتالي لا يترك روابط نمط↔حدث يتيمة |
hiddensteps-redaction | محرك التنقيح (Redaction Engine) (docs/design/05-privacy-model.md §4): كاشفات regex+Luhn لمفاتيح API/الرموز (tokens)/مفاتيح PEM/البريد الإلكتروني/SSN/بطاقات الائتمان، وكاشف أسرار غامضة قائم على الانتروبيا، وسياسة الإسقاط عند عدم اليقين | 30 اختباراً، بما فيها مدخلات عدائية عمداً (أسرار مضمّنة في نثر، وشبه أسرار قريبة غير أسرار مثل git SHAs، وأرقام SSN بلا شرطات/بمسافات، وأرقام بطاقات محشوة بأرقام، ورموز عالية الانتروبيا بحالة واحدة) |
hiddensteps-pipeline | خط أنابيب الأحداث (Event Pipeline) (ADR-0006): تصنيف → تنقيح → تلخيص، وبوابة مستوى الخصوصية لكل نوع إشارة، وتعيين TTL للوضع العميق | 8 اختبارات تغطي عمليات الإسقاط الناتجة عن التنقيح، والإسقاط بسبب بوابات المستوى، والتلخيص الناجح |
hiddensteps-observation | ObservationSource (ADR-0005) + لينكس: ActiveWindowSource (X11 GetInputFocus)، FileOperationSource (inotify عبر notify)، ClipboardMetadataSource (تحديد X11، بيانات وصفية فقط)، GlobalShortcutSource (X11 XGrabKey). بالإضافة إلى ملفات مصادر macOS/Windows (انظر أدناه) | 10 من 11 اختباراً تعمل مقابل خلفيات حقيقية في هذه البيئة — شاشة X11 حية (DISPLAY=:0 من WSLg) وinotify حقيقي، وليست نماذج محاكاة. اختبار واحد (الالتقاط الحقيقي لـGlobalShortcutSource) مؤجَّل بـ #[ignore] عن قصد |
hiddensteps-llm-provider | LlmProvider (ADR-0004): عميل Ollama (مع حقل طلب think: Option<bool> لنماذج الاستدلال الهجين)، وعميل متوافق مع بروتوكول OpenAI الأسلاك (يغطي OpenAI/Azure/OpenRouter/Together/Groq/DeepSeek/LocalAI)، وعميل Anthropic Messages، واكتشاف تلقائي لبيئة التشغيل المحلية. يضبط كل عميل مهلة زمنية للطلب (build_http_client) بحيث لا يمكن لخادم بعيد معلّق أن يحجب استدعاءً إلى الأبد؛ يمرر Ollama max_tokens كقيمة options.num_predict المتداخلة | 19 اختباراً مقابل خوادم wiremock المحاكاة (بما فيها فحص حقيقي لانطلاق المهلة وأن Ollama يرسل num_predict فعلاً)، بالإضافة إلى اختباري تكامل حقيقيين مع Ollama (tests/ollama_live.rs، مؤجَّلان بـ #[ignore] — انظر أدناه) اكتشفا وأصلا مشكلة حقيقية: نفس المطالبة استغرقت أكثر من دقيقتين مع نموذج تفكير هجين محلي حقيقي عندما تُرك think على قيمته الافتراضية، وبضع ثوانٍ مع think: Some(false) |
hiddensteps-patterns | اكتشاف الأنماط (مطابقة متواليات n-gram بنافذة منزلقة) + مخطط سير العمل (مخطط انتقالي بأوزان حواف) — الطبقة 1 من ADR-0010 | 16 اختباراً، بما فيها تماثل مباشر لمثال PROMPT.md الخاص "لُوحظ 31 مرة" واختبار انحدار يتحقق من أن النوافذ المتداخلة فوق تكرار مستمر لا تُحتسب مرتين |
hiddensteps-recommendations | الطبقة 2 من محرك التوصيات (ADR-0010): توليف LLM مع عقد مطالبة JSON منظم، ومدقق تناقض سردي، وحلقة إعادة محاولة — والأهم أن الحقول الرقمية (estimated_time_saved_minutes) لا تُحلَّل من مخرجات LLM إطلاقاً أبداً، بل تُحتسب فقط من الطبقة 1 | 23 اختباراً، بما فيها إعادة المحاولة عند JSON تالف، وإعادة المحاولة عند التناقض السردي (تغطي الأرقام المكتوبة حروفاً وكل حقل يتحكم به LLM، وليس why فقط)، واستخراج JSON يراعي السلاسل النصية، مقابل مزوّد اختبار مبرمَج (scripted) |
hiddensteps-privacy-engine | بوابة الإرسال إلى السحابة (docs/design/03-data-flow-diagrams.md §5) وإصدارات الموافقة (docs/design/05-privacy-model.md §5)؛ يغلّف PrivacyGatedProvider أي LlmProvider بحيث لا يمكن تجاوز البوابة عبر مسار الاستدعاء العادي | 13 اختباراً، بما فيها أن محتوى المستوى 4 محظور حتى مع منح كل الموافقات |
hiddensteps-plugin-host | مضيف إضافات WASM (ADR-0009): تعداد قدرات مغلق، والتحقق من صحة البيان (manifest)، وصندوق رمل مدعوم بـ wasmtime يربط دوال المضيف للقدرات الممنوحة فقط، بالإضافة إلى عداد الوقود (fuel metering) وResourceLimiter للذاكرة يحدّان من CPU/ذاكرة مثيل الإضافة بغض النظر عن القدرات التي يحملها — وهما المحوران اللذان يسميهما قسم منع الخدمة (Denial-of-Service) في docs/research/06-threat-model.md ولا يستطيع فرض القدرات وحده معالجتهما (فالوحدة الخالية من القدرات يمكنها مع ذلك التكرار أو تضخيم الذاكرة إلى الأبد). instantiate_from_manifest هو نقطة الدخول الآمنة: فهو يفرض التحقق من البيان (قاعدة المستوى 4 المطلوب للقطة الشاشة) ويرفض منح أي شيء لم يصرّح به البيان، قبل وصول أي قدرة إلى الرابط (linker) — أما شريحة القدرات البسيطة instantiate فلا صلة لها بأي بيان إطلاقاً | 20 اختباراً، بما فيها محاولات هروب قدرات حقيقية: وحدات WAT مكتوبة يدوياً تُترجم وقت الاختبار، لإثبات أن استيراد قدرة غير ممنوحة غير محلول فعلياً (يفشل الإنشاء)، وليس مجرد غير مستخدم؛ بالإضافة إلى وحدة تكرار لانهائي حقيقي ووحدة memory.grow غير محدودة تتوقف (trap) بدلاً من التعليق/استنزاف الذاكرة |