{"id":51025385,"url":"https://github.com/edycutjong/quorum","last_synced_at":"2026-06-21T19:01:57.927Z","repository":{"id":364286434,"uuid":"1259559006","full_name":"edycutjong/quorum","owner":"edycutjong","description":"🏛️ Offline multi-agent document council — 3 AI agents debate your documents to a cited answer. The visible disagreement IS the trust mechanism. Built for QVAC Edge AI Hackathon.","archived":false,"fork":false,"pushed_at":"2026-06-12T11:20:47.000Z","size":264,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-12T13:12:08.547Z","etag":null,"topics":["edge-ai","hackathon","local-llm","multi-agent","offline-ai","qvac-sdk","rag","react","typescript","vite"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/edycutjong.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-04T16:17:59.000Z","updated_at":"2026-06-12T11:20:51.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/edycutjong/quorum","commit_stats":null,"previous_names":["edycutjong/quorum"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/edycutjong/quorum","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fquorum","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fquorum/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fquorum/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fquorum/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/edycutjong","download_url":"https://codeload.github.com/edycutjong/quorum/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edycutjong%2Fquorum/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34622271,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-21T02:00:05.568Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["edge-ai","hackathon","local-llm","multi-agent","offline-ai","qvac-sdk","rag","react","typescript","vite"],"created_at":"2026-06-21T19:01:52.183Z","updated_at":"2026-06-21T19:01:57.918Z","avatar_url":"https://github.com/edycutjong.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## 🧑‍⚖️ For Judges — Review in 5 Steps\n\n\u003e Offline multi-agent document council on `@qvac/sdk`. **Zero cloud — verifiable.**\n\n1. **▶ Watch the 3-min demo** (network off on camera): https://youtu.be/tnVqrbXNMco\n2. **Run it locally** (first launch downloads models ~2 GB):\n   ```bash\n   npm install\n   npm run start          # backend :3001 + web app :5173  (keep running)\n   make seed              # 2nd terminal — ingest the dossier (curl -X POST :3001/api/seed)\n   # open http://localhost:5173  →  status pill reads \"LIVE · QVAC\"\n   ```\n3. **Ask the demo query:** *“Who authorized the Entity X payment and was it legitimate?”* → watch the **Researcher → Skeptic → Synthesizer** debate stream in. The Skeptic catches the planted contradiction (VP Chen \"authorized\" a payment while on PTO); the Synthesizer returns a **cited, disputed verdict with lowered confidence**.\n4. **Verify the claims:**\n   - 🔒 **No remote APIs** — zero cloud calls: [`docs/REMOTE_APIS.md`](docs/REMOTE_APIS.md)\n   - 📋 **Structured audit log** — model loads/unloads + per-inference TTFT / tokens / tokens-per-sec: [`docs/AUDIT_LOG.md`](docs/AUDIT_LOG.md) → real run in [`docs/audit-log.jsonl`](docs/audit-log.jsonl)\n   - `python3 scripts/verify_offline.py` — **0 outbound** (disconnect network first) · 18/18 checks\n   - `npm run bench` — real on-device latency + contradiction recall → [`data/bench_results.json`](data/bench_results.json) (p50 ≈ **2.1 s**, peak RAM ≈ **180 MB**, citation coverage **1.0**)\n   - `npm run ci` — **163 unit tests, 100% core coverage** + lint + typecheck\n5. **Why only QVAC / no remote APIs** ([`docs/REMOTE_APIS.md`](docs/REMOTE_APIS.md)): all inference is local (Llama 3.2 1B + GTE-Large via `@qvac/sdk`). See [Why ONLY QVAC?](#-why-only-qvac) — remove QVAC and you'd need a cloud LLM + hosted vector DB, and the confidentiality premise is gone.\n\n---\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"docs/icon.svg\" alt=\"Quorum\" width=\"120\" height=\"120\"\u003e\n\n  \u003ch1\u003eQuorum 🏛️\u003c/h1\u003e\n  \u003cp\u003e\u003cem\u003eOffline multi-agent document council — 3 AI agents debate your documents to a cited answer. The visible disagreement IS the trust mechanism.\u003c/em\u003e\u003c/p\u003e\n  \u003cimg src=\"docs/readme-hero.svg\" alt=\"Quorum\" width=\"100%\"\u003e\n\n  \u003cbr/\u003e\n\n  [![Watch the Demo](https://img.shields.io/badge/Watch_Demo-YouTube-FF0000?style=for-the-badge\u0026logo=youtube\u0026logoColor=white)](https://youtu.be/tnVqrbXNMco)\n  [![Built for QVAC Hackathon](https://img.shields.io/badge/DoraHacks-QVAC%20Edge%20AI-8b5cf6?style=for-the-badge)](https://dorahacks.io/hackathon/qvac-unleach-edge-ai-i/detail)\n  [![Track](https://img.shields.io/badge/Track-General%20Purpose-06b6d4?style=for-the-badge)](https://dorahacks.io/hackathon/qvac-unleach-edge-ai-i/tracks)\n\n  \u003cbr/\u003e\n\n  ![Vite](https://img.shields.io/badge/Vite_8-646CFF?style=flat\u0026logo=vite\u0026logoColor=white)\n  ![React](https://img.shields.io/badge/React_19-61DAFB?style=flat\u0026logo=react\u0026logoColor=black)\n  ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=flat\u0026logo=typescript\u0026logoColor=white)\n  ![QVAC](https://img.shields.io/badge/@qvac/sdk-06b6d4?style=flat)\n  [![CI](https://github.com/edycutjong/quorum/actions/workflows/ci.yml/badge.svg)](https://github.com/edycutjong/quorum/actions/workflows/ci.yml)\n\n\u003c/div\u003e\n\n---\n\n## 💡 The Problem \u0026 Solution\n\nWhen analyzing confidential documents — legal dossiers, financial audits, HR records — you can't upload them to cloud AI. But a single LLM will just parrot the first document it reads, missing contradictions.\n\n**Quorum** solves this with a **3-agent council** that cross-examines your corpus entirely offline:\n\n**Key Features:**\n- 🔍 **Researcher** — Retrieves relevant documents, proposes initial answer with citations\n- ⚡ **Skeptic** — Counter-retrieves to challenge claims, finds planted contradictions\n- 🧩 **Synthesizer** — Reconciles viewpoints, assigns HIGH/MEDIUM/LOW confidence\n- 📚 **Every claim cited** — Source chunk mapped to exact document\n- 🔴 **Contradiction detection** — Skeptic catches what a single LLM would miss\n\n## 🎥 See It In Action\n\n*Real local inference — the network is off the entire time (note the **`● LIVE · QVAC`** pill).*\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/user-attachments/assets/93573b63-54e9-419e-99b4-42141032077b\" alt=\"Quorum interface — 100% offline, LIVE · QVAC\" width=\"80%\"\u003e\n\u003c/p\u003e\n\n**The contradiction catch.** Ask *\"Who authorized the Entity X payment and was it legitimate?\"* — a naive RAG repeats the memo (*\"VP Chen, March 12\"*), but Quorum's Skeptic re-queries and surfaces the conflicting HR access logs and board minutes, so the Synthesizer returns a **cited, disputed verdict with lowered confidence**:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/user-attachments/assets/3baae085-429d-4ef7-aefe-56aafb3a1955\" alt=\"Quorum's council catches a planted contradiction, fully offline\" width=\"100%\"\u003e\n\u003c/p\u003e\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd width=\"50%\" align=\"center\"\u003e\u003cimg src=\"https://github.com/user-attachments/assets/7b847d84-32a9-4e62-a57e-4a67d74e0b58\" alt=\"Every claim maps to an exact source chunk\" width=\"100%\"\u003e\u003c/td\u003e\n    \u003ctd width=\"50%\" align=\"center\"\u003e\u003cimg src=\"https://github.com/user-attachments/assets/d180e411-642e-4877-a941-c97f7e56b634\" alt=\"A second debate — governance Section 4.2 compliance\" width=\"100%\"\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003cem\u003e📚 Every claim maps to an exact source chunk\u003c/em\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003cem\u003e⚖️ A second debate — governance §4.2 compliance\u003c/em\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## 🏗️ Architecture \u0026 Tech Stack\n\n```mermaid\nflowchart LR\n    Q[\"🗣️ User Query\"] --\u003e R[\"🔍 Researcher\"]\n    R --\u003e S[\"⚡ Skeptic\"]\n    S --\u003e Y[\"🧩 Synthesizer\"]\n    Y --\u003e A[\"📋 Cited Answer\"]\n\n    R -.- R1[\"RAG retrieve\\n+ propose\"]\n    S -.- S1[\"Counter-retrieve\\n+ challenge\"]\n    Y -.- Y1[\"Reconcile\\n+ confidence\"]\n\n    style Q fill:#1e293b,stroke:#06b6d4,color:#f1f5f9\n    style R fill:#0e2a30,stroke:#06b6d4,color:#06b6d4\n    style S fill:#2a1f0e,stroke:#f59e0b,color:#f59e0b\n    style Y fill:#0e2a14,stroke:#22c55e,color:#22c55e\n    style A fill:#1e293b,stroke:#06b6d4,color:#f1f5f9\n    style R1 fill:none,stroke:#06b6d4,color:#94a3b8,stroke-dasharray:4\n    style S1 fill:none,stroke:#f59e0b,color:#94a3b8,stroke-dasharray:4\n    style Y1 fill:none,stroke:#22c55e,color:#94a3b8,stroke-dasharray:4\n```\n\n| Layer | Technology |\n|---|---|\n| **Frontend** | Vite 8, React 19, TypeScript |\n| **AI Engine** | @qvac/sdk (completion, RAG) |\n| **Embeddings** | GTE-Large-FP16 via @qvac/sdk |\n| **LLM** | Llama 3.2 1B (local) |\n\n## 🏆 Why ONLY QVAC?\n\n| QVAC SDK Method | Quorum Usage | Cloud Alternative You'd Need |\n|---|---|---|\n| `loadModel()` + `completion()` | Runs all 3 agents (Researcher, Skeptic, Synthesizer) | OpenAI API ($0.03/query × 3 agents) |\n| `ragIngest()` + `ragSearch()` | Embeds \u0026 searches private dossier locally | Pinecone + OpenAI Embeddings API |\n| `loadModel(GTE_LARGE_FP16)` | 1024-dim embeddings for citation matching | Cohere Embed API |\n| `unloadModel()` | Memory lifecycle — load once, 3 agents, unload | N/A (cloud doesn't care) |\n\n**Take QVAC out and you'd need 3 separate cloud services** (OpenAI + Pinecone + Cohere), a network connection, and your confidential documents would leave your machine.\n\n## 📋 Dossier — Planted Contradictions\n\nThe demo includes a 5-document **Northwind dossier** with deliberate contradictions:\n\n| Document | Claims | Contradiction |\n|---|---|---|\n| `memo_ref_4821.txt` | VP Chen authorized $2.4M payment March 12 | Chen was on PTO |\n| `board_minutes_march.txt` | Chen PTO March 11-15, no Entity X discussion | Memo claims March 12 |\n| `q1_financial_report.txt` | Audit flags: no SOW, no deliverables | Payment processed |\n| `hr_access_logs.txt` | No badge/VPN access March 12 | Memo timestamped March 12 |\n| `governance_charter.txt` | \u003e$1M needs board resolution | No board approval |\n\n## 🚀 Getting Started\n\n```bash\ngit clone https://github.com/edycutjong/quorum.git\ncd quorum\nnpm install\nnpm run start          # backend (:3001) + web app (:5173) — keep this running (make start)\n\n# then, in a SECOND terminal, ingest the dossier into the running backend:\ncurl -X POST http://localhost:3001/api/seed        # or: make seed\n# open http://localhost:5173 — status pill should read \"LIVE · QVAC\"\n```\n\n\u003e First launch downloads the local models. The status pill reads **DEMO · OFFLINE**\n\u003e until the backend is reachable; once it's up and seeded it switches to **LIVE · QVAC**.\n\n\u003e **Devastating Demo Query:** \"Who authorized the Entity X payment and was it legitimate?\"\n\n## 📊 Benchmarks\n\nRun `npm run bench` to reproduce. This runs the **real** 3-agent council over the\ndossier via `@qvac/sdk` and writes `data/bench_results.json` (latency, contradiction\nrecall, citation coverage). Use `npm run bench -- --assert` to fail on budget regressions.\n\nRepresentative run on an **Apple M1 Max (32 GB)** — reproduce with `npm run bench`:\n\n| Metric | Measured | Budget |\n|---|---|---|\n| Full Council Round (p50 / p95) | ~2.5s / ~2.7s | \u003c15,000ms |\n| Model Load (cold) | ~1.2s | \u003c10,000ms |\n| Corpus Ingest (5 docs → 9 chunks) | ~1.8s | — |\n| Citation coverage | 1.0 | ≥0.95 |\n| Contradiction recall (planted set) | 0.67–1.0¹ | 1.0 |\n| Peak RAM | ~196 MB | \u003c4,096MB |\n\n\u003e ¹ Recall varies run-to-run: the Skeptic reliably retrieves the conflicting\n\u003e documents, but Llama-3.2-1B is non-deterministic and doesn't always phrase an\n\u003e explicit objection — an honest limitation of a 1B model on-device. `npm run bench`\n\u003e records real measurements from your hardware into `data/bench_results.json`.\n\u003e (The legacy `scripts/bench.py` is a deterministic simulation kept only as a CI smoke test.)\n\n## 🧪 Testing \u0026 CI\n\n**171 tests · 100% core coverage:** 163 unit tests (Vitest) covering RAG citation mapping \u0026 chunking, agent orchestration, contradiction-driven confidence, the audit log, and the offline SDK wrappers, plus 8 E2E specs (Playwright) — backed by 18 offline-verification checks (`verify_offline.py`).\n\n## 🔍 Verification \u0026 Compliance\n\nEverything the judges' verification asks for, as concrete artifacts:\n\n| Gate | Where | How to reproduce |\n|---|---|---|\n| **No remote APIs** — zero cloud calls | [`docs/REMOTE_APIS.md`](docs/REMOTE_APIS.md) | `python3 scripts/verify_offline.py` (scans for banned cloud SDKs; 18/18) |\n| **Structured audit log** — model loads/unloads + inference perf (prompt, tokens, TTFT, tokens/sec) | [`docs/AUDIT_LOG.md`](docs/AUDIT_LOG.md) → [`docs/audit-log.jsonl`](docs/audit-log.jsonl) | on by default; `npm run start` + a query writes it |\n| **Offline proof** — 0 outbound connections | `scripts/verify_offline.py` | disconnect network, then run |\n| **Real on-device benchmarks** — latency, recall, RAM | [`data/bench_results.json`](data/bench_results.json) | `npm run bench` |\n\n**7-stage pipeline:** Quality → Security → Build → E2E → Performance → Offline → Deploy\n\n```bash\n# ── Code Quality ────────────────────────────\nnpm run lint           # ESLint\nnpm run typecheck      # TypeScript check\nnpm run ci             # Full quality gate\n\n# ── E2E \u0026 Performance ──────────────────────\nnpm run e2e            # Playwright E2E (3 suites)\nnpm run lighthouse     # Lighthouse CI audit\n\n# ── Evidence Bundle ─────────────────────────\npython3 scripts/verify_offline.py     # airgapped run — disconnect network first\nnpm run bench                         # real council latency + contradiction recall\npython3 scripts/check_submission_readiness.py\n```\n\n| Layer | Tool | Status |\n|---|---|---|\n| Code Quality | ESLint + TypeScript | ✅ |\n| E2E Testing | Playwright (3 suites) | ✅ |\n| Security (SAST) | CodeQL | ✅ |\n| Security (SCA) | Dependabot + npm audit | ✅ |\n| Secret Scanning | TruffleHog | ✅ |\n| Performance | Lighthouse CI | ✅ |\n| Offline Verification | verify_offline.py (18/18) | ✅ |\n\n## 📁 Project Structure\n```\nquorum/\n├── docs/                   # README assets\n├── data/fixtures/\n│   └── northwind_dossier/  # 5 docs with planted contradictions\n├── e2e/                    # Playwright E2E tests\n├── scripts/                # seed, bench, verify, readiness\n├── src/\n│   ├── core/\n│   │   ├── qvac.ts         # @qvac/sdk wrapper\n│   │   ├── rag.ts          # Corpus RAG pipeline\n│   │   └── council.ts      # 3-agent council orchestration\n│   ├── App.tsx             # Debate transcript viewer\n│   └── App.css             # Dark mode theme\n├── .github/                # CI/CD + CodeQL + Dependabot\n├── playwright.config.ts\n├── lighthouserc.json\n└── README.md\n```\n\n## ⚠️ Honest Limitations\n\n1. Small model — limited reasoning depth vs cloud LLMs\n2. Sequential agents — no true parallel debate\n3. English only\n4. Fixed dossier — no live document upload yet\n5. Mock inference in demo mode\n\n## 📄 License\n[MIT](LICENSE) © 2026 Edy Cu\n\n## 🙏 Acknowledgments\nBuilt for **QVAC Hackathon I — Unleash Edge AI** (DoraHacks). Thank you to the QVAC team for making multi-agent AI possible on the edge.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedycutjong%2Fquorum","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedycutjong%2Fquorum","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedycutjong%2Fquorum/lists"}