# ADR-0001：Monorepo 与技术栈选型

- 日期：2026-07-27
- 状态：已接受

## 背景

第一波要同时出前端控制台、控制平面、Host Agent 三个可交付物，团队规模是 1-2 人。

## 决定

单仓库（monorepo），三个可独立部署的单元：`apps/console`、`services/control-plane`、
`services/host-agent`。技术栈按方案 §6.1：Next.js + FastAPI + PostgreSQL。

**开发态零外部依赖**：SQLite 替 Postgres、进程内 asyncio 替 Redis、
本地目录替 MinIO。三者都在接口后面，`docker-compose.yml` 给出生产形态。

## 理由

- 1-2 人团队用多仓库，跨仓改一个接口要开三个 PR，纯损耗。
- 控制平面与 Agent 的 HTTP 契约会在接第一个客户时频繁改。同仓库能一次改完、
  一次跑通端到端测试。
- 开发态零依赖是为了**降低启动摩擦**：这台机器上没有 Docker，客户现场的
  Windows 测试主机上也大概率装不了 Docker。能 `python -m` 直接跑起来的东西，
  在实验室里活得久。
- Python 3.9 兼容：客户测试主机的 Python 版本不可控，Agent 必须往低了兼容。
  所以全仓库用 `Optional[X]` 而不是 `X | None`，用 `List[X]` 而不是 `list[X]`。

## 代价

- SQLite 与 Postgres 有行为差异（并发写、JSON 查询、事务隔离）。
  缓解：ORM 层不用任何方言特有类型；CI 后续要在 Postgres 上再跑一遍测试。
- monorepo 在团队超过 5 人后会需要更强的 CI 分区。届时再拆。

## 什么时候推翻

- 团队 >5 人且前后端分离开发节奏明显不同步 → 拆仓。
- Agent 需要单文件分发到无 Python 环境的 Windows → 把 Agent 用 Go 重写
  （方案 §6.1 已经把这条写成演进建议）。届时 HTTP 契约不变，只换实现语言。
