mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-06-17 14:59:35 +00:00
feat(tier1): docs-governance CI, evidence gate, closure artifacts, trust/execution docs
- Replace repo-preflight with docs-governance workflow and check_docs_links.py - Class B bundle: require correlation_id for external_*; AuditMetadata trace fields - Root-safe TIER1 §2; optional .githooks pre-push for main - Add RELEASE_READINESS_MATRIX_AR, SOURCE_OF_TRUTH_INDEX, operational severity, external index - ExecWeeklyGovernanceContract; expand trust-fabric, execution-fabric, ADR-0001, ws5, Saudi overlays - Wire MASTER TOC, enterprise-readiness, completion-program, architecture_brief paths Made-with: Cursor
This commit is contained in:
parent
33af10127d
commit
b4531f0a4c
42
.githooks/README.md
Normal file
42
.githooks/README.md
Normal file
@ -0,0 +1,42 @@
|
||||
# Git hooks (اختياري — Root-safe)
|
||||
|
||||
**مصدر الحقيقة للامتثال:** CI في `.github/workflows/docs-governance.yml` (وليس هذا المجلد).
|
||||
|
||||
## الهدف
|
||||
|
||||
تذكير محلي بأن أوامر الحوكمة تُشغَّل من **جذر الريبو** (`cwd` = المجلد الذي يحتوي `scripts/` و`docs/`).
|
||||
|
||||
## تفعيل pre-push (فرع `main` فقط)
|
||||
|
||||
من جذر الريبو:
|
||||
|
||||
```bash
|
||||
git config core.hooksPath .githooks
|
||||
```
|
||||
|
||||
انسخ أو أنشئ ملف `.githooks/pre-push` (تنفيذي) بالمحتوى التالي:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
protected_branch="refs/heads/main"
|
||||
while read local_ref local_sha remote_ref remote_sha; do
|
||||
if [[ "$remote_ref" != "$protected_branch" ]]; then
|
||||
continue
|
||||
fi
|
||||
repo_root="$(git rev-parse --show-toplevel)"
|
||||
cd "$repo_root"
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
python3 scripts/architecture_brief.py
|
||||
elif command -v py >/dev/null 2>&1; then
|
||||
py -3 scripts/architecture_brief.py
|
||||
else
|
||||
echo "pre-push: لا يوجد python3/py — تخطي architecture_brief"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
ثم (على Unix): `chmod +x .githooks/pre-push`.
|
||||
|
||||
على Windows يمكن استخدام Git Bash أو WSL لتشغيل نفس السكربت.
|
||||
20
.githooks/pre-push
Normal file
20
.githooks/pre-push
Normal file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
# Optional: run only when pushing to main. CI remains source of truth.
|
||||
set -euo pipefail
|
||||
|
||||
protected_branch="refs/heads/main"
|
||||
|
||||
while read -r local_ref local_sha remote_ref remote_sha; do
|
||||
if [[ "${remote_ref:-}" != "$protected_branch" ]]; then
|
||||
continue
|
||||
fi
|
||||
repo_root="$(git rev-parse --show-toplevel)"
|
||||
cd "$repo_root"
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
python3 scripts/architecture_brief.py
|
||||
elif command -v py >/dev/null 2>&1; then
|
||||
py -3 scripts/architecture_brief.py
|
||||
else
|
||||
echo "pre-push: python3/py not found; skipping architecture_brief" >&2
|
||||
fi
|
||||
done
|
||||
@ -1,5 +1,5 @@
|
||||
# Preflight when repo-level governance / scripts change (no salesflow-saas code required)
|
||||
name: Repo preflight
|
||||
# Tier-1 P0: governance + docs integrity (fast, no salesflow-saas backend deps)
|
||||
name: Docs governance
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -7,29 +7,45 @@ on:
|
||||
paths:
|
||||
- "docs/**"
|
||||
- "scripts/architecture_brief.py"
|
||||
- "scripts/check_docs_links.py"
|
||||
- ".github/workflows/docs-governance.yml"
|
||||
- "MASTER_OPERATING_PROMPT.md"
|
||||
- "AGENTS.md"
|
||||
- "CLAUDE.md"
|
||||
- "Execution_Matrix.md"
|
||||
- "Execution_Matrix_v2.md"
|
||||
- "Architecture_Pack.md"
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "docs/**"
|
||||
- "scripts/architecture_brief.py"
|
||||
- "scripts/check_docs_links.py"
|
||||
- ".github/workflows/docs-governance.yml"
|
||||
- "MASTER_OPERATING_PROMPT.md"
|
||||
- "AGENTS.md"
|
||||
- "CLAUDE.md"
|
||||
- "Execution_Matrix.md"
|
||||
- "Execution_Matrix_v2.md"
|
||||
- "Architecture_Pack.md"
|
||||
|
||||
jobs:
|
||||
architecture_brief:
|
||||
name: Constitution path check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- name: Architecture brief (constitution paths)
|
||||
run: python scripts/architecture_brief.py
|
||||
- run: python scripts/architecture_brief.py
|
||||
|
||||
docs_links:
|
||||
name: Markdown internal links
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- run: python scripts/check_docs_links.py
|
||||
@ -27,6 +27,8 @@ Deep-dive topics live under [`docs/governance/`](docs/governance/) (keep this fi
|
||||
| Master architecture blueprint (index) | [`docs/blueprint-master-architecture.md`](docs/blueprint-master-architecture.md) |
|
||||
| 90-day Tier-1 execution matrix | [`docs/execution-matrix-90d-tier1.md`](docs/execution-matrix-90d-tier1.md) |
|
||||
| Enterprise readiness (B2B checklist) | [`docs/enterprise-readiness.md`](docs/enterprise-readiness.md) |
|
||||
| Release readiness matrix (AR) | [`docs/RELEASE_READINESS_MATRIX_AR.md`](docs/RELEASE_READINESS_MATRIX_AR.md) |
|
||||
| Source of truth index (canonical vs shadow) | [`docs/SOURCE_OF_TRUTH_INDEX.md`](docs/SOURCE_OF_TRUTH_INDEX.md) |
|
||||
| Completion Program (8 workstreams) | [`docs/completion-program-workstreams.md`](docs/completion-program-workstreams.md) |
|
||||
| Architecture register (subsystem status) | [`docs/architecture-register.md`](docs/architecture-register.md) |
|
||||
| ADR: Execution matrix canonical (v1 vs v2) | [`docs/adr/0002-execution-matrix-canonical-source.md`](docs/adr/0002-execution-matrix-canonical-source.md) |
|
||||
|
||||
23
docs/RELEASE_READINESS_MATRIX_AR.md
Normal file
23
docs/RELEASE_READINESS_MATRIX_AR.md
Normal file
@ -0,0 +1,23 @@
|
||||
# مصفوفة جاهزية الإصدار (Tier-1) — Release Readiness Matrix
|
||||
|
||||
**الغرض:** صف واحد (أو صف أسبوعي) لكل **مرشح إصدار (RC)** يربط الأبعاد التشغيلية بالدليل والمالك.
|
||||
**مرجع:** [`enterprise-readiness.md`](enterprise-readiness.md)، [`TIER1_MASTER_CLOSURE_CHECKLIST_AR.md`](TIER1_MASTER_CLOSURE_CHECKLIST_AR.md)، [`governance/pdpl-nca-ai-control-matrices.md`](governance/pdpl-nca-ai-control-matrices.md) (بوابة enterprise).
|
||||
|
||||
## قالب الجدول (انسخ صفًا لكل RC)
|
||||
|
||||
| البُعد | الحالة | الدليل | المالك |
|
||||
|--------|--------|--------|--------|
|
||||
| **docs truth** (مصدر واحد) | | [`SOURCE_OF_TRUTH_INDEX.md`](SOURCE_OF_TRUTH_INDEX.md) + CI `docs-governance` | Tech Writer |
|
||||
| **schema adherence** (Pydantic / عقود) | | `pytest` على `schemas` + مسارات Class B | Backend |
|
||||
| **approval SLA** (Class B) | | طوابير / API موافقات + سجلات | Governance |
|
||||
| **contradiction backlog** (ledger) | | [`trust/ledger-vs-tool-verification.md`](trust/ledger-vs-tool-verification.md) | Trust |
|
||||
| **connector health** (واجهات) | | [`ws5-connector-events-metrics.md`](ws5-connector-events-metrics.md) | Integrations |
|
||||
| **security checklist** | | `verify-launch` + [`LAUNCH_CHECKLIST.md`](../salesflow-saas/docs/LAUNCH_CHECKLIST.md) | Security |
|
||||
| **Saudi controls** (PDPL/NCA/AI) | | [`governance/pdpl-nca-ai-control-matrices.md`](governance/pdpl-nca-ai-control-matrices.md) | Compliance |
|
||||
| **provenance** (commit SHA / build) | | Git tag + artifact CI | Release |
|
||||
|
||||
**حالات مقترحة للعمود «الحالة»:** `OK` | `Risk` | `Blocked` — مع أعلى [`operational-severity-model.md`](governance/operational-severity-model.md) مفتوحة في الملاحظات.
|
||||
|
||||
## بوابة جودة البيانات (Great Expectations)
|
||||
|
||||
عند تفعيل GE: اربط **checkpoint** ناجحًا بصف «schema adherence» أو صف فرعي «data quality»؛ لا تعتبر GE مجرد ملحق Data plane — انظر [`ws5-connector-events-metrics.md`](ws5-connector-events-metrics.md).
|
||||
18
docs/SOURCE_OF_TRUTH_INDEX.md
Normal file
18
docs/SOURCE_OF_TRUTH_INDEX.md
Normal file
@ -0,0 +1,18 @@
|
||||
# فهرس مصدر الحقيقة (Canonical vs Shadow)
|
||||
|
||||
**الغرض:** تقليل **ازدواجية** المسارات بين `docs/` جذر الريبو و[`salesflow-saas/docs/`](../salesflow-saas/docs/) عبر جدول صريح: أي موضوع يُعتبر **canonical**، وأين تبقى نسخ **legacy / shadow** للمرجع فقط.
|
||||
|
||||
| الموضوع | Canonical (مصدر الحقيقة) | Shadow / legacy | المالك | دورة المراجعة |
|
||||
|---------|---------------------------|-----------------|--------|----------------|
|
||||
| دستور التشغيل للوكلاء | [`MASTER_OPERATING_PROMPT.md`](../MASTER_OPERATING_PROMPT.md) | [`AGENTS.md`](../AGENTS.md)، [`CLAUDE.md`](../CLAUDE.md) (ملخصات) | Architect | عند تغيير حوكمة رئيسية |
|
||||
| إغلاق Tier-1 (عربي) | [`TIER1_MASTER_CLOSURE_CHECKLIST_AR.md`](TIER1_MASTER_CLOSURE_CHECKLIST_AR.md) | — | Program | كل أسبوعين مع السجل |
|
||||
| إغلاق Tier-1 (50 بندًا EN) | [`salesflow-saas/docs/tier1-master-closure-checklist.md`](../salesflow-saas/docs/tier1-master-closure-checklist.md) | — | Program | مع PR إغلاق |
|
||||
| سجل الأنظمة الفرعية | [`architecture-register.md`](architecture-register.md) | تكرار حالة في checklists طالما عمود واحد للحالة | Platform | أسبوعيًا |
|
||||
| مصفوفة التنفيذ | [`adr/0002-execution-matrix-canonical-source.md`](adr/0002-execution-matrix-canonical-source.md) + الملف الذي يحدده الـ ADR | نسخ قديمة بأسماء متعددة إن وُجدت | PMO | عند إعادة تسمية المصفوفة |
|
||||
| حوكمة الموصلات / Data plane | [`governance/connectors-and-data-plane.md`](governance/connectors-and-data-plane.md) | [`ws5-connector-events-metrics.md`](ws5-connector-events-metrics.md) (تفاصيل WS5) | Integrations | مع كل موصل جديد |
|
||||
| أحداث وعقود | [`governance/events-and-schema.md`](governance/events-and-schema.md) | حقول **CloudEvents** الخارجية — انظر الملحق أدناه | Platform | عند تغيير الحدث |
|
||||
| جاهزية الإصدار (RC) | [`RELEASE_READINESS_MATRIX_AR.md`](RELEASE_READINESS_MATRIX_AR.md) | — | Release | كل RC |
|
||||
|
||||
## ملحق: مراجع خارجية (تجمع هنا لتقليل rot)
|
||||
|
||||
انظر [`references/tier1-external-index.md`](references/tier1-external-index.md).
|
||||
@ -29,12 +29,14 @@
|
||||
|
||||
---
|
||||
|
||||
## §2 سلامة الريبو والأوامر
|
||||
## §2 سلامة الريبو والأوامر (Root-safe)
|
||||
|
||||
| # | البند | الحالة | الدليل في الريبو | المالك | معيار الخروج |
|
||||
|---|--------|--------|-------------------|--------|---------------|
|
||||
| 2.1 | أوامر من جذر الريبو | Pilot | [`scripts/architecture_brief.py`](../scripts/architecture_brief.py) + CI | DevEx | `architecture_brief` في CI |
|
||||
| 2.0 | **أول خطوة:** `cwd` = جذر الريبو (مسار المستودع الذي يحتوي `scripts/` و`docs/`) قبل أي أمر أو سكربت | Pilot | هذا القسم + [`scripts/architecture_brief.py`](../scripts/architecture_brief.py) | DevEx | لا تشغيل من مجلدات فرعية بلا `PYTHONPATH`/مسارات صريحة |
|
||||
| 2.1 | أوامر من جذر الريبو | Pilot | [`scripts/architecture_brief.py`](../scripts/architecture_brief.py) + CI | DevEx | `architecture_brief` في CI (`docs-governance`) |
|
||||
| 2.2 | توافق أوامر Cursor/Claude | DocOnly | [`.cursor/commands/`](../.cursor/commands/) + [`CLAUDE.md`](../CLAUDE.md) | AI Platform | جدول تطابق في [`governance/discovery-and-output-checklist.md`](governance/discovery-and-output-checklist.md) |
|
||||
| 2.3 | Hook اختياري pre-push للفرع الحساس | DocOnly | [`.githooks/README.md`](../.githooks/README.md) | DevEx | **مصدر الحقيقة = CI**؛ الـ hook تكميلي فقط |
|
||||
|
||||
---
|
||||
|
||||
@ -54,7 +56,7 @@
|
||||
|---|--------|--------|-------------------|--------|---------------|
|
||||
| 4.1 | مخططات منظمة (17 نوعًا) | Production | [`salesflow-saas/backend/app/schemas/structured_outputs.py`](../salesflow-saas/backend/app/schemas/structured_outputs.py) | AI Lead | Pydantic يمر |
|
||||
| 4.2 | حزمة قرار موحّدة | Production | [`decision_plane_contracts.py`](../salesflow-saas/backend/app/services/core_os/decision_plane_contracts.py) | Backend | مفاتيح bundle كاملة |
|
||||
| 4.3 | فرض مسار Class B | Pilot | `GET /api/v1/approval-center/class-b-decision-bundle` | AI Lead | استجابة = bundle + اختبار |
|
||||
| 4.3 | فرض مسار Class B + **correlation لـ external** | Pilot | `GET /api/v1/approval-center/class-b-decision-bundle` + `validate_class_b_bundle` | AI Lead | `external_*` بدون `correlation_id` = رفض؛ راجع [`approval-policy.md`](governance/approval-policy.md) |
|
||||
|
||||
---
|
||||
|
||||
@ -94,7 +96,7 @@
|
||||
|---|--------|--------|-------------------|--------|---------------|
|
||||
| 8.1 | قائمة تسليم GitHub/OIDC | DocOnly | [`github-enterprise-delivery-completion.md`](github-enterprise-delivery-completion.md) | DevOps | rulesets موثّقة |
|
||||
| 8.2 | CI يغطي التطبيق | Production | [`.github/workflows/dealix-ci.yml`](../.github/workflows/dealix-ci.yml) | Platform | pytest + frontend |
|
||||
| 8.3 | CI preflight للوثائق | Pilot | [`.github/workflows/repo-preflight.yml`](../.github/workflows/repo-preflight.yml) | DevEx | عند تغيير docs/scripts |
|
||||
| 8.3 | CI حوكمة الوثائق (P0) | Pilot | [`.github/workflows/docs-governance.yml`](../.github/workflows/docs-governance.yml) | DevEx | `architecture_brief` + `check_docs_links` |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -59,3 +59,15 @@ Each spike produces: design note, threat assumptions, test commands and results,
|
||||
|
||||
- [`../execution-matrix-90d-tier1.md`](../execution-matrix-90d-tier1.md) Phase 0–1
|
||||
- [`../blueprint-master-architecture.md`](../blueprint-master-architecture.md)
|
||||
|
||||
---
|
||||
|
||||
## Annex — Temporal operational criteria (high-risk paths)
|
||||
|
||||
When Temporal moves from *Planned* to *Pilot* for **high-risk** workflow types (money movement, regulated messaging, cross-tenant admin):
|
||||
|
||||
1. **Pinned workflow types** — register each workflow type + task queue in the service catalog; no anonymous “catch-all” workers for governed domains.
|
||||
2. **Rollback rehearsal** — run a **simulated rollback** (cancel + compensation or documented manual playbook) in staging before every production worker upgrade that changes workflow code.
|
||||
3. **Worker versioning** — adopt Temporal’s worker versioning policy before expanding beyond the pilot; track preview/beta notes in [`../references/tier1-external-index.md`](../references/tier1-external-index.md) (Temporal changelog link).
|
||||
|
||||
These criteria are **release gate** rows in [`../RELEASE_READINESS_MATRIX_AR.md`](../RELEASE_READINESS_MATRIX_AR.md) when Temporal is claimed for a candidate build.
|
||||
|
||||
@ -6,7 +6,8 @@
|
||||
**Living registers:** [`architecture-register.md`](architecture-register.md) (subsystem status), [`adr/0002-execution-matrix-canonical-source.md`](adr/0002-execution-matrix-canonical-source.md) (matrix source of truth).
|
||||
|
||||
**PR #16 closure bundle (merged):** [`salesflow-saas/docs/tier1-master-closure-checklist.md`](../salesflow-saas/docs/tier1-master-closure-checklist.md) (50-item master gates) + supporting tracks under [`salesflow-saas/docs/`](../salesflow-saas/docs/) and [`salesflow-saas/docs/governance/`](../salesflow-saas/docs/governance/) — use alongside this index; prefer **one** status column between the register and the master checklist to avoid drift.
|
||||
**Arabic master index (15 sections):** [`TIER1_MASTER_CLOSURE_CHECKLIST_AR.md`](TIER1_MASTER_CLOSURE_CHECKLIST_AR.md).
|
||||
**Arabic master index (15 sections):** [`TIER1_MASTER_CLOSURE_CHECKLIST_AR.md`](TIER1_MASTER_CLOSURE_CHECKLIST_AR.md).
|
||||
**فهرس مصدر الحقيقة:** [`SOURCE_OF_TRUTH_INDEX.md`](SOURCE_OF_TRUTH_INDEX.md) (canonical vs shadow).
|
||||
|
||||
| WS | Name | SLA (target) | Primary deliverable docs / code |
|
||||
|----|------|--------------|-----------------------------------|
|
||||
|
||||
@ -14,7 +14,9 @@ This checklist helps **internal teams** prepare for **B2B / enterprise** convers
|
||||
8. [`completion-program-workstreams.md`](completion-program-workstreams.md) — eight workstreams from constitution to production.
|
||||
9. [`architecture-register.md`](architecture-register.md) — subsystem status snapshot.
|
||||
10. [`TIER1_MASTER_CLOSURE_CHECKLIST_AR.md`](TIER1_MASTER_CLOSURE_CHECKLIST_AR.md) — إغلاق Tier-1 (عربي) + [`salesflow-saas/docs/tier1-master-closure-checklist.md`](../salesflow-saas/docs/tier1-master-closure-checklist.md) (50 بندًا).
|
||||
11. [`governance/pdpl-nca-ai-control-matrices.md`](governance/pdpl-nca-ai-control-matrices.md) — **بوابة إصدار enterprise:** اتبع قسم «Enterprise release gate» قبل وسم الإصدار.
|
||||
11. [`SOURCE_OF_TRUTH_INDEX.md`](SOURCE_OF_TRUTH_INDEX.md) — مصدر واحد لكل موضوع (تقليل drift بين `docs/` و`salesflow-saas/docs/`).
|
||||
12. [`RELEASE_READINESS_MATRIX_AR.md`](RELEASE_READINESS_MATRIX_AR.md) — صف لكل RC: docs truth، موصلات، أمان، سعودي، provenance.
|
||||
13. [`governance/pdpl-nca-ai-control-matrices.md`](governance/pdpl-nca-ai-control-matrices.md) — **بوابة إصدار enterprise:** اتبع قسم «Enterprise release gate» قبل وسم الإصدار.
|
||||
|
||||
## 2. Product and legal surface
|
||||
|
||||
|
||||
@ -2,6 +2,11 @@
|
||||
|
||||
**Goal:** Executive-visible surfaces backed by **trusted data only** (no hallucinated KPIs).
|
||||
|
||||
## Structured weekly contract (WS8 — single UI/API shape)
|
||||
|
||||
**Canonical schema:** [`ExecWeeklyGovernanceContract`](../salesflow-saas/backend/app/schemas/structured_outputs.py) — حقول `changes_summary`, `pending_decisions`, `blockers_summary`, `at_risk_items`, `next_best_actions`, `week_of`, `provenance`.
|
||||
**Legacy / PMI richness:** [`ExecWeeklyPack`](../salesflow-saas/backend/app/schemas/structured_outputs.py) (RAG، synergy SAR، إلخ) يبقى للتقارير المالية؛ الواجهات التنفيذية الجديدة تفضّل `ExecWeeklyGovernanceContract`.
|
||||
|
||||
## Milestones
|
||||
|
||||
0. **Class B bundle API (pilot)** — `GET /api/v1/approval-center/class-b-decision-bundle` returns a validated bundle (`validate_class_b_bundle`); frontend can bind read-only viewers to this shape before DB-backed queues exist.
|
||||
|
||||
@ -27,3 +27,7 @@
|
||||
## Evidence
|
||||
|
||||
Store screenshots or org policy links (internal) as evidence for enterprise questionnaires; do not commit secrets.
|
||||
|
||||
## Observability (OTel-style correlation)
|
||||
|
||||
Deploy and approval workflows SHOULD propagate **`trace_id` / `span_id` / `correlation_id`** into internal audit exports so GitHub Actions events can be joined with application logs — aligned with [`governance/trust-fabric.md`](governance/trust-fabric.md) runtime policies.
|
||||
|
||||
@ -83,6 +83,24 @@ For Class B and any R2/R3 decision: sources, assumptions, timestamps/freshness,
|
||||
|
||||
A **decision memo without an evidence pack is incomplete.**
|
||||
|
||||
## Class B decision bundle gate (P0 — Tier-1 enterprise)
|
||||
|
||||
Any **Class B or higher** response that represents a governed decision MUST expose the unified bundle (see [`decision_plane_contracts.py`](../../salesflow-saas/backend/app/services/core_os/decision_plane_contracts.py)) with at minimum:
|
||||
|
||||
| Key | Role |
|
||||
|-----|------|
|
||||
| `memo_json` | `DecisionMemo` including non-empty `required_approvals` |
|
||||
| `evidence_pack_json` | Structured evidence |
|
||||
| `risk_register_json` | List (may be empty only if explicitly allowed by policy) |
|
||||
| `approval_packet_json` | A/R/S + actor |
|
||||
| `execution_intent_json` | Workflow key + idempotency + side-effect class |
|
||||
|
||||
**Correlation / trace (P0):** For `requested_side_effect_class` of `external_message` or `external_commitment`, `execution_intent_json.correlation_id` MUST be non-empty (enforced by `validate_class_b_bundle`). Prefer propagating the same value into `audit_metadata.trace_id` on the memo when OpenTelemetry is enabled. See [`trust-fabric.md`](trust-fabric.md) observability section.
|
||||
|
||||
## Operational severity (V0–V3)
|
||||
|
||||
Policy violations, contradictions, connector failures, and workflow failures SHOULD be classified with one scale for dashboards and release gates — see [`operational-severity-model.md`](operational-severity-model.md) and [`../RELEASE_READINESS_MATRIX_AR.md`](../RELEASE_READINESS_MATRIX_AR.md).
|
||||
|
||||
## GitHub governance (surface)
|
||||
|
||||
See [github-and-release.md](github-and-release.md) for the full model. Summary: protected `main`, required reviews and checks, CODEOWNERS as team scales, secret scanning and dependency review, OIDC for deploy keys where possible, environment promotion (dev → staging → canary → prod).
|
||||
|
||||
@ -60,3 +60,23 @@ Any new execution path that sends customer messages, moves money, signs contract
|
||||
3. Pass **security gate** and release checklist for the environment.
|
||||
|
||||
See also: [events-and-schema.md](events-and-schema.md), [trust-fabric.md](trust-fabric.md), [github-and-release.md](github-and-release.md).
|
||||
|
||||
---
|
||||
|
||||
## LangGraph durability modes (policy sketch)
|
||||
|
||||
Classify each graph by **how state must survive** process restarts and deploys:
|
||||
|
||||
| Mode | When to use | Notes |
|
||||
|------|-------------|--------|
|
||||
| **`exit`** | Ephemeral assistance, no business state | Graph ends with the HTTP/session; no recovery requirement. |
|
||||
| **`async`** | Bounded background continuation acceptable | Tasks may be lost on crash unless explicitly checkpointed — document the loss window. |
|
||||
| **`sync` / durable checkpoint** | HITL waits, multi-step approvals, or any path that can cause **external_message** / **external_commitment** | Require checkpointing + idempotency keys aligned with `ExecutionIntent`; prefer graduating external effects to Temporal per division-of-labor above. |
|
||||
|
||||
External references: LangGraph durable execution — [`../references/tier1-external-index.md`](../references/tier1-external-index.md).
|
||||
|
||||
## HITL taxonomy (approve / edit / reject)
|
||||
|
||||
Human-in-the-loop steps on governed paths MUST record one of: **`approve`** (proceed as proposed), **`edit`** (proceed with amended structured payload), **`reject`** (terminate with reason). Map API fields and audit events to this taxonomy consistently (LangChain HITL vocabulary — same external index).
|
||||
|
||||
**Rule:** `reject` on Class B / R2+ MUST emit a policy-safe audit row and MUST NOT leave dangling `ExecutionIntent` rows marked runnable.
|
||||
|
||||
18
docs/governance/operational-severity-model.md
Normal file
18
docs/governance/operational-severity-model.md
Normal file
@ -0,0 +1,18 @@
|
||||
# Operational severity model (V0–V3)
|
||||
|
||||
**Canonical:** [`MASTER_OPERATING_PROMPT.md`](../../MASTER_OPERATING_PROMPT.md).
|
||||
**Related:** [approval-policy.md](approval-policy.md) (A/R/S), [`RELEASE_READINESS_MATRIX_AR.md`](../RELEASE_READINESS_MATRIX_AR.md).
|
||||
|
||||
Use this scale for **policy violations**, **ledger contradictions**, **connector health**, **workflow failures**, and **release gate** items so dashboards and runbooks speak one language.
|
||||
|
||||
| Level | Name (EN) | تعريف مختصر (AR) | أمثلة | تأثير على الإصدار |
|
||||
|-------|-----------|------------------|--------|---------------------|
|
||||
| **V0** | Informational | ملاحظة تشغيلية بلا تأثير مباشر على العميل | تحذيرات deprecated، drift توثيقي | لا يعطل RC |
|
||||
| **V1** | Operational | يتطلب إجراءًا داخليًا في SLA قصير | فشل مهمة خلفية مع إعادة محاولة، انحراف مقياس داخلي | لا يعطل RC إن وُجدت آلية تعويض |
|
||||
| **V2** | Customer-impacting | يؤثر على تجربة عميل أو بيانات حساسة | فشل موصل حرج، تأخير موافقة Class B، تعارض أدلة جزئي | **يمنع** ترقية canary→prod حتى التخفيف أو الاستثناء المسجل |
|
||||
| **V3** | Regulatory / release-blocking | يعطل الإصدار أو يرفع مخاطر امتثال | تسريب محتمل، تعارض أدلة على مسار R2/R3، غياب بوابة أمان | **Stop ship**؛ راجع [`trust-fabric.md`](trust-fabric.md) و[`github-and-release.md`](github-and-release.md) |
|
||||
|
||||
## Wiring (target)
|
||||
|
||||
- اربط كل حدث حوكمة بـ `severity` (V0–V3) في السجلات واللوحات.
|
||||
- صفوف [`RELEASE_READINESS_MATRIX_AR.md`](../RELEASE_READINESS_MATRIX_AR.md) تلخص أعلى خطورة مفتوحة لكل مرشح إصدار.
|
||||
@ -35,6 +35,23 @@
|
||||
| Insecure output handling | Schema validation on outputs | pytest |
|
||||
| Excessive agency | Executor vs recommender separation | Policy review |
|
||||
|
||||
### NIST AI RMF GenAI profile + OWASP LLM Top 10 (2025) → Dealix planes
|
||||
|
||||
Map each control or test case to **one primary plane** so WS owners stay accountable (see [`../SOURCE_OF_TRUTH_INDEX.md`](../SOURCE_OF_TRUTH_INDEX.md) for doc hierarchy).
|
||||
|
||||
| مصدر / مخاطرة | طائرة القرار (Decision) | طائرة الثقة (Trust) | الموصلات (Connector) | البيانات (Data) | التشغيل / التكلفة (Runtime) |
|
||||
|----------------|-------------------------|----------------------|----------------------|-----------------|-------------------------------|
|
||||
| GenAI profile — Govern | سياسات memos، تصنيف A/R/S | سياسات تدقيق وسجلات | — | سياسات الاحتفاظ | حدود ميزانية نماذج |
|
||||
| GenAI profile — Map | تدفق prompt/PII في القرار | تدفق أدوات وMCP | حدود موصل الطرف الثالث | مصادر بيانات حساسة | تتبع تكلفة tokens |
|
||||
| GenAI profile — Measure | تقييم structured outputs | red-team، contradictions | اختبارات فشل موصل | GE checkpoints | SLO زمن استجابة |
|
||||
| GenAI profile — Manage | HITL، رفض مسار | حوادث، rollback | تعطيل موصل | إيقاف تزامن بيانات | إصدار نماذج |
|
||||
| OWASP LLM — Prompt injection | وكلاء + prompts | tool verification | واجهات runtime tools | — | — |
|
||||
| OWASP LLM — Insecure output handling | Pydantic / JSON schema | ledger على المطالبات | — | — | — |
|
||||
| OWASP LLM — Excessive agency | Decision vs Execution فصل | ApprovalPacket | — | — | workflow gates |
|
||||
| OWASP LLM — Sensitive disclosure | تصنيف S2/S3 | تدقيق تصدير | scopes موصل | PDPL minimization | تسجيل مراقبة |
|
||||
|
||||
**مراجع خارجية:** [`../references/tier1-external-index.md`](../references/tier1-external-index.md).
|
||||
|
||||
## Region / residency flags
|
||||
|
||||
Define configuration keys for **data region** and **LLM routing** per tenant; document in ADR when enforced in `policy_engine` or external PDP.
|
||||
@ -46,5 +63,6 @@ Define configuration keys for **data region** and **LLM routing** per tenant; do
|
||||
Before tagging an **enterprise** release candidate:
|
||||
|
||||
1. Reconcile this matrix with [`../enterprise-readiness.md`](../enterprise-readiness.md) and [`saudi-compliance-and-ai-governance.md`](saudi-compliance-and-ai-governance.md).
|
||||
2. Attach evidence: PDPL rows above filled (no `…` placeholders for production claims), NCA gap register owner + date, AI RMF row sign-off.
|
||||
3. Cross-check [`../TIER1_MASTER_CLOSURE_CHECKLIST_AR.md`](../TIER1_MASTER_CLOSURE_CHECKLIST_AR.md) §14 and [`../../salesflow-saas/docs/tier1-master-closure-checklist.md`](../../salesflow-saas/docs/tier1-master-closure-checklist.md) Gate 8.
|
||||
2. Fill a row in [`../RELEASE_READINESS_MATRIX_AR.md`](../RELEASE_READINESS_MATRIX_AR.md) for the RC (docs truth, connectors, security, Saudi, provenance).
|
||||
3. Attach evidence: PDPL rows above filled (no `…` placeholders for production claims), NCA gap register owner + date, AI RMF row sign-off.
|
||||
4. Cross-check [`../TIER1_MASTER_CLOSURE_CHECKLIST_AR.md`](../TIER1_MASTER_CLOSURE_CHECKLIST_AR.md) §14 and [`../../salesflow-saas/docs/tier1-master-closure-checklist.md`](../../salesflow-saas/docs/tier1-master-closure-checklist.md) Gate 8.
|
||||
|
||||
@ -43,6 +43,18 @@ Use as a **risk and testing** frame for agentic features:
|
||||
|
||||
Pair with [trust-fabric.md](trust-fabric.md): red-team workflows, structured output validation, tool allowlists, and rollback plans for Class B / R2+.
|
||||
|
||||
### Plane overlay (where each frame lands)
|
||||
|
||||
| Plane | NIST GenAI emphasis | OWASP LLM emphasis |
|
||||
|-------|---------------------|-------------------|
|
||||
| **Decision** | Map/manage model behavior in prompts & memos | Prompt injection, insecure output handling |
|
||||
| **Trust** | Measure/manage evaluations & incidents | Sensitive disclosure, excessive agency (governance) |
|
||||
| **Connector** | Map third-party tool/data exposure | Supply chain for tools/MCP |
|
||||
| **Data** | Map PDPL-relevant flows | Training data poisoning (if applicable) |
|
||||
| **Runtime / cost** | Manage capacity & monitoring | Unbounded tool loops, denial of wallet |
|
||||
|
||||
Detailed control rows live in [pdpl-nca-ai-control-matrices.md](pdpl-nca-ai-control-matrices.md). External link list: [`../references/tier1-external-index.md`](../references/tier1-external-index.md).
|
||||
|
||||
**References (external):** NIST publications portal; OWASP LLM Top 10 and GenAI security project pages.
|
||||
|
||||
---
|
||||
|
||||
@ -71,3 +71,22 @@ The following are **architecture targets** for enterprise-grade trust. They are
|
||||
**Integration pattern:** policy engines and PDPs should consume the same **A/R/S** and **actor_type** fields as events (see [events-and-schema.md](events-and-schema.md)) — avoid duplicating conflicting rules in prompts.
|
||||
|
||||
**Spike gate:** no production dependency on OPA/OpenFGA/Vault/Keycloak until ADR + security review + tests; see [`../adr/0001-tier1-execution-policy-spikes.md`](../adr/0001-tier1-execution-policy-spikes.md).
|
||||
|
||||
---
|
||||
|
||||
## Runtime policies (Tier-1 operational — beyond the radar)
|
||||
|
||||
These are **enforcement expectations** once a component is in-path in production (pair with [`github-and-release.md`](github-and-release.md) and [`operational-severity-model.md`](operational-severity-model.md)).
|
||||
|
||||
### OpenFGA — pinned authorization models
|
||||
|
||||
- **No production call path** without a recorded **`authorization_model_id`** (or equivalent immutable model version) in configuration and deploy manifests. Models are **immutable** in OpenFGA; pin IDs per environment and rotate via controlled rollout — see [`../references/tier1-external-index.md`](../references/tier1-external-index.md) (OpenFGA links).
|
||||
- Agent-on-behalf-of-user flows MUST be modeled explicitly (no implicit super-user tuples).
|
||||
|
||||
### Vault (or equivalent) — dual audit devices
|
||||
|
||||
- Production clusters MUST enable **at least two** independent audit devices (e.g. file + SIEM socket) so tampering or loss of one sink does not erase the audit trail — see Vault audit documentation in [`../references/tier1-external-index.md`](../references/tier1-external-index.md).
|
||||
|
||||
### OpenTelemetry — log correlation
|
||||
|
||||
- Critical paths (approvals, external commitments, connector facade calls) MUST emit **`trace_id`**, **`span_id`**, and a stable **`correlation_id`** (or equivalent) in structured logs and audit receipts so SIEM queries can join API ↔ worker ↔ workflow — see OTel logging spec in [`../references/tier1-external-index.md`](../references/tier1-external-index.md).
|
||||
|
||||
23
docs/references/tier1-external-index.md
Normal file
23
docs/references/tier1-external-index.md
Normal file
@ -0,0 +1,23 @@
|
||||
# Tier-1 external references (appendix)
|
||||
|
||||
روابط خارجية تُستخدم في الحوكمة والخطط؛ **لا تُكرر النص الطويل** في الوثائق الرئيسية—أشر إلى هذا الملف.
|
||||
|
||||
| الموضوع | مرجع |
|
||||
|---------|--------|
|
||||
| OpenAI Structured Outputs | https://openai.com/index/introducing-structured-outputs-in-the-api/ |
|
||||
| OpenAI Responses API | https://platform.openai.com/docs/api-reference/responses |
|
||||
| LangGraph durable execution | https://docs.langchain.com/oss/javascript/langgraph/durable-execution |
|
||||
| LangGraph / LangChain HITL | https://docs.langchain.com/oss/javascript/langchain/frontend/human-in-the-loop |
|
||||
| Temporal worker versioning | https://temporal.io/change-log/worker-versioning-public-preview |
|
||||
| OpenFGA immutable models | https://openfga.dev/docs/getting-started/immutable-models |
|
||||
| OpenFGA authorization for agents | https://openfga.dev/docs/modeling/agents |
|
||||
| HashiCorp Vault audit devices | https://developer.hashicorp.com/vault/docs/audit |
|
||||
| OPA | https://www.openpolicyagent.org/docs |
|
||||
| Keycloak Server Admin | https://www.keycloak.org/docs/latest/server_admin/index.html |
|
||||
| OpenTelemetry Logging | https://opentelemetry.io/docs/specification/logs/ |
|
||||
| CloudEvents spec | https://github.com/cloudevents/spec |
|
||||
| NIST AI RMF GenAI profile | https://www.nist.gov/publications/artificial-intelligence-risk-management-framework-generative-artificial-intelligence |
|
||||
| OWASP LLM Top 10 | https://owasp.org/www-project-top-10-for-large-language-model-applications/ |
|
||||
| Great Expectations checkpoints | https://docs.greatexpectations.io/docs/0.18/reference/learn/terms/checkpoint |
|
||||
| Airbyte docs | https://docs.airbyte.com/ |
|
||||
| Airbyte MCP / agentic data | https://airbyte.com/agentic-data/mcp-connectors |
|
||||
@ -19,3 +19,29 @@ Authoritative definitions: [`semantic-metrics-dictionary.md`](semantic-metrics-d
|
||||
## Lineage / catalog
|
||||
|
||||
Single choice documented in [`lineage-catalog-choice.md`](lineage-catalog-choice.md) until an ADR changes it.
|
||||
|
||||
---
|
||||
|
||||
## Dual connector strategy (runtime tools vs data movement)
|
||||
|
||||
| Layer | Purpose | Examples | Governance |
|
||||
|-------|---------|-----------|------------|
|
||||
| **Runtime tool connectors** | LLM/agent tool calls during a session (read/write bounded) | MCP tools, built-in HTTP tools behind facade | Decision plane + tool verification + allowlists |
|
||||
| **Data movement connectors** | Scheduled/batch replication or sync between systems | ELT/CDC-style pipelines (Airbyte-class) | Execution plane ownership, SLAs, backfill runbooks |
|
||||
|
||||
**Rule:** never confuse the two in architecture diagrams — they share “connector” language but have different failure domains, retention, and approval classes.
|
||||
|
||||
### MCP Tasks / async operations (watchlist)
|
||||
|
||||
Long-running MCP operations (tasks that outlive a single HTTP interaction) MUST have: visible **status polling** or webhook, **timeout**, **idempotency key**, and an owner in [`semantic-metrics-dictionary.md`](semantic-metrics-dictionary.md) or the connector runbook. Track vendor-specific “MCP Tasks” behavior as **V1–V2** severity candidates when SLAs slip — see [`governance/operational-severity-model.md`](governance/operational-severity-model.md). External overview: [`references/tier1-external-index.md`](references/tier1-external-index.md) (Airbyte MCP).
|
||||
|
||||
---
|
||||
|
||||
## Great Expectations (GE) as a release gate
|
||||
|
||||
When GE is in-path:
|
||||
|
||||
- Tie **checkpoint success** explicitly to [`RELEASE_READINESS_MATRIX_AR.md`](RELEASE_READINESS_MATRIX_AR.md) (row: schema adherence / data quality) and to promotion of workflows that consume the underlying datasets.
|
||||
- Failed checkpoints are **V2** by default if customer reports or downstream models consume the data; **V3** if PII/regulated fields are involved.
|
||||
|
||||
Reference: GE checkpoints — [`references/tier1-external-index.md`](references/tier1-external-index.md).
|
||||
|
||||
@ -69,9 +69,9 @@ async def class_b_decision_bundle_demo() -> Dict[str, Any]:
|
||||
execution_intent = ExecutionIntent(
|
||||
workflow_key="governance_class_b_review_v1",
|
||||
idempotency_key="class-b-demo-approval-center-001",
|
||||
requested_side_effect_class="internal_write",
|
||||
requested_side_effect_class="external_message",
|
||||
correlation_id="corr_class_b_demo",
|
||||
payload_summary="Record approval decision in internal audit trail",
|
||||
payload_summary="Demo external-class path; correlation_id mandatory per validate_class_b_bundle",
|
||||
)
|
||||
bundle = assemble_decision_bundle(
|
||||
evidence_pack=evidence,
|
||||
|
||||
@ -269,3 +269,25 @@ class ExecWeeklyPack(BaseModel):
|
||||
people_update: str
|
||||
risk_summary: List[str]
|
||||
provenance: Provenance
|
||||
|
||||
|
||||
class ExecWeeklyGovernanceContract(BaseModel):
|
||||
"""Unified executive weekly contract (WS8) — structured fields for UI/API.
|
||||
|
||||
Use alongside :class:`ExecWeeklyPack` for legacy synergy/RAG rows; prefer this
|
||||
model for new executive surfaces and approval-room summaries.
|
||||
"""
|
||||
|
||||
week_of: str = Field(description="ISO week label, e.g. 2026-W16")
|
||||
changes_summary: str = Field(description="What moved this week (facts + links)")
|
||||
pending_decisions: List[str] = Field(
|
||||
default_factory=list, description="Items awaiting human decision"
|
||||
)
|
||||
blockers_summary: str = Field(description="Single narrative of blockers")
|
||||
at_risk_items: List[str] = Field(
|
||||
default_factory=list, description="Initiatives or gates at risk"
|
||||
)
|
||||
next_best_actions: List[str] = Field(
|
||||
default_factory=list, description="Prioritized next actions with owners if known"
|
||||
)
|
||||
provenance: Provenance
|
||||
|
||||
@ -19,6 +19,11 @@ class AuditMetadata(BaseModel):
|
||||
policy_check_passed: bool = False
|
||||
agent_id: str
|
||||
timestamp: str
|
||||
trace_id: Optional[str] = Field(
|
||||
default=None,
|
||||
description="Distributed trace id (align with OpenTelemetry trace_id when OTel is enabled)",
|
||||
)
|
||||
span_id: Optional[str] = Field(default=None, description="Optional OTel span id for log correlation")
|
||||
|
||||
class DecisionMemo(BaseModel):
|
||||
"""
|
||||
|
||||
@ -86,7 +86,14 @@ def validate_class_b_bundle(bundle: Dict[str, Any]) -> None:
|
||||
raise ValueError("memo_json.required_approvals must be non-empty for Class B paths")
|
||||
EvidencePack.model_validate(bundle["evidence_pack_json"])
|
||||
ApprovalPacket.model_validate(bundle["approval_packet_json"])
|
||||
ExecutionIntent.model_validate(bundle["execution_intent_json"])
|
||||
ei = ExecutionIntent.model_validate(bundle["execution_intent_json"])
|
||||
if ei.requested_side_effect_class in ("external_message", "external_commitment"):
|
||||
cid = (ei.correlation_id or "").strip()
|
||||
if not cid:
|
||||
raise ValueError(
|
||||
"execution_intent_json.correlation_id is required for "
|
||||
f"requested_side_effect_class={ei.requested_side_effect_class!r} (traceability / OTel)"
|
||||
)
|
||||
rr = bundle["risk_register_json"]
|
||||
if not isinstance(rr, list):
|
||||
raise ValueError("risk_register_json must be a list")
|
||||
|
||||
@ -67,6 +67,48 @@ def test_assemble_decision_bundle_keys():
|
||||
validate_class_b_bundle(bundle)
|
||||
|
||||
|
||||
def test_validate_class_b_bundle_requires_correlation_for_external_commitment():
|
||||
memo = DecisionMemo(
|
||||
objective="x",
|
||||
decision_context="c",
|
||||
inputs_used=["i"],
|
||||
assumptions=["a"],
|
||||
recommendation_ar="r",
|
||||
alternatives_considered=["b"],
|
||||
expected_financial_impact=FinancialImpact(),
|
||||
risk_register=[],
|
||||
confidence_score=50.0,
|
||||
required_approvals=["CFO"],
|
||||
next_best_action="n",
|
||||
rollback_plan="rb",
|
||||
evidence_links=[],
|
||||
audit_metadata=AuditMetadata(agent_id="a", timestamp="2026-01-01T00:00:00Z"),
|
||||
)
|
||||
ep = EvidencePack(pack_id=new_evidence_pack_id(), provenance_score=1.0)
|
||||
ap = ApprovalPacket(
|
||||
approval_class="A2",
|
||||
reversibility_class="R2",
|
||||
sensitivity_class="S2",
|
||||
actor_type="executor_system",
|
||||
approvers_required=["CFO"],
|
||||
)
|
||||
ei = ExecutionIntent(
|
||||
workflow_key="w",
|
||||
idempotency_key="k",
|
||||
requested_side_effect_class="external_commitment",
|
||||
correlation_id=" ",
|
||||
payload_summary="x",
|
||||
)
|
||||
bundle = assemble_decision_bundle(
|
||||
evidence_pack=ep,
|
||||
approval_packet=ap,
|
||||
execution_intent=ei,
|
||||
memo_json=memo.to_json(),
|
||||
)
|
||||
with pytest.raises(ValueError, match="correlation_id"):
|
||||
validate_class_b_bundle(bundle)
|
||||
|
||||
|
||||
def test_validate_class_b_bundle_rejects_missing_memo_approvals():
|
||||
memo = DecisionMemo(
|
||||
objective="x",
|
||||
|
||||
@ -18,6 +18,13 @@ CONSTITUTION_PATHS = [
|
||||
"docs/architecture-register.md",
|
||||
"docs/execution-matrix-90d-tier1.md",
|
||||
"docs/enterprise-readiness.md",
|
||||
"docs/RELEASE_READINESS_MATRIX_AR.md",
|
||||
"docs/SOURCE_OF_TRUTH_INDEX.md",
|
||||
"docs/references/tier1-external-index.md",
|
||||
"docs/ws5-connector-events-metrics.md",
|
||||
"docs/executive-room-completion-spec.md",
|
||||
"docs/governance/pdpl-nca-ai-control-matrices.md",
|
||||
"docs/governance/operational-severity-model.md",
|
||||
"docs/adr/0001-tier1-execution-policy-spikes.md",
|
||||
"docs/adr/0002-execution-matrix-canonical-source.md",
|
||||
"docs/TIER1_MASTER_CLOSURE_CHECKLIST_AR.md",
|
||||
|
||||
81
scripts/check_docs_links.py
Normal file
81
scripts/check_docs_links.py
Normal file
@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Verify relative markdown links from repo root (Tier-1 docs governance CI)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
LINK_RE = re.compile(r"\[[^\]]*\]\(([^)]+)\)")
|
||||
|
||||
# Markdown files to scan (repo-grounded governance spine)
|
||||
GLOBS = [
|
||||
"docs/**/*.md",
|
||||
"MASTER_OPERATING_PROMPT.md",
|
||||
"AGENTS.md",
|
||||
"CLAUDE.md",
|
||||
"Execution_Matrix.md",
|
||||
"Execution_Matrix_v2.md",
|
||||
"Architecture_Pack.md",
|
||||
]
|
||||
|
||||
|
||||
def collect_files() -> list[Path]:
|
||||
out: list[Path] = []
|
||||
for g in GLOBS:
|
||||
if "**" in g:
|
||||
out.extend(p for p in ROOT.glob(g) if p.is_file())
|
||||
else:
|
||||
p = ROOT / g
|
||||
if p.is_file():
|
||||
out.append(p)
|
||||
return sorted(set(out))
|
||||
|
||||
|
||||
def resolve_link(source: Path, raw_target: str) -> Path | None:
|
||||
target = raw_target.split("#", 1)[0].strip()
|
||||
if not target or target.startswith(("http://", "https://", "mailto:", "vscode:", "file:")):
|
||||
return None
|
||||
if target.startswith("/"):
|
||||
return (ROOT / target.lstrip("/")).resolve()
|
||||
base = source.parent
|
||||
return (base / target).resolve()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
errors: list[str] = []
|
||||
for md in collect_files():
|
||||
try:
|
||||
text = md.read_text(encoding="utf-8")
|
||||
except OSError as e:
|
||||
errors.append(f"{md.relative_to(ROOT)}: read error {e}")
|
||||
continue
|
||||
for m in LINK_RE.finditer(text):
|
||||
raw = m.group(1).strip()
|
||||
if "`" in raw or raw.startswith("{{"):
|
||||
continue
|
||||
resolved = resolve_link(md, raw)
|
||||
if resolved is None:
|
||||
continue
|
||||
try:
|
||||
resolved.relative_to(ROOT)
|
||||
except ValueError:
|
||||
errors.append(f"{md.relative_to(ROOT)}: escape path {raw}")
|
||||
continue
|
||||
if not resolved.exists():
|
||||
errors.append(f"{md.relative_to(ROOT)}: broken link -> {raw} (resolved {resolved.relative_to(ROOT)})")
|
||||
|
||||
if errors:
|
||||
print("Docs link check FAILED:\n", file=sys.stderr)
|
||||
for e in errors[:80]:
|
||||
print(f" {e}", file=sys.stderr)
|
||||
if len(errors) > 80:
|
||||
print(f" ... and {len(errors) - 80} more", file=sys.stderr)
|
||||
return 1
|
||||
print(f"Docs link check OK ({len(collect_files())} files scanned)")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Loading…
Reference in New Issue
Block a user