> ## Documentation Index
> Fetch the complete documentation index at: https://exosphere-auto-translate-docs-20260624-1149.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

title: العمارة
description: "كيفية عمل معالج الخطاف وتحميل الإعدادات وتقييم السياسات بشكل داخلي"
icon: sitemap
-------------

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

***

## نظرة عامة

يمتلك failproofai نظامين فرعيين مستقلين:

1. **معالج الخطاف** - عملية سطر أوامر سريعة يستدعيها Claude Code على كل استدعاء أداة وكيل. يقيّم السياسات ويعيد قرارًا.
2. **مراقب الوكيل (لوحة التحكم)** - تطبيق ويب Next.js لمراقبة جلسات الوكيل وإدارة السياسات.

يشترك كلا النظامين الفرعيين في ملفات الإعدادات في `~/.failproofai/` ومجلد `.failproofai/` الخاص بالمشروع، لكنهما يعملان كعمليات منفصلة ويتصلان فقط عبر نظام الملفات.

***

## معالج الخطاف

### التكامل مع Claude Code

عند تشغيل `failproofai policies --install`، يكتب إدخالات مثل هذه في `~/.claude/settings.json`:

```json theme={null}
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "failproofai --hook PreToolUse"
          }
        ]
      }
    ],
    "PostToolUse": [ ... ]
  }
}
```

ثم يستدعي Claude Code `failproofai --hook PreToolUse` كعملية فرعية قبل كل استدعاء أداة، مرسلاً حمولة JSON عبر stdin.

### تنسيق الحمولة

```json theme={null}
{
  "session_id": "abc123",
  "transcript_path": "/home/user/.claude/projects/myproject/sessions/abc123.jsonl",
  "cwd": "/home/user/myproject",
  "permission_mode": "default",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": { "command": "sudo apt install nodejs" }
}
```

بالنسبة لأحداث `PostToolUse`، تحتوي الحمولة أيضًا على `tool_result` مع مخرجات الأداة.

يفرض المعالج حدًا أقصى لـ stdin بحجم 1 ميجابايت. يتم تجاهل الحمولات التي تتجاوز هذا الحد وجميع السياسات تسمح ضمنيًا.

### تنسيق الاستجابة

**رفض (PreToolUse):**

```json theme={null}
{
  "hookSpecificOutput": {
    "permissionDecision": "deny",
    "permissionDecisionReason": "Blocked by failproofai: sudo command blocked"
  }
}
```

**رفض (PostToolUse):**

```json theme={null}
{
  "hookSpecificOutput": {
    "additionalContext": "Blocked by failproofai because: API key detected in output"
  }
}
```

**توجيه (أي حدث ما عدا Stop):**

```json theme={null}
{
  "hookSpecificOutput": {
    "additionalContext": "Instruction from failproofai: Verify tests pass before committing."
  }
}
```

**توجيه حدث التوقف:**

* رمز الخروج: `2`
* السبب مكتوب في stderr (وليس stdout)

**السماح:**

* رمز الخروج: `0`
* stdout فارغ

**السماح مع رسالة:**

يسمح `allow(message)` للسياسة بإرسال سياق معلومات إلى Claude حتى عند السماح بالعملية. يكتب معالج الخطاف JSON التالي إلى **stdout** (وليس ملف إعدادات — هذه هي استجابة المعالج لـ Claude Code، تماماً مثل الإجابات على الرفض والتوجيه أعلاه):

```json theme={null}
// Written to stdout by the hook handler process
{
  "hookSpecificOutput": {
    "additionalContext": "All CI checks passed on branch 'feat/my-feature'."
  }
}
```

* رمز الخروج: `0` (العملية مسموحة)
* عند عودة عدة سياسات `allow` برسالة، يتم ربط رسائلها بفواصل سطر جديد في سلسلة `additionalContext` واحدة
* إذا لم توفر أي سياسة رسالة، يكون stdout فارغاً (نفس السابق)

### خط أنابيب المعالجة

ينفذ `src/hooks/handler.ts` خط الأنابيب الكامل:

```text theme={null}
stdin JSON
  → parse payload (max 1 MB)
  → extract session metadata (session_id, cwd, tool_name, tool_input, etc.)
  → readMergedHooksConfig(cwd)    ← merges project + local + global config
  → register enabled builtin policies with resolved params
  → load custom policies from customPoliciesPath (if set)
  → register custom policies into policy registry
  → evaluate all policies (builtins first, then custom)
      → first deny short-circuits
      → instruct decisions accumulate
      → allow messages accumulate
  → write JSON decision to stdout
  → persist event to ~/.failproofai/hook-activity.jsonl
  → exit
```

تعمل العملية بأكملها في أقل من 100 ميلي ثانية للحمولات النموذجية بدون استدعاءات LLM.

