يمكن لوكلاء الذكاء الاصطناعي توليد أكواد تُترجَم بنجاح.
لكن هذا ليس المستوى الذي تريده. المستوى المطلوب هو كود لا يستورد أشياء لا يستخدمها أبدًا، ولا يهرب من نظام الأنواع عبر تحويلات any، ولا يتجاهل قيم الخطأ المُعادة، ولا يضمّن بيانات اعتماد ثابتة كان ينبغي لـ gosec التقاطها قبل المراجعة.
تتدرّب نماذج الذكاء الاصطناعي على إجابات Stack Overflow القديمة وتُنتج الأنماط التي تعلّمتها هناك، بما في ذلك واجهات APIs المهجورة، وغياب التعليقات التوضيحية للأنواع، ودوال صحيحة تقنيًا لكنها أكبر من أن تُراجَع بأمان. أنت بحاجة إلى أداة فحص ضمن الحلقة. ليست كاقتراح، بل كبوابة.
يغطّي هذا الدليل الإعدادات الخاصة بثلاث منظومات (Python مع Ruff، وTypeScript/JavaScript مع تنسيق flat config في ESLint v10، وGo مع golangci-lint) بقواعد مضبوطة تحديدًا لأنماط الفشل التي يُدخلها الذكاء الاصطناعي. ثم يشرح كيفية جعل البوابة أصعب بكثير على التخطّي، بحيث لا يستطيع الوكيل ببساطة تجاوز الخطافات المحلية باستخدام --no-verify دون أن تلتقطه طبقة أخرى.
الإعداد متدرّج: الفحص على مستوى الـ IDE يلتقط المشكلات مباشرة أثناء كتابة الوكيل، وخطافات pre-commit تلتقط أي شيء يصل إلى محاولة الالتزام (commit)، والـ CI يلتقط أي شيء يمر محليًا. كل طبقة مستقلة، ويمكنك اختيار أقسام اللغة التي تنطبق على بيئتك التقنية. تعمل طبقة الفرض بالطريقة نفسها بغض النظر عن اللغة التي تفحصها.
الخلاصة السريعة
- تمتلك كل من Ruff (Python) وESLint v10 (TS/JS) وgolangci-lint (Go) قواعد محددة تلتقط أكثر إخفاقات الذكاء الاصطناعي شيوعًا
- الإعدادات أدناه مشروحة؛ وكل قاعدة موجودة لسبب وجيه
- يتولّى Lefthook بوابة pre-commit؛ وخطاف afterFileEdit في Cursor يشغّل الفحص مباشرة
- أربع طبقات فرض تجعل تخطّي البوابة باستخدام --no-verify أصعب بكثير على وكلاء الذكاء الاصطناعي
- الـ CI هو خط الدفاع الأخير: لا يستطيع الوكلاء تمرير --no-verify إلى GitHub Actions
كيفية ضبط Ruff لأكواد Python المولّدة بالذكاء الاصطناعي
Ruff هو أداة فحص Python المناسبة للقواعد البرمجية المدعومة بالذكاء الاصطناعي. فهو سريع بما يكفي ليعمل عند كل حفظ للملف دون أن يعيق أي شيء، ويغطّي كلًّا من النمط وأخطاء المنطق الحقيقية، ويأتي بسلوك المنسّق (formatter) (ليحل محل Black) في الملف الثنائي نفسه. تستهدف القواعد أدناه أنماط الفشل المحددة التي تُدخلها نماذج الذكاء الاصطناعي بأكبر تكرار في Python.
تثبيت Ruff
pip install ruff
# or via uv (faster for new projects):
uv add --dev ruff
هذا كل شيء. لا منظومة إضافات، ولا تفاوض على اعتماديات الأقران.
إعداد pyproject.toml
[tool.ruff]
line-length = 88
target-version = "py311"
[tool.ruff.lint]
select = [
"E", # pycodestyle — style consistency
"F", # pyflakes — catches unused imports (the most common AI artifact)
"I", # isort — import ordering (AI frequently reorders imports incorrectly)
"N", # pep8-naming — naming conventions
"UP", # pyupgrade — flags deprecated APIs (AI trains on old Stack Overflow answers)
"S", # flake8-bandit — security rules: subprocess.shell=True, eval(), hardcoded creds
"ANN", # type annotation enforcement (AI frequently omits return type annotations)
]
ignore = [] # intentional: do not add sweeping ignores in AI-assisted codebases
[tool.ruff.lint.per-file-ignores]
"tests/**" = ["S101"] # allow assert in tests
تثبت قواعد F جدواها فورًا. يولّد كود الذكاء الاصطناعي عبارات استيراد لحزم لا ينتهي به الأمر إلى استخدامها، وتلتقط F401 (الاستيراد غير المستخدَم) كلًّا منها. وتلتقط قواعد UP استدعاءات أنماط APIs المهجورة التي تعلّمها الذكاء الاصطناعي من إجابات Python ما قبل الإصدار 3.10؛ فالقاعدتان UP006 وUP007 وحدهما تشيران إلى عشرات أنماط فحص الأنواع غير الضرورية. وتلتقط قواعد S (Bandit) إخفاقات الأمان: السلاسل الثابتة التي تبدو كبيانات اعتماد (S105/S106)، وحقن الأوامر عبر subprocess(shell=True) (S603/S607)، وخيارات التشفير الضعيفة (S324).
السطر ignore = [] متعمَّد. كل استثناء تضيفه إلى هذه القائمة هو فئة من فشل الذكاء الاصطناعي قررت السماح بها.
تشغيل Ruff
ruff check . # lint only — see what's wrong
ruff check --fix . # auto-fix safe violations (imports, formatting)
ruff format . # format the codebase (replaces Black)
يطبّق --fix إصلاحات Ruff الآمنة افتراضيًا، مثل إزالة عمليات الاستيراد غير المستخدَمة أو تطبيق تصحيحات التنسيق والفحص المباشرة. يمتلك Ruff أيضًا إصلاحات غير آمنة، لكنها تتطلب موافقة صريحة وينبغي مراجعتها بعناية أكبر. راجع يدويًا أي شيء لا يستطيع Ruff إصلاحه بأمان.
كيفية ضبط ESLint v10 لأكواد TypeScript وJavaScript المولّدة بالذكاء الاصطناعي
أسقط ESLint v10 تنسيق الإعداد القديم .eslintrc.*. أصبح كل شيء الآن flat config في eslint.config.mjs. إذا وجدت درسًا تعليميًا يستخدم .eslintrc.json أو .eslintrc.js، فهو يستهدف ESLint v8 أو v9، حيث الصياغة مختلفة. استخدم ما يلي.
تستهدف قواعد @typescript-eslint في هذا الإعداد أنماط الفشل المحددة التي تتكرر في TypeScript المولّد بالذكاء الاصطناعي: مهرب any، والدوال الضخمة التي يصعب مراجعتها، والقيم الثابتة التي ينبغي أن تكون ثوابت.
تثبيت ESLint v10 مع دعم TypeScript
npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
# or with pnpm:
pnpm add -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
ESLint v10.5.0 هو الإصدار الحالي اعتبارًا من يونيو 2026. ينبغي أن تطابق حزم @typescript-eslint إصدار TypeScript لديك؛ تحقق من ملف README الخاص بها للاطلاع على مصفوفة التوافق.
إعداد eslint.config.mjs
import tseslint from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
export default [
{
files: ['**/*.ts', '**/*.tsx'],
languageOptions: {
parser: tsParser,
parserOptions: { project: './tsconfig.json' },
},
plugins: { '@typescript-eslint': tseslint },
rules: {
// AI defaults to `any` to bypass the type system — this blocks it
'@typescript-eslint/no-explicit-any': 'error',
// AI generates variables it declares but never uses
'@typescript-eslint/no-unused-vars': 'error',
// AI writes functions that work but are too long to review safely
'max-lines-per-function': ['error', { max: 50 }],
// AI overloads function signatures; this forces decomposition
'max-params': ['error', 2],
// AI hardcodes values that should be named constants
'no-magic-numbers': ['error', { ignore: [0, 1, -1] }],
// AI writes files that are too large to reason about in a single review
'max-lines': ['error', { max: 250 }],
// AI leaves console.log debugging in production code
'no-console': 'warn',
},
},
];
القاعدة max-lines-per-function: 50 هي أكثر ما في هذا الإعداد صرامة. ستصطدم بها باستمرار في التشغيل الأول ضمن قاعدة برمجية مدعومة بالذكاء الاصطناعي. وهذا هو المقصود. ينبغي أن تصطدم بها. الدوال التي تتجاوز 50 سطرًا هي أول ما يصبح من المستحيل استيعابه عندما تراجع مخرجات الذكاء الاصطناعي بكميات كبيرة.
القاعدة max-params: 2 تفرض التفكيك. تتعلّم نماذج الذكاء الاصطناعي من قواعد برمجية تكون فيها الدوال ذات الوسائط الخمس أمرًا طبيعيًا؛ وتدفع القاعدة عكس ذلك بإلزام الوكيل باستخدام كائن خيارات (options object)، وهو تصميم أفضل وأسهل في القراءة.
تشغيل ESLint
npx eslint . # lint
npx eslint . --fix # auto-fix safe issues
npx eslint . --max-warnings 0 # CI mode — treats warnings as errors
استخدم --max-warnings 0 في خطوة الـ CI لديك. فهو يرفع تحذيرات no-console من "مُلاحَظة تقنيًا" إلى "حاجزة فعليًا".
اختياري: قواعد أكثر صرامة للملفات المولّدة بالذكاء الاصطناعي
إذا كان فريقك يستخدم اصطلاح تسمية للملفات لتمييز الأكواد المولّدة بالذكاء الاصطناعي (*.ai.ts أو *-generated.ts أو ما شابه)، فيمكنك تطبيق قواعد أكثر تشددًا على تلك الملفات تحديدًا:
// Add to eslint.config.mjs after the main config object
{
files: ['**/*.ai.ts', '**/*.ai.tsx', '**/*-generated.ts'],
rules: {
'max-lines': ['error', { max: 100 }], // tighter file ceiling
'complexity': ['error', 5], // McCabe complexity limit
},
}
كيفية ضبط golangci-lint لأكواد Go المولّدة بالذكاء الاصطناعي
golangci-lint هو المشغّل المعياري متعدد أدوات الفحص لـ Go. ويأتي مع gosec وerrcheck وstaticcheck وأكثر من 40 أداة فحص أخرى قابلة للضبط من ملف YAML واحد. بالنسبة لأكواد Go المولّدة بالذكاء الاصطناعي، فإن القواعد الحاسمة هي فحص قيم الخطأ المُعادة واكتشاف أنماط الأمان: وهما فئتا الفشل اللتان تخفق فيهما نماذج الذكاء الاصطناعي بأكبر تكرار في Go.
تثبيت golangci-lint
# Official binary installer:
curl -sSfL https://golangci-lint.run/install.sh | sh -s -- -b "$(go env GOPATH)/bin" v2.12.2
# or via Homebrew:
brew install golangci-lint
إعداد .golangci.yml
version: "2"
linters:
enable:
- gosec # security: flags hardcoded creds (G101), file path injection (G304), weak crypto (G401)
- unused # flags unused vars and functions — a common AI artifact in Go
- errcheck # AI frequently ignores error returns — this blocks it
- govet # catches subtle correctness bugs AI introduces
- staticcheck # comprehensive static analysis
- revive # style: catches non-idiomatic Go patterns AI writes
- misspell # AI occasionally misspells in comments and string literals
settings:
gosec:
severity: medium
confidence: medium
errcheck:
check-type-assertions: true # check `val, ok := x.(Type)` patterns
check-blank: true # catch `_ = someErr` error suppression
run:
timeout: 3m
issues-exit-code: 1
نمط معالجة الأخطاء في Go صريح بحكم التصميم: كل دالة قابلة للفشل تعيد قيمة خطأ. تفهم نماذج الذكاء الاصطناعي ذلك لكنها لا توليه الوزن الكافي؛ فهي تحذف فحوص الأخطاء في مسارات الكود غير الحرجة. وتجعل errcheck ذلك الإغفال فشلًا في الفحص.
gosec هو أداة فحص الأمان. وبالنسبة لأكواد الذكاء الاصطناعي، فهو يلتقط الأنماط التي اكتسبها الذكاء الاصطناعي من دروس Go ما قبل 2020: التوليد غير الآمن للأرقام العشوائية (G404)، ودوال التجزئة غير الآمنة (G401)، ومشكلات أذونات الملفات (G306). هذه هي الأخطاء التي لا تلتقطها في مراجعة الكود لأنها تبدو طبيعية من حيث الصياغة.
تشغيل golangci-lint
golangci-lint run ./... # lint all packages
golangci-lint run --fix ./... # auto-fix where possible
كيفية ربط أداة الفحص بخطافات pre-commit
يشغّل خطاف pre-commit الفحص قبل كل التزام (commit) في git ويحجب الالتزام إذا فشل الفحص. وهذا يعني أن وكيل الذكاء الاصطناعي لا يستطيع الالتزام بكود يفشل في القواعد التي ضبطتها. عليه إصلاح المخالفات أولًا.
Lefthook هو الخيار الموصى به. فهو متعدد المنصات وسريع وله نمط إعداد يعمل تحديدًا مع فرض القواعد على وكلاء الذكاء الاصطناعي (نتناوله في القسم التالي).
Lefthook
npm install --save-dev lefthook
npx lefthook install
lefthook.yml:
pre-commit:
parallel: true
commands:
lint-python:
glob: "*.py"
run: ruff check {staged_files} --fix
lint-js-ts:
glob: "*.{js,ts,tsx}"
run: npx eslint {staged_files} --fix
lint-go:
glob: "*.go"
run: golangci-lint run {staged_files}
fail_text: |
Lint failed. For AI Agents: fix all lint violations before committing.
Do not use --no-verify to bypass this gate.
تقرأ وكلاء الذكاء الاصطناعي رسالة fail_text عند فشل الالتزام. والنمط موثّق في مقالة Liam Bigelow عن فرض فحص Lefthook لأجل Claude Code. لن يوقف هذا وحده وكيلًا مصمّمًا، لكنه يعطيه التعليمة الصحيحة التالية ("أصلح مخالفات الفحص") بدلًا من تركه يستنتج حلًّا التفافيًا.
بديل: pre-commit (للإعدادات المعتمدة على Python فقط)
إذا كنت تعمل ضمن بيئة معتمدة على Python فقط وتفضّل إطار pre-commit:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.17
hooks:
- id: ruff-check
args: [--fix]
- id: ruff-format
Cursor: الفحص المباشر عبر خطاف afterFileEdit
إذا كنت تستخدم Cursor، فيمكنك تشغيل الفحص فورًا عندما يعدّل الذكاء الاصطناعي ملفًا، قبل أن يحاول حتى الالتزام. أنشئ ملف .cursor/hooks.json في جذر مشروعك:
{
"hooks": {
"afterFileEdit": [
{
"match": "*.py",
"run": "ruff check {file} --fix"
},
{
"match": "*.{ts,tsx,js}",
"run": "npx eslint {file} --fix"
},
{
"match": "*.go",
"run": "golangci-lint run {file}"
}
]
}
}
يعمل هذا في كل مرة يعدّل فيها ذكاء Cursor الاصطناعي ملفًا. يحصل الوكيل على ملاحظات الفحص مباشرة، قبل أن يعتبر المهمة مكتملة، فتُصلَح معظم المخالفات قبل أن تصل إلى بوابة pre-commit.
كيفية جعل البوابة أصعب على وكلاء الذكاء الاصطناعي للتخطّي
أربع طبقات فرض تجعل تخطّي بوابة pre-commit باستخدام --no-verify أصعب بكثير على وكيل الذكاء الاصطناعي. تستهدف كل طبقة سطح هجوم مختلفًا: السياسة في CLAUDE.md، وقاعدة منع (deny) في Claude Code، وخطاف PreToolUse، وخط دفاع أخير في الـ CI. تعامل معها كإعداد متعدد الطبقات، لا كأربع ضمانات مستقلة.
تمرّر وكلاء الذكاء الاصطناعي أحيانًا --no-verify إلى git commit لتخطّي خطافات pre-commit عندما يفشل الفحص ويقرّر الوكيل أن الإخفاقات "غير متعلقة بتغييراته". القرار ليس خاطئًا دائمًا، لكن لا ينبغي أن تدع الوكيل يتخذه من جانب واحد. الغرض الكامل من بوابة الفحص هو أن إنسانًا وضع السياسة؛ ومهمة الوكيل أن يلبّيها، لا أن يلتف حولها.
إليك كل طبقة وسطح الهجوم الذي تغطّيه.
الطبقة 1: توثيق السياسة في CLAUDE.md
## Linting Policy
NEVER use `git commit --no-verify`. All commits must pass pre-commit hooks.
Pre-commit hooks run lint. Fix lint violations before committing. Do not treat
lint failures as unrelated to your changes — they may not be, and you don't get
to decide that.
يقرأ Claude Code ملف CLAUDE.md عند بدء الجلسة. هذا ليس فرضًا؛ فما زال بإمكان الوكيل محاولة التخطّي. لكنه يزيل مسار "لم أكن أعلم" ويضع سياسة واضحة يجب على الوكيل أن يختار انتهاكها بنشاط، وهو أمر أقل احتمالًا منه أن يستنتج حلًّا التفافيًا من الصمت.
الطبقة 2: قاعدة منع في Claude Code
أضف إلى .claude/settings.json:
{
"permissions": {
"deny": [
"Bash(git commit --no-verify*)"
]
}
}
يحجب هذا الاستدعاء الصريح. قيد واحد: تستخدم قاعدة المنع مطابقة البادئة، لذا فهي تلتقط فقط --no-verify الواقعة مباشرة بعد commit. يمكن لوكيل مبدع بما يكفي أن يبني الاستدعاء بطريقة مختلفة. لا تعتمد على هذا وحده.
الطبقة 3: خطاف PreToolUse
ثبّت حزمة block-no-verify:
npm install --save-dev block-no-verify
ثم اضبطها كخطاف PreToolUse في إعدادات Claude Code. يعمل هذا قبل كل استدعاء أداة ويفحص الوسائط بحثًا عن --no-verify عبر ستة أوامر فرعية في git، لا commit فقط. ويخرج بقيمة غير صفرية لحجب الاستدعاء قبل أن يُنفَّذ.
الدليل المرجعي في pydevtools.com صريح بشأن ذلك: "طبقة الخطاف هي الوحيدة التي تفرض القاعدة بشكل موثوق". استخدم هذا مع الطبقات الأخرى؛ ولا تعامل أي خطاف محلي على أنه الضمان الكامل.
الطبقة 4: خط الدفاع الأخير في الـ CI
يعمل الـ CI على الخادم، حيث لا يملك الوكيل أي صدفة (shell) ليمرّر إليها الرايات:
# .github/workflows/lint.yml
name: Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Lint Python
run: |
pip install ruff
ruff check . --output-format github
- name: Lint JS/TS
run: npx eslint . --max-warnings 0
- name: Lint Go
uses: golangci/golangci-lint-action@v9
with:
version: v2.12.2
لا تستطيع وكلاء الذكاء الاصطناعي تمرير --no-verify إلى الـ CI. تعمل GitHub Actions بشكل مستقل عن أي شيء فعله الوكيل محليًا. إذا مرّ التزام ما بكود فاشل في الفحص، فإن الـ CI يلتقطه قبل أن يندمج.
هذا هو خط الدفاع الأخير.
إضافة: خادم ESLint MCP
إذا كنت تستخدم Claude Code، فهناك طبقة استباقية تقلّل عدد مرات اصطدامك بالبوابة من الأساس.
يدمج خادم ESLint MCP (@eslint/mcp) أداة ESLint مباشرة في حلقة أدوات الوكيل. يمكن للوكيل الاستعلام من ESLint أثناء المهمة، قبل أن يحاول الالتزام. ثبّته بشكل عام:
npm install -g @eslint/mcp@latest
أضف إلى .claude/settings.json:
{
"mcpServers": {
"eslint": {
"command": "npx",
"args": ["@eslint/mcp@latest"]
}
}
}
مع ضبط هذا، يمكن للوكيل الاستعلام من ESLint أثناء المهمة. يحصل الوكيل على ملاحظات الفحص مباشرة، ويمكن تصحيح بعض المخالفات قبل أن تصل إلى الخطاف. لا يحل هذا محل البوابة، بل يقلّل الضجيج عليها.
الأسئلة الشائعة
هل أحتاج إلى ضبط أدوات الفحص الثلاث جميعها إذا كنت أعمل بلغة واحدة فقط؟
لا. اضبط أداة الفحص للغتك الأساسية وطبقة الفرض. إذا كانت بيئتك التقنية TypeScript فقط، فاضبط ESLint وتخطَّ Ruff وgolangci-lint. ينطبق قسم منع تخطّي الوكيل بغض النظر عن اللغة التي تفحصها.
هل ستعطّل هذه الإعدادات قاعدتي البرمجية الحالية في التشغيل الأول؟
بكل تأكيد تقريبًا، وعن قصد. شغّل ruff check --fix . أو npx eslint . --fix لتصحيح المخالفات الآمنة تلقائيًا أولًا. ما يتبقى بعد الإصلاح التلقائي هو قائمة المراجعة اليدوية: تحويلات no-explicit-any، والدوال التي تتجاوز 50 سطرًا، ومعالجة الأخطاء الغائبة. اعمل على معالجتها تدريجيًا. لا تضف قواعد ignore لتتجنب التعامل معها.
هل أصبح Biome بديلًا عن ESLint في هذه المرحلة؟
Biome v2.5.0 (الصادر في يونيو 2026) منافس في التنسيق وقواعد الفحص الأساسية. فهو أسرع من ESLint وبلا أي عبء إعداد إذا ثبّته عبر bun x ultracite@latest init. وبالنسبة للفرق التي تريد أداة واحدة ولا تحتاج عمق قواعد @typescript-eslint الكامل، يكون Biome خيارًا معقولًا. أما بالنسبة للقواعد الخاصة بالذكاء الاصطناعي في هذا الدليل (max-params وno-magic-numbers وmax-lines-per-function بعتبات موجّهة للذكاء الاصطناعي)، فإن ESLint مع @typescript-eslint ما زال يمتلك تغطية أوسع. يمكنك تشغيل كليهما: Biome للتنسيق والفحص الأساسي، وESLint للقواعد الخاصة بالذكاء الاصطناعي.
ماذا لو ظل وكيل الذكاء الاصطناعي لدي يعيد توليد مخالفات الفحص نفسها؟
الوكيل يلتف حول القاعدة بدلًا من إصلاح المشكلة الكامنة. بالنسبة لـ no-explicit-any، يعني هذا إضافة تأكيد نوع (type assertion) بدلًا من تعريف النوع الفعلي. وبالنسبة لـ max-lines-per-function، يعني استخراج دالة مساعدة لا تفعل شيئًا مفيدًا لكنها تُبقي عدد الأسطر تحت العتبة. لا يجتاز أي من الحلَّين مراجعة الكود. التقطت قاعدة الفحص العَرَض؛ أما السبب الجذري فهو موجّه (prompt) الوكيل. حسّن الموجّه ليحدد قيد النوع أو التفكيك المتوقع؛ سيتبع الوكيل التوجيه البنيوي الصريح بموثوقية أكبر من القواعد الضمنية. وإذا كنت تشغّل إعداد وكلاء أكثر تعقيدًا، فإن تحديد نطاق العمل لوكيل فرعي مخصص مع تضمين القيود في تعليماته يميل إلى الصمود بشكل أفضل من موجّه واحد عام.
هل يحل خادم ESLint MCP محل بوابة pre-commit؟
لا. فهو يقلّل عدد المرات التي يولّد فيها الوكيل كودًا يفشل في البوابة. ما زالت البوابة تعمل عند كل التزام. والفحص المباشر لخادم MCP وفرض خطاف pre-commit مكمّلان لبعضهما، لذا لا تُزل أيًّا منهما.