ARTIFACT / THEATRON
Theatron
PROTOTYPE给带教教师和练判断的学生,一个把训练场景演出来、把评分留在人手里的系统;M0/M1/M2 已跑通,M3 和换代收尾没做完。
◈ System Profile ◈
◈ Access · 访问入口 ◈
◈ Sections · 章节 ◈
◈ README ◈
Theatron
给带教教师和练判断的学生,一个把训练场景演出来、把评分留在人手里的系统;M0/M1/M2 已跑通,M3 和换代收尾没做完。
状态:可用但未定版(v3 换代期,单部署单租户);入口:本地运行 bun run dev → :3100;仓库:fire-disposal/theatron
本质
让 LLM 扮演场景角色、把评分留给教师与量具的护理培训推演系统。
选型
基于 Bun 的单体 SSR 应用,前端 React Router + React + Tailwind,后端同进程 Hono,数据 PostgreSQL + Drizzle,部署单容器。
- 运行时
- Bun 1.4
- 前端
- React 19
- React Router 8
- react-router-hono-server
- Vite 8
- Tailwind CSS 4
- shadcn/ui
- Radix UI
- lucide-react
- 后端
- Hono 4
- zod 4
- jose
- Hono 4
- 数据
- PostgreSQL 15
- Drizzle ORM
- drizzle-kit
- Drizzle ORM
- PostgreSQL 15
- 外部服务
- DeepSeek
- 火山引擎 SeedTTS
- 工具链
- TypeScript 5
- Biome
- 部署
- Docker
- Docker Compose
- Nginx
- GitHub Actions
功能
- M0 垂直切片:内容 → 会话 → 评分 → 记录/复核,共用同一套 session/score_run
- M1:分组、作业、复核改分、任务级多标准评分(选量具建批次 → 队列逐条评 → α/β 对照)
- M2:
director:model的隔离扮演 + 世界裁定,裁定者写不了台词、扮演者改不了世界,边界由 strict 工具 schema 保证 - 内容与量具:
cases/9 个场景(急性心梗、分诊隐性出血、双床优先级、凌晨支付故障等),instruments/4 份量具(临床决策、沟通、问病史、情境推理) - 教学面:场景可见性双门(已上架 + 命分组白名单,都没设=看不见)、
/go/<slug>直达、作业导出、班级配额闸门 - 诊断面:
/api/ops/report(模型闸门在途、评分队列深度、备份分项年龄)、错误检索、export:trace一行一步决策导出 - 验证:74 个测试文件走
bun test,无浏览器 e2e;bun run smoke打真实构建产物,60 秒内查健康、鉴权、开局、上传、结束 - 未完成:M3 历史数据导入与旧库转只读(未开始,导入干跑也没做);TTS 真实供应商闭环(缺凭据未验);首屏 124 KB gzip(目标 ≤60 KB)
启动流程
# 前置:本机 Postgres
cp .env.example .env # 填 DATABASE_URL / JWT_SECRET / DEEPSEEK_API_KEY
createdb -h localhost -U postgres theatron_dev
bun install
bun run setup # migrate + cases:sync + seed,一步到位
bun run dev # http://localhost:3100
bun run build && bun run start # 生产形态,同一端口
bun run check # typegen + tsc
bun test # 单测
bun run build && bun run smoke # 打真实构建产物再冒烟
bun run score <sessionId> --instrument <slug> --replay # 换标准重放
bun run seed 会建演示账号,口令写死在 scripts/seed.ts;生产环境里它见到默认口令会直接拒绝执行,首个教师走 bun run bootstrap:teacher 并显式给口令。
边界与已知问题
- 单实例假设写在实现里:评分 worker 进程内每秒轮询串行消费、图片只存本地磁盘、DB 客户端不加连接池、compose 只有一个 app 容器。横向扩得先改这四处。
- 三处双源还在:内容(宿主
shared/cases文件 vs 库)、量具(instruments/*.mdvs 库)、评分实现(两套机制无法互证)。TODO 的「结束换代脆弱期」四条一条没勾。 - 宿主
shared/cases是运行时输入,却不在任何备份数据集里:容器重建能保住(bind mount),备份恢复演练覆盖不到。 - 一键登录
/login?u=&p=明文留在浏览器历史和 nginx access log,只能用于一次性演示账号;/go/<slug>的安全靠startSession那道闸,别绕过它开局。 .env.example里没有DEEPSEEK_API_KEY,README 却要求填;VOLC_TTS_SPEAKER示例值与代码兜底值不一致。Bun 只在环境缺该变量时才读.env,shell 残留的旧DATABASE_URL会静默生效(现象是「关系不存在」),启动那行[db] 库名@主机用来对账。- 遗留物:
scene/turn.ts(director:none的确定性实现)只剩测试在消费;uploads路由注释还写着「登录切片没落地」。 - Apache-2.0;
/terms、/license页已挂,但「不承诺稳定过渡」不等于可以无声丢数据,交接范围要在试用前写清。
文档索引
- docs/spec.md — 规格与里程碑
- docs/architecture.md — 架构
- docs/decisions.md — 决策记录
- docs/direction.md — 方向
- docs/ux-tree.md — 交互树
- TODO.md — 当前任务