> ## Documentation Index
> Fetch the complete documentation index at: https://docs.befailproof.ai/llms.txt
> Use this file to discover all available pages before exploring further.

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

> اكتب سياساتك الخاصة في JavaScript - فرض الاتفاقيات، منع الانجراف، كشف الأعطال، التكامل مع الأنظمة الخارجية

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

***

## مثال سريع

```js theme={null}
// my-policies.js
import { customPolicies, allow, deny, instruct } from "failproofai";

customPolicies.add({
  name: "no-production-writes",
  description: "Block writes to paths containing 'production'",
  match: { events: ["PreToolUse"] },
  fn: async (ctx) => {
    if (ctx.toolName !== "Write" && ctx.toolName !== "Edit") return allow();
    const path = ctx.toolInput?.file_path ?? "";
    if (path.includes("production")) {
      return deny("Writes to production paths are blocked");
    }
    return allow();
  },
});
```

قم بتثبيتها:

```bash theme={null}
failproofai policies --install --custom ./my-policies.js
```

***

## طريقتان لتحميل السياسات المخصصة

### الخيار 1: المستند على الاتفاقية (موصى به)

ضع ملفات `*policies.{js,mjs,ts}` في `.failproofai/policies/` وسيتم تحميلها تلقائياً — لا تحتاج إلى أعلام أو تغييرات إعدادات. يعمل هذا مثل git hooks: ضع ملفاً وبالتالي يعمل.

```
# مستوى المشروع — يتم الالتزام به على git، مشاركته مع الفريق
.failproofai/policies/security-policies.mjs
.failproofai/policies/workflow-policies.mjs

# مستوى المستخدم — شخصي، ينطبق على جميع المشاريع
~/.failproofai/policies/my-policies.mjs
```

**كيف يعمل:**

* يتم فحص كلا المديرين (الدمج — وليس first-scope-wins)
* يتم تحميل الملفات أبجدياً ضمن كل دليل. استخدم البادئة `01-` و `02-` للتحكم في الترتيب
* يتم تحميل الملفات التي تطابق `*policies.{js,mjs,ts}` فقط؛ يتم تجاهل الملفات الأخرى
* يتم تحميل كل ملف بشكل مستقل (fail-open لكل ملف)
* يعمل جنباً إلى جنب مع السياسات الصريحة `--custom` والسياسات المدمجة

<Tip>
  سياسات الاتفاقية هي الطريقة الأسهل لبناء معيار جودة لمؤسستك. التزم `.failproofai/policies/` إلى git وكل عضو في الفريق يحصل على نفس القواعد تلقائياً — لا حاجة لإعداد لكل مطور. مع اكتشاف فريقك لأنماط فشل جديدة، أضف سياسة وادفع. بمرور الوقت تصبح هذه معيار جودة حي يتحسن باستمرار مع كل مساهمة.
</Tip>

### الخيار 2: مسار الملف الصريح

```bash theme={null}
# التثبيت مع ملف سياسات مخصص
failproofai policies --install --custom ./my-policies.js

# استبدال مسار ملف السياسات
failproofai policies --install --custom ./new-policies.js

# إزالة مسار السياسات المخصصة من الإعدادات
failproofai policies --uninstall --custom
```

يتم تخزين المسار المطلق الذي تم حله في `policies-config.json` باسم `customPoliciesPath`. يتم تحميل الملف بشكل جديد في كل حدث خطاف - لا يوجد caching بين الأحداث.

### استخدام كليهما معاً

يمكن للسياسات المستندة على الاتفاقية والملف الصريح `--custom` أن يتعايشا. ترتيب التحميل:

1. ملف `customPoliciesPath` الصريح (إن تم تكوينه)
2. ملفات اتفاقية المشروع (`{cwd}/.failproofai/policies/`، أبجدي)
3. ملفات اتفاقية المستخدم (`~/.failproofai/policies/`، أبجدي)

***

## API

### الاستيراد

```js theme={null}
import { customPolicies, allow, deny, instruct } from "failproofai";
```

### `customPolicies.add(hook)`

تسجيل سياسة. استدعِ هذا عدة مرات حسب الحاجة لسياسات متعددة في نفس الملف.

```ts theme={null}
customPolicies.add({
  name: string;                         // مطلوب - معرّف فريد
  description?: string;                 // موضح في مخرجات `failproofai policies`
  match?: { events?: HookEventType[] }; // تصفية حسب نوع الحدث؛ احذف لمطابقة الكل
  fn: (ctx: PolicyContext) => PolicyResult | Promise<PolicyResult>;
});
```

### مساعدات القرار

| الدالة              | التأثير              | الاستخدام عندما                               |
| ------------------- | -------------------- | --------------------------------------------- |
| `allow()`           | السماح بالعملية بصمت | الإجراء آمن، لا حاجة لرسالة                   |
| `deny(message)`     | حظر العملية          | يجب ألا يتخذ الوكيل هذا الإجراء               |
| `instruct(message)` | إضافة سياق بدون حظر  | إعطاء الوكيل سياقاً إضافياً للبقاء على المسار |

`deny(message)` - تظهر الرسالة أمام Claude مع البادئة `Blocked by failproofai:`. رفض واحد يختصر كل التقييم الإضافي.

`instruct(message)` - يتم إلحاق الرسالة بسياق Claude لاستدعاء الأداة الحالي. يتم تجميع جميع رسائل `instruct` وتسليمها معاً.

<Tip>
  يمكنك إلحاق إرشادات إضافية برسالة `deny` أو `instruct` بإضافة حقل `hint` في `policyParams` — لا حاجة لتغيير الكود. يعمل هذا للسياسات المخصصة (`custom/`)، واتفاقية المشروع (`.failproofai-project/`)، واتفاقية المستخدم (`.failproofai-user/`) أيضاً. انظر [التكوين → hint](/ar/configuration#hint-cross-cutting) للتفاصيل.
</Tip>

### رسائل السماح المعلوماتية

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

| الدالة           | التأثير                         | الاستخدام عندما                     |
| ---------------- | ------------------------------- | ----------------------------------- |
| `allow(message)` | السماح وإرسال السياق إلى Claude | تأكيد نجاح فحص، أو شرح سبب تخطي فحص |

حالات الاستخدام:

* **تأكيدات الحالة:** `allow("All CI checks passed.")` — أخبر Claude أن كل شيء أخضر
* **شروحات fail-open:** `allow("GitHub CLI not installed, skipping CI check.")` — أخبر Claude لماذا تم تخطي فحص حتى يكون لديه السياق الكامل
* **تراكم الرسائل المتعددة:** إذا أرجعت عدة سياسات `allow(message)`، يتم دمج جميع الرسائل بأسطر جديدة وتسليمها معاً

```js theme={null}
customPolicies.add({
  name: "confirm-branch-status",
  match: { events: ["Stop"] },
  fn: async (ctx) => {
    const cwd = ctx.session?.cwd;
    if (!cwd) return allow("No working directory, skipping branch check.");

    // ... check branch status ...
    if (allPushed) {
      return allow("Branch is up to date with remote.");
    }
    return deny("Unpushed changes detected.");
  },
});
```

### حقول `PolicyContext`

| الحقل       | النوع                                  | الوصف                                                         |
| ----------- | -------------------------------------- | ------------------------------------------------------------- |
| `eventType` | `string`                               | `"PreToolUse"`, `"PostToolUse"`, `"Notification"`, `"Stop"`   |
| `toolName`  | `string \| undefined`                  | الأداة التي يتم استدعاؤها (مثل `"Bash"`، `"Write"`، `"Read"`) |
| `toolInput` | `Record<string, unknown> \| undefined` | معاملات إدخال الأداة                                          |
| `payload`   | `Record<string, unknown>`              | حمل الحدث الخام الكامل من Claude Code                         |
| `session`   | `SessionMetadata \| undefined`         | سياق الجلسة (انظر أدناه)                                      |

### حقول `SessionMetadata`

| الحقل            | النوع    | الوصف                               |
| ---------------- | -------- | ----------------------------------- |
| `sessionId`      | `string` | معرّف جلسة Claude Code              |
| `cwd`            | `string` | مجلد العمل لجلسة Claude Code        |
| `transcriptPath` | `string` | مسار ملف النسخ الكاملة JSONL للجلسة |

### أنواع الأحداث

| الحدث          | متى يتم تشغيله            | محتويات `toolInput`                                                                                                                             |
| -------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `PreToolUse`   | قبل تشغيل Claude لأداة    | إدخال الأداة (مثل `{ command: "..." }` لـ Bash)                                                                                                 |
| `PostToolUse`  | بعد اكتمال أداة           | إدخال الأداة + `tool_result` (الإخراج)                                                                                                          |
| `Notification` | عندما يرسل Claude إشعاراً | `{ message: "...", notification_type: "idle" \| "permission_prompt" \| ... }` - يجب أن تُرجع الخطافات دائماً `allow()`، لا يمكنها حظر الإشعارات |
| `Stop`         | عند انتهاء جلسة Claude    | فارغ                                                                                                                                            |

***

## ترتيب التقييم

يتم تقييم السياسات بهذا الترتيب:

1. السياسات المدمجة (بترتيب التعريف)
2. السياسات المخصصة الصريحة من `customPoliciesPath` (بترتيب `.add()`)
3. سياسات الاتفاقية من `.failproofai/policies/` للمشروع (الملفات أبجدياً، بترتيب `.add()` بداخلها)
4. سياسات الاتفاقية من `~/.failproofai/policies/` للمستخدم (الملفات أبجدياً، بترتيب `.add()` بداخلها)

<Note>
  أول رفض `deny` يختصر جميع السياسات اللاحقة. يتم تجميع جميع رسائل `instruct` وتسليمها معاً.
</Note>

***

## الاستيرادات المتعدية

يمكن لملفات السياسات المخصصة استيراد وحدات محلية باستخدام مسارات نسبية:

```js theme={null}
// my-policies.js
import { isBlockedPath } from "./utils.js";
import { checkApproval } from "./approval-client.js";

customPolicies.add({
  name: "approval-gate",
  fn: async (ctx) => {
    if (ctx.toolName !== "Bash") return allow();
    const approved = await checkApproval(ctx.toolInput?.command, ctx.session?.sessionId);
    return approved ? allow() : deny("Approval required for this command");
  },
});
```

يتم حل جميع الاستيرادات النسبية التي يمكن الوصول إليها من ملف الإدخال. يتم تنفيذ هذا بإعادة كتابة استيرادات `from "failproofai"` إلى مسار dist الفعلي وإنشاء ملفات `.mjs` مؤقتة لضمان التوافقية ESM.

***

## تصفية نوع الحدث

استخدم `match.events` لتحديد متى يتم تشغيل السياسة:

```js theme={null}
customPolicies.add({
  name: "require-summary-on-stop",
  match: { events: ["Stop"] },
  fn: async (ctx) => {
    // يتم التشغيل فقط عند انتهاء الجلسة
    // ctx.session.transcriptPath يحتوي على سجل الجلسة الكامل
    return allow();
  },
});
```

احذف `match` بالكامل للتشغيل على كل نوع حدث.

***

## معالجة الأخطاء وأنماط الفشل

السياسات المخصصة **fail-open**: الأخطاء لا تحظر السياسات المدمجة أو تعطل معالج الخطاف.

| الفشل                               | السلوك                                                                         |
| ----------------------------------- | ------------------------------------------------------------------------------ |
| `customPoliciesPath` غير محدد       | لا تعمل السياسات المخصصة الصريحة؛ تستمر السياسات المدمجة والاتفاقية بشكل طبيعي |
| الملف غير موجود                     | تحذير مسجل إلى `~/.failproofai/hook.log`؛ تستمر السياسات المدمجة               |
| خطأ بناء الجملة/الاستيراد (صريح)    | خطأ مسجل إلى `~/.failproofai/hook.log`؛ السياسات المخصصة الصريحة متخطاة        |
| خطأ بناء الجملة/الاستيراد (اتفاقية) | خطأ مسجل؛ هذا الملف متخطى، الملفات الأخرى تحمل بشكل طبيعي                      |
| `fn` يرمي في وقت التشغيل            | خطأ مسجل؛ يتم التعامل مع هذا الخطاف كـ `allow`؛ يستمر الخطافات الأخرى          |
| `fn` يستغرق أكثر من 10 ثواني        | انتهاء وقت مسجل؛ معامل كـ `allow`                                              |
| دليل الاتفاقية مفقود                | لا تعمل سياسات الاتفاقية؛ لا خطأ                                               |

<Tip>
  لتصحيح أخطاء السياسات المخصصة، راقب ملف السجل:

  ```bash theme={null}
  tail -f ~/.failproofai/hook.log
  ```
</Tip>

***

## مثال كامل: سياسات متعددة

```js theme={null}
// my-policies.js
import { customPolicies, allow, deny, instruct } from "failproofai";

// منع الوكيل من الكتابة إلى دليل secrets/
customPolicies.add({
  name: "block-secrets-dir",
  description: "Prevent agent from writing to secrets/ directory",
  match: { events: ["PreToolUse"] },
  fn: async (ctx) => {
    if (!["Write", "Edit"].includes(ctx.toolName ?? "")) return allow();
    const path = ctx.toolInput?.file_path ?? "";
    if (path.includes("secrets/")) return deny("Writing to secrets/ is not permitted");
    return allow();
  },
});

// إبقاء الوكيل على المسار: التحقق من الاختبارات قبل الالتزام
customPolicies.add({
  name: "remind-test-before-commit",
  description: "Keep the agent on track: verify tests pass before committing",
  match: { events: ["PreToolUse"] },
  fn: async (ctx) => {
    if (ctx.toolName !== "Bash") return allow();
    const cmd = ctx.toolInput?.command ?? "";
    if (/git\s+commit/.test(cmd)) {
      return instruct("Verify all tests pass before committing. Run `bun test` if you haven't already.");
    }
    return allow();
  },
});

// منع تغييرات المكتبات غير المخطط لها أثناء فترة التجميد
customPolicies.add({
  name: "dependency-freeze",
  description: "Prevent unplanned dependency changes during freeze period",
  match: { events: ["PreToolUse"] },
  fn: async (ctx) => {
    if (ctx.toolName !== "Bash") return allow();
    const cmd = ctx.toolInput?.command ?? "";
    const isInstall = /^(npm install|yarn add|bun add|pnpm add)\s+\S/.test(cmd);
    if (isInstall && process.env.DEPENDENCY_FREEZE === "1") {
      return deny("Package installs are frozen. Unset DEPENDENCY_FREEZE to allow.");
    }
    return allow();
  },
});

export { customPolicies };
```

***

## أمثلة

يحتوي دليل `examples/` على ملفات سياسات جاهزة للتشغيل:

| الملف                                                | المحتويات                                                                                |
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `examples/policies-basic.js`                         | خمس سياسات مبدئية تغطي أنماط فشل الوكيل الشائعة                                          |
| `examples/policies-advanced/index.js`                | أنماط متقدمة: استيرادات متعدية، استدعاءات غير متزامنة، كشط الإخراج، وخطافات نهاية الجلسة |
| `examples/convention-policies/security-policies.mjs` | سياسات أمان مستندة على الاتفاقية (حظر كتابات .env، منع إعادة كتابة سجل git)              |
| `examples/convention-policies/workflow-policies.mjs` | سياسات سير عمل مستندة على الاتفاقية (تذكيرات الاختبار، ملفات التدقيق الكتابة)            |

### استخدام أمثلة الملفات الصريحة

```bash theme={null}
failproofai policies --install --custom ./examples/policies-basic.js
```

### استخدام أمثلة مستندة على الاتفاقية

```bash theme={null}
# نسخ إلى مستوى المشروع
mkdir -p .failproofai/policies
cp examples/convention-policies/*.mjs .failproofai/policies/

# أو نسخ إلى مستوى المستخدم
mkdir -p ~/.failproofai/policies
cp examples/convention-policies/*.mjs ~/.failproofai/policies/
```

لا حاجة لأمر التثبيت — يتم التقاط الملفات تلقائياً في حدث الخطاف التالي.
