البدء مع بوابة القرار
نظرة سريعة
ما: تشغيل سيناريو بوابة القرار بشكل محلي لماذا: رؤية دورة الحياة الكاملة: تعريف -> بدء -> تقييم من: المطورون الذين يدمجون بوابة القرار في CI/CD، الوكلاء، أو سير العمل المتعلقة بالامتثال المتطلبات المسبقة: الإلمام بـ JSON-RPC 2.0 و curl
النموذج العقلي: دورة حياة السيناريو
تقييم بوابات باستخدام الشروط (فحوصات الأدلة). دورة الحياة هي:
1. scenario_define -> registers a ScenarioSpec
2. scenario_start -> creates a RunState (new run)
3. scenario_next -> evaluates current stage and returns a DecisionRecord
مخرجات API الرئيسية:
scenario_defineتعيد{ scenario_id, spec_hash }.scenario_startيعيد الحالة الكاملة لـRunState.scenario_nextreturns{ decision, packets, status }(aNextResult).
ما هو السيناريو؟
سيناريو هو تعريف سير العمل يتكون من:
- Stages: Ordered steps in the workflow. Think of stages as the top-level المراحل: خطوات مرتبة في سير العمل. اعتبر المراحل كالتسلسل الأعلى الذي تنتقل من خلاله مع تقدم التشغيل.
- Gates: Decision points inside a stage. A stage can include one or more البوابات: نقاط القرار داخل مرحلة. يمكن أن تتضمن المرحلة بوابة واحدة أو أكثر يجب اجتيازها للمضي قدمًا.
- Conditions: Evidence checks used by gates. Each gate evaluates one or more الشروط: فحوصات الأدلة المستخدمة من قبل البوابات. تقوم كل بوابة بتقييم شرط أو أكثر لتحديد ما إذا كانت ستمر.
- Providers: Evidence sources (builtin or MCP). Conditions don’t fetch data المزودون: مصادر الأدلة (مضمنة أو MCP). الشروط لا تستخرج البيانات بنفسها؛ بل تطلب من المزودين تقديم الأدلة للتقييم.
يمكن أن تكون المزودات:
- مضمن:
time,env,json,http - MCP الخارجي: أي أداة تنفذ بروتوكول
evidence_query
بدء سريع
الخطوة 0: الحصول على واجهة سطر الأوامر
إذا قمت بتثبيت واجهة سطر الأوامر (CLI)، استخدم decision-gate. إذا كنت تعمل من المصدر، استخدم cargo run:
# Installed binary
decision-gate --help
# From source (repo checkout)
cargo run -p decision-gate-cli -- --help
اختبار الدخان بأمر واحد: scripts/bootstrap/quickstart.sh (bash/WSL) أو scripts/bootstrap/quickstart.ps1 (PowerShell) يقوم بتشغيل التدفق الكامل من تعريف → بدء → التالي → تشغيل الحزمة → التحقق المسبق مع معرفات فريدة.
الخطوة 1: اختر إعدادًا مسبقًا
اختر تكوينًا مسبقًا من configs/presets/ (التفاصيل في preset_configs.md). لاستخدام هذا الدليل، استخدم Quickstart-Dev لجعل التشغيل الأول سلسًا.
إعدادات مسبقة أخرى:
- موصى به بشكل افتراضي: محلي فقط + تعيين رئيسي صريح.
- محصن: يتطلب مصادقة الحامل + توقيع المخطط.
- Container-Prod: مصادقة حامل + إنهاء TLS العلوي (أساسيات الحاوية).
إذا كنت ترغب في تعديل الإعدادات، قم بنسخ الإعدادات المسبقة أولاً:
cp configs/presets/quickstart-dev.toml decision-gate.toml
ملاحظات:
- معرف مساحة الاسم الافتراضية
1محجوز ما لم يكنnamespace.allow_default = trueو معرف المستأجر مدرج فيnamespace.default_tenants. - بالنسبة لربط HTTP/SSE غير المتكرر، يتطلب Decision Gate
--allow-non-loopbackبالإضافة إلى TLS أوserver.tls_termination = "upstream"ومصادقة غير محلية. راجع security_guide.md. - نصيحة ويندوز: PowerShell/CMD لا تدعم
curlمتعددة الأسطر على نمط bash. استخدم أمرًا في سطر واحد أو سلسلة نصية PowerShell@'... '@.
الخطوة 2: بدء خادم MCP
# Installed binary:
decision-gate serve --config configs/presets/quickstart-dev.toml
# From source (repo checkout):
# cargo run -p decision-gate-cli -- serve --config configs/presets/quickstart-dev.toml
الخطوة 3: تحديد سيناريو
هذا السيناريو يعتمد على فحص الوقت: time.after(timestamp).
إذا كنت تستخدم الإعدادات المحصنة: أضف -H 'Authorization: Bearer <token>' إلى كل curl، وانتقل إلى مساحة أسماء غير افتراضية (على سبيل المثال، namespace_id: 2) لأن allow_default = false.
curl -s http://127.0.0.1:4000/rpc \
-H 'Content-Type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "scenario_define",
"arguments": {
"spec": {
"scenario_id": "quickstart",
"namespace_id": 1,
"spec_version": "v1",
"stages": [
{
"stage_id": "main",
"entry_packets": [],
"gates": [
{
"gate_id": "after-time",
"requirement": { "Condition": "after" }
}
],
"advance_to": { "kind": "terminal" },
"timeout": null,
"on_timeout": "fail"
}
],
"conditions": [
{
"condition_id": "after",
"query": {
"provider_id": "time",
"check_id": "after",
"params": { "timestamp": 1700000000000 }
},
"comparator": "equals",
"expected": true,
"policy_tags": []
}
],
"policies": [],
"schemas": [],
"default_tenant_id": 1
}
}
}
}'
دلالات الوقت: time.after تعيد true فقط إذا trigger_time > timestamp (أكبر بشكل صارم). تعيد المساواة false.
استجابة (مغلفة بـ MCP):
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "json",
"json": {
"scenario_id": "quickstart",
"spec_hash": { "algorithm": "sha256", "value": "<hex>" }
}
}
]
}
}
الخطوة 4: بدء تشغيل
curl -s http://127.0.0.1:4000/rpc \
-H 'Content-Type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "scenario_start",
"arguments": {
"scenario_id": "quickstart",
"run_config": {
"tenant_id": 1,
"namespace_id": 1,
"run_id": "run-1",
"scenario_id": "quickstart",
"dispatch_targets": [],
"policy_tags": []
},
"started_at": { "kind": "unix_millis", "value": 1710000000000 },
"issue_entry_packets": false
}
}
}'
ملاحظة: يجب أن تكون قيم run_id فريدة. إذا قمت بإعادة تشغيل هذا الدليل، قم بتغيير run_id (على سبيل المثال، run-2) أو احذف حالة التشغيل المحلية المخزنة (decision-gate.db بشكل افتراضي).
الاستجابة (مغلفة بـ MCP): scenario_start يعيد الحالة الكاملة لـ RunState داخل result.content[0].json.
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "json",
"json": {
"tenant_id": 1,
"namespace_id": 1,
"run_id": "run-1",
"scenario_id": "quickstart",
"spec_hash": { "algorithm": "sha256", "value": "<hex>" },
"current_stage_id": "main",
"stage_entered_at": { "kind": "unix_millis", "value": 1710000000000 },
"status": "active",
"dispatch_targets": [],
"triggers": [],
"gate_evals": [],
"decisions": [],
"packets": [],
"submissions": [],
"tool_calls": []
}
}
]
}
}
الخطوة 5: تقييم بوابة التحفيز
curl -s http://127.0.0.1:4000/rpc \
-H 'Content-Type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "scenario_next",
"arguments": {
"scenario_id": "quickstart",
"request": {
"run_id": "run-1",
"tenant_id": 1,
"namespace_id": 1,
"trigger_id": "trigger-1",
"agent_id": "agent-1",
"time": { "kind": "unix_millis", "value": 1710000000000 },
"correlation_id": null
}
}
}
}'
مع time.after و timestamp = 1700000000000، تعود نتيجة الفحص true لأن 1710000000000 > 1700000000000.
اختياري: أضف "feedback": "trace" داخل arguments للحصول على حالة البوابة/الشرط عندما يسمح بذلك سياسة ردود خادم.
استجابة (مغلفة بـ MCP):
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "json",
"json": {
"decision": {
"decision_id": "decision-1",
"seq": 1,
"trigger_id": "trigger-1",
"stage_id": "main",
"decided_at": { "kind": "unix_millis", "value": 1710000000000 },
"outcome": { "kind": "complete", "stage_id": "main" },
"correlation_id": null
},
"packets": [],
"status": "completed"
}
}
]
}
}
استكشاف الأخطاء وإصلاحها
نتيجة البوابة هي hold
إذا لم يكن بالإمكان إثبات صحة البوابة true أو false، ستكون نتيجة القرار hold وستتضمن الاستجابة SafeSummary. بالنسبة للطلبات غير المحلية، يكون scenario_next افتراضيًا مخصصًا للتعليقات فقط؛ في وضع المحلي فقط، يكون الافتراضي trace. يمكنك دائمًا طلب feedback: "trace" (إذا كان مسموحًا) أو استخدام precheck للتكرار السريع.
{
"result": {
"content": [
{
"type": "json",
"json": {
"decision": {
"outcome": {
"kind": "hold",
"summary": {
"status": "hold",
"unmet_gates": ["after-time"],
"retry_hint": "await_evidence",
"policy_tags": []
}
}
}
}
}
]
}
}
كيفية تصحيح الأخطاء بدقة:
- تصدير الـ runpack باستخدام
runpack_exportوفحصgate_evalsوأخطاء الأدلة في البيان. - استخدم
evidence_query(إذا كانت سياسة الإفصاح تسمح بذلك) لإعادة إنتاج استدعاء المزود ورؤيةEvidenceResult.
المصادقة مطلوبة
إذا قمت بتكوين [server.auth]، قم بتضمين رأس المصادقة المناسب:
curl -s http://127.0.0.1:4000/rpc \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_TOKEN' \
-d '{ ... }'
الخطوات التالية
- condition_authoring.md: كتابة شروط دقيقة ومقارنات
- json_evidence_playbook.md: وصفات دليل الأدلة بتنسيق JSON
- llm_native_playbook.md: تدقيق مسبق لعمليات العمل لوكلاء LLM
- security_guide.md: تعزيز الإنتاج (المصادقة، TLS، التوقيعات، المراسي)