الانتقال إلى المحتوى الرئيسي

title: السياسات المخصصة description: “اكتب سياساتك الخاصة في JavaScript - فرض الاتفاقيات والوقاية من الانجراف واكتشاف الأعطال والتكامل مع الأنظمة الخارجية” icon: code

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

مثال سريع

// 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();
  },
});
ثبّتها:
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
كيفية العمل:
  • يتم مسح كلا دليل المشروع والمستخدم (اتحاد — ليس أول نطاق-يفوز)
  • يتم تحميل الملفات أبجدياً في كل دليل. البادئة مع 01- و 02- للتحكم في الترتيب
  • يتم تحميل الملفات المطابقة فقط *policies.{js,mjs,ts}؛ يتم تجاهل الملفات الأخرى
  • يتم تحميل كل ملف بشكل مستقل (fail-open لكل ملف)
  • يعمل إلى جانب السياسات المخصصة والمدمجة الواضحة --custom
سياسات الاتفاقية هي أسهل طريقة لبناء معيار جودة لمؤسستك. التزم .failproofai/policies/ في git وكل عضو في الفريق يحصل على نفس القواعد تلقائياً — لا حاجة إلى إعدادات لكل مطور. مع اكتشاف فريقك لأنماط الفشل الجديدة، أضف سياسة وادفع. بمرور الوقت، تصبح هذه معيار جودة حي يتحسن باستمرار مع كل مساهمة.

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

# التثبيت بملف سياسات مخصص
failproofai policies --install --custom ./my-policies.js

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

# إزالة مسار السياسات المخصصة من الإعدادات
failproofai policies --uninstall --custom
يتم تخزين المسار المطلق المحل في policies-config.json كـ customPoliciesPath. يتم تحميل الملف بشكل جديد في كل حدث خطاف — لا يوجد تخزين مؤقت بين الأحداث.

استخدام الاثنين معاً

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

واجهة برمجية التطبيقات

استيراد

import { customPolicies, allow, deny, instruct } from "failproofai";

customPolicies.add(hook)

يسجل سياسة. استدعِ هذا عدة مرات حسب الحاجة لسياسات متعددة في نفس الملف.
customPolicies.add({
  name: string;                         // required - unique identifier
  description?: string;                 // shown in `failproofai policies` output
  match?: { events?: HookEventType[] }; // filter by event type; omit to match all
  fn: (ctx: PolicyContext) => PolicyResult | Promise<PolicyResult>;
});

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

الدالةالتأثيرالاستخدام عند
allow()السماح بالعملية بصمتالإجراء آمن، لا حاجة إلى رسالة
deny(message)حجب العمليةلا يجب على الوكيل اتخاذ هذا الإجراء
instruct(message)إضافة السياق دون الحجبإعطاء الوكيل سياق إضافي للبقاء على المسار
deny(message) - تظهر الرسالة في Claude مسبوقة بـ "Blocked by failproofai:". يقطع deny واحد كل التقييم الإضافي. instruct(message) - يتم إضافة الرسالة إلى سياق Claude للاستدعاء الأداة الحالي. يتم تجميع جميع رسائل instruct وتسليمها معاً.
يمكنك إضافة إرشادات إضافية إلى أي رسالة deny أو instruct بإضافة حقل hint في policyParams — لا حاجة إلى تغيير الكود. يعمل هذا مع السياسات المخصصة (custom/) واتفاقية المشروع (.failproofai-project/) واتفاقية المستخدم (.failproofai-user/) أيضاً. انظر Configuration → hint للتفاصيل.

رسائل allow إعلامية

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)، يتم دمج جميع الرسائل مع فواصل الأسطر وتسليمها معاً
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

الحقلالنوعالوصف
eventTypestring"PreToolUse"، "PostToolUse"، "Notification"، "Stop"
toolNamestring | undefinedالأداة التي يتم استدعاؤها (على سبيل المثال "Bash"، "Write"، "Read")
toolInputRecord<string, unknown> | undefinedمعاملات إدخال الأداة
payloadRecord<string, unknown>حمولة الحدث الخام الكاملة من Claude Code
sessionSessionMetadata | undefinedسياق الجلسة (انظر أدناه)

حقول SessionMetadata

الحقلالنوعالوصف
sessionIdstringمعرف جلسة Claude Code
cwdstringدليل العمل لجلسة Claude Code
transcriptPathstringمسار ملف نسخة 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() بالداخل)
يقطع أول deny جميع السياسات اللاحقة. يتم تجميع جميع رسائل instruct وتسليمها معاً.

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

يمكن لملفات السياسات المخصصة أن تستورد الوحدات المحلية باستخدام المسارات النسبية:
// 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" إلى مسار التوزيع الفعلي وإنشاء ملفات .mjs مؤقتة لضمان التوافق ESM.

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

استخدم match.events لتقييد وقت تشغيل السياسة:
customPolicies.add({
  name: "require-summary-on-stop",
  match: { events: ["Stop"] },
  fn: async (ctx) => {
    // Only fires when the session ends
    // ctx.session.transcriptPath contains the full session log
    return allow();
  },
});
حذف match بالكامل للتشغيل على كل نوع حدث.

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

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

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

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

// Prevent agent from writing to secrets/ directory
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();
  },
});

// Keep the agent on track: verify tests before committing
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();
  },
});

// Prevent unplanned dependency changes during freeze
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سياسات سير عمل مستند على الاتفاقية (تذكيرات الاختبار والملفات المكتوبة بالتدقيق)

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

failproofai policies --install --custom ./examples/policies-basic.js

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

# Copy to project level
mkdir -p .failproofai/policies
cp examples/convention-policies/*.mjs .failproofai/policies/

# Or copy to user level
mkdir -p ~/.failproofai/policies
cp examples/convention-policies/*.mjs ~/.failproofai/policies/
لا حاجة إلى أمر تثبيت — يتم التقاط الملفات تلقائياً في حدث الخطاف التالي.