14

بنية التقرير

تقرير ProjectReport بصيغة JSON الناتج عن --json، حقلاً بحقل

3 دقائق قراءة5 أقسام

cleanlens --json يطبع كائن ProjectReport. الأنواع معرّفة في src/types/index.ts. هذا الملف يصف كل حقل.

ProjectReport

الحقلالنوعالوصف
schemaVersionرقم2 لمحرّك commit-diff
generatedAtنص (ISO 8601)وقت إنشاء التقرير
engine"commit-diff"محرّك النسب المستخدم ("head-blame" كان القديم)
analysisConfigHashنصبصمة القواعد + الاستثناءات + التقييم (وهي أيضاً مفتاح الذاكرة المؤقتة)؛ البصمات المتساوية تعني تقارير قابلة للمقارنة
developerCountرقمعدد المطورين بعد دمج الهويات
totalViolationsرقمالمخالفات في الكود الحالي
unattributedViolationsرقمالمخالفات التي تعذّرت قراءة ملفها
analyzedFilesرقمالملفات المحللة في فحص HEAD
analyzedCommitsرقمالـ commits التي أُعيد تشغيلها
developersDeveloper[]انظر أدناه
violationsViolation[]انظر أدناه، مرتبة حسب الخطورة، ثم المسار، ثم السطر

Developer

الحقلالنوعالوصف
idنصdev-1 وdev-2، … حسب عدد الـ commits. ثابت داخل التقرير الواحد فقط. طابق المطورين بين التقارير باستخدام emails.
displayNameنصالاسم (الأسماء المدموجة تُربط بـ -)
emailsمصفوفة نصوصعناوين بريد الكتّاب بأحرف صغيرة
cleanCodeScoreرقم | nullمن 0 إلى 100، مقرّبة؛ null = لا يوجد كود محلل
scoreExactرقم | nullالدرجة غير المقرّبة
scoreByCategoryكائن{ duplication, structure, hygiene }، كل منها { density, subScore }؛ وdensity هنا بعد التقليص
violationCountرقمالمخالفات التي أُدخلت بثقة high/medium
weightedViolationPointsرقممجموع أوزان تلك المخالفات
analyzedLinesرقمالأسطر المضافة/المعدّلة في الـ commits المحللة
attributedCodeLinesرقمنفس القيمة (اسم تاريخي)
violationDensityرقمالنقاط الموزونة لكل KLOC، قبل التقليص
confidenceLevelinsufficient | provisional | reliable | highly_reliableمن الأسطر المحللة
rankableمنطقيلديه درجة وأسطر كافية لدخول الترتيب
contributionPercentرقم من 0 إلى 1حصته من كل الأسطر المحللة
breakdownكائنانظر أدناه
activeDaysرقمأيام UTC المختلفة التي فيها commit (السجل كاملاً)
firstContribution، lastContributionنص (ISO)تاريخ أول/آخر commit (السجل كاملاً)

breakdown

الحقلالوصف
introducedالمخالفات التي أُدخلت بثقة high/medium (مثل violationCount)
fixedالمخالفات التي أزالتها الـ commits الخاصة به
existingالمخالفات الموجودة سابقاً في الملفات التي غيّرها (للمعلومة)
excludedدائماً 0 على مستوى المطوّر (موجود لثبات البنية)
unattributedالمخالفات التي جعلتها الـ commits الخاصة به غير قابلة للتحليل (للمعلومة)
introducedWeightedمجموع أوزان introduced
fixedWeightedمجموع أوزان fixed
netQualityImpactintroducedWeighted − fixedWeighted (الموجب = أضاف دَيناً أكثر مما أزال)

تذكّر أن introduced وfixed أعداد تاريخية عبر الـ commits المحللة، بينما violations[] تسرد فقط ما هو موجود في الكود الآن.

Violation

الحقلالنوعالوصف
idنصبصمة القاعدة + المسار + السطر + الرسالة؛ فريدة داخل التقرير
ruleIdنصأحد معرّفات القواعد الأربعة عشر
messageنصتفصيل مقروء، مثل Function load has 58 lines (limit 40).
severitycritical | high | medium | lowمن إعداد القاعدة
weightرقموزن الخطورة
categoryduplication | structure | hygiene
filePathنصنسبي لجذر المستودع، بشرطات /
startLine، endLineرقميبدأ الترقيم من 1؛ وقد لا يوجد endLine
symbolNameنص؟الدالة/الـ class المحيطة
fingerprintنصهوية ثابتة (انظر 07)
statusintroduced | existing | fixed | excluded | unattributedحالة النسب
confidencehigh | medium | lowثقة النسب
developerIdنص؟المطوّر الذي تُحسب عليه (فقط high/medium)
introducedByنص؟المطوّر الذي أدخلها الـ commit الخاص به (بأي ثقة)
introducedCommitنص؟معرّف الـ commit
introducedAtنص؟تاريخ كتابة الـ commit ‏(ISO)
source"internal"دائماً internal حالياً (القيم eslint وruff وpylint محجوزة)

مثال

json
{
  "schemaVersion": 2,
  "generatedAt": "2026-09-30T10:12:44.120Z",
  "engine": "commit-diff",
  "analysisConfigHash": "1x9k2ab",
  "developerCount": 2,
  "totalViolations": 1,
  "unattributedViolations": 0,
  "analyzedFiles": 12,
  "analyzedCommits": 40,
  "developers": [
    {
      "id": "dev-1",
      "displayName": "Alice",
      "emails": ["alice@example.com"],
      "cleanCodeScore": 82,
      "scoreExact": 81.7,
      "scoreByCategory": {
        "duplication": { "density": 0.8, "subScore": 95 },
        "structure": { "density": 9.1, "subScore": 82 },
        "hygiene": { "density": 12.4, "subScore": 72 }
      },
      "violationCount": 9,
      "weightedViolationPoints": 27,
      "analyzedLines": 2400,
      "attributedCodeLines": 2400,
      "violationDensity": 11.25,
      "confidenceLevel": "reliable",
      "rankable": true,
      "contributionPercent": 0.8,
      "breakdown": {
        "introduced": 9, "existing": 3, "fixed": 4, "excluded": 0, "unattributed": 0,
        "introducedWeighted": 27, "fixedWeighted": 10, "netQualityImpact": 17
      },
      "activeDays": 21,
      "firstContribution": "2026-05-02T09:00:00+03:00",
      "lastContribution": "2026-09-28T17:40:00+03:00"
    }
  ],
  "violations": [
    {
      "id": "k2j3h1",
      "ruleId": "maxComplexity",
      "message": "Function parse has complexity 14 (limit 10).",
      "severity": "high",
      "weight": 5,
      "category": "structure",
      "filePath": "src/parser.ts",
      "startLine": 40,
      "endLine": 96,
      "symbolName": "parse",
      "fingerprint": "1a2b3c",
      "status": "introduced",
      "confidence": "high",
      "developerId": "dev-1",
      "introducedBy": "dev-1",
      "introducedCommit": "3f9e1c…",
      "introducedAt": "2026-08-14T11:02:00+03:00",
      "source": "internal"
    }
  ]
}

(القيم للتوضيح فقط.)

استعلامات مفيدة بـ jq

bash
# الدرجات، الأدنى أولاً
jq -r '.developers | sort_by(.cleanCodeScore) | .[] | "\(.cleanCodeScore)\t\(.displayName)"' report.json

# المخالفات الحرجة ومن أدخلها
jq -r '.violations[] | select(.severity=="critical") | "\(.filePath):\(.startLine)\t\(.introducedBy // "-")"' report.json

# عدد المخالفات لكل قاعدة
jq -r '.violations | group_by(.ruleId) | map("\(length)\t\(.[0].ruleId)") | .[]' report.json