{"id":31536575,"url":"https://github.com/radical-data/supermind","last_synced_at":"2025-10-04T07:46:20.551Z","repository":{"id":317410385,"uuid":"1066714409","full_name":"radical-data/supermind","owner":"radical-data","description":null,"archived":false,"fork":false,"pushed_at":"2025-09-30T17:35:34.000Z","size":110,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-30T18:31:29.559Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/radical-data.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-29T21:24:52.000Z","updated_at":"2025-09-30T17:35:37.000Z","dependencies_parsed_at":"2025-09-30T18:31:39.931Z","dependency_job_id":null,"html_url":"https://github.com/radical-data/supermind","commit_stats":null,"previous_names":["radical-data/supermind"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/radical-data/supermind","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radical-data%2Fsupermind","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radical-data%2Fsupermind/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radical-data%2Fsupermind/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radical-data%2Fsupermind/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/radical-data","download_url":"https://codeload.github.com/radical-data/supermind/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radical-data%2Fsupermind/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278283493,"owners_count":25961310,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-04T02:00:05.491Z","response_time":63,"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":[],"created_at":"2025-10-04T07:46:19.348Z","updated_at":"2025-10-04T07:46:20.542Z","avatar_url":"https://github.com/radical-data.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Supermind\n\n**Purpose:** a 20-minute, in-room exercise where **30 people** submit one short line each, watch a **live \"brain\"** form on screen, and see an **AI summary** of themes, tensions, and outliers. Optional: show each person a **most-similar match** to spark conversations later.\n\nAI is the **facilitator/connector**, not a replacement.\n\n## TL;DR\n\n- **Participants (phones):** scan QR → pick table (A/B) → **submit one short line**.\n- **Big screen:** the **graph** grows live; then a **summary** appears (themes, contradictions, outliers).\n- **Optional:** each phone shows a **suggested match** across tables.\n\nTime budget (suggested): **Join 1’ • Submit 2’ • Watch graph 1’ • Summary 1’ • (Optional) Match 1’**.\n\n## Architecture\n\n- **SvelteKit (Node adapter)** — single runtime (no Docker, no Python), easy on hotel Wi‑Fi.\n- **SQLite + Drizzle** — local, fast, WAL-enabled.\n- **SSE (Server-Sent Events)** — push `graph` + `summary` (and `matches`) to clients.\n- **LLM** — one JSON-only call for summary; **embeddings** for links \u0026 matching.\n\n```\nphones → /api/join + /api/submit ─┐\n                                  ├─ DB (SQLite) → build embeddings → broadcast via SSE → visualiser\nfacilitator → /api/summary ───────┘\n```\n\n## Data model (Drizzle / SQLite)\n\n- **participants**: `id`, `name`, `tableSide` ('A'|'B'), `createdAt`\n- **runs**: `id`, `createdAt`, `clustersJson?`, `optionsJson?`, `pairsJson?`\n- **submissions**: `id`, `runId`, `participantId`, `kind` (default `'triad'`), `payloadJson`, `createdAt`  \n  _Unique_: (`runId`,`participantId`,`kind`)\n- **normalised**: `submissionId` (PK), `dataJson`, `embeddingJson?`\n\n\u003e For the sprint we only need **participants**, **submissions**, **normalised** (with `embeddingJson`). **runs** is used to keep sessions separate.\n\n## HTTP \u0026 SSE interface\n\n**Already in repo (MVP):**\n\n- `POST /api/join` → `{ participantId }`\n- `POST /api/submit` → stores submission, normalises, (now) embeds, then broadcasts counts/graph\n- `GET  /api/stream` (SSE) → emits:\n  - `event: submission_count` → `{ count }`\n  - `event: graph` → `{ nodes:[{id,label,table}], links:[{source,target,value}] }`\n  - (later) `event: summary`, `event: matches`\n- `POST /api/vote` + `GET /api/vote/medians` (optional, unused in this sprint)\n\n**To add (short tasks):**\n\n- `POST /api/summary` → runs one LLM call across all submissions → broadcasts `summary`\n- `POST /api/match` (optional) → cross-table nearest-neighbour pairs → broadcasts `matches`\n\n## LLM contracts (strict JSON)\n\n### 1) **Summary** (one call per exercise)\n\nInput (server assembles):\n\n```json\n[\n\t{ \"id\": 12, \"text\": \"...\" },\n\t{ \"id\": 7, \"text\": \"...\" }\n]\n```\n\nSystem prompt (essence):\n\n\u003e Cluster 30 short lines about \"AI \u0026 logistics\" into **3–6 themes**, list **clear contradictions** and **1–2 outliers**. **Return ONLY valid JSON**:\n\n```json\n{\n  \"themes\":[{\"label\":\"...\", \"why\":\"...\", \"members\":[12,7, ...]}],\n  \"contradictions\":[{\"a\":12, \"b\":7, \"explain\":\"...\"}],\n  \"outliers\":[{\"participantId\":3, \"explain\":\"...\"}],\n  \"stats\":{\"count\":30}\n}\n```\n\nOn parse failure: **retry once**, then **fallback** to heuristic (k-means on embeddings for themes; farthest points for outliers).\n\n### 2) **Matching** (no LLM)\n\n- Use **cosine similarity** on embeddings.\n- Prefer **A↔B** matches (cross-table).\n- Greedy pairing; allow \"no match\" if below threshold.\n\n## Visuals\n\n- **Graph:** `force-graph` (2D). Nodes coloured by table. Links when `cosine \u003e= threshold` (start ~**0.78**, tune live). Limit each node to **top-3** links to avoid hairballs.\n- **Summary view:** Right panel lists **themes** and **tensions**. (Nice-to-have: draw soft hulls around theme members.)\n\n## Local development\n\n### Prereqs\n\n- Node **≥ 20**\n- SQLite (bundled with better-sqlite3)\n- An LLM key (for summary + embeddings) — e.g. `OPENAI_API_KEY`\n\n### Environment\n\n```\ncp .env.example .env\n# edit:\nDATABASE_URL=/data/app.db           # or ./local.db\nLLM_API_KEY=sk-...\n```\n\n### Install \u0026 DB\n\n```bash\nnpm install\nnpm run db:push\nnpm run dev\n```\n\nOpen:\n\n- **Participants**: `http://localhost:5173/join`\n- **Facilitator**: `http://localhost:5173/visualiser` and `http://localhost:5173/control`\n\n## Event-day playbook (Hotel Arena, 2 long tables)\n\n### Pre-event checklist (10 mins)\n\n- ✅ Laptop on mains power; **Do Not Sleep**.\n- ✅ Local network stable (hotspot fallback ready).\n- ✅ `.env` set; app running (`npm run dev` or `node build`).\n- ✅ Big screen on **/visualiser**.\n- ✅ Print two QR codes:\n  - Table A → `/join?table=A`\n  - Table B → `/join?table=B`\n- ✅ Threshold set (start **0.78**); test with 3 dummy submissions.\n\n### Live run (6–8 mins exercise)\n\n1. **Join (1 min)**  \n   \"Scan the QR, type your **first name**, select **your table**.\"\n2. **Submit (2 mins)**  \n   Prompt on screen:\n   \u003e \"In one short line, share a **fact, fear, or hope** about AI in logistics.\"\n3. **Graph (1 min)**  \n   Narrate what they see: similar ideas linking, two tables mixing.\n4. **Summary (1–2 mins)**  \n   Tap **Summarise** on `/control`. Read out **3–6 themes**, **key tension(s)**, **1–2 outliers**.\n5. **(Optional) Match (1 min)**  \n   Tap **Match** on `/control`. Each phone shows a cross-table match. Invite them to connect after dessert.\n\n### Fail-safes\n\n- If LLM is slow: continue speaking over the **live graph**; trigger summary once.\n- If SSE drops: refresh the visualiser; clients keep submitting (HTTP still works).\n- If Wi‑Fi fails: use your phone’s hotspot (no external internet needed if embeddings are pre-enabled or stubbed).\n\n## Operator pages\n\n- `/visualiser` — big screen.\n- `/control` — buttons: **Show Graph** (default), **Summarise**, **Show Matches** (optional).\n- `/join` — phone page (query param `?table=A|B` preselects side).\n- `/input` — phone submission page (1 text field).\n- `/vote` — **not used** for this sprint (kept for future A/B).\n\n## Configuration knobs\n\n- **SIM_THRESHOLD** (cosine) — start `0.78`, adjust to control density.\n- **TOP_K_LINKS** per node — start `3`.\n- **MAX_INPUT_LEN** — 120 chars (guard rail).\n- **RUN_RESET** — optional `/api/admin/reset` if you want to wipe mid-rehearsal.\n\n## Privacy\n\n- Store **first name** and one **short line**.\n- No emails, no phone numbers.\n- Data is **ephemeral**; a JSON dump is kept locally for post-event notes. Delete after.\n\n## Roadmap\n\n- [x] Join / Submit\n- [x] SSE bus\n- [x] Graph from embeddings\n- [ ] `/api/summary` (LLM JSON + heuristic fallback)\n- [ ] `/api/match` (cross-table)\n- [ ] Visualiser: summary panel + (optional) hulls\n- [ ] Control page buttons\n- [ ] QR param preselect (`?table=A|B`)\n- [ ] JSON data dump on exit\n\n## Definition of done (for the event)\n\n- Participants can **join**, **submit** a line, and see the **graph** react live.\n- Facilitator can press **Summarise** and a **valid JSON** summary is shown on screen within ~10s.\n- (Optional) Everyone sees a **cross-table match** on their phone.\n- The whole flow runs on a **single laptop** with flaky hotel Wi‑Fi.\n\n## Licence\n\nPrivate, event use. © You.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fradical-data%2Fsupermind","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fradical-data%2Fsupermind","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fradical-data%2Fsupermind/lists"}