Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 19 additions & 10 deletions .github/workflows/sync-check.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# ============================================================================
# فحص مزامنة الدليل مع كود اللغة (drift detection) — مربوطٌ بإصدارات اللغة.
# يقيس الانجراف تجاه **آخر وسم إصدار** للغة (لا تجاه dev المتقلّب)، فتعكس النتيجة
# «هل يطابق الدليلُ الإصدارَ المنشور؟». يعمل: عند إصدار لغة جديد (repository_dispatch
# من مستودع اللغة)، أسبوعيًّا، ويدويًّا. عند الانجراف يفتح/يحدّث قضيّة بالفصول المتأثّرة.
# فحص مزامنة الدليل مع كود اللغة (drift detection).
# يقيس الانجراف تجاه **مرجع القفل نفسِه** (`sources.lock.json`.ref)، لأنّ البصمات أُخذت
# عنده، فقياسُها عند مرجعٍ سواه يقارن شيئًا بغيره. كان الافتراضُ «آخر وسم إصدار»،
# وv1.0.0 وسمُ 2026-03-09 سابقٌ لـ`language-truth/` و`scripts/codegen`، فكان التقريرُ يعلن
# حذفَ 30 مسارًا وتعذّرَ 47 (القضيّة #1)، وكلّها قائمةٌ سليمةٌ على dev — فصار الإنذارُ ضجيجًا
# لا يُقرأ. ولقياس الدليل تجاه إصدارٍ منشور: أعِد البصم عند وسمِه
# (`--ref vX --update --set-version X`)، ثمّ يصير هو مرجعَ القفل تلقائيًّا.
# يعمل: عند إصدار لغة جديد (repository_dispatch)، أسبوعيًّا، ويدويًّا.
# عند الانجراف يفتح/يحدّث قضيّة بالفصول المتأثّرة.
# ============================================================================
name: sync-check

Expand All @@ -12,7 +17,7 @@ on:
workflow_dispatch:
inputs:
ref:
description: "ref/وسم لقياس الانجراف تجاهه (افتراضيًّا آخر إصدار)"
description: "ref/وسم لقياس الانجراف تجاهه (افتراضيًّا مرجعُ القفل)"
required: false
repository_dispatch:
types: [language-release] # يطلقه مستودع اللغة عند نشر إصدار
Expand All @@ -32,16 +37,15 @@ jobs:
python-version: "3.12"
- run: pip install pyyaml

- name: تحديد الـref (وسم الإصدار > مُدخَل يدويّ > آخر إصدار > dev)
- name: تحديد الـref (وسم الإصدار > مُدخَل يدويّ > مرجع القفل > dev)
id: ref
env:
GH_TOKEN: ${{ github.token }}
run: |
REF="${{ github.event.client_payload.tag }}"
[ -z "$REF" ] && REF="${{ github.event.inputs.ref }}"
# (AR) الافتراضيّ: المرجعُ الذي أُخذت عنده البصماتُ نفسُه — وحده
# يجعل «تغيّر/حُذف» تعفّنًا فعليًّا لا فرقَ مرجعين.
if [ -z "$REF" ]; then
REF=$(gh api repos/sadlang/s-programming-language/releases/latest \
--jq .tag_name 2>/dev/null || true)
REF=$(python -c "import json;print(json.load(open('sync/sources.lock.json',encoding='utf-8')).get('ref',''))" || true)
fi
[ -z "$REF" ] && REF="dev"
echo "ref=$REF" >> "$GITHUB_OUTPUT"
Expand Down Expand Up @@ -69,6 +73,11 @@ jobs:
L = [f"رصد فحص المزامنة انجرافًا بين الدليل وكود اللغة عند **`{ref}`** "
f"(النسخة المُغطّاة في الدليل: `{r.get('covers_version')}`).\n",
"أي أن مصادر تغيّرت في اللغة وقد لا يطابقها الدليل بعد.\n"]
lock_ref = r.get("lock_ref")
if lock_ref and lock_ref != ref:
L.append(f"> ⚠️ البصماتُ المخزّنة أُخذت عند `{lock_ref}` لا عند "
f"`{ref}`؛ فـ«حُذف» و«متعذّر الوصول» أدناه تعنيان «غير "
f"موجودٍ عند `{ref}`» لا «أُزيل من اللغة».\n")
def sec(t, items):
if items:
L.append(f"### {t}")
Expand Down
43 changes: 37 additions & 6 deletions scripts/check_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
--json تقرير JSON للأتمتة.
--update يثبّت البصمات الحاليّة (بعد مراجعة الدليل).
--ref REF يتجاوز ref البيان (مثلًا وسم إصدار: v1.2.0) — لربط المزامنة بالإصدارات.
تنبيه: البصماتُ المخزّنة أُخذت عند `lock.ref`، فقياسُها عند مرجعٍ سواه
يجعل «حُذف/متعذّر» تعني «غير موجودٍ عند ذلك المرجع» لا «أُزيل من اللغة»؛
لذا يرفع الفحصُ لافتةً على المعيار حين يختلف المرجعان. ولربط الدليل
بإصدارٍ منشور: أعِد البصم عنده (--ref vX --update --set-version X).
--set-version V مع --update: يكتب covers_version=V في القفل (ارفعه عند مراجعة إصدار).
--validate حارس بلا شبكة: يتحقّق من سلامة البيان (مسارات الفصول، تكرار المفاتيح،
صيغة الأسطر، وأن كل فصل تقنيّ في SUMMARY مسجَّل).
Expand Down Expand Up @@ -238,21 +242,33 @@ def cmd_guard_lock(manifest: dict, base_path: str, changed_path: str) -> int:
changed_files = {l.strip().replace("\\", "/")
for l in Path(changed_path).read_text(encoding="utf-8").splitlines()
if l.strip()}
# (AR) القاعدة: **كلّ** فصلٍ يستشهد بالمصدر يجب أن يُعدَّل، لا أيّ فصلٍ منها.
# المفتاحُ المشترك (`scripts/codegen` بين codegen.md وphilosophy.md مثلًا)
# كان يمرّ بتعديل أحدهما فَيَسِمُ الآخرَ طازجًا دون أن يقرأه أحد — أي أنّ الحارسَ
# نفسَه كان يكتم ما بُني لِيَكشِفَه. (أربعة مفاتيحَ مشتركةٍ اليوم.)
offenders = []
for key in advanced + added:
chapters = chapters_for_key(manifest, key)
if not any(c in changed_files for c in chapters):
offenders.append((key, chapters))
untouched = [c for c in chapters if c not in changed_files]
if untouched or not chapters:
offenders.append((key, chapters, untouched))
if offenders:
print("❌ كتمٌ صامت مرصود: تقدّمت بصماتٌ في القفل دون تعديل فصولها:\n")
for key, chapters in offenders:
print(f" • المصدر `{key}` تقدّم، لكن لم يُعدَّل أيّ من: "
f"{', '.join(chapters) or '(لا فصل!)'}")
for key, chapters, untouched in offenders:
if not chapters:
print(f" • المصدر `{key}` تقدّم، ولا فصلَ يستشهد به أصلًا!")
continue
shared = [c for c in chapters if c not in untouched]
print(f" • المصدر `{key}` تقدّم، ولم يُعدَّل: "
f"{', '.join(untouched)}")
if shared:
print(f" (مشتركٌ مع فصولٍ عُدّلت: "
f"{', '.join(shared)} — تعديلُ أحدها لا يُبرّئُ البقية)")
print("\nالقاعدة: لا تثبّت بصمةً جديدة (`--update`) إلّا بعد مراجعة الفصل "
"المرتبط وتعديله فعليًّا. راجع الفصل، عدّله، ثم أعِد --update.")
return 1
print(f"✅ الحارس مرّ: كل بصمةٍ تقدّمت ({len(advanced)+len(added)}) رافقها "
"تعديلُ فصلها.")
"تعديلُ **كلّ** فصلٍ يستشهد بها.")
return 0


Expand All @@ -266,6 +282,20 @@ def cmd_check(manifest: dict, ref: str, as_json: bool) -> int:
lock = json.loads(LOCKFILE.read_text(encoding="utf-8"))
old = lock.get("sources", {})

# (AR) البصماتُ المخزّنة أُخذت عند `lock["ref"]`. قياسُها عند مرجعٍ آخر
# يقارن شيئًا بشيءٍ سواه: مسارٌ لم يكن قد وُجد بعدُ عند وسمٍ قديم
# يُقرأ «حُذف». (قِيس: v1.0.0 وسمُ 2026-03-09، وهو قبل `language-truth/`
# و`scripts/codegen`، فكان التقريرُ الأسبوعيّ يعلن حذفَ 30 مسارًا
# وتعذّرَ 47، وكلّها قائمةٌ سليمةٌ على dev. القضيّة #1 شاهدُها.)
lock_ref = lock.get("ref")
if lock_ref and lock_ref != ref:
print(f"⚠️ المرجع المقيس `{ref}` يخالف مرجع القفل `{lock_ref}`.\n"
f" «حُذف» و«متعذّر الوصول» أدناه تعني «غير موجودٍ عند `{ref}`» "
f"لا «أُزيل من اللغة».\n"
f" لقياس تعفّنٍ حقيقيّ: قِس عند مرجع القفل (--ref {lock_ref})، "
f"أو أعِد البصم عند `{ref}` (--ref {ref} --update).\n",
file=sys.stderr)

changed = [k for k, s in shas.items() if k in old and old[k] != s]
added = [k for k in shas if k not in old]
removed = [k for k in old if k not in shas]
Expand All @@ -275,6 +305,7 @@ def cmd_check(manifest: dict, ref: str, as_json: bool) -> int:
report = {
"drift": bool(drift_keys or missing or added),
"ref": ref,
"lock_ref": lock_ref,
"changed": sorted(changed),
"added": sorted(added),
"removed": sorted(removed),
Expand Down
4 changes: 2 additions & 2 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@

- [المفسّر الشجري (Interpreter)](backend/interpreter.md)
- [التمثيل الوسيط SIR](backend/sir.md)
- [توليد LLVM (المترجم sadc)](backend/llvm.md)
- [توليد LLVM (المترجم sad-build)](backend/llvm.md)
- [الخلفيّة الأصليّة بلا LLVM (SIR → ELF64)](backend/native.md)
- [دراسة حالة: توحيد هاش/شفّر/فك_تشفير](backend/crypto-unification.md)
- [دراسة حالة: توحيد هاش/شفر/فك_تشفير](backend/crypto-unification.md)
- [دراسة حالة: توسيع مكتبة التشفير (٥ مراحل + Argon2id)](backend/crypto-library-expansion.md)

# الجزء السادس · أنظمة اللغة
Expand Down
2 changes: 1 addition & 1 deletion src/architecture/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
| الخلفيّة الأصليّة | `compiler/include/backend/native/` | SIR → شيفرة آلة → ELF64 ساكن بلا LLVM ولا رابطٍ أجنبيّ — [الفصل](../backend/native.md) |
| ~~الآلة الافتراضية~~ | — | `vm/` أُزيل من الشجرة بالإيداع `bcf0a746` («ستُعاد كتابتها من الصفر») — لا فصل له حتّى تُكتب |
| المكتبة القياسية | `stdlib/` | وحدات عربية: core/io/math/string/network/graphics |
| الأدوات | `tools/` | lsp · formatter · pkg · repl · sadc CLI · sadinfo |
| الأدوات | `tools/` | ١٥ مجلّدًا على `dev`: analyze · apk_builder · build · check · compiler (واجهة `sad-build`) · formatter · hub (موزِّع `sad`) · installers · lsp · pkg · profiler · repl · security-scanner · shared · wasm |
| مصدر الحقيقة | `language-truth/` | YAML SoT لكل بيانات اللغة + القواعد |

## القاعدة الطبقيّة (CW-02)
Expand Down
6 changes: 3 additions & 3 deletions src/architecture/pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ flowchart LR
`InterpreterCore` يزور AST مباشرةً: يدير النطاقات والمتغيّرات والدوال، ويقيّم التعابير،
وينفّذ الجمل. سريع للتطوير والاختبار.

## المرحلة 4ب — الترجمة (sadc)
## المرحلة 4ب — الترجمة (`sad-build`)
1. **`SIRBuilder`**: AST → **SIR** (تمثيل وسيط بتعليمات ملكية، `sir_types.h`).
2. **`SIROptimizer`**: تمريرات على SIR.
3. **`LLVMCodeGen`**: SIR → LLVM IR، ثم LLVM يُنتج كائنًا يُربَط لملفّ تنفيذيّ.

> **لماذا SIR وسيط؟** يفصل دلالة الملكية/الأنواع عن تفاصيل LLVM، ويسهّل التحسين والتشخيص (`--emit-llvm`, SIR dumps).
> **لماذا SIR وسيط؟** يفصل دلالة الملكية/الأنواع عن تفاصيل LLVM، ويسهّل التحسين والتشخيص (`--أظهر-llvm`، وتفريغات SIR).

## نقاط تشخيص مفيدة
- اختلاف سلوك المفسّر عن المترجم ⇒ المشكلة في `SIRBuilder` أو `LLVMCodeGen` (BF-08).
- ولّد LLVM IR بـ`--emit-llvm` وافحص: الكتلة الأولى، تطابق أنواع الحقول، ترتيب التعليمات، `getelementptr`.
- ولّد LLVM IR بـ`--أظهر-llvm` وافحص: الكتلة الأولى، تطابق أنواع الحقول، ترتيب التعليمات، `getelementptr`.

---
**اقرأ بعده:** [الأنظمة المتشابكة](interconnected.md).
8 changes: 4 additions & 4 deletions src/backend/crypto-library-expansion.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# دراسة حالة: توسيع مكتبة التشفير (٥ مراحل + Argon2id)

بعد [توحيد هاش/شفّر](crypto-unification.md) (`هاش`/`شفّر`/`فك_تشفير` في وحدة `تأكيدات`)، وُسِّعت
بعد [توحيد هاش/شفر](crypto-unification.md) (`هاش`/`شفر`/`فك_تشفير` في وحدة `تأكيدات`)، وُسِّعت
اللغة بمكتبة تشفير حديثة كاملة في وحدة منفصلة `تشفير` — عبر RFC كامل
(`sadlang-rfcs/text/0000-توسيع-مكتبة-التشفير.md`) نُفِّذ على ٥ مراحل + مرحلة
إضافيّة (Argon2id) بطلب صريح من المالك رغم تأجيلها في نصّ RFC الأصليّ. المرجع
Expand All @@ -21,7 +21,7 @@
| ٤ | `ولّد_مفتاح_خاص_x25519` وعائلتها (7 دوال) | X25519 (RFC 7748) + Ed25519 (RFC 8032) + SHA-512 ذاتيّ | #221 |

كل الدوال ذاتيّة التنفيذ (self-rolled، بلا OpenSSL/libsodium) حفاظًا على قابليّة
العمل على هدف الوضع الحرّ (نفس قيد [[crypto-unification|توحيد هاش/شفّر]])، وسطح
العمل على هدف الوضع الحرّ (نفس قيد [[crypto-unification|توحيد هاش/شفر]])، وسطح
اللغة لكل دالّة **سلسلة تدخل ⇒ سلسلة تخرج** حصرًا على كلا المحرِّكين — لا كائنات
مركَّبة عابرة للحدود.

Expand Down Expand Up @@ -124,12 +124,12 @@ AEAD في **نفس** القطعة بعد حلّ التعارض أعاد تجاو
كل مرحلة أضافت ملفّات إلى
`tests/behavior/sections/09_المكتبة_القياسية/04_تشفير/` (**20 ملفًّا** في `dev` اليوم؛
كانت 14 عند كتابة الفصل)،
كلّ واحد يُشغَّل عبر `sad-run.exe` **و**`sadc.exe` ويُقارَن الناتج حرفيًّا —
كلّ واحد يُشغَّل عبر `sad-run.exe` **و**`sad-build.exe` ويُقارَن الناتج حرفيًّا —
شعاعات RFC/مسابقة رسميّة لكل معيار (BLAKE3-team، RFC 2898/5869/7748/8032/8439/
9106)، إضافة إلى حالات رفض صريحة (سرّ مشترك كلّه أصفار في X25519، توقيع/مفتاح
مُعبَث بهما في Ed25519، بارامترات خارج الحدود الآمنة في KDFs).

---
**اقرأ بعده:** [توحيد هاش/شفّر/فك_تشفير](crypto-unification.md) ·
**اقرأ بعده:** [توحيد هاش/شفر/فك_تشفير](crypto-unification.md) ·
[دوال مضمنة ووحدات](../systems/builtins.md) ·
[نظام معالجة الأخطاء](../systems/errors.md).
Loading
Loading