***

## تحميل الإعدادات

يطبق `src/hooks/hooks-config.ts` تحميل الإعدادات بثلاث نطاقات.

```text theme={null}
[1] {cwd}/.failproofai/policies-config.json        ← project  (highest priority)
[2] {cwd}/.failproofai/policies-config.local.json  ← local
[3] ~/.failproofai/policies-config.json             ← global   (lowest priority)
```

منطق الدمج:

* `enabledPolicies` - اتحاد مزال التكرار عبر جميع الملفات الثلاثة
* `policyParams` - لكل سياسة، الملف الأول الذي يعرّفها يفوز بالكامل
* `customPoliciesPath` - الملف الأول الذي يعرّفه يفوز
* `llm` - الملف الأول الذي يعرّفه يفوز

تستخدم لوحة تحكم الويب `readHooksConfig()` (العام فقط) للقراءة والكتابة، حيث لا يتم استدعاؤها مع cwd المشروع.

***

## تقييم السياسة

يشغل `src/hooks/policy-evaluator.ts` السياسات بالترتيب.

لكل سياسة:

1. البحث عن مخطط `params` الخاص بالسياسة (إن وجد).
2. قراءة `policyParams[policy.name]` من الإعدادات المدمجة.
3. دمج القيم المقدمة من قبل المستخدم فوق الافتراضيات في المخطط لإنتاج `ctx.params`.
4. استدعاء `policy.fn(ctx)` مع السياق المحل.
5. إذا كانت النتيجة `deny`، توقف على الفور وأعد هذا القرار.
6. إذا كانت النتيجة `instruct`، تراكم الرسالة والمتابعة.
7. إذا كانت النتيجة `allow`، انتقل إلى السياسة التالية.

بعد تشغيل جميع السياسات:

* إذا تم إرجاع أي `deny`، أصدر استجابة الرفض.
* إذا تم جمع أي عائدات `instruct`، أصدر استجابة توجيه واحدة مع ربط جميع الرسائل.
* وإلا، أصدر استجابة السماح (stdout فارغ، الخروج 0).

***

## السياسات المدمجة

يعرّف `src/hooks/builtin-policies.ts` جميع 39 سياسة مدمجة كائنات `BuiltinPolicyDefinition`:

```typescript theme={null}
interface BuiltinPolicyDefinition {
  name: string;
  description: string;
  fn: (ctx: PolicyContext) => PolicyResult;
  match: {
    events: HookEventType[];
    tools?: string[];
  };
  defaultEnabled: boolean;
  category: string;
  beta?: boolean;
  params?: PolicyParamsSchema;
}
```

السياسات التي تقبل `params` تعلن `PolicyParamsSchema` بأنواع وافتراضيات لكل معامل. يحقن مقيّم السياسة القيم المحلة في `ctx.params` قبل استدعاء `fn`. تقرأ دوال السياسة `ctx.params` بدون حماية فارغة لأن الافتراضيات تُطبق دائماً أولاً.

يستخدم مطابقة الأنماط داخل السياسات رموز الأوامر المحللة (argv)، وليس مطابقة السلسلة النصية الخام. وهذا يمنع الالتفاف عبر حقن عامل الأوامر (على سبيل المثال، نمط لـ `sudo systemctl status *` لا يمكن الالتفاف عليه بإضافة `; rm -rf /` إلى الأمر).

***

## السياسات المخصصة

ينفذ `src/hooks/custom-hooks-registry.ts` سجل مدعوم `globalThis`:

```typescript theme={null}
const REGISTRY_KEY = "__failproofai_custom_hooks__";

export const customPolicies = {
  add(hook: CustomHook): void { ... }
};

export function getCustomHooks(): CustomHook[] { ... }
export function clearCustomHooks(): void { ... }  // used in tests
```

يحمل `src/hooks/custom-hooks-loader.ts` ملف السياسة الخاص بالمستخدم:

1. اقرأ `customPoliciesPath` من الإعدادات؛ تخطي إذا كان غائباً.
2. حل إلى مسار مطلق؛ تحقق من وجود الملف.
3. أعد كتابة جميع واردات `from "failproofai"` إلى مسار dist الفعلي حتى يتم حل `customPolicies` إلى نفس سجل `globalThis`.
4. أعد كتابة الواردات المحلية العابرة بشكل متكرر لضمان التوافقية ESM.
5. اكتب ملفات `.mjs` مؤقتة و`import()` ملف الدخول.
6. اتصل بـ `getCustomHooks()` لاسترجاع الخطافات المسجلة.
7. نظف جميع الملفات المؤقتة في كتلة `finally`.

في حالة حدوث أي خطأ (ملف غير موجود، خطأ بناء جملة، فشل الاستيراد)، يتم تسجيل الخطأ في `~/.failproofai/hook.log` ويعيد المحمل مصفوفة فارغة. السياسات المدمجة غير متأثرة.

يتم تقييم السياسات المخصصة بعد جميع السياسات المدمجة. إنكار السياسة المخصصة لا يزال يختصر السياسات المخصصة الإضافية (لكن جميع المدمجة قد عملت بالفعل في تلك النقطة).

***

## تسجيل النشاط

بعد كل حدث خطاف، يضيف المعالج سطر JSONL إلى `~/.failproofai/hook-activity.jsonl`:

```json theme={null}
{
  "timestamp": "2026-04-06T12:34:56.789Z",
  "sessionId": "abc123",
  "eventType": "PreToolUse",
  "toolName": "Bash",
  "policyName": "block-sudo",
  "decision": "deny",
  "reason": "sudo command blocked by failproofai",
  "durationMs": 12
}
```

سطر واحد لكل سياسة اتخذت قرار غير سماح. لا يتم تسجيل قرارات السماح (للحفاظ على صغر حجم الملف).

***

## عمارة لوحة التحكم

لوحة التحكم هي تطبيق **Next.js 16** يستخدم App Router مع React Server Components و Server Actions.

```text theme={null}
app/
  layout.tsx                  ← Root layout (theme, telemetry, nav)
  projects/page.tsx           ← Server component: list all Claude projects
  project/[name]/page.tsx     ← Server component: list sessions in a project
  project/[name]/session/
    [sessionId]/page.tsx      ← Server component: render session viewer
  policies/page.tsx           ← Client component: policy management + activity log
  actions/
    get-hooks-config.ts       ← Read config + policy list
    update-hooks-config.ts    ← Toggle policy on/off
    update-policy-params.ts   ← Update policy parameters
    get-hook-activity.ts      ← Paginate/search activity log
    install-hooks-web.ts      ← Install/remove hooks from the browser
  api/
    download/[project]/[session]/route.ts   ← Per-CLI session export (JSONL or JSON)
```

**تدفق البيانات:**

* تستدعي مكونات الصفحة `lib/projects.ts` و `lib/log-entries.ts` لقراءة بيانات المشروع/الجلسة مباشرة من نظام الملفات (بدون طبقة API للقراءات).
* تستخدم صفحة السياسات Server Actions لجميع التطبيقات (تبديل، تحديث المعاملات، التثبيت/الإزالة).
* يحلل عارض الجلسة تنسيق نص Claude JSONL ويعرض جدول زمني للرسائل واستدعاءات الأدوات.

**قرارات التصميم الرئيسية:**

* بدون قاعدة بيانات - جميع الحالة الدائمة موجودة في ملفات عادية (`~/.failproofai/`، `~/.claude/projects/`).
* Server Actions للتطبيقات - لا حاجة إلى REST API لعمليات CRUD.
* React Server Components لصفحات القراءة - تحميل أولي أسرع، بدون حزمة عميل لجلب البيانات.
* مكونات العميل فقط حيث تكون التفاعلية مطلوبة (تبديلات السياسة، بحث النشاط، عارض السجل).

***

## تخطيط الملفات

```text theme={null}
failproofai/
├── bin/
│   └── failproofai.mjs           # CLI router (hook / dashboard / install / etc.)
├── src/hooks/
│   ├── handler.ts                # Hook event pipeline
│   ├── builtin-policies.ts       # 39 policy definitions
│   ├── policy-evaluator.ts       # Policy execution engine
│   ├── policy-registry.ts        # Policy registration and lookup
│   ├── policy-types.ts           # TypeScript interfaces
│   ├── hooks-config.ts           # Multi-scope config loading
│   ├── custom-hooks-registry.ts  # globalThis-backed hook registry
│   ├── custom-hooks-loader.ts    # ESM loader for user JS hooks
│   ├── manager.ts                # install / remove / list operations
│   ├── install-prompt.ts         # Interactive policy selection prompt
│   ├── hook-logger.ts            # Logging to hook.log
│   ├── hook-activity-store.ts    # Persist activity to hook-activity.jsonl
│   └── llm-client.ts             # LLM API client (for AI-powered policies)
├── app/                          # Next.js dashboard (pages + server actions)
├── lib/                          # Shared utilities
│   ├── projects.ts               # Enumerate Claude projects from filesystem
│   ├── log-entries.ts            # Parse Claude transcript JSONL format
│   ├── paths.ts                  # Resolve system paths
│   └── ...
├── components/                   # Shared React UI components
├── contexts/                     # React context providers (theme, auto-refresh, telemetry)
├── examples/                     # Example custom hook files
└── __tests__/                    # Unit and E2E tests
```
