# MVP v3.0 进展记录(milestone log) 本文档用于记录 v3.0 按 `specs/mvp/v3.0/v3.0_dev_plan.md` 实施过程中的里程碑完成情况。 约定:每完成一个里程碑,追加一条记录,包含**日期**、**完成内容**、**涉及文件**、**验证方式/结果**、**待办/风险**。 --- ## M1:Path policy + tests(已完成) - 日期:2025-12-30 - 范围:按 v3.0 路径策略升级 API submit 的路径校验(不扩展 TaskSpec YAML 结构)。 - 完成内容: - `code_path`:仍只允许 `/private/common/...`(v3.0 不执行 user code)。 - `train_file`/`val_file`:允许 `/private/common/datasets/...` 或 `/private/users//datasets/...`。 - `model_id`:若以 `/private/` 开头则视为本地路径,仅允许: - `/private/common/models/...` 或 - `/private/users//models/...` 否则仍按 HuggingFace repo id(如 `Qwen/...`)处理。 - 拒绝跨用户路径(例如 `bob` 提交 `/private/users/alice/datasets/...`)。 - 拒绝本地模型路径不在 `models/`(例如指向 `jobs/`)。 - 涉及文件: - `src/mvp/py/argus/service/app.py` - `src/mvp/py/tests/test_users.py` - 验证方式与结果: - 本地单测:`.venv/bin/python -m pytest -q` - 结果:全部通过(`54 passed`),覆盖率阈值保持 `>= 90%`。 - 待办/风险: - `model_id=/private/...` 的“本地模型路径语义”需要在用户文档/WebUI 中明确提示(避免误用)。 - 后续 M2/M3 需要把该路径策略同步到 UI 表单/提示文本(避免用户填错路径)。 --- ## M2:SFTPGo 集成(方案 A:用户联动创建 + password)(已完成) - 日期:2025-12-30 - 范围:SFTPGo(Data Management)最小集成 + 用户自助信息 `/api/v2/me` + 用户目录结构落盘。 - 完成内容: - 新增 `data` 配置段: - `data.user_root`:用户数据根目录(默认 `/private/users`) - `data.sftpgo`:SFTPGo 可选联动(enabled/host/sftp_port/admin_api_base/admin_user/admin_password_env) - `data.retention`:jobs 过期策略配置(3 天移入 trash,7 天 purge;janitor 在 M4 实现) - 新增 `SFTPGoAdminClient`(`urllib` 实现,不使用 `requests`): - `create_user` / `disable_user` / `reset_password`(最小集合) - API server 增强: - `POST /api/v2/users`:创建 DB user + 同步创建目录结构(`datasets/models/code/jobs/trash/jobs`) - 当 `data.sftpgo.enabled=true` 时,创建用户会联动调用 SFTPGo admin API,并返回一次性密码(明文仅返回一次,服务端不保存) - `POST /api/v2/users/{user_id}:disable`:禁用用户(SFTPGo 禁用 best-effort) - `POST /api/v2/users/{user_id}/sftp:reset_password`:管理员重置一次性密码(SFTPGo enabled 才允许) - `GET /api/v2/me`:返回当前用户的目录约定、retention 提示,以及(可选)SFTP 连接信息 - 同步更新 `src/mvp/configs/dev.yaml`:补齐 v3.0 相关 `data.*` 配置(默认关闭 sftpgo)。 - 涉及文件: - `src/mvp/py/argus/service/config.py` - `src/mvp/py/argus/service/sftpgo.py` - `src/mvp/py/argus/service/app.py` - `src/mvp/py/tests/test_sftpgo.py` - `src/mvp/py/tests/test_users.py` - `src/mvp/py/tests/test_app.py` - `src/mvp/py/tests/test_service_config.py` - `src/mvp/configs/dev.yaml` - `specs/mvp/v3.0/v3.0_api.md` - 验证方式与结果: - 本地单测:`.venv/bin/python -m pytest -q` - 结果:全部通过(`62 passed`),覆盖率 `90.11%`(阈值 `>= 90%`)。 - 待办/风险: - M2 仅做了“API 侧联动 + 单测”,未在真实 SFTPGo 容器上端到端验证(按计划在 M5 完成)。 - 目录创建依赖文件系统权限:生产部署时需确保 API/head 容器对 `/private/users` 可写。 --- ## M3:WebUI(最小可用,多页面 + 侧边栏)(已完成) - 日期:2025-12-30 - 范围:API server 托管最小 WebUI(同源,不引入 Node 构建),用于登录/提交/查看任务与日志、查看 data 信息。 - 完成内容: - 新增 UI 路由(HTML+少量 JS): - `/ui`(重定向到 tasks) - `/ui/login`:token 粘贴并写入浏览器 localStorage(key=`mvp_token`) - `/ui/tasks`:任务队列列表(调用 `/api/v2/queue`) - `/ui/tasks/new`:提交 TaskSpec YAML(POST `/api/v2/tasks`) - `/ui/tasks/{task_id}`:任务详情(GET `/api/v2/tasks/{task_id}`,支持 cancel) - `/ui/tasks/{task_id}/logs`:日志查看(GET `/api/v2/tasks/{task_id}/logs`,可选自动刷新) - `/ui/data`:展示 `/api/v2/me` 返回的路径/SFTP/retention 信息 - 统一侧边栏导航:Tasks / New Task / Data / Login。 - UI 不做服务端 session:所有 API 调用均由浏览器带 `Authorization: Bearer `(localStorage 注入)。 - 涉及文件: - `src/mvp/py/argus/service/ui.py` - `src/mvp/py/argus/service/app.py` - `src/mvp/py/tests/test_ui.py` - 验证方式与结果: - 本地单测:`.venv/bin/python -m pytest -q` - 结果:全部通过(`65 passed`),覆盖率 `90.53%`(阈值 `>= 90%`)。 - 待办/风险: - WebUI 当前为“骨架+API 驱动”,不做复杂交互与大文件下载;上传/下载仍以 SFTP 为主(按设计)。 - Starlette TestClient 的 `allow_redirects` 有弃用告警(不影响功能,可在后续清理)。 --- ## M4:Jobs Retention janitor(3 天移入 trash,7 天后 purge)(已完成) - 日期:2025-12-30 - 范围:API server 内置后台线程,对“已结束 attempt”的 job 目录执行保留策略(文件系统直连,不依赖 SFTPGo)。 - 完成内容: - 新增 `JobsJanitor`: - 以 `attempts.end_time` 为基准计算 TTL(从 job 结束开始算) - `>= 3 天 && < 7 天`:把目录从 `.../jobs/` 移动到 `.../trash/jobs/` - `>= 7 天`:确保目录进入 trash 后删除(`shutil.rmtree`) - 对缺失目录、异常移动/删除为 best-effort(不影响服务主流程) - DB 增强:新增查询 `list_ended_attempts_before()`,用于 janitor 扫描候选 attempt。 - API server 启动时启动 janitor 线程(可通过 `data.retention.janitor_interval_s` 控制;<=0 视为关闭)。 - 涉及文件: - `src/mvp/py/argus/service/janitor.py` - `src/mvp/py/argus/service/db.py` - `src/mvp/py/argus/service/app.py` - `src/mvp/py/tests/test_janitor.py` - 验证方式与结果: - 本地单测:`.venv/bin/python -m pytest -q` - 结果:全部通过(`75 passed`),覆盖率 `90.72%`(阈值 `>= 90%`)。 - 待办/风险: - M4 只做“逻辑 + 单测”,实际 `/private/users/...` 的权限与在 `argus@h1` 的行为验证放到 M5(端到端)。 --- ## M5:端到端(h1)— SFTPGo compose + v3.0 E2E 脚本(已完成:交付脚本/配置) - 日期:2025-12-30 - 范围:补齐 h1 端到端所需的 compose/service、配置与一键脚本(实际运行/验收由你在 `argus@h1` 执行)。 - 完成内容: - SFTPGo 集成到 `docker compose`: - 新增 `argus-sftpgo` service(SFTP 2022;Admin API/UI 8080→host 8081,避免与 MVP API 8080 冲突) - 同挂载 `../../shared:/private`,并持久化元数据到 `../../shared/common/sftpgo` - SFTPGoAdminClient 实装(对齐 upstream OpenAPI): - `GET /api/v2/token`(BasicAuth)获取 admin token - `POST /api/v2/users` 创建用户(含 `permissions: {"/":["*"]}`) - `PUT /api/v2/users/{username}` 禁用/重置密码 - 新增 v3.0 dev 配置:`configs/dev_v30.yaml`(启用 `data.sftpgo` 并配置 `admin_api_base=http://argus-sftpgo:8080/api/v2`) - 新增 v3.0 一键脚本: - `scripts/run_all_v30_api.sh`:起 Ray+SFTPGo、启动 API、创建用户并提交 PPO/GRPO/SFT(引用 user dataset 路径) - `scripts/run_e2e_v30_cases.sh`:最小 E2E runner(HP-1) - API 启动脚本增强:`scripts/60_start_api.sh` 支持透传 `SFTPGO_ADMIN_PASSWORD` 到 head 容器内的 API 进程。 - 涉及文件: - `src/mvp/docker-compose.yaml` - `src/mvp/configs/dev_v30.yaml` - `src/mvp/scripts/run_all_v30_api.sh` - `src/mvp/scripts/run_e2e_v30_cases.sh` - `src/mvp/scripts/60_start_api.sh` - `src/mvp/py/argus/service/sftpgo.py` - `src/mvp/py/tests/test_sftpgo.py` - `src/mvp/README.md` - `specs/mvp/v3.0/v3.0_api.md` - 验证方式与结果: - 本地单测:`.venv/bin/python -m pytest -q` - 结果:全部通过(`75 passed`),覆盖率 `90.35%`(阈值 `>= 90%`)。 - 待办/风险: - 需要你在 `argus@h1` 实跑 `scripts/run_all_v30_api.sh` 完成真正的 SFTP 上传/下载与 retention 验收(按 `v3.0_acceptance.md`)。