Forum / Q&A — implementation & runbook
Design rationale lives in ../FORUM_PROPOSAL_2026-06.md. This file is the operator runbook.
What shipped
Backend (worker):
migrations/0034_forum.sql— questions, answers, votes, tags, reports, AI approval outbox, and the disclosedcinevva-assistantuser.src/db/forum.ts—ForumDBdata access.src/forum/index.ts— request handlers (list, detail, ask, answer, vote, accept, report, admin AI-draft queue).src/forum-ai.ts— AI responder: drafts answers into the approval outbox and posts approved drafts as the Cinevva Assistant. Wired into the 2-minute cron insrc/index.ts.- Routes mounted under
/forum/*insrc/index.ts(reuse session auth, admin gate, chat moderation + cost logging).
Frontend (site):
../.vitepress/components/ForumPage.vue— live list + detail + ask/answer/vote UI.../forum.md— mounts the component at/forum; nav link added under "Learn".
Content + SEO:
scripts/forum-seed.mjs— generatesscripts/forum-seed.sql: curated, anonymized real Q&As (source='seed', published).../scripts/build-forum-pages.mjs— pre-renders answered questions to crawlableforum/q/<slug>.mdwith JSON-LD QAPage. This is the SEO asset (runtime-fetched content is not indexable).
Deploy
# 1. Apply the schema (remote D1)
cd worker
npx wrangler d1 execute <DB_NAME> --remote --file migrations/0034_forum.sql
# 2. Seed real Q&As so the forum is never empty
node scripts/forum-seed.mjs > scripts/forum-seed.sql
npx wrangler d1 execute <DB_NAME> --remote --file scripts/forum-seed.sql
# 3. Deploy the worker (adds /forum/* routes + AI cron)
npx wrangler deploy
# 4. Pre-render the SEO pages, then build the site
cd ..
node scripts/build-forum-pages.mjs && npm run buildUse the same <DB_NAME> as the other migrations (see wrangler.toml d1 binding).
Operating the AI responder
Launch posture is approval-gated: nothing the AI writes goes live without an admin approving it.
- The cron drafts an answer for each unanswered user question into
forum_ai_outbox(statuspending_approval). - Admin reviews the queue:
GET /forum/ai-drafts(admin session or none — gated byisUserAdmin). - Approve/reject:
POST /forum/ai-drafts/<id>/decidewith{"decision":"approved"}or"rejected". - The next cron run posts approved drafts as the Cinevva Assistant (
is_ai=1, rendered with an "AI" badge), and skips any question a human already answered.
To relax to delayed-fallback later (AI answers only if no human has within N hours), change getQuestionsNeedingAiAnswer to add an age filter and auto-approve in draftForumAnswers. Keep the disclosure label regardless.
Scaling the seed corpus
The starter set is 16 curated pairs across all 8 categories. To reach the 150–250 estimated in the proposal, run an LLM extractor over the live game_messages table (cluster recurring questions, pair with the in-transcript assistant reply, anonymize) and append rows to forum-seed.sql in the same shape.
Endpoints
Public: GET /forum/categories, GET /forum/questions, GET /forum/questions/:slug. Auth: POST /forum/questions, POST /forum/questions/:id/answers, POST /forum/vote, POST /forum/accept, POST /forum/reports. Admin: GET /forum/ai-drafts, POST /forum/ai-drafts/:id/decide.