diff --git a/AGENTS.md b/AGENTS.md
index 1d4c074..e9a59be 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -69,6 +69,15 @@ black aicertify/
- **Reports are user-facing legal artifacts** — when changing report generation, run the quickstart and inspect the output PDF before claiming success.
- **Avoid breaking the public API** — anything re-exported from `aicertify/__init__.py` is part of the user-facing contract. Bump the version and note in CHANGELOG.md if you must.
+## Diagrams and visual assets
+
+All README diagrams live in [`diagrams/`](diagrams/) as paired **light and dark SVGs**, embedded via `` for GitHub theme switching. The full design system (palette, type, shape language, naming, contribution flow) is documented in [`diagrams/STYLE.md`](diagrams/STYLE.md). Read it before adding or modifying any diagram.
+
+- **Edit existing diagrams in place** — they are hand-authored SVGs, not generated. Open the file, change it, validate with `python3 -c "import xml.etree.ElementTree as ET; ET.parse('')"`.
+- **Do not reintroduce a matplotlib generator** — the previous `generate_diagrams.py` was deliberately removed. Hand-authored SVGs are the source of truth.
+- **New diagrams must ship both `_light.svg` and `_dark.svg` variants.** Use `` markup; verify GitHub theme switching by viewing the rendered README on both light and dark settings.
+- **The logo `aicertify/assets/aic.png`** is *not* the README asset — it is bundled into generated PDF reports via [`aicertify/report_generation/report_generator.py`](aicertify/report_generation/report_generator.py). Don't delete it. README assets are the SVGs in `diagrams/`.
+
## What NOT to do
- Don't pin new dependencies aggressively — many users will install AICertify alongside their own stack; tight pins create conflicts.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b304f8a..8bf0bda 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
-_No unreleased changes._
+### Changed
+
+- **Visual refresh** — all README diagrams replaced with hand-authored, theme-aware SVGs in [`diagrams/`](diagrams/). Each diagram now ships as a paired `_light.svg` + `_dark.svg` and is embedded via `` so GitHub light- and dark-theme readers each see the variant that matches their canvas. The top-of-README logo is replaced with a hero banner SVG. The previous matplotlib generator (`diagrams/generate_diagrams.py`) and 5 baked-in PNG diagrams have been removed in favour of the hand-authored SVG system documented in [`diagrams/STYLE.md`](diagrams/STYLE.md).
+- **OG / social card** — added [`diagrams/og_card.png`](diagrams/og_card.png) (1200×630) for GitHub Settings → Social preview, plus its `_light` / `_dark` SVG sources.
+- **AGENTS.md** — added a "Diagrams and visual assets" section pointing future agents at the new style system.
## [0.7.0] — 2026-05-14 (first PyPI release)
@@ -17,7 +21,7 @@ This is the first AICertify release on PyPI (`pip install aicertify`). It bundle
- **First-party Claude Code skills** under [`skills/`](skills/): `run-compliance-check`, `evaluate-contract`, `explain-regulation`, `draft-policy`. Install with `cp -r skills/* ~/.claude/skills/`.
- **AGENTS.md and CLAUDE.md** for AI coding agents (Claude Code, Cursor, Codex, Gemini CLI, Copilot, …).
-- **Marketing diagrams** (5 PNG, regenerable via [`diagrams/generate_diagrams.py`](diagrams/generate_diagrams.py)) embedded in the README.
+- **Marketing diagrams** — five PNG diagrams generated by a matplotlib script, embedded in the README. _(Superseded in the next release by hand-authored, theme-aware SVGs; see Unreleased.)_
- **Translated READMEs** for Simplified Chinese, Japanese, Korean, and Hindi.
- **SECURITY.md** with a private vulnerability-disclosure flow at `security@principledevolution.ai`.
- **docs/why-aicertify.md** — long-form positioning doc covering the gap, the shift, the artefact AICertify produces, and the honest scope of what it does not do.
diff --git a/README.hi-IN.md b/README.hi-IN.md
index 70319df..58ed955 100644
--- a/README.hi-IN.md
+++ b/README.hi-IN.md
@@ -1,5 +1,8 @@
-
+
+
+
+
AICertify
@@ -32,7 +35,10 @@
-
+
+
+
+
@@ -108,10 +114,6 @@ await app.evaluate(regulations=regs, report_format="pdf", output_dir="reports")
AICertify उसी आर्टिफैक्ट के लिए बनाया गया है।
-
-
-
-
| | AICertify | Fairlearn / AIF360 | MS RAI Toolbox | Credo AI |
|---|---|---|---|---|
| ओपन सोर्स | ✅ Apache 2.0 | ✅ MIT | ✅ MIT | ❌ क्लोज़्ड |
@@ -127,7 +129,10 @@ AICertify उसी आर्टिफैक्ट के लिए बनाय
## यह कैसे काम करता है
-
+
+
+
+
1. **Contract** — आपके AI एप्लिकेशन का एक JSON विवरण: model, version, कैप्चर की गई interactions, metadata।
@@ -142,7 +147,10 @@ AICertify उसी आर्टिफैक्ट के लिए बनाय
## रेगुलेटरी कवरेज
-
+
+
+
+
AICertify [gopal](https://github.com/Principled-Evolution/gopal) पॉलिसी लाइब्रेरी के विरुद्ध चलता है — इन फ्रेमवर्क्स में **94 प्रोडक्शन OPA पॉलिसीज़**:
@@ -198,7 +206,10 @@ python -m aicertify.cli \
## सैंपल रिपोर्ट्स
-
+
+
+
+
`examples/outputs/` डायरेक्टरी में वास्तविक मूल्यांकनों से जनरेट की गई रिपोर्ट्स हैं जिन्हें आप कुछ भी चलाने से पहले देख सकते हैं:
diff --git a/README.ja-JP.md b/README.ja-JP.md
index b01dabf..3c8f3db 100644
--- a/README.ja-JP.md
+++ b/README.ja-JP.md
@@ -1,5 +1,8 @@
-
+
+
+
+
AICertify
@@ -32,7 +35,10 @@
-
+
+
+
+
@@ -108,10 +114,6 @@ await app.evaluate(regulations=regs, report_format="pdf", output_dir="reports")
AICertify はまさにその成果物のために構築されています。
-
-
-
-
| | AICertify | Fairlearn / AIF360 | MS RAI Toolbox | Credo AI |
|---|---|---|---|---|
| オープンソース | ✅ Apache 2.0 | ✅ MIT | ✅ MIT | ❌ クローズド |
@@ -127,7 +129,10 @@ AICertify はまさにその成果物のために構築されています。
## 仕組み
-
+
+
+
+
1. **契約 (Contract)** — AI アプリケーションを記述した JSON です。モデル、バージョン、収集したやり取り、メタデータを含みます。
@@ -142,7 +147,10 @@ AICertify はまさにその成果物のために構築されています。
## 規制カバレッジ
-
+
+
+
+
AICertify は [gopal](https://github.com/Principled-Evolution/gopal) ポリシーライブラリ — **本番運用可能な 94 個の OPA ポリシー** — を用いて、以下のフレームワークに対する評価を実行します。
@@ -198,7 +206,10 @@ Python API の全体像は [`examples/quickstart.py`](examples/quickstart.py)
## サンプルレポート
-
+
+
+
+
`examples/outputs/` ディレクトリには、実評価から生成されたレポートが含まれており、実行前に内容を確認できます。
diff --git a/README.ko-KR.md b/README.ko-KR.md
index 4b80793..070e497 100644
--- a/README.ko-KR.md
+++ b/README.ko-KR.md
@@ -1,5 +1,8 @@
-
+
+
+
+
AICertify
@@ -32,7 +35,10 @@
-
+
+
+
+
@@ -108,10 +114,6 @@ await app.evaluate(regulations=regs, report_format="pdf", output_dir="reports")
AICertify는 바로 그 산출물을 위해 만들어졌습니다.
-
-
-
-
| | AICertify | Fairlearn / AIF360 | MS RAI Toolbox | Credo AI |
|---|---|---|---|---|
| 오픈소스 | ✅ Apache 2.0 | ✅ MIT | ✅ MIT | ❌ 비공개 |
@@ -127,7 +129,10 @@ AICertify는 바로 그 산출물을 위해 만들어졌습니다.
## 작동 방식
-
+
+
+
+
1. **계약(Contract)** — AI 애플리케이션에 대한 JSON 설명: 모델, 버전, 수집된 상호작용, 메타데이터.
@@ -142,7 +147,10 @@ AICertify는 바로 그 산출물을 위해 만들어졌습니다.
## 규제 커버리지
-
+
+
+
+
AICertify는 [gopal](https://github.com/Principled-Evolution/gopal) 정책 라이브러리에서 실행됩니다 — 다음 프레임워크들에 걸친 **94개의 프로덕션 OPA 정책**입니다.
@@ -201,7 +209,10 @@ python -m aicertify.cli \
## 샘플 리포트
-
+
+
+
+
`examples/outputs/` 디렉터리에는 실제 평가에서 생성된 리포트가 들어 있어, 직접 실행하기 전에 살펴볼 수 있습니다.
diff --git a/README.md b/README.md
index e64b34f..97466d9 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,8 @@
-
+
+
+
+
AICertify
@@ -32,7 +35,10 @@
-
+
+
+
+
@@ -120,10 +126,6 @@ Neither produces the document a regulator actually asks for: *evidence that you
AICertify is built for that artifact.
-
-
-
-
| | AICertify | Fairlearn / AIF360 | MS RAI Toolbox | Credo AI |
|---|---|---|---|---|
| Open source | ✅ Apache 2.0 | ✅ MIT | ✅ MIT | ❌ Closed |
@@ -139,7 +141,10 @@ AICertify is built for that artifact.
## How It Works
-
+
+
+
+
1. **Contract** — A JSON description of your AI application: model, version, captured interactions, metadata.
@@ -154,7 +159,10 @@ Because the policies are declarative Rego, they version, diff, and review like a
## Regulatory Coverage
-
+
+
+
+
AICertify runs against the [gopal](https://github.com/Principled-Evolution/gopal) policy library — **94 production OPA policies** across these frameworks:
@@ -217,7 +225,10 @@ You don't have to install anything to see what AICertify produces. Pre-generated
- [examples/outputs/medical_diagnosis/](examples/outputs/medical_diagnosis/) — a clinical-decision-support model evaluated for patient safety
-
+
+
+
+
Open the PDFs. That's what your auditor wants.
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 6ee34b4..44abcba 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -1,5 +1,8 @@
-
+
+
+
+
AICertify
@@ -32,7 +35,10 @@
-
+
+
+
+
@@ -108,10 +114,6 @@ await app.evaluate(regulations=regs, report_format="pdf", output_dir="reports")
AICertify 正是为这份交付物而生。
-
-
-
-
| | AICertify | Fairlearn / AIF360 | MS RAI Toolbox | Credo AI |
|---|---|---|---|---|
| 开源 | ✅ Apache 2.0 | ✅ MIT | ✅ MIT | ❌ 闭源 |
@@ -127,7 +129,10 @@ AICertify 正是为这份交付物而生。
## 工作原理
-
+
+
+
+
1. **合约(Contract)** —— 用 JSON 描述您的 AI 应用:模型、版本、采集的交互、元数据。
@@ -142,7 +147,10 @@ AICertify 正是为这份交付物而生。
## 法规覆盖
-
+
+
+
+
AICertify 运行于 [gopal](https://github.com/Principled-Evolution/gopal) 策略库之上 —— **94 条生产级 OPA 策略**,覆盖以下框架:
@@ -201,7 +209,10 @@ python -m aicertify.cli \
## 示例报告
-
+
+
+
+
`examples/outputs/` 目录中包含来自真实评估的生成报告,您可以在运行前先行查阅:
diff --git a/diagrams/STYLE.md b/diagrams/STYLE.md
new file mode 100644
index 0000000..5f49dfb
--- /dev/null
+++ b/diagrams/STYLE.md
@@ -0,0 +1,94 @@
+# AICertify diagram style
+
+A short, opinionated reference so future diagrams (yours, mine, or a contributor's) stay visually coherent with the existing set. If you can read [diagram1_hero_flow_light.svg](diagram1_hero_flow_light.svg) and the matching `_dark.svg`, you have already seen the whole system applied.
+
+## The principle
+
+Two colors with intent, flat fills, no animation, no shadows. The polish is in restraint and consistency, not effects.
+
+## Palette
+
+| Token | Light | Dark | Used for |
+|---|---|---|---|
+| **Indigo (primary)** | `#4f46e5` | `#6366f1` | Process, structure, the "happy path" |
+| **Indigo (light fill)** | `#eef2ff` | `#312e81` | Card backgrounds for indigo elements |
+| **Indigo (text on fill)** | `#4338ca` | `#c7d2fe` | Text inside indigo chips/badges |
+| **Amber (accent)** | `#d97706` | `#fbbf24` | The **output** of the flow — audit report, deliverable, industry-specific framework |
+| **Amber (light fill)** | `#fffbeb` / `#fef3c7` | `#2a1f06` / `#533404` | Card / chip backgrounds for amber elements |
+| **Amber (text on fill)** | `#92400e` / `#b45309` | `#fcd34d` / `#fde68a` | Text inside amber chips |
+| **Foreground (text)** | `#0f172a` | `#f0f6fc` | Primary body / heading text |
+| **Foreground (muted)** | `#64748b` | `#8b949e` | Secondary captions, labels |
+| **Border** | `#e2e8f0` | `#30363d` | Card outlines, dividers |
+| **Card surface** | `#ffffff` | `#161b22` | Card backgrounds |
+| **Arrow / line** | `#94a3b8` | `#6e7681` | Connectors |
+
+**Amber is precious.** Reserve it for the deliverable in a flow and for industry-specific (vertical) frameworks. If everything is highlighted, nothing is highlighted.
+
+## Typography
+
+- Single stack, declared on every ``: `font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"`. No webfont hosting, no licensing, picks up the reader's OS font.
+- **Headings inside cards**: 13–15px, `font-weight="500"`.
+- **Body / captions**: 10–12px, `font-weight="400"`.
+- **Stat numerals** (e.g. "94"): 36px, `font-weight="500"`, amber.
+- Wordmark on the hero banner / OG card uses `letter-spacing="-0.025em"` for tightness at large sizes.
+
+## Shape language
+
+- **Cards / chips**: rounded rectangles. Corner radius `rx="10"` for cards, `rx="12"` (or larger) for chip pills.
+- **Card stroke**: `1px` border in the border token, no shadows, no gradients.
+- **Arrows**: `1.5px` line in the muted line color, with the marker defined per-file in ``. Don't reuse `id="al"` etc. across files in case both are inlined.
+- **Icons inside cards**: `1.5px` stroke in the indigo (or dark variant) color, `stroke-linecap="round"`, `stroke-linejoin="round"`. Compact (~24×24 unit) line icons, no fills unless intentional.
+
+## Light/dark pattern
+
+Diagrams ship as **paired files** with matching `_light.svg` and `_dark.svg`. README markup uses ``:
+
+```html
+
+
+
+
+```
+
+That gives GitHub-light readers the light variant and GitHub-dark readers the dark variant — same on mobile, on PR previews, and anywhere else `` is honored.
+
+- Light variants use white card surfaces, slate text.
+- Dark variants use `#161b22` cards (GitHub's `--color-canvas-subtle`) and `#30363d` borders so cards sit into the page rather than floating on top of it.
+- Don't bake in a background `` filling the viewBox unless the asset is meant to be self-contained (e.g. OG cards). Otherwise let GitHub's page color show through.
+
+## Files and naming
+
+```
+diagrams/
+├── STYLE.md (this file)
+├── hero_banner_{light,dark}.svg top-of-README banner
+├── logo_{light,dark}.svg standalone square mark
+├── og_card_{light,dark}.svg 1200×630 social-preview card
+├── og_card.png rasterized light variant (1200×630), for GitHub Settings → Social preview
+├── diagram1_hero_flow_{light,dark}.svg contract → OPA → report
+├── diagram2_architecture_{light,dark}.svg evaluator bus + OPA engine
+├── diagram3_regulatory_coverage_{light,dark}.svg stats + four category cards
+└── diagram5_report_anatomy_{light,dark}.svg report mockup with callouts
+```
+
+Diagram 4 (comparison) was deliberately removed — the markdown comparison table in the README is the single source of truth.
+
+## Adding a new diagram
+
+1. Sketch the content first in markdown (what does the reader need to understand?). Cut anything that is also said in nearby text.
+2. Pick a layout that mirrors an existing diagram if you can — most additions are variations of "flow", "bus", or "stats + cards".
+3. Hand-author the SVG. Use the existing files as templates; copy a card definition, swap the content.
+4. Validate XML: `python3 -c "import xml.etree.ElementTree as ET; ET.parse('diagrams/_light.svg')"`. Repeat for the dark variant.
+5. Embed with the `` snippet above in every README that should reference it (en + 4 translated).
+6. **No automation, no matplotlib, no Python generator.** The old `generate_diagrams.py` was retired because hand-authored SVGs are easier to read, edit, and review than rendered raster output. Keep them hand-authored.
+
+## Rasterizing (only when needed)
+
+The only raster output we keep in the repo is `og_card.png` — GitHub's Social Preview upload requires PNG/JPG. To regenerate:
+
+```bash
+inkscape --export-type=png --export-width=1200 --export-height=630 \
+ --export-filename=diagrams/og_card.png diagrams/og_card_light.svg
+```
+
+GitHub social preview is uploaded manually at: **Settings → General → Social preview → Edit → Upload an image**. The repo's checked-in `og_card.png` is the source artifact.
diff --git a/diagrams/diagram1_hero_flow.png b/diagrams/diagram1_hero_flow.png
deleted file mode 100644
index 03760fe..0000000
Binary files a/diagrams/diagram1_hero_flow.png and /dev/null differ
diff --git a/diagrams/diagram1_hero_flow_dark.svg b/diagrams/diagram1_hero_flow_dark.svg
new file mode 100644
index 0000000..810e600
--- /dev/null
+++ b/diagrams/diagram1_hero_flow_dark.svg
@@ -0,0 +1,66 @@
+
+
+How AICertify works
+Four-step flow from AI application to audit-ready report.
+
+
+
+
+
+
+
+01
+
+
+
+
+
+
+
+AI application
+Real interactions
+
+
+
+
+
+
+
+02
+
+
+
+
+Contract
+Inputs + outputs
+
+
+
+
+
+
+
+03
+
+
+
+
+OPA evaluation
+Policy as code
+
+
+
+
+
+
+
+04
+
+
+
+
+
+Audit report
+PDF · MD · JSON
+
+
diff --git a/diagrams/diagram1_hero_flow_light.svg b/diagrams/diagram1_hero_flow_light.svg
new file mode 100644
index 0000000..607fda6
--- /dev/null
+++ b/diagrams/diagram1_hero_flow_light.svg
@@ -0,0 +1,66 @@
+
+
+How AICertify works
+Four-step flow from AI application to audit-ready report.
+
+
+
+
+
+
+
+01
+
+
+
+
+
+
+
+AI application
+Real interactions
+
+
+
+
+
+
+
+02
+
+
+
+
+Contract
+Inputs + outputs
+
+
+
+
+
+
+
+03
+
+
+
+
+OPA evaluation
+Policy as code
+
+
+
+
+
+
+
+04
+
+
+
+
+
+Audit report
+PDF · MD · JSON
+
+
diff --git a/diagrams/diagram2_architecture.png b/diagrams/diagram2_architecture.png
deleted file mode 100644
index cef83ac..0000000
Binary files a/diagrams/diagram2_architecture.png and /dev/null differ
diff --git a/diagrams/diagram2_architecture_dark.svg b/diagrams/diagram2_architecture_dark.svg
new file mode 100644
index 0000000..bd77b6a
--- /dev/null
+++ b/diagrams/diagram2_architecture_dark.svg
@@ -0,0 +1,93 @@
+
+
+AICertify architecture
+Contract feeds four evaluators, which feed the OPA policy engine, producing an audit report.
+
+
+
+
+
+
+
+
+Contract
+JSON definition
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fairness
+Bias & equity
+
+
+
+
+
+
+
+Content safety
+Toxicity, PII
+
+
+
+
+
+
+
+
+Risk mgmt
+NIST controls
+
+
+
+
+
+
+
+
+Compliance
+Framework checks
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+OPA policy engine
+94 production Rego policies · gopal library
+
+
+
+
+
+
+
+
+
+
+Audit report
+PDF · MD · JSON · HTML
+
+
diff --git a/diagrams/diagram2_architecture_light.svg b/diagrams/diagram2_architecture_light.svg
new file mode 100644
index 0000000..6bee4e3
--- /dev/null
+++ b/diagrams/diagram2_architecture_light.svg
@@ -0,0 +1,93 @@
+
+
+AICertify architecture
+Contract feeds four evaluators, which feed the OPA policy engine, producing an audit report.
+
+
+
+
+
+
+
+
+Contract
+JSON definition
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Fairness
+Bias & equity
+
+
+
+
+
+
+
+Content safety
+Toxicity, PII
+
+
+
+
+
+
+
+
+Risk mgmt
+NIST controls
+
+
+
+
+
+
+
+
+Compliance
+Framework checks
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+OPA policy engine
+94 production Rego policies · gopal library
+
+
+
+
+
+
+
+
+
+
+Audit report
+PDF · MD · JSON · HTML
+
+
diff --git a/diagrams/diagram3_regulatory_coverage.png b/diagrams/diagram3_regulatory_coverage.png
deleted file mode 100644
index 82b344c..0000000
Binary files a/diagrams/diagram3_regulatory_coverage.png and /dev/null differ
diff --git a/diagrams/diagram3_regulatory_coverage_dark.svg b/diagrams/diagram3_regulatory_coverage_dark.svg
new file mode 100644
index 0000000..012633e
--- /dev/null
+++ b/diagrams/diagram3_regulatory_coverage_dark.svg
@@ -0,0 +1,70 @@
+
+
+Regulatory coverage
+94 production Rego policies across 15+ frameworks and 5 industries.
+
+94
+Rego policies
+15+
+frameworks
+5
+industries
+
+
+
+
+
+
+
+
+
+International standards
+
+EU AI Act
+NIST AI RMF
+India DPDP
+Brazil AI Bill
+
+
+
+
+
+
+
+
+Aviation
+
+ICAO Doc 10019
+FAA Part 107
+EASA SORA
+RTCA DO-365/366
+
+
+
+
+
+
+
+
+Industry verticals
+
+Healthcare
+Banking & finance
+Automotive
+Education
+
+
+
+
+
+
+
+
+Cross-cutting principles
+
+Fairness & bias
+Content safety
+Transparency
+Risk management
+
+
diff --git a/diagrams/diagram3_regulatory_coverage_light.svg b/diagrams/diagram3_regulatory_coverage_light.svg
new file mode 100644
index 0000000..4b9305c
--- /dev/null
+++ b/diagrams/diagram3_regulatory_coverage_light.svg
@@ -0,0 +1,70 @@
+
+
+Regulatory coverage
+94 production Rego policies across 15+ frameworks and 5 industries.
+
+94
+Rego policies
+15+
+frameworks
+5
+industries
+
+
+
+
+
+
+
+
+
+International standards
+
+EU AI Act
+NIST AI RMF
+India DPDP
+Brazil AI Bill
+
+
+
+
+
+
+
+
+Aviation
+
+ICAO Doc 10019
+FAA Part 107
+EASA SORA
+RTCA DO-365/366
+
+
+
+
+
+
+
+
+Industry verticals
+
+Healthcare
+Banking & finance
+Automotive
+Education
+
+
+
+
+
+
+
+
+Cross-cutting principles
+
+Fairness & bias
+Content safety
+Transparency
+Risk management
+
+
diff --git a/diagrams/diagram4_comparison.png b/diagrams/diagram4_comparison.png
deleted file mode 100644
index 8cdad65..0000000
Binary files a/diagrams/diagram4_comparison.png and /dev/null differ
diff --git a/diagrams/diagram5_report_anatomy.png b/diagrams/diagram5_report_anatomy.png
deleted file mode 100644
index bb55b47..0000000
Binary files a/diagrams/diagram5_report_anatomy.png and /dev/null differ
diff --git a/diagrams/diagram5_report_anatomy_dark.svg b/diagrams/diagram5_report_anatomy_dark.svg
new file mode 100644
index 0000000..81b6696
--- /dev/null
+++ b/diagrams/diagram5_report_anatomy_dark.svg
@@ -0,0 +1,76 @@
+
+
+Anatomy of an audit-ready report
+Stylized AICertify report showing header, executive summary, policy results, risk assessment, and remediation sections.
+
+
+
+
+EU AI Act compliance
+customer-support-bot · 2026-05-14
+
+Executive summary
+
+
+
+
+
+Policy results
+
+
+
+
+
+
+
+
+
+
+
+
+Risk assessment
+
+
+
+
+
+
+
+
+
+Remediation
+
+
+
+
+
+
+
+
+AICertify v0.7.0 · run #a4f3 · Apache 2.0
+
+
+
+Header
+Framework, model, date
+
+
+
+Executive summary
+Outcome at a glance
+
+
+
+Policy results
+Per-rule pass status
+
+
+
+Risk assessment
+Severity by category
+
+
+
+Remediation
+Required follow-ups
+
diff --git a/diagrams/diagram5_report_anatomy_light.svg b/diagrams/diagram5_report_anatomy_light.svg
new file mode 100644
index 0000000..fd8cd1c
--- /dev/null
+++ b/diagrams/diagram5_report_anatomy_light.svg
@@ -0,0 +1,76 @@
+
+
+Anatomy of an audit-ready report
+Stylized AICertify report showing header, executive summary, policy results, risk assessment, and remediation sections.
+
+
+
+
+EU AI Act compliance
+customer-support-bot · 2026-05-14
+
+Executive summary
+
+
+
+
+
+Policy results
+
+
+
+
+
+
+
+
+
+
+
+
+Risk assessment
+
+
+
+
+
+
+
+
+
+Remediation
+
+
+
+
+
+
+
+
+AICertify v0.7.0 · run #a4f3 · Apache 2.0
+
+
+
+Header
+Framework, model, date
+
+
+
+Executive summary
+Outcome at a glance
+
+
+
+Policy results
+Per-rule pass status
+
+
+
+Risk assessment
+Severity by category
+
+
+
+Remediation
+Required follow-ups
+
diff --git a/diagrams/generate_diagrams.py b/diagrams/generate_diagrams.py
deleted file mode 100644
index 27920a3..0000000
--- a/diagrams/generate_diagrams.py
+++ /dev/null
@@ -1,1028 +0,0 @@
-"""Generate marketing diagrams for the AICertify README.
-
-Run from repo root: python diagrams/generate_diagrams.py
-Outputs 5 PNGs (1600x900, ~retina-2x) into the diagrams/ directory.
-"""
-
-from __future__ import annotations
-
-import os
-from pathlib import Path
-
-import matplotlib.pyplot as plt
-from matplotlib.patches import FancyBboxPatch, FancyArrowPatch, Rectangle
-
-# ---------- shared style ----------
-PURPLE = "#7D4698"
-PURPLE_DARK = "#5C2E76"
-BLUE = "#1971c2"
-GREEN = "#2f9e44"
-ORANGE = "#e8590c"
-TEXT = "#212529"
-MUTED = "#495057"
-LIGHT_BG = "#f1f3f5"
-LIGHTER_BG = "#f8f9fa"
-BORDER = "#dee2e6"
-WHITE = "#ffffff"
-RED = "#c92a2a"
-
-# Figure size: 16x9 inches at 100 dpi -> 1600x900px (retina-friendly)
-FIGSIZE = (16, 9)
-DPI = 100
-
-# Typography
-TITLE_SIZE = 30
-SUBTITLE_SIZE = 18
-BODY_SIZE = 16
-SMALL_SIZE = 13
-
-HERE = Path(__file__).resolve().parent
-
-
-# ---------- helpers ----------
-def new_fig():
- """Create a clean 16:9 figure with white background."""
- fig, ax = plt.subplots(figsize=FIGSIZE, dpi=DPI)
- fig.patch.set_facecolor(WHITE)
- ax.set_facecolor(WHITE)
- ax.set_xlim(0, 100)
- ax.set_ylim(0, 56.25) # keeps a 16:9 aspect in data coords
- ax.set_xticks([])
- ax.set_yticks([])
- for spine in ax.spines.values():
- spine.set_visible(False)
- return fig, ax
-
-
-def title(ax, text, y=52, color=TEXT, size=TITLE_SIZE, weight="bold"):
- ax.text(
- 50,
- y,
- text,
- ha="center",
- va="center",
- fontsize=size,
- fontweight=weight,
- color=color,
- )
-
-
-def subtitle(ax, text, y=47, color=MUTED, size=SUBTITLE_SIZE):
- ax.text(50, y, text, ha="center", va="center", fontsize=size, color=color)
-
-
-def draw_box(
- ax,
- x,
- y,
- w,
- h,
- facecolor=WHITE,
- edgecolor=PURPLE,
- linewidth=2.2,
- rounding=0.4,
- shadow=False,
-):
- """Draw a rounded rectangle centered on (x, y) with width w, height h."""
- if shadow:
- # offset shadow
- shadow_box = FancyBboxPatch(
- (x - w / 2 + 0.25, y - h / 2 - 0.35),
- w,
- h,
- boxstyle=f"round,pad=0.02,rounding_size={rounding}",
- linewidth=0,
- facecolor="#000000",
- alpha=0.08,
- zorder=1,
- )
- ax.add_patch(shadow_box)
- box = FancyBboxPatch(
- (x - w / 2, y - h / 2),
- w,
- h,
- boxstyle=f"round,pad=0.02,rounding_size={rounding}",
- linewidth=linewidth,
- edgecolor=edgecolor,
- facecolor=facecolor,
- zorder=2,
- )
- ax.add_patch(box)
- return box
-
-
-def labeled_box(
- ax,
- cx,
- cy,
- w,
- h,
- title_text,
- subtitle_text=None,
- facecolor=WHITE,
- edgecolor=PURPLE,
- title_color=None,
- subtitle_color=None,
- title_size=BODY_SIZE + 2,
- subtitle_size=SMALL_SIZE,
- shadow=True,
-):
- draw_box(
- ax,
- cx,
- cy,
- w,
- h,
- facecolor=facecolor,
- edgecolor=edgecolor,
- shadow=shadow,
- )
- tc = (
- title_color
- if title_color
- else (WHITE if facecolor in (PURPLE, PURPLE_DARK) else TEXT)
- )
- sc = (
- subtitle_color
- if subtitle_color
- else (WHITE if facecolor in (PURPLE, PURPLE_DARK) else MUTED)
- )
- if subtitle_text:
- title_lines = title_text.count("\n") + 1
- sub_lines = subtitle_text.count("\n") + 1
- # vertical spacing roughly proportional to font size (1 unit ~ 14pt)
- title_line_h = title_size / 14.0
- sub_line_h = subtitle_size / 14.0
- gap = 0.8
- total_h = title_lines * title_line_h + gap + sub_lines * sub_line_h
- # top of text block
- top = cy + total_h / 2
- # title block center
- title_cy = top - (title_lines * title_line_h) / 2
- sub_cy = (
- title_cy
- - (title_lines * title_line_h) / 2
- - gap
- - (sub_lines * sub_line_h) / 2
- )
- ax.text(
- cx,
- title_cy,
- title_text,
- ha="center",
- va="center",
- fontsize=title_size,
- fontweight="bold",
- color=tc,
- zorder=3,
- linespacing=1.0,
- )
- ax.text(
- cx,
- sub_cy,
- subtitle_text,
- ha="center",
- va="center",
- fontsize=subtitle_size,
- color=sc,
- zorder=3,
- linespacing=1.1,
- )
- else:
- ax.text(
- cx,
- cy,
- title_text,
- ha="center",
- va="center",
- fontsize=title_size,
- fontweight="bold",
- color=tc,
- zorder=3,
- )
-
-
-def draw_arrow(ax, x1, y1, x2, y2, color=PURPLE, lw=2.8, mutation_scale=28):
- arr = FancyArrowPatch(
- (x1, y1),
- (x2, y2),
- arrowstyle="-|>",
- mutation_scale=mutation_scale,
- linewidth=lw,
- color=color,
- zorder=2,
- )
- ax.add_patch(arr)
-
-
-def save_fig(fig, name):
- out = HERE / name
- fig.savefig(out, dpi=DPI, bbox_inches="tight", facecolor=WHITE, pad_inches=0.25)
- plt.close(fig)
- size_kb = os.path.getsize(out) / 1024
- print(f" wrote {name} ({size_kb:.1f} KB)")
-
-
-# ---------- diagram 1: hero flow ----------
-def diagram1_hero_flow():
- fig, ax = new_fig()
- title(ax, "From AI app to audit-ready report")
- subtitle(
- ax,
- "One contract. One command. One report your auditor accepts.",
- )
-
- steps = [
- ("AI\nApplication", "model + interactions\n+ metadata", BLUE),
- ("AICertify\nContract", "captured\nas JSON", PURPLE),
- ("OPA Policy\nEvaluation", "EU AI Act, NIST\n+ 13 more", GREEN),
- ("Compliance\nReport", "PDF, Markdown,\nJSON, HTML", ORANGE),
- ]
-
- box_w = 19
- box_h = 18
- y = 26
- # 4 boxes spaced with clear gaps for arrows
- centers = [12, 37.33, 62.66, 88]
-
- for i, (cx, (t, s, color)) in enumerate(zip(centers, steps)):
- # numbered circle on top of each box
- circle = plt.Circle(
- (cx - box_w / 2 + 1.8, y + box_h / 2 - 1.2),
- 1.3,
- color=color,
- zorder=4,
- )
- ax.add_patch(circle)
- ax.text(
- cx - box_w / 2 + 1.8,
- y + box_h / 2 - 1.2,
- str(i + 1),
- ha="center",
- va="center",
- color=WHITE,
- fontsize=14,
- fontweight="bold",
- zorder=5,
- )
- labeled_box(
- ax,
- cx,
- y,
- box_w,
- box_h,
- t,
- s,
- facecolor=WHITE,
- edgecolor=color,
- title_size=18,
- subtitle_size=13,
- shadow=True,
- )
-
- # arrows
- for i in range(3):
- x_from = centers[i] + box_w / 2 + 0.2
- x_to = centers[i + 1] - box_w / 2 - 0.2
- draw_arrow(ax, x_from, y, x_to, y, color=MUTED, lw=2.5, mutation_scale=24)
-
- # footer tag
- ax.text(
- 50,
- 7,
- "Open source - Apache 2.0 | Built on Open Policy Agent | 94 Rego policies",
- ha="center",
- va="center",
- fontsize=14,
- color=MUTED,
- )
-
- save_fig(fig, "diagram1_hero_flow.png")
-
-
-# ---------- diagram 2: architecture ----------
-def diagram2_architecture():
- fig, ax = new_fig()
- title(ax, "How AICertify works", y=53)
- subtitle(
- ax,
- "Pluggable evaluators feed OPA. OPA produces the report.",
- y=48.5,
- )
-
- # LEFT: your AI app
- labeled_box(
- ax,
- 10,
- 24,
- 14,
- 11,
- "Your AI App",
- "any LLM, agent,\nor pipeline",
- facecolor=BLUE,
- edgecolor=BLUE,
- title_color=WHITE,
- subtitle_color=WHITE,
- title_size=16,
- subtitle_size=11,
- shadow=True,
- )
-
- # CENTER stack
- cx = 50
- box_w = 44
- box_h = 7.2
- rows = [
- (
- 38.5,
- "Contract",
- "model_name | version | interactions | metadata",
- PURPLE,
- ),
- (
- 29,
- "Evaluators",
- "Fairness | ContentSafety | RiskManagement | Compliance",
- PURPLE,
- ),
- (
- 19.5,
- "OPA Engine + Rego Policies",
- "94 policies sourced from the gopal library",
- PURPLE_DARK,
- ),
- (
- 10,
- "Report Generator",
- "ReportLab PDF | Markdown | JSON | HTML",
- PURPLE,
- ),
- ]
-
- for y, t, s, color in rows:
- labeled_box(
- ax,
- cx,
- y,
- box_w,
- box_h,
- t,
- s,
- facecolor=color,
- edgecolor=color,
- title_color=WHITE,
- subtitle_color="#e9d5f0",
- title_size=17,
- subtitle_size=12,
- shadow=True,
- )
-
- # arrows down the stack
- for i in range(len(rows) - 1):
- y_from = rows[i][0] - box_h / 2 - 0.05
- y_to = rows[i + 1][0] + box_h / 2 + 0.05
- draw_arrow(ax, cx, y_from, cx, y_to, color=MUTED, lw=2.4, mutation_scale=22)
-
- # arrow from left box into center stack (top)
- draw_arrow(ax, 10 + 14 / 2 + 0.2, 24, cx - box_w / 2 - 0.2, rows[0][0], color=MUTED)
-
- # RIGHT: audit deliverable
- labeled_box(
- ax,
- 90,
- 24,
- 14,
- 11,
- "Audit\nDeliverable",
- "dated, signed,\nreproducible",
- facecolor=ORANGE,
- edgecolor=ORANGE,
- title_color=WHITE,
- subtitle_color=WHITE,
- title_size=16,
- subtitle_size=11,
- shadow=True,
- )
- # arrow from bottom of stack out to the right box
- draw_arrow(
- ax,
- cx + box_w / 2 + 0.2,
- rows[-1][0],
- 90 - 14 / 2 - 0.2,
- 24,
- color=MUTED,
- )
-
- save_fig(fig, "diagram2_architecture.png")
-
-
-# ---------- diagram 3: regulatory coverage ----------
-def diagram3_regulatory_coverage():
- fig, ax = new_fig()
- title(ax, "Regulatory coverage - 15+ frameworks", y=53)
- ax.text(
- 50,
- 47.5,
- "94 policies | 15+ frameworks | 5 industries",
- ha="center",
- va="center",
- fontsize=22,
- fontweight="bold",
- color=PURPLE,
- )
-
- # row category labels
- row_labels = [
- "International",
- "Aviation Safety",
- "Industry",
- "Cross-cutting",
- ]
-
- cells = [
- # row 1: International
- [
- ("EU AI Act", "29"),
- ("NIST AI RMF", "5"),
- ("India DPDP", "1"),
- ("Brazil AI Bill", "1"),
- ],
- # row 2: Aviation Safety
- [
- ("RTCA DO-365/366", "2"),
- ("FAA Part 107", "2"),
- ("EASA SORA", "2"),
- ("ICAO Doc 10019", "1"),
- ],
- # row 3: Industry
- [
- ("Healthcare", "2"),
- ("Banking & FS", "2"),
- ("Automotive", "1"),
- ("Education", "12"),
- ],
- # row 4: Cross-cutting
- [
- ("Global", "9"),
- ("Aviation Vertical", "17"),
- ("AIOps", "1"),
- ("Corporate", "2"),
- ],
- ]
-
- # grid layout area: rows centered at y values, columns centered at x values
- col_x = [22, 41, 60, 79]
- row_y = [37, 28, 19, 10]
- cell_w = 16.5
- cell_h = 7.4
-
- # row labels on the far left
- for ry, label in zip(row_y, row_labels):
- ax.text(
- 6.5,
- ry,
- label,
- ha="center",
- va="center",
- fontsize=13,
- fontweight="bold",
- color=MUTED,
- rotation=0,
- )
-
- for r_i, row in enumerate(cells):
- for c_i, (name, count) in enumerate(row):
- cx = col_x[c_i]
- cy = row_y[r_i]
- draw_box(
- ax,
- cx,
- cy,
- cell_w,
- cell_h,
- facecolor=PURPLE,
- edgecolor=PURPLE_DARK,
- linewidth=1.5,
- rounding=0.3,
- shadow=True,
- )
- # framework name
- ax.text(
- cx,
- cy + 1.1,
- name,
- ha="center",
- va="center",
- fontsize=14,
- fontweight="bold",
- color=WHITE,
- zorder=3,
- )
- # policy count pill
- ax.text(
- cx,
- cy - 1.5,
- f"{count} {'policy' if count == '1' else 'policies'}",
- ha="center",
- va="center",
- fontsize=12,
- color="#e9d5f0",
- zorder=3,
- )
-
- save_fig(fig, "diagram3_regulatory_coverage.png")
-
-
-# ---------- diagram 4: comparison ----------
-def diagram4_comparison():
- fig, ax = new_fig()
- title(ax, "AICertify vs alternatives", y=53.5)
- subtitle(
- ax,
- "The only open-source, policy-as-code option with named regulatory coverage.",
- y=48.8,
- )
-
- columns = [
- "Feature",
- "AICertify",
- "Fairlearn",
- "AI Fairness 360",
- "MS RAI Toolbox",
- "Credo AI",
- ]
- rows = [
- (
- "Open source (Apache 2.0)",
- ["YES", "YES (MIT)", "YES (MIT)", "YES (MIT)", "NO"],
- ),
- ("On-prem capable", ["YES", "YES", "YES", "YES", "NO"]),
- ("Policy-as-code (OPA / Rego)", ["YES", "NO", "NO", "NO", "NO"]),
- ("Named regulatory frameworks (15+)", ["YES", "NO", "NO", "NO", "PARTIAL"]),
- ("Industry verticals out of box", ["YES", "NO", "NO", "NO", "PARTIAL"]),
- ("Audit-ready report output", ["YES", "NO", "NO", "PARTIAL", "YES"]),
- ("Custom policies via `.rego`", ["YES", "NO", "NO", "NO", "PAID"]),
- ]
-
- # Layout: columns
- col_x = [18, 39, 52, 65, 78, 91]
- col_w = [26, 11, 13, 13, 13, 11]
- header_y = 42
- row_h = 4.2
- first_row_y = 38
-
- # column header strip
- for cx, cw, name in zip(col_x, col_w, columns):
- is_aic = name == "AICertify"
- ax.add_patch(
- Rectangle(
- (cx - cw / 2, header_y - row_h / 2),
- cw,
- row_h,
- facecolor=PURPLE if is_aic else "#343a40",
- edgecolor="none",
- zorder=2,
- )
- )
- ax.text(
- cx,
- header_y,
- name,
- ha="center",
- va="center",
- fontsize=14 if is_aic else 12,
- fontweight="bold",
- color=WHITE,
- zorder=3,
- )
-
- # highlight strip for AICertify column behind rows
- aic_x = col_x[1]
- aic_w = col_w[1]
- rows_total_h = row_h * len(rows)
- ax.add_patch(
- Rectangle(
- (aic_x - aic_w / 2, first_row_y - row_h * (len(rows) - 1) - row_h / 2),
- aic_w,
- rows_total_h,
- facecolor="#f3e8f7",
- edgecolor="none",
- zorder=1,
- )
- )
-
- def cell_marker(value):
- if value == "YES":
- return ("Yes", GREEN, "bold")
- if value == "NO":
- return ("No", RED, "bold")
- if value == "PARTIAL":
- return ("Partial", ORANGE, "bold")
- if value == "PAID":
- return ("Paid", ORANGE, "bold")
- if value.startswith("YES "):
- return (value.replace("YES ", "Yes "), GREEN, "bold")
- return (value, TEXT, "normal")
-
- for r_i, (feature, vals) in enumerate(rows):
- y = first_row_y - r_i * row_h
- # alternating row band
- if r_i % 2 == 0:
- ax.add_patch(
- Rectangle(
- (col_x[0] - col_w[0] / 2, y - row_h / 2),
- sum(col_w)
- + (col_x[-1] + col_w[-1] / 2 - (col_x[0] - col_w[0] / 2))
- - sum(col_w),
- row_h,
- facecolor=LIGHTER_BG,
- edgecolor="none",
- zorder=0,
- )
- )
- # feature label (left col)
- ax.text(
- col_x[0] - col_w[0] / 2 + 1,
- y,
- feature,
- ha="left",
- va="center",
- fontsize=13,
- color=TEXT,
- zorder=3,
- )
- # value cells
- for c_i, v in enumerate(vals):
- label, color, weight = cell_marker(v)
- ax.text(
- col_x[c_i + 1],
- y,
- label,
- ha="center",
- va="center",
- fontsize=13,
- color=color,
- fontweight=weight,
- zorder=3,
- )
-
- # bottom border
- ax.plot(
- [col_x[0] - col_w[0] / 2, col_x[-1] + col_w[-1] / 2],
- [
- first_row_y - len(rows) * row_h + row_h / 2,
- first_row_y - len(rows) * row_h + row_h / 2,
- ],
- color=BORDER,
- lw=1.5,
- zorder=2,
- )
-
- # footer
- ax.text(
- 50,
- 4,
- "Source: public docs and source repos as of 2025. AICertify is community-maintained.",
- ha="center",
- va="center",
- fontsize=11,
- color=MUTED,
- style="italic",
- )
-
- save_fig(fig, "diagram4_comparison.png")
-
-
-# ---------- diagram 5: report anatomy ----------
-def diagram5_report_anatomy():
- fig, ax = new_fig()
- title(ax, "Anatomy of an audit-ready report", y=53.5)
- subtitle(
- ax,
- "What the generated PDF actually contains.",
- y=48.8,
- )
-
- # The "document" page
- page_x, page_y = 50, 23.5
- page_w, page_h = 70, 41
-
- # shadow
- shadow_rect = Rectangle(
- (page_x - page_w / 2 + 0.5, page_y - page_h / 2 - 0.6),
- page_w,
- page_h,
- facecolor="#000000",
- alpha=0.10,
- edgecolor="none",
- zorder=1,
- )
- ax.add_patch(shadow_rect)
- # page background
- ax.add_patch(
- Rectangle(
- (page_x - page_w / 2, page_y - page_h / 2),
- page_w,
- page_h,
- facecolor=WHITE,
- edgecolor=BORDER,
- linewidth=1.5,
- zorder=2,
- )
- )
-
- left = page_x - page_w / 2 + 2.5
- right = page_x + page_w / 2 - 2.5
- top = page_y + page_h / 2
-
- # Header band
- ax.add_patch(
- Rectangle(
- (page_x - page_w / 2, top - 5.5),
- page_w,
- 5.5,
- facecolor=PURPLE,
- edgecolor="none",
- zorder=3,
- )
- )
- ax.text(
- left,
- top - 2.0,
- "EU AI Act Compliance Report",
- ha="left",
- va="center",
- fontsize=17,
- fontweight="bold",
- color=WHITE,
- zorder=4,
- )
- ax.text(
- left,
- top - 4.0,
- "customer-support-bot | gpt-4o | 2026-05-14",
- ha="left",
- va="center",
- fontsize=12,
- color="#e9d5f0",
- zorder=4,
- )
- # PASS stamp on header
- ax.add_patch(
- FancyBboxPatch(
- (right - 9, top - 4.6),
- 8,
- 3.4,
- boxstyle="round,pad=0.02,rounding_size=0.4",
- facecolor=GREEN,
- edgecolor=GREEN,
- zorder=4,
- )
- )
- ax.text(
- right - 5,
- top - 2.9,
- "PASS",
- ha="center",
- va="center",
- fontsize=15,
- fontweight="bold",
- color=WHITE,
- zorder=5,
- )
-
- # Section 1: Executive Summary
- sec_y = top - 8.5
- ax.text(
- left,
- sec_y,
- "1. Executive Summary",
- ha="left",
- va="center",
- fontsize=14,
- fontweight="bold",
- color=PURPLE,
- zorder=4,
- )
- for i, line in enumerate(
- [
- "27 of 29 EU AI Act policies passed. 2 advisory findings.",
- "Risk classification: limited risk (Article 52 transparency).",
- ]
- ):
- ax.text(
- left,
- sec_y - 2 - i * 1.7,
- line,
- ha="left",
- va="center",
- fontsize=11.5,
- color=TEXT,
- zorder=4,
- )
-
- # Section 2: Policy Results table
- sec_y2 = sec_y - 7.5
- ax.text(
- left,
- sec_y2,
- "2. Policy Results",
- ha="left",
- va="center",
- fontsize=14,
- fontweight="bold",
- color=PURPLE,
- zorder=4,
- )
-
- tbl_top = sec_y2 - 2
- # header row
- ax.add_patch(
- Rectangle(
- (left, tbl_top - 1.4),
- right - left - 22,
- 1.4,
- facecolor=LIGHT_BG,
- edgecolor=BORDER,
- zorder=3,
- )
- )
- headers = ["Policy", "Status", "Evidence"]
- hxs = [left + 0.5, left + 22, left + 30]
- for hx, h in zip(hxs, headers):
- ax.text(
- hx,
- tbl_top - 0.7,
- h,
- ha="left",
- va="center",
- fontsize=11,
- fontweight="bold",
- color=MUTED,
- zorder=4,
- )
-
- rows = [
- ("Art. 5 Prohibited practices", "Pass", "0/127 interactions flagged"),
- ("Art. 10 Data governance", "Pass", "training set documented"),
- ("Art. 13 Transparency", "Pass", "user notice present"),
- ("Art. 14 Human oversight", "Advisory", "review queue partial"),
- ]
- for i, (p, status, ev) in enumerate(rows):
- y = tbl_top - 1.4 - 1.4 - i * 1.5
- color = GREEN if status == "Pass" else ORANGE
- ax.text(
- left + 0.5,
- y,
- p,
- ha="left",
- va="center",
- fontsize=10.5,
- color=TEXT,
- zorder=4,
- )
- ax.text(
- left + 22,
- y,
- status,
- ha="left",
- va="center",
- fontsize=10.5,
- fontweight="bold",
- color=color,
- zorder=4,
- )
- ax.text(
- left + 30,
- y,
- ev,
- ha="left",
- va="center",
- fontsize=10.5,
- color=MUTED,
- zorder=4,
- )
-
- # Section 3: Risk Assessment with mini bar chart
- sec_y3 = sec_y2 - 12.5
- ax.text(
- left,
- sec_y3,
- "3. Risk Assessment",
- ha="left",
- va="center",
- fontsize=14,
- fontweight="bold",
- color=PURPLE,
- zorder=4,
- )
- bar_labels = ["Fair", "Safe", "Priv", "Robust"]
- bar_vals = [0.92, 0.88, 0.95, 0.71]
- bar_colors = [GREEN, GREEN, GREEN, ORANGE]
- bx_start = left + 0.5
- bar_w = 3.6
- gap = 1.6
- base_y = sec_y3 - 6.2
- max_h = 4.5
- for i, (lbl, v, c) in enumerate(zip(bar_labels, bar_vals, bar_colors)):
- bx = bx_start + i * (bar_w + gap)
- ax.add_patch(
- Rectangle(
- (bx, base_y),
- bar_w,
- v * max_h,
- facecolor=c,
- edgecolor="none",
- zorder=4,
- )
- )
- ax.text(
- bx + bar_w / 2,
- base_y - 0.7,
- lbl,
- ha="center",
- va="top",
- fontsize=10,
- color=MUTED,
- zorder=4,
- )
- ax.text(
- bx + bar_w / 2,
- base_y + v * max_h + 0.3,
- f"{int(v * 100)}",
- ha="center",
- va="bottom",
- fontsize=9.5,
- color=TEXT,
- zorder=4,
- )
-
- # Section 4: Remediation Guidance (right side, next to chart)
- ax.text(
- left + 24,
- sec_y3,
- "4. Remediation Guidance",
- ha="left",
- va="center",
- fontsize=14,
- fontweight="bold",
- color=PURPLE,
- zorder=4,
- )
- for i, line in enumerate(
- [
- "- Expand human-in-loop for low-confidence replies",
- "- Add adversarial test set for robustness",
- "- Document data-source provenance",
- ]
- ):
- ax.text(
- left + 24,
- sec_y3 - 2 - i * 1.6,
- line,
- ha="left",
- va="center",
- fontsize=11,
- color=TEXT,
- zorder=4,
- )
-
- # Footer band
- foot_y = page_y - page_h / 2
- ax.add_patch(
- Rectangle(
- (page_x - page_w / 2, foot_y),
- page_w,
- 2.0,
- facecolor=LIGHTER_BG,
- edgecolor="none",
- zorder=3,
- )
- )
- ax.text(
- page_x,
- foot_y + 1.0,
- "Generated by AICertify v0.7.0 | Apache 2.0 | reproducible from contract.json",
- ha="center",
- va="center",
- fontsize=10.5,
- color=MUTED,
- zorder=4,
- )
-
- save_fig(fig, "diagram5_report_anatomy.png")
-
-
-# ---------- entrypoint ----------
-def main():
- print(f"Generating diagrams into {HERE}")
- diagram1_hero_flow()
- diagram2_architecture()
- diagram3_regulatory_coverage()
- diagram4_comparison()
- diagram5_report_anatomy()
- print("done.")
-
-
-if __name__ == "__main__":
- main()
diff --git a/diagrams/hero_banner_dark.svg b/diagrams/hero_banner_dark.svg
new file mode 100644
index 0000000..ffbcae4
--- /dev/null
+++ b/diagrams/hero_banner_dark.svg
@@ -0,0 +1,23 @@
+
+
+AICertify
+AICertify hero banner with logo, wordmark, tagline, and framework badges.
+
+
+AICertify
+Compliance-as-code for AI systems
+One contract. One command. Audit-ready reports.
+
+
+
+EU AI Act
+
+
+
+NIST AI RMF
+
+
+
+ICAO Doc 10019
+
+
diff --git a/diagrams/hero_banner_light.svg b/diagrams/hero_banner_light.svg
new file mode 100644
index 0000000..4d694b2
--- /dev/null
+++ b/diagrams/hero_banner_light.svg
@@ -0,0 +1,23 @@
+
+
+AICertify
+AICertify hero banner with logo, wordmark, tagline, and framework badges.
+
+
+AICertify
+Compliance-as-code for AI systems
+One contract. One command. Audit-ready reports.
+
+
+
+EU AI Act
+
+
+
+NIST AI RMF
+
+
+
+ICAO Doc 10019
+
+
diff --git a/diagrams/logo_dark.svg b/diagrams/logo_dark.svg
new file mode 100644
index 0000000..5fed7c6
--- /dev/null
+++ b/diagrams/logo_dark.svg
@@ -0,0 +1,7 @@
+
+
+AICertify
+AICertify mark — flat-top hexagon with a checkmark.
+
+
+
diff --git a/diagrams/logo_light.svg b/diagrams/logo_light.svg
new file mode 100644
index 0000000..4c208ee
--- /dev/null
+++ b/diagrams/logo_light.svg
@@ -0,0 +1,7 @@
+
+
+AICertify
+AICertify mark — flat-top hexagon with a checkmark.
+
+
+
diff --git a/diagrams/og_card.png b/diagrams/og_card.png
new file mode 100644
index 0000000..b8cb9a3
Binary files /dev/null and b/diagrams/og_card.png differ
diff --git a/diagrams/og_card_dark.svg b/diagrams/og_card_dark.svg
new file mode 100644
index 0000000..6fb331f
--- /dev/null
+++ b/diagrams/og_card_dark.svg
@@ -0,0 +1,38 @@
+
+
+AICertify — Compliance-as-code for AI systems
+AICertify social card with logo, wordmark, tagline, framework chips, and project URL.
+
+
+
+
+
+
+
+
+AICertify
+
+Compliance-as-code for AI systems
+One contract · One command · Audit-ready reports
+
+
+
+EU AI Act
+
+
+
+NIST AI RMF
+
+
+
+ICAO Doc 10019
+
+
+
++13 more
+
+
+
+github.com/Principled-Evolution/aicertify
+94 Rego policies · Apache 2.0
+
diff --git a/diagrams/og_card_light.svg b/diagrams/og_card_light.svg
new file mode 100644
index 0000000..2c41bb8
--- /dev/null
+++ b/diagrams/og_card_light.svg
@@ -0,0 +1,38 @@
+
+
+AICertify — Compliance-as-code for AI systems
+AICertify social card with logo, wordmark, tagline, framework chips, and project URL.
+
+
+
+
+
+
+
+
+AICertify
+
+Compliance-as-code for AI systems
+One contract · One command · Audit-ready reports
+
+
+
+EU AI Act
+
+
+
+NIST AI RMF
+
+
+
+ICAO Doc 10019
+
+
+
++13 more
+
+
+
+github.com/Principled-Evolution/aicertify
+94 Rego policies · Apache 2.0
+