لماذا Grub
دمجنا ميزات من كل الزاحفين الرئيسيين — ثم أضفنا ما لا يمتلكه أيٌّ منها.
الزاحفون المستضافون ذاتيًا
| الميزة | Crawl4AI | Firecrawl | Scrapy | Grub |
|---|---|---|---|
| عرض JavaScript | ✅ Playwright | ✅ Playwright | ❌ HTTP فقط | ✅ Playwright |
| متصفح مضاد للاكتشاف | إضافة تخفي | ❌ | ❌ | ✅ Camoufox |
| بروتوكول Ghost | ❌ | ❌ | ❌ | ✅ تراجع تلقائي |
| بروكسي لكل طلب | ✅ تصعيد | ❌ | وسيط | ✅ لكل طلب |
| تصحيحات التخفي | ✅ | ❌ | ❌ | ✅ اختياري |
| حلقة الوكيل | ✅ وكيل | ✅ /agent | ❌ عناكب | ✅ SM محدود |
| بث المتصفح المباشر | ✅ WebSocket | ✅ Live View | ❌ | ✅ WS + MJPEG |
| إخراج Markdown | ✅ Fit Markdown | ✅ أساسي | ❌ | ✅ محرك Rust |
| أدوات MCP | ✅ مجتمعي | ✅ رسمي | ⚠️ مجتمعي | ✅ 15 أداة |
| LLM متعدد المزوّدين | ✅ كل نماذج LLM | ⚠️ Gemini | ❌ | ✅ OpenAI/Anthropic/Ollama |
| شبكة P2P ندّية | ❌ | ❌ | ❌ | ✅ بروتوكول gossip |
| فرض السياسات | ❌ | ❌ | ❌ | ✅ بوابات نطاق + تنقيح |
| الدفاع ضد حقن الأوامر | ❌ | ❌ | ❌ | ✅ عزل + فرق النص المرئي |
| الترخيص | Apache 2.0 | AGPL-3.0 | BSD | ملكية خاصة |
| التسعير | مجاني | مجاني–$333/شهر | مجاني | استضافة ذاتية |
الزاحفون السحابيون / المُدارون
| الميزة | Browserbase | Scrapfly | Firecrawl Cloud | Grub |
|---|---|---|---|
| عرض JavaScript | ✅ Chromium مخصص | ✅ خاص | ✅ تخفي سحابي | ✅ Playwright |
| متصفح مضاد للاكتشاف | ✅ Chromium مخصص | ✅ خاص | ✅ تخفي سحابي | ✅ Camoufox |
| بروتوكول Ghost | ❌ | ❌ | ❌ | ✅ تراجع تلقائي |
| بروكسي لكل طلب | ✅ مُدار | ✅ أكثر من 130 مليون IP | ✅ مُدار سحابيًا | ✅ لكل طلب |
| تصحيحات التخفي | ✅ مدمج | ✅ مدمج | ✅ مدمج | ✅ اختياري |
| حلقة الوكيل | ✅ Stagehand | ⚠️ عبر التكاملات | ✅ /agent | ✅ SM محدود |
| بث المتصفح المباشر | ✅ iFrame + CDP | ✅ CDP | ✅ Live View | ✅ WS + MJPEG |
| إخراج Markdown | ✅ عبر MCP | ✅ مدمج | ✅ أساسي | ✅ محرك Rust |
| أدوات MCP | ✅ رسمي | ✅ رسمي | ✅ رسمي | ✅ 15 أداة |
| شبكة P2P ندّية | ❌ | ❌ | ❌ | ✅ بروتوكول gossip |
| فرض السياسات | ❌ | ❌ | ❌ | ✅ بوابات نطاق + تنقيح |
| الدفاع ضد حقن الأوامر | ❌ | ❌ | ❌ | ✅ عزل + فرق النص المرئي |
| القابلية للاستضافة الذاتية | ❌ سحابي فقط | ❌ سحابي فقط | ⚠️ OSS محدود | ✅ كامل + Cloud Run |
| التسعير | مجاني–$99/شهر | حسب الاستخدام | مجاني–$333/شهر | استضافة ذاتية |
Grub وحدها لديها بروتوكول Ghost — تراجع تلقائي يعتمد على الرؤية، يلتقط لقطة شاشة للصفحات المحظورة ويستخرج المحتوى عبر LLM عندما يفشل الزحف العادي. يعالج الوقاية (Camoufox + بروكسي + تخفي) 95% من الحظر. ويتولى بروتوكول Ghost معالجة الباقي.
نقاط نهاية API
الزحف الأساسي
الوكيل (الوضع B)
إدارة المهام
التخزين المؤقت البعيد
إدارة الجلسات
البث المباشر
الشبكة الندّية
النظام
أدوات MCP (grub-crawl.py)
جسر MCP يكشف كل الإمكانات لأي مضيف متوافق مع MCP:
الوحدات الداخلية
نواة الوكيل (app/agent/)
محوّلات المزوّدين (app/agent/providers/)
بوابات السياسات (app/policy/)
قابلية المراقبة (app/observability/)
طبقة API
مكافحة الاكتشاف (app/)
| File | Purpose | Status |
|---|
stealth.py | تصحيحات playwright-stealth، حظر نطاقات المتتبعين | مكتمل |
proxy.py | تحديد البروكسي لكل طلب مع تراجع إلى متغيرات البيئة | مكتمل |
الشبكة الندّية (app/mesh/)
البنية التحتية
آلة حالة الوكيل```
INIT -> PLAN -> EXECUTE_TOOL -> OBSERVE -> PLAN -> ... -> RESPOND -> STOP
| |
+-- policy_denied ---------------------->+
+-- max_steps / max_wall_time / max_failures -> STOP
+-- no_op_loop (3x empty) ------------> STOP
+-- blocked (ghost trigger) -----------> GHOST -> OBSERVE
شروط الإيقاف المفروضة في كل تكرار:
- `max_steps` (الافتراضي: 12)
- `max_wall_time` (الافتراضي: 90 ثانية)
- `max_failures` (الافتراضي: 3)
- `no_op_loop` (ثلاث استجابات فارغة متتالية)
- `policy_denied` (أداة/نطاق محظور)
- `completed` (يستجيب الوكيل بنص)
## مكافحة الاكتشاف
ثلاث طبقات من مكافحة الاكتشاف تتراكب معًا. الوقاية تمنع الحظر قبل حدوثه، بينما يتولى Ghost Protocol معالجته بعد ذلك.
### محرك Camoufox
متصفح قابل للتوصيل لمكافحة الكشف مع تزوير للبصمة على مستوى C++. لا حيل يدوية لـ user-agent — يولّد Camoufox بصمات واقعية لكل سياق على مستوى المتصفح، بما في ذلك canvas وWebGL والخطوط وخصائص navigator.```bash
# Switch engine (default: chromium)
BROWSER_ENGINE=camoufox
بروكسي لكل طلب
وجّه حركة الزحف عبر مجمعات بروكسي سكنية أو مراكز بيانات أو مخصصة. تجاوز لكل طلب مع افتراضيات قائمة على متغيرات البيئة. إعداد بروكسي متوافق تمامًا مع Playwright.```bash
Env-based default
PROXY_SERVER=http://proxy.example.com:10001
PROXY_USERNAME=your_username
PROXY_PASSWORD=your_password
Or per-request
curl -X POST http://localhost:6792/api/crawl
-H "Content-Type: application/json"
-d '{
"url": "https://example.com",
"options": {
"proxy": {
"server": "http://proxy.example.com:10001",
"username": "your_username",
"password": "your_password"
}
}
}'
### وضع التخفي
تصحيحات `playwright-stealth` اختيارية لمتصفح Chromium (تُتخطى في Camoufox حيث أنها مدمجة فيه). تقوم بحجب أكثر من 20 نطاقًا للتتبع/التحليلات (Google Analytics, DataDome, PerimeterX، إلخ) لتقليل سطح البصمة.```bash
STEALTH_ENABLED=true
BLOCK_TRACKING_DOMAINS=true
بروتوكول الشبح
عندما تشير نتيجة الزحف إلى حظر لمكافحة البوتات (تحدّي Cloudflare، CAPTCHA،
قشرة SPA فارغة)، يمكن للوكيل التبديل إلى وضع التمويه:
- التقاط لقطة شاشة للصفحة كاملة عبر Playwright
- إرسال الصورة إلى نموذج لغوي كبير قادر على الرؤية (Claude Sonnet أو GPT-4o)
- استخراج المحتوى من البكسلات المعروضة
- إرجاع النص المستخرج مع
render_mode: "ghost" في التتبّع
يتجاوز هذا كشف مكافحة البوتات القائم على DOM بالكامل.
يتطلب AGENT_GHOST_ENABLED=true. يتفعّل تلقائيًا عند رصد عمليات الحظر عندما يكون AGENT_GHOST_AUTO_TRIGGER=true.
شبكة
وكلاء يتواصلون مع وكلاء. كل مثيل Grub هو عامل ومنسّق في آنٍ واحد. العقدة المحلية تُحمّل المهام إلى السحابة، بينما تفوّض السحابة إلى المحلية. استدعاءات الأدوات تعبر عبر الشبكة بشفافية.```
Node A (local) Node B (cloud)
┌─────────────┐ ┌─────────────┐
│ AgentEngine │ │ AgentEngine │
│ ↓ │ │ ↓ │
│ MeshDispatcher ──── HTTP ────→ MeshDispatcher │
│ ↓ │ │ ↓ │
│ Dispatcher │ │ Dispatcher │
│ ↓ │ │ ↓ │
│ ToolRegistry │ │ ToolRegistry │
└─────────────┘ └─────────────┘
↕ heartbeat (15s) ↕
└────────────────────────────────┘
**كيف يعمل:**
- **الاكتشاف** — تنضم العقد عبر قائمة الأقران الأولية، ثم تتبادل المعلومات عبر القيل والقال (خطوة واحدة) لتتعرف على العقد الأخرى
- **نبض** — كل 15 ثانية، تتبادل العقد مقاييس الحمل. 3 مرات فقدان = غير سليمة. دقيقتان = تُزال
- **التوجيه** — يقوم MeshDispatcher بتقييم جميع العقد حسب الحمل والموقع المحلي والتقارب، ثم يوجّه استدعاءات الأدوات إلى أفضل عقدة
- **قفزة واحدة كحد أقصى** — العقدة A → B فقط، ولا تمر عبر A → B → C. يمنع حلقات التوجيه
- **التراجع المحلي** — إذا فشل التنفيذ عن بُعد، يتراجع إلى Dispatcher المحلي
- **مصادقة HMAC** — كل حركة مرور شبكة الـ mesh موقّعة بسر مشترك (SHA-256، مدة الصلاحية 60 ثانية)
### تشغيل شبكة Mesh من عقدتين محليًا```bash
# Docker Compose (recommended)
./deploy.sh mesh # Linux/Mac
./deploy.ps1 -Target mesh # Windows
# Verify
curl http://localhost:6792/mesh/peers # Node A sees Node B
curl http://localhost:6793/mesh/peers # Node B sees Node A
ربط المحلي بـ Cloud Run```bash
Deploy to Cloud Run with mesh
./deploy.sh cloudrun latest --mesh-peer http://your-local-ip:6792 --mesh-secret mysecret
Start local node
MESH_ENABLED=true MESH_SECRET=mysecret MESH_PEERS=https://your-cloud-run-url
MESH_ADVERTISE_URL=http://your-local-ip:6792
uvicorn app.main:app --port 6792
### الإعداد اليدوي```bash
# Node A
MESH_ENABLED=true MESH_NODE_NAME=local MESH_SECRET=test123 \
MESH_ADVERTISE_URL=http://localhost:6792 \
uvicorn app.main:app --port 6792
# Node B
MESH_ENABLED=true MESH_NODE_NAME=cloud MESH_SECRET=test123 \
MESH_PEERS=http://localhost:6792 \
MESH_ADVERTISE_URL=http://localhost:8081 \
uvicorn app.main:app --port 8081
عندما تكون خاصية mesh معطلة (MESH_ENABLED=false، الافتراضي)، يعمل Grub كزاحف عادي أحادي العقدة بدون أي عبء شبكي.
البث المباشر
شاهد الزاحف يعمل في الوقت الفعلي. تجمع دائم من نسخ Chromium الدافئة يبث إطارات منفذ العرض عبر WebSocket أو MJPEG.
WebSocket — اتصل وأرسل أوامر تفاعلية:```javascript
const ws = new WebSocket("ws://localhost:6792/stream/my-session?url=https://example.com");
ws.onmessage = (e) => {
const msg = JSON.parse(e.data);
if (msg.type === "frame") document.getElementById("viewport").src = "data:image/jpeg;base64," + msg.data;
};
// Navigate, click, scroll, type — all over the same socket
ws.send(JSON.stringify({ action: "navigate", url: "https://example.com/pricing" }));
ws.send(JSON.stringify({ action: "click", selector: "#signup-btn" }));
ws.send(JSON.stringify({ action: "scroll", direction: "down" }));
**MJPEG** — ضعها في وسم ``، فيديو فوري:```html
<img src="http://localhost:6792/stream/my-session/mjpeg?url=https://example.com" />
يتطلب BROWSER_STREAM_ENABLED=true. كل مثيل Chromium يستهلك حوالي 150-300MB من الذاكرة (RAM).
بدء سريع
التطوير المحلي```bash
git clone
cd grub-crawl
cp .env.example .env
pip install -r requirements.txt
uvicorn app.main:app --reload --host 0.0.0.0 --port 6792
### تفعيل وضع الوكيل B```bash
# Add to .env
AGENT_ENABLED=true
OPENAI_API_KEY=sk-...
# or
ANTHROPIC_API_KEY=sk-ant-...
AGENT_PROVIDER=anthropic
إرسال مهمة وكيل```bash
curl -X POST http://localhost:6792/api/agent/run
-H "Content-Type: application/json"
-d '{
"task": "Find the pricing page on example.com and extract plan details",
"max_steps": 10,
"allowed_domains": ["example.com"]
}'
### Docker```bash
# Single node
./deploy.sh local # or ./deploy.ps1 -Target local
# 2-node mesh
./deploy.sh mesh # or ./deploy.ps1 -Target mesh
# Cloud Run
./deploy.sh cloudrun v1.0.0 # or ./deploy.ps1 -Target cloudrun -Tag v1.0.0
# Cloud Run + mesh (connect to local node)
./deploy.sh cloudrun v1.0.0 --mesh-peer http://your-ip:6792 --mesh-secret mykey
مكافحة الكشف (Camoufox + Proxy)```bash
Add to .env
BROWSER_ENGINE=camoufox
STEALTH_ENABLED=true
BLOCK_TRACKING_DOMAINS=true
Optional: proxy
PROXY_SERVER=http://proxy.example.com:10001
PROXY_USERNAME=your_username
PROXY_PASSWORD=your_password
### Ghost Protocol (تجاوز مكافحة البوت)```bash
# Add to .env
AGENT_GHOST_ENABLED=true
curl -X POST http://localhost:6792/api/agent/ghost \
-H "Content-Type: application/json" \
-d '{"url": "https://blocked-site.com"}'
البث المباشر للمتصفح```bash
Add to .env
BROWSER_STREAM_ENABLED=true
BROWSER_POOL_SIZE=2
MJPEG (open in browser)
open "http://localhost:6792/stream/demo/mjpeg?url=https://example.com"
## الإعداد
### الخادم
- `HOST` (الافتراضي: 0.0.0.0)
- `PORT` (الافتراضي: 6792)
- `DEBUG` (الافتراضي: false)
### التخزين
- `STORAGE_PATH` (الافتراضي: ./storage)
- `RUNNING_IN_CLOUD` (الافتراضي: false)
- `GCS_BUCKET_NAME`
- `GOOGLE_CLOUD_PROJECT`
### المصادقة
- `DISABLE_AUTH` (الافتراضي: false)
- `GNOSIS_AUTH_URL` (الافتراضي: http://gnosis-auth:5000)
### محرك المتصفح
- `BROWSER_ENGINE` — chromium | camoufox (الافتراضي: chromium)
### الزحف
- `MAX_CONCURRENT_CRAWLS` (الافتراضي: 5)
- `CRAWL_TIMEOUT` (الافتراضي: 30)
- `ENABLE_JAVASCRIPT` (الافتراضي: true)
- `ENABLE_SCREENSHOTS` (الافتراضي: false)
### البروكسي
- `PROXY_SERVER` — عنوان URL للبروكسي (مثل: http://proxy:10001)
- `PROXY_USERNAME`
- `PROXY_PASSWORD`
- `PROXY_BYPASS` — قائمة تجاوز مفصولة بفواصل
### التخفي
- `STEALTH_ENABLED` (الافتراضي: false) — تصحيحات playwright-stealth
- `BLOCK_TRACKING_DOMAINS` (الافتراضي: false) — حظر طلبات التحليلات/التتبع
### الوكيل (الوضع B)
- `AGENT_ENABLED` (الافتراضي: false)
- `AGENT_MAX_STEPS` (الافتراضي: 12)
- `AGENT_MAX_WALL_TIME_MS` (الافتراضي: 90000)
- `AGENT_MAX_FAILURES` (الافتراضي: 3)
- `AGENT_ALLOWED_TOOLS` — قائمة سماح مفصولة بفواصل
- `AGENT_ALLOWED_DOMAINS` — قائمة سماح مفصولة بفواصل
- `AGENT_BLOCK_PRIVATE_RANGES` (الافتراضي: true)
- `AGENT_REDACT_SECRETS` (الافتراضي: true)
### مزودو LLM
- `AGENT_PROVIDER` — openai | anthropic | ollama (الافتراضي: openai)
- `OPENAI_API_KEY`
- `OPENAI_MODEL` (الافتراضي: gpt-4.1-mini)
- `ANTHROPIC_API_KEY`
- `ANTHROPIC_MODEL` (الافتراضي: claude-3-5-sonnet-latest)
- `OLLAMA_BASE_URL` (الافتراضي: http://localhost:11434)
- `OLLAMA_MODEL` (الافتراضي: llama3.1:8b-instruct)
### بروتوكول Ghost
- `AGENT_GHOST_ENABLED` (الافتراضي: false)
- `AGENT_GHOST_AUTO_TRIGGER` (الافتراضي: true)
- `AGENT_GHOST_VISION_PROVIDER` — يُورث من AGENT_PROVIDER
- `AGENT_GHOST_MAX_IMAGE_WIDTH` (الافتراضي: 1280)
### الشبكة
- `MESH_ENABLED` (الافتراضي: false) — المفتاح الرئيسي
- `MESH_PEERS` — عناوين URL للنظائر مفصولة بفواصل
- `MESH_NODE_NAME` — اسم مقروء بشريًا (الافتراضي: hostname)
- `MESH_SECRET` — سر HMAC مشترك لمصادقة العقد
- `MESH_ADVERTISE_URL` — عنوان URL الذي تستخدمه النظائر للوصول إلى هذه العقدة
- `MESH_PREFER_LOCAL` (الافتراضي: true) — الميل نحو التنفيذ المحلي
- `MESH_HEARTBEAT_INTERVAL_S` (الافتراضي: 15)
- `MESH_PEER_TIMEOUT_S` (الافتراضي: 45) — وضع علامة غير صحية بعد هذه المدة
- `MESH_PEER_REMOVE_S` (الافتراضي: 120) — الإزالة من جدول النظائر بعد هذه المدة
- `MESH_REMOTE_TIMEOUT_MS` (الافتراضي: 35000) — مهلة لاستدعاءات الأدوات عن بُعد
### البث المباشر
- `BROWSER_POOL_SIZE` (الافتراضي: 1)
- `BROWSER_STREAM_ENABLED` (الافتراضي: false)
- `BROWSER_STREAM_QUALITY` (الافتراضي: 25) — جودة JPEG من 1 إلى 100
- `BROWSER_STREAM_MAX_WIDTH` (الافتراضي: 854)
- `BROWSER_STREAM_MAX_LEASE_SECONDS` (الافتراضي: 300)
## عقد الاستجابة
`POST /api/markdown` يعيد:
`success`, `url`, `final_url`, `status_code`, `markdown`, `markdown_plain`, `content`, `render_mode`, `wait_strategy`, `timings_ms`, `blocked`, `block_reason`, `captcha_detected`, `http_error_family`, `body_char_count`, `body_word_count`, `visible_char_count`, `visible_word_count`, `visible_similarity`, `quarantined`, `quarantine_reason`, `policy_flags`, `content_quality`, `extractor_version`, `normalized_url`, `content_hash`
### جودة المحتوى
- `blocked` — مكافحة البوت/كابتشا/تحدٍّ
- `empty` — إشارة منخفضة جدًا
- `minimal` — صفحات رقيقة/أخطاء
- `sufficient` — قابلة للاستخدام للتلخيص
لا تلخّص إلا إذا كانت `content_quality == "sufficient"`.
### الدفاع ضد حقن التعليمات
- `quarantined=true` تعني أن المستخرج اكتشف نصًا شبيهًا بالتعليمات في المحتوى المستخرج لم يكن موجودًا في النص المرئي المعروض للصفحة (شائع في إساءة استخدام `.sr-only`/المخفية بصريًا).
- عند العزل، يتم تخفيض `content_quality` إلى `minimal`، وتتضمن `policy_flags` القيمتين `hidden_text_suspected` و`quarantined`، ويتم إفراغ مخرجات `content`/`markdown` (إغلاق عند الفشل).
### تنسيق الخطأ```json
{"error": "http_error|validation_error|internal_error", "status": 400, "details": {}}
المعايير
ساحة القتال — معايير وجهاً لوجه ضد Crawl4AI وFirecrawl (مستضاف ذاتياً) وScrapy. جميع الاختبارات تُجرى على نفس الجهاز، ونفس عناوين URL، ونفس الظروف. يعمل Grub أولاً كخط أساس، ثم بقية المحولات بترتيب عشوائي مع تأخير 10 ثوانٍ بين كل منها لمنع انحياز تحديد المعدل.
سرعة عنوان URL واحد (ms، الأقل أفضل)
يفوز Grub في 4/5 من سباقات سرعة عنوان URL واحد. يتم تحويل Markdown خلال 0-21 مللي ثانية عبر محرك Rust الأصلي (grub_md).
تحليل مراحل Grub (مللي ثانية من جانب الخادم)
يهيمن التنقل؛ ويكون تحويل Markdown أقل من مللي ثانية في معظم الصفحات بفضل محرك Rust.
إنتاجية الدفعة (ms، الأقل أفضل)
يفوز Grub في 2/3 من أحجام الدفعات. التكلفة لكل عنوان URL: 163-312 مللي ثانية (Grub) مقابل 255-477 مللي ثانية (الآخرين).
كيفية التشغيل```bash
Start Grub
docker compose up -d
Start Firecrawl (optional)
docker compose -f combat/firecrawl-compose.yaml up -d
Install combat deps
pip install crawl4ai scrapy markdownify tabulate
Run the arena
pytest combat/ -m combat -v
Generate report
python -m combat.report
## حالة التطوير
### المرحلة 1: البنية التحتية الأساسية ✅
### المرحلة 2: الزحف ✅
### المرحلة 3: وحدة الوكيل ✅
- [x] نواة الوكيل — آلة الحالة، الأنواع، الأخطاء (W1)
- [x] عقد الأدوات الموحّد — مُوزِّع مع مهلة/إعادة محاولة (W2)
- [x] بوابات السياسات — قائمة النطاقات المسموحة، رفض النطاقات الخاصة، التنقيح (W3)
- [x] قابلية المراقبة — EventBus، TraceCollector، استمرارية RunSummary (W4)
- [x] ربط API — `/api/agent/run`، `/api/agent/status`، JobType.AGENT_RUN (W5)
- [x] محوّلات المزوّدين — OpenAI، Anthropic، Ollama مع احتياطي (W6)
- [x] خيارات التكوين — الوكيل، المزوّد، الشبح، إعدادات البث (W7)
### المرحلة 4: بروتوكول الشبح ✅
- [x] كشف محفّز وضع التمويه (W8)
- [x] خط أنابيب التقاط لقطات الشاشة (W8)
- [x] استخراج الرؤية عبر Claude/GPT-4o (W8)
- [x] سلسلة الاحتياط في المحرك (W8)
- [x] أداة الشبح للمتصلين الخارجيين (W8)
- [x] أداة Ghost MCP + نقطة نهاية REST (W8)
### المرحلة 5: بث المتصفح المباشر ✅
- [x] تجمّع متصفحات دائم مع استئجار/إرجاع (W9)
- [x] مرحّل بث الشاشة عبر CDP (W9)
- [x] نقطة نهاية WebSocket مع أوامر تفاعلية (W9)
- [x] بث احتياطي MJPEG (W9)
- [x] نقاط نهاية حالة البث + حالة التجمّع (W9)
### المرحلة 5.5: مكافحة الكشف ✅
- [x] محرك متصفح Camoufox المضاد للكشف (W10)
- [x] وكيل لكل طلب مع احتياطي عبر متغيرات البيئة (W10)
- [x] تصحيحات التخفي لـ Chromium (W10)
- [x] حظر نطاقات التتبّع/التحليلات (W10)
- [x] إصلاح اكتشاف تنسيق الرؤية في Anthropic (W10)
### المرحلة 6: منسّق الشبكة المتداخلة ✅
- [x] اكتشاف الأقران عبر القيل والقال (قفزة واحدة) (W11)
- [x] مصادقة بين العقد عبر HMAC-SHA256 (W11)
- [x] حلقة نبضات القلب مع مقاييس الحمل + إعادة محاولة البذرة (W11)
- [x] MeshDispatcher — توجيه شفاف للأدوات بين العقد (W12)
- [x] تسجيل قائم على الحمل مع مكافأة القرب/الألفة (W12)
- [x] نصوص النشر — محلي، شبكة متداخلة، Cloud Run (W12)
- [x] طوبولوجيا شبكة متداخلة من عقدتين عبر Docker Compose (W12)
- [x] صفحة هبوط مضمّنة (grub-site) (W12)
### المرحلة 7: الأداء + التحصين
- [x] محرك Markdown بلغة Rust (`grub_md`) — امتداد أصلي بـ PyO3، تحويل بأقل من ملي ثانية
- [x] ساحة القتال — معايير أداء آلية مقابل Crawl4AI، Firecrawl، Scrapy
- [x] مجموعة اختبارات الوحدة — 176 اختبارًا عبر جميع الوحدات
- [ ] تحسينات معالجة الأخطاء
- [ ] المراقبة والتنبيهات
راجع [MASTER_PLAN.md](https://github.com/deepbluedynamics/grubcrawler/blob/HEAD/MASTER_PLAN.md) للحصول على خطة الهندسة الكاملة.
## الترخيص
ترخيص مشروع Grub Crawler