From a single source of truth to a published, navigable knowledge graph — and a three-phase contribution loop that lets anyone add content, with human review at every gate.
Source builds the graph; the graph powers the site; people read it and contribute back; you approve; the agent promotes — and it's live again. One closed loop.
DBA KNOWLEDGE BASE — ARCHITECTURE & INFORMATION FLOW (all phases LIVE)
LEGEND: [LIVE] [FUTURE] ──► data flow ═╌► deliberate human gate
╔══════════════════════════════════════════════════════════════════════════════════╗
║ 1 · SOURCE OF TRUTH git repo bundle/*.md [LIVE] ║
║ 6 courses · 74 sessions · 23 concepts · 4 references · 11 assignments = 118 nodes ║
║ each node = Markdown + YAML front-matter, cross-linked by relative .md paths ║
╚════════════════════════════════════════╤═══════════════════════════════════════════╝
│ tools/build_bundle.py (md → parse → edges)
▼
┌───────────────────────────────┐
│ bundle.json {nodes, edges, │ [LIVE] 118 nodes / 1,121 edges
│ bodies, types, palette} │
└──────┬─────────────────┬──────┘
tools/gen_viz_v2 │ │ copied → docs/kb-data.json
▼ ▼
╔══════════════════════════════════════════════════════════════════════════════════╗
║ 2 · PUBLISHED SITE GitHub Pages (static, served from docs/) [LIVE] ║
║ index.html · map.html (Cytoscape graph) · okf-explained · vision ║
║ ask.html ──► kb-tools.js (8 read-only tools) ──► tutor backends: ║
║ search·node·related·outline·concept·rubric·path·cite ║
║ 1. BYO Gemini key → 2. on-device Nano → 3. keyword search ║
║ contribute.html ──► the intake form (dedup · size · PII · honeypot) ║
╚════════════════════════════════════════╤═══════════════════════════════════════════╝
│
════════════════ CONTRIBUTION → REVIEW → PROMOTE LOOP ════════════════
│
CONTRIBUTOR fills contribute.html ▼
│
├──── PHASE 1 ───────────────────────────────────────────────────── [LIVE]
│ pre-filled GitHub issue ═╌► signs in, clicks Submit
│ └─► PUBLIC repo issue (labels: contribution, needs-review)
│
└──── PHASE 2 · account-free ────────────────────────────────────── [LIVE]
Turnstile CAPTCHA
│ POST (JSON + file as base64)
▼
Cloudflare Worker dba-kb-contrib.dba-kb.workers.dev
fail-closed captcha · per-IP rate-limit · validate · sanitize
│ one scoped token (cannot touch main)
▼
PRIVATE inbox repo dba-kb-contrib-inbox
· issue (review queue) · raw file → inbox/<refid>/<file>
· returns reference ID (nothing public yet)
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ REVIEW GATE you read the inbox issue + file ═╌► [LIVE] │
│ approve (run the agent) · reject (close the issue) │
└───────────────────────────────┬─────────────────────────────────────────┘
│ approve
▼
┌──── PHASE 3 · promotion agent ── tools/promote.py ────────── [LIVE] ──┐
│ fetch issue+file ─► catalogue of 118 node ids ─► Gemini 3.5-flash │
│ (PDF inline/multimodal) ─► STRICT JSON {title,desc,tags,body,related} │
│ ─► validate (links ⊆ catalogue, never invent) ─► synthesise (not copy) │
│ ─► write bundle/<dir>/<slug>.md ─► rebuild (+1-node assertion) │
│ ─► branch + PR on the public repo │
└───────────────────────────────┬─────────────────────────────────────────┘
│ PR
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ MERGE GATE you review the PR's .md node, click Merge ═╌► [LIVE] │
└───────────────────────────────┬─────────────────────────────────────────┘
│ merge
▼
back to ① SOURCE → Pages rebuilds → live in map + tutor
(loop closed — contributor credited by name)
[FUTURE] optional GitHub Action: trigger promote.py on an `approved` label →
unattended drafting (you'd still merge the PR). Build only when volume justifies.
Every phase is built, deployed, and verified. The only deferred item is unattended automation — deliberately, until contribution volume justifies it.
| Stage | Status | What it is |
|---|---|---|
| Source → build → site | LIVE | bundle/*.md → build_bundle.py → bundle.json → gen_viz_v2.py → map.html, served on GitHub Pages. |
| Ask the KB (tutor) | LIVE | 8 read-only tools in kb-tools.js; backends fall back BYO-key → on-device → keyword search. |
| Phase 1 — issue submission | LIVE | The form pre-fills a GitHub issue on the public repo. Needs a GitHub login. |
| Phase 2 — account-free proxy | LIVE | Turnstile → Cloudflare Worker → private inbox repo (issue + raw file). No login; nothing public until approved. |
| Phase 3 — promotion agent | LIVE | tools/promote.py synthesises an approved submission into an OKF node (Gemini 3.5-flash) and opens a PR. |
| Unattended automation | FUTURE | An optional GitHub Action to run the agent on an approved label — you'd still merge the PR. |
Everything between these is automated. The gates are deliberate — content is published only when a person decides.
You read the inbox issue and its file in the private repo. Approve by running the promotion agent; reject by closing the issue. Nothing reaches the public KB at this stage.
The agent drafts a PR with the synthesised node (regenerated artifacts collapsed in the diff). You review the Markdown node and merge — the merge is what publishes. Pages rebuilds and it's live.
Five moving parts, each with a single responsibility.
OKF Markdown in bundle/ → graph JSON via build_bundle.py; the map via gen_viz_v2.py.
Static GitHub Pages — home, knowledge map, the AI tutor, and the contribution form.
A Cloudflare Worker behind Turnstile that records submissions into a private inbox using one scoped token.
A separate private repo holding the review queue (issues) and raw uploads under inbox/<refid>/.
tools/promote.py — synthesises approved content into a cross-linked node and opens a PR for approval.