Files
openmaic/OpenMAIC/progress.md
2026-08-16 14:58:47 +08:00

295 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Progress Log
## Session: 2026-08-15
### Phase 1基线与第一批外围改造
- **Status:** complete
- **Started:** 2026-08-15
- Actions taken:
- 完成现有架构、课堂内核、大课编排和三端边界的并行只读审计。
- 与用户确认先封能力边界、后拆三端应用。
- 明确原互动课堂为受保护内核,外围恢复/增强功能。
- 验证 `mcp__deepseek_harness__run` 已加载并能只读访问 OpenMAIC。
- 创建持久化计划、发现与进度记录。
- 尝试并行委派三项只读设计审计;底层调用未在超时后收束,已主动终止,未产生代码写入。
- 主线程核查 middleware、首页提交、generation-preview 会话恢复、课堂 learner 外挂和发布 Token 使用点。
- 确认前台生成 Session 的最小结构、文档 Blob 持久化要求及现有 E2E 与新双路径行为的差异。
- 实现首页双路径提交:普通需求继续走后台任务,材料/互动/职教模式写入前台 Session 后进入原 `/generation-preview`
- 从 classroom learner 外层取消平行 `AssistantPanel` 挂载,保留原 Stage 内 ChatArea/Roundtable。
- 用户要求停止使用 DeepSeek Harness后续实现与验证全部切回主线程和本地工具。
- 更新首页 Playwright page object 和 4 条生成链路 E2E使普通需求断言后台任务、互动模式断言原前台预览。
- 新增部署角色解析与 `requireOpsAccess`:生产默认 learnerops 生产强制 ACCESS_CODE会话校验在每个 `/api/courses/**` 路由重复执行。
- 首页与课堂发布入口改为由非敏感部署角色控制;浏览器不再读取或发送 `NEXT_PUBLIC_COURSEWARE_PUBLISH_TOKEN`
- 课件发布 POST 在 ops 实例接受 ACCESS_CODE 会话,在独立 server 实例继续要求服务端 Bearer Token。
- Files created/modified:
- `task_plan.md`(创建)
- `findings.md`(创建)
- `progress.md`(创建)
- `lib/generation/foreground-session.ts`(创建)
- `tests/generation/foreground-session.test.ts`(创建)
- `app/page.tsx`(修改:首页前台/后台双路径)
- `app/classroom/[id]/page.tsx`(修改:移除平行助教挂载)
- `e2e/pages/home.page.ts`(修改:动态前台/后台按钮与互动模式操作)
- `e2e/tests/home-to-generation.spec.ts`(修改:双路径断言)
- `e2e/tests/full-happy-path.spec.ts`(修改:显式互动模式)
- `e2e/tests/slide-content-surface-647.spec.ts`(修改:显式互动模式)
- `e2e/tests/slide-scene-creation-gate.spec.ts`(修改:显式互动模式)
- `lib/config/deployment-role.ts`(创建:部署能力契约)
- `lib/server/ops-access.ts`(创建:运营服务端守卫)
- `tests/config/deployment-role.test.ts`(创建)
- `tests/server/ops-access.test.ts`(创建)
- `middleware.ts`(修改:运营路由部署角色边界)
- `app/api/courses/**/route.ts`(修改:逐路由运营会话守卫)
- `app/api/coursewares/route.ts`修改ops 会话或 server token 双入口)
- `lib/config/feature-flags.ts``lib/bundle/client-upload.ts``lib/bundle/use-publish-courseware.ts`(修改:移除浏览器发布密钥)
- `app/courses/[courseId]/page.tsx`(修改:发布请求不再携带公开 token
- `.env.example`(修改:部署角色与服务端发布凭据说明)
## Test Results
| Test | Input | Expected | Actual | Status |
|---|---|---|---|---|
| DeepSeek Harness 只读自检 | OpenMAIC package 基础信息 | 可读取且无写入 | 识别 `openmaic@0.3.2`,无文件变更 | ✓ |
| 前台 Session 单元测试 | `tests/generation/foreground-session.test.ts` | 标志映射、材料顺序与空材料会话正确 | 2 tests passed | ✓ |
| 首批 TypeScript 检查 | `pnpm exec tsc --noEmit` | 无类型错误 | exit 0 | ✓ |
| 首批针对性 ESLint | 首页、课堂外层、Session helper/test | 无 lint 错误 | exit 0 | ✓ |
| 首页双路径 Playwright | `e2e/tests/home-to-generation.spec.ts` | 后台 POST、互动模式前台路由、设置弹窗均正常 | 3 passed | ✓ |
| 部署角色与运营访问单测 | deployment role、ops access、bundle repo、course manifest | 角色/会话/旧发布合约均通过 | 4 files / 20 tests passed | ✓ |
| learner 部署边界 Playwright | 隐藏入口、拒绝 API、重定向运营页 | 三项全部成立 | 1 passed | ✓ |
| Phase 2 course-framework 单测 | 主契约校验、旧数据兼容、顺序互斥、runner 输入传递 | 全部通过 | 4 files / 31 tests passed | ✓ |
| Phase 2 TypeScript | `pnpm exec tsc --noEmit` | 无类型错误 | exit 0 | ✓ |
| Phase 2 定向 ESLint | course framework、运营审核 UI、生成路由和测试 | 无 lint 错误 | exit 0 | ✓ |
| Phase 3 连续性与互动回归 | course framework、Interactive prompt/backend、task-engine/media/scene 回归 | 全部通过 | 10 files / 70 tests passed | ✓ |
| Phase 3 TypeScript / ESLint | 全量 TSC 与 Phase 3 触及文件 | 无错误 | exit 0 | ✓ |
| 定向既有测试基线(此前审计) | `tests/bundle tests/qa tests/course-framework tests/courseware` | 全部通过 | 14 files / 83 tests passed | ✓ |
| i18n key check此前审计 | `node scripts/check-i18n-keys.mjs` | 全部语言键完整 | 9 种语言各缺 158 个新键 | ✗ 已记录,非本批核心阻塞 |
### Phase 2大型课程主 Agent 契约
- **Status:** complete
- **Started:** 2026-08-15
- Actions taken:
- 扩展主 Agent 契约:目标学习者、整课目标、术语/风格/难度/考核连续性契约、模块专属提示词和输入/输出/排除知识边界。
- 严格校验新 AI 输出;新增旧课程读取兼容层,不在只读时改写旧文件。
- runner 保存提示词快照,并把完整课程契约、语言、准确时长和知识边界传入原单课件生成 requirement。
- 运营确认页展示完整主 Agent 产物;页面改用共享 API 类型并修正 `id/courseId` 漂移。
- 为同一课程增加 runner 级互斥,并在 start/resume/framework regenerate/module regenerate 路由同步防并发。
- Files created/modified:
- `lib/course-framework/compat.ts`(创建:旧框架读取规范化)
- `lib/course-framework/types.ts``generate-framework.ts``runner.ts``store.ts`
- `lib/prompts/templates/course-framework/system.md`
- `app/courses/[courseId]/page.tsx`
- `app/api/courses/[courseId]/{start,resume,framework/regenerate,modules/[index]/regenerate}/route.ts`
- `lib/i18n/locales/{zh-CN,en-US}.json`
- `tests/course-framework/{framework,runner,store}.test.ts`
### Phase 3跨模块连续性与互动生成
- **Status:** complete
- **Started:** 2026-08-15
- Actions taken:
- 新增确定性模块 output digest从持久化的 slide/quiz/interactive/PBL Scene 与教学 Action 提取实际覆盖、互动和考核证据。
- digest 保存语义哈希;后续模块保存 `continuityInputRefs` 并把前序实际产出注入单课件 requirement。
- 模块失败时暂停后续流水线;修复后按顺序继续,禁止跨越没有实际产出的前序模块。
- 后台单课件输入支持 `interactiveMode`,大型课程模块统一启用;前台与后台共用原 Interactive Mode prompt builder。
- Interactive Mode 在原子持久化前验收非空 HTML 互动 Scene防止模型违约或内容生成失败后产出纯幻灯片。
- 运营页增加模块实际产出、语义哈希、互动与考核证据的只读查看。
- Files created/modified:
- `lib/course-framework/module-digest.ts`(创建)
- `lib/course-framework/types.ts``runner.ts``store.ts`
- `lib/server/classroom-outline-mode.ts`(创建)
- `lib/server/classroom-generation.ts`
- `app/api/generate-classroom/route.ts``app/api/generate/scene-outlines-stream/route.ts`
- `app/courses/[courseId]/page.tsx`
- `lib/i18n/locales/{zh-CN,en-US}.json`
- `tests/course-framework/{module-digest,runner,store}.test.ts`
- `tests/server/{classroom-outline-mode,classroom-generation-retry}.test.ts`
### Phase 4冻结发布与版本锁定
- **Status:** complete
- **Started:** 2026-08-15
- Actions taken:
- course manifest 改为保留不可覆盖的版本历史;每个模块固定 `coursewareId + version + contentHash`,旧 singleton 记录只读兼容并要求重新发布后才能进入学习端。
- courseware record/ZIP 改为 append-only并在同一课件发布锁内分配版本、生成 bundle 和落库。
- learner 目录、课程页、模块入口和 loader 全链路携带精确版本/hash下载后重算 hash、核对 bundle 身份,再使用 hash 隔离的本地 stage ID 物化。
- 冻结契约补齐 Stage 初始白板/模式、Agent persona/voicespeech 已有 bundle audioRef 时删除远端 audioUrl。
- 新增服务端 persisted classroom → frozen bundle 适配层,收集本地媒体/TTS拒绝未解析素材严格内联互动 HTML复用原四类 Scene/Action 与导入器。
- 大课发布前重算每模块实际输出 digest、核对全部前序 continuity refs 和非空 HTML打包后再次核对来源快照再提交精确 manifest。
- 大课统一开启 TTS确保冻结发布有持久化讲解音频。
- 并发发布和旧课程未记录连续性引用改为明确 409/未验证语义;注释明确只禁止课程生成调用,不禁用原课堂教学 Agent。
- 模块先冻结为 unpublished全部模块和来源快照通过后统一转 published 并提交 manifest失败时回滚本批可见状态。
- 冻结测试发现并修复 `audioRef` 已存在时对象展开仍泄漏 `audioUrl` 的真实缺陷。
- Files created/modified:
- `lib/course-manifest-repo/{types,store,index}.ts`
- `lib/courseware-repo/{types,store,bundle-store,index}.ts`
- `lib/server/classroom-courseware-publish.ts`(创建)
- `lib/course-framework/{publish-state,publish-validation}.ts`(创建)
- `app/api/courses/[courseId]/publish/route.ts`
- `app/api/learn/courses/{route.ts,[courseId]/route.ts}`
- `app/api/coursewares/[id]/route.ts`
- `lib/bundle/{packager,serialize,learner-load,use-publish-courseware}.ts`
- `lib/export/{classroom-zip-types,classroom-zip-utils,use-export-classroom}.ts`
- `lib/import/import-classroom-core.ts`
- `lib/orchestration/registry/store.ts`
- `lib/server/classroom-generation.ts`
- `app/learn/{page.tsx,[coursewareId]/page.tsx,course/[courseId]/page.tsx}`
- `app/classroom/[id]/page.tsx`(仅 learner 返回导航Stage 挂载未改)
- `app/courses/page.tsx``lib/course-framework/runner.ts`
### Phase 5三端拆分准备与验收
- **Status:** complete
- **Started:** 2026-08-15
- Actions taken:
- Phase 4 合并回归通过10 files / 85 testsTSC 与定向 ESLint 均通过。
- 受保护课堂广泛回归执行 130 files / 1,294 tests128 files / 1,291 tests 通过。
- 隔离复现剩余 3 个既有 Chat director 断言;文件时间和代码范围确认不由 Phase 4 产生,按保护边界不修改 Chat 内核。
- 修正 Playwright 测试服务角色:默认 E2E 显式使用 learner不再受 development 的 `all` fallback 影响。
- learner 部署边界 Playwright 隔离重跑通过1/1首页双路径同批此前 3/3 通过。
- `pnpm build` 生产构建通过Next.js 编译、TypeScript、51 个静态页面生成和全部大课/学习端路由收集完成。
- 首轮受保护浏览器回归的 5 个失败已证明为旧 IndexedDB fixture + 残留无响应 dev server/并行干扰;迁移测试 seed 后单 worker 合并回归 11/11 通过。
- 新增真实文件仓储的大课发布边界测试 3/3正常冻结+pin、中途失败不可见、v1 manifest 不随模块 v2 漂移。
- 完成三端架构、部署、大课模式和交接四份事实文档,明确当前单实例限制及 server → learner → ops 机械拆分顺序。
- Files created/modified:
- `e2e/tests/classroom-interaction.spec.ts`(测试存储契约迁移)
- `playwright.config.ts`(默认 learner 角色)
- `tests/course-framework/large-course-publish-boundary.test.ts`
- `../docs/{architecture-3-tier,deployment-3-tier,large-course-mode,handover}.md`
### Phase 6独立部署边界加固
- **Status:** complete
- **Started:** 2026-08-15
- Actions taken:
- learner 任务面板已将单课件 jobs 与 ops courses 请求解耦learner 不再探测受限 API首页增加大课目录入口`/publish` 纳入 ops gating。
- 大课 learner-facing courseware id 从 courseId+module index 稳定派生,不再泄漏可变 source classroom id私有 source metadata 仅存于 registry不进入公开 summary。
- learner/server 角色对已冻结发布的源 classroom JSON/媒体 fail closedops 仍可用源 classroom 审阅legacy 同 id 发布记录也会被识别。
- learner 路由即使遇到异常/legacy outlines 也明确跳过 Scene/媒体生成恢复;作者课堂的中断恢复保持原行为。
- Dockerfile 在 Next build 前注入公开角色Compose 已有 learner/ops/server 三个 build/runtime 角色一致的独立服务与数据卷。ops 生产构建实测通过并确认静态 chunk 内联 `ops`
- 上游模块从任意成功/失败位置重生成时,目标及全部下游的旧 classroom/job/digest/continuity/timestamp 先原子清理,再严格顺序重建;课程立即离开 completed。
- 浏览器无显式版本 ZIP 由 server 在 publish lock 内分配 registry version 并规范化 `bundle.json`learner 校验包内 versionlegacy migrate 的显式 version 也传入 packager。
- ACCESS_CODE 会话现在具有统一默认 7 天 TTL、未来/过期 Token 拒绝、Cookie 同步过期、有界单进程登录限流和同源运营写请求保护。
- server 角色现在是无头服务:所有页面直接 404运营 courses/ops/access-code API 也返回 404内部 Bearer 发布和原课堂/单课件 API 继续交由各路由边界处理。
- ops → server 整课跨进程发布已闭环metadata+全 ZIP 单请求、Bearer、固定目的地、上传上限、结构化错误、安全重试、本地/远端幂等语义和 publication receipt 均已落地。
- course-scoped 冻结包只在 manifest exact pin 提交后才可列表、读取和下载;存储中途失败不会给 learner 留下部分可见课程。
- 冻结哈希升级为忽略导出时间的 v2 规则legacy v1 按旧算法验证;发布回执使用全源 revision 判断当前性。
- classroom/courseware 文件路径防穿越已收紧;课件同版本重试必须读回真实 ZIP 并核对字节/身份/归属,不存在或损坏时明确失败。
- ACCESS_CODE verify 在 JSON 解析前限制声明与实际请求体为 8 KiB运营 CSRF 校验改用 `OPS_PUBLIC_ORIGIN`,不再信任 forwarded host。
- 修复课堂源与课件库路径穿越SSRF guard 补齐 RFC6598 `100.64.0.0/10`server 无头边界禁用未鉴权 `/api/proxy-media`
- server 继续隐藏 provider 验证、MP4 export、开发态 persistence、usage 和全局 job 列表job DELETE 不再能删除已发布 classroom 源。
- QA/TTS 限流不再默认相信客户端 XFF并以硬容量上限+共享 overflow bucket 避免 Map/CPU 放大;多副本共享额度仍等待 Redis/数据库/WAF。
- Phase 6 最终合并回归 26 files / 236 tests 全过,全量 TypeScript、定向 ESLint、Prettier 与 Next.js 生产构建均通过52 个页面)。
- 独立浏览器合并回归 11/11 通过包括原课堂切场、Roundtable、HTML iframe 保活、Quiz、播放恢复、生成跳转和 learner 部署边界。
### Phase 7公网安全网络与身份边界
- **Status:** in_progress
- **Started:** 2026-08-15
- Actions taken:
- 将 Phase 6 标记为完整单实例里程碑,并把账号/owner、共享限流、数据库事务和对象存储明确迁入生产化阶段避免把架构前置条件误报为普通收尾。
- 并行启动公网 URL safe-fetch 实现、专用 server 边界复核和 learner identity/capability 决策设计;继续冻结原互动课堂内核且不使用 DeepSeek。
- Phase 7 开始时记录受保护课堂内核聚合 SHA-256`238041e89d96b0a2e3a187988af2e7cef97a7355775f242c35aabf42f38c7097`,收口时再次计算以验证本阶段零漂移。
- 完成 learner 身份/资源授权只读设计:推荐账号主体 + 桌面设备 DPoP + exact-resource runtime grant整理 owner、entitlement、quota、匿名数据迁移与验收矩阵生产代码尚未在产品决策前擅自强制。
- 新增连接级 public URL fetch 与媒体代理边界:预解析结果固定到 Undici connector、逐跳重新解析与 pin、public-only 地址策略、8 KiB 请求/25 MiB 响应上限。
- safe-fetch 验证完成:安全定向 37/37、周边回归 100/100、TSC/ESLint/Prettier 与 Next.js 生产构建52 pages通过live HTTPS pinned 请求 200确认 Host/SNI 正常。
- 专用 server/发布源复核已落最小修复GET+HEAD 全局 job list deny、Azure voice probe deny、remote current publication receipt 源反查、发布/删除 source 互斥,以及 manifest repo 自身 ID/version/path 防御;正在完成定向回归。
- 专用 server method/path 边界复核已补齐 HEAD 与尾斜杠旁路,并将 Azure voices provider 探测移出 server 公开面。
- 远程发布的当前 ops receipt 现在参与已发布 source 反查;发布/删除用同进程 source claim 消除 TOCTOU冲突返回 409。重生后历史 source 保留语义与跨副本原子性仍明确留待持久化决策。
- course manifest 文件仓库补齐 id/version/direct-child 自校验,不再仅依赖 HTTP 路由上游的路径防穿越。
- server/source/storage 合并定向回归 18 files / 181 tests 全过,全量 TypeScript、定向 ESLint 与代码/文档 Prettier 全过。
- 主线再次独立验收:安全/发布边界 11 files / 160 tests 全过;课堂相关 87 files / 946 tests 全过;全量 TSC、定向 ESLint、Prettier 和最终 Next.js build52 pages通过。
- Phase 7 复验的受保护课堂聚合哈希仍为 `238041e89d96b0a2e3a187988af2e7cef97a7355775f242c35aabf42f38c7097`,与开始前完全一致。
- 身份基础复核确认可先做“纯策略 + generation job observe-only”竖切resolver 当前明确 unavailable、owner 字段向后兼容可选、决策只记录不改变响应;已委派实现,强制鉴权仍等待正式账号主体决策。
- outbound safe-fetch 第二批完成Azure voices 与 MinerU Cloud verification 使用 DNS-pinned public GET认证头不跨重定向helper 拒绝 Host override为兼容本地自托管model probe/PDF self-hosted/SDK/adapters 明确保留为后续策略迁移。
- 第二批验证9 files / 137 tests、TSC/ESLint/Prettier 与 Next.js build52 pages全过。
- 身份最小竖切完成:新增 provider-neutral principal、纯 ownership policy、异常隔离的 observe-only observer并把 generation job 的 detail/cancel/delete/resume 接入;当前 resolver 恒为 unavailable路由响应不受 decision 影响,旧 job 无 owner 继续兼容。
- 身份竖切经独立只读审查无阻断;主线合并验证 13 files / 144 tests、全量 TSC、定向 ESLint 与最终 Next.js build52 pages通过。
- 完成全量 outbound 只读审计:确认 dedicated server 仍公开多条 BYOK 生成入口,旧 SSRF guard 存在 validate-then-connect DNS TOCTOU并定位 MinerU upload/ZIP 与 Qwen audio 两条未复核 provider-returned URL 的 P0 链路。
- 下一批已按兼容性拆分并行推进AliDoc OSS 图片 DNS pin、server-managed-only 公网 provider 门禁、MinerU 任意 method/body 二次 URL secure transport保留桌面/运营自托管能力,不把 private provider 一刀切为 public-only。
- AliDoc OSS 图片下载已切到 DNS-pinned helper并在连接前把 legacy HTTP URL 升级为 HTTPS保留 OSS host allowlist、30 秒 timeout、10 MiB 声明/实际双上限和失败返回 null 语义。
- secure transport 新增有界 PUTMinerU presigned upload 与 ZIP download、Qwen returned audio 已全部逐 URL DNS pin、拒绝 3xx、不转发 API 凭据、限制 body 并在所有路径释放 dispatcher。
- dedicated server 新增中央 managed-provider gateunmanaged caller key/baseUrl 在 resolver 前被拒绝server-managed 配置覆盖伪造值desktop/ops/learner BYOK、自托管 Ollama 和本地 unpdf 保持兼容extract-document 的 AliDoc media 直连旁路也已补齐。
- provider denial 已统一映射为稳定 `403/FORBIDDEN`,覆盖 image/video/TTS/voice/ASR/PDF/document/web-search 与 LLM error boundary代表测试确认拒绝后 provider 不会被调用,非 server 成功路径不变。
- 主线最终合并回归通过:安全/身份/provider 27 files / 316 tests大课/冻结发布 19 files / 149 tests互动课堂相关 114 files / 1,181 tests。全量 TSC、目标 ESLint、Prettier 和 Next.js 生产 build52 pages全部通过。
- 本轮所有触及文件仍位于受保护课堂边界外;最近 60 分钟受保护路径无文件修改,互动课堂 1,181 项回归全绿。
- 2026-08-16 用户确认账号主体决策:正式账号作为永久 owner/权益主体,设备身份仅作持有证明或可迁移游客身份。下一步开始 owner 不可变绑定与可切换 enforcement不在登录提供方未选定前伪造 authenticated principal。
- 新增 `shadow|required` 身份 enforcement、账号/绑定设备/游客 subject 映射和稳定 401/403/409/503 denial默认 shadow真实 resolver 未安装时不会伪造账号。
- generation job create 现在可原子绑定 account owner 或 device guest普通状态 patch 禁止修改归属。guest→account 迁移必须 compare-and-set 原 guestlegacy ownerless 还需显式 administrative opt-in已绑定账号不可转移。
- job create/list/detail/cancel/resume/delete 已全部接入同一外围门禁required 下 list 仅返回本人资源,精确 `manage:any` capability 才可全局查看shadow 下响应保持不变。
- 第一轮身份定向验证6 files / 37 tests 与全量 TypeScript 通过。
## Error Log
| Timestamp | Error | Attempt | Resolution |
|---|---|---:|---|
| 2026-08-15 | 当前工作区不是 Git 仓库 | 1 | 采用小范围补丁、触及文件清单和逐批测试 |
| 2026-08-15 | DeepSeek Harness 未在旧任务工具清单出现 | 1 | 重启桌面应用后工具已加载并通过自检 |
| 2026-08-15 | 三个 Harness 长任务并行调用超过预期超时且无返回 | 1 | 终止并行组;下一次改用更小的串行任务,不重复同一调用方式 |
| 2026-08-15 | Prettier check 报告两个新文件格式不合规 | 1 | 运行项目 Prettier 格式化后重新验证 |
| 2026-08-15 | 运营边界首轮 TSC/发布测试/格式命令出现 3 个问题 | 1 | 已定位为残留变量、环境角色兼容和 zsh glob采用三个独立定向修复 |
| 2026-08-15 | Prettier 对 `.env.example` 无可用 parser | 1 | 排除环境示例,仅格式化 TS/TSX/Markdown 支持文件 |
| 2026-08-15 | learner 部署边界 E2E 首次格式检查不通过 | 1 | 单文件 Prettier 格式化后重验 |
| 2026-08-15 | Phase 2 首次 TSCframework AI mock 被推断为无参数函数,读取调用参数触发 TS2493 | 1 | 为 mock 显式声明 system/user 两个字符串参数后重验 |
| 2026-08-15 | Phase 2 UI 首轮 TSC/ESLint详情类型未覆盖模块 DTOcompat 使用了 Next.js 禁用的 `module` 局部名 | 1 | 详情类型改为 `CourseModuleView[]`,并把局部变量改为 `moduleObj` |
| 2026-08-15 | Phase 3 首轮 TSCprompt adapter 测试的 base mock 被推断为空参数元组 | 1 | 显式声明 AICall 的 system/user/images 参数后重验 |
| 2026-08-15 | Phase 4 发布路由补丁因 import 上下文已变化而未套用 | 1 | 重新读取当前文件并以更小补丁重试成功 |
| 2026-08-15 | Phase 4 定向测试有 3 个 learner-loader 断言仍依赖旧版无哈希 fixture/stage ID | 1 | 确认为新不可变身份契约带来的测试漂移,委派更新 fixture 并补精确版本负向测试 |
| 2026-08-15 | Phase 4 计划日志补丁使用了旧版错误行文本 | 1 | 用 `rg` 获取精确上下文后修正补丁 |
| 2026-08-15 | Phase 4 server publish/export 测试发现 speech 序列化仍携带远端 audioUrl | 1 | 从展开对象中显式剔除 audioUrl仅在无 bundle audioRef 时兼容回填 |
| 2026-08-15 | 受保护课堂广泛回归130 files / 1,294 tests 中 3 个既有 Chat director 断言失败 | 1 | 其余 128 files / 1,291 tests 通过;只读诊断是否为既有 prompt/evidence 测试漂移,不修改用户要求冻结的 Chat 内核 |
| 2026-08-15 | Playwright `deployment-role-boundary` 在默认/复用 dev server 上看到了 ops 入口 | 1 | E2E webServer 显式固定 learner 角色;隔离重跑 1 test 通过,同批首页双路径 3 tests 此前通过 |
| 2026-08-15 | 受保护 Playwright 9 tests 并行执行时 5 tests 失败 | 1 | 3 个 beforeEach 卡在 IndexedDB seed另有 generation redirect/scene heading 断言;改为单 worker 分组隔离,不修改课堂核心 |
| 2026-08-15 | Docker CLI 不可用,且 Next 构建打印既有 traced-file 缺失 warning | 1 | 用 YAML 契约测试 + 真实 ops `pnpm build` 验证角色内联BUILD_ID/standalone 产物实际存在 |
| 2026-08-15 | 级联重生首次断言把省略的可选键当成 `undefined` 键 | 1 | 改为断言该键不存在course-framework 47 tests 通过 |
| 2026-08-15 | ACCESS_CODE 加固首轮 TSC 报角色冗余分支和 WebCrypto BufferSource 类型 | 1 | 修正类型后 32 tests、TSC、ESLint 与完整构建通过 |
| 2026-08-15 | 查找 ACCESS_CODE 文档时首次使用了不存在的 `README.zh-CN.md` | 1 | 确认实际中文文件是 `README-zh.md`,对正确文件重跑检查 |
| 2026-08-15 | 更新 Phase 6 计划时首个大补丁使用了远程任务更新前的状态行 | 1 | 重读 `task_plan.md`,改为小范围补丁 |
| 2026-08-15 | `OPS_PUBLIC_ORIGIN` 首个联合补丁未匹配 `.env.example` 的注释形式 | 1 | 分离代码/测试与 env 补丁,按实际上下文完成 |
| 2026-08-15 | Phase 7 查看尚未落盘的 safe-fetch 文件时 zsh 未匹配 `*safe*` glob | 1 | 后续只用 `rg --files` 或显式路径读取,不重复该 glob |
| 2026-08-15 | Phase 7 主线补丁匹配了代理已经更新前的 server 复核状态行 | 1 | 重新读取当前计划/进度,保留已记录的 181 项结果并追加独立 160+946 项复验 |
| 2026-08-15 | 两个探索性的受保护哈希复算命令分别因 zsh 不拆分字符串变量和嵌套 awk 转义失败 | 1 | 不再猜测旧命令;使用已记录哈希基线、触及文件清单和受保护回归验证,本批身份竖切未进入任何受保护目录 |
| 2026-08-15 | 主线新增 AliDoc HTTP→HTTPS 用例首次格式检查失败 | 1 | 用项目 Prettier 格式化测试,随后 check 通过 |
| 2026-08-15 | Qwen 超时测试首轮较晚挂载 rejection 断言Vitest 报 unhandled rejection | 1 | 在推进 fake timer 前先建立 rejection 断言,重跑无未处理错误 |
| 2026-08-15 | provider 扩展回归受宿主 HTTP(S)_PROXY 干扰4 个既有 mock 请求进入真实 Undici 代理 | 1 | 清除代理环境后重跑 99 files / 773 tests 全绿,确认不是生产代码回归 |
| 2026-08-15 | 复核 extract-document 时使用了不存在的 `tests/api/extract-document.test.ts` | 1 | 用 `rg --files` 定位实际 `tests/document/extract-document-route.test.ts` 后完成检查 |
| 2026-08-15 | provider 403 响应测试 mock 首次使用 rest 参数,触发 TypeScript 签名不兼容 | 1 | 改为显式 route 参数签名TSC 与全部定向测试通过 |
| 2026-08-16 | 追加账号归属发现的补丁误指工作区顶层规划文件 | 1 | 用 `rg --files` 确认文件位于 `OpenMAIC/`,改用精确绝对路径更新 |
| 2026-08-16 | 账号 owner 竖切收口时尝试 `git status/diff`,项目目录没有 Git 元数据 | 1 | 沿用已记录的无 Git 工作流:精确文件清单 + Prettier/ESLint/TSC + 定向回归 |
## 5-Question Reboot Check
- 2026-08-15 Phase 6 跨进程发布:已将 course manifest 文件仓库改为可指定目录的工厂,生产全局实例保持不变,用于隔离 server 事务测试。首个大补丁因上下文/误字失败,重读后拆小已成功。
- 2026-08-15 Phase 6 跨进程发布:已新增固定远程 origin + Bearer 的整批 multipart transport、server 单进程课程事务、实际流式上限、幂等 manifest 重试和 ops publication receipt本地共享文件 fallback 保留。首轮 Prettier + 全量 `tsc --noEmit` 通过。
- 2026-08-15 新增远程发布集成测试首轮4 项中 3 项通过(成功+幂等、第二模块失败回滚、manifest 失败回滚ops route 回执闭环返回 409正在读取结构化错误定位。
- 2026-08-15 远程发布定向回归 5 files / 37 tests 全通过:包括真实 multipart route、两个隔离文件根、Bearer+ACCESS_CODE 并存、canonical public URL、超时安全重试、第二模块失败、manifest 失败、身份漂移、精确 learner 读取和 receipt 失效。
- 2026-08-15 远程发布专项扩展到 7/7 通过,新增非安全 HTTP/整批大小上限和 ACCESS_CODE 不能代替 Bearer 的负向用例。同一命令后的全量 TSC 被并发新增的 classroom-storage-security Stage fixture 两处类型错误阻断,已报告主线协调。
- 2026-08-15 安全重试深化发现包内 publishedAt 参与 contentHash正在将 ops 远程打包时间固定为本次课程源快照 updatedAt并用首次 server 成功后丢弃响应、第二次重试的集成用例验证不新增版本。
- 2026-08-15 远程安全重试已完成:集成测试首次让 server 完成发布后丢弃响应ops 未写 receipt第二次使用同一 source snapshot updatedAt 重新冻结server 幂等返回 manifest v1courseware/manifest 数量均未增加。7/7 通过。
- 2026-08-15 冻结包哈希契约升级为向后兼容 v2新包不再让 `manifest.exportedAt` 扰动 contentHash远程测试改为以不同导出时间重新打包后重试验证哈希稳定且 server 不新增版本/manifest。
- 2026-08-15 跨进程发布最终收口:幂等命中复用完整 frozen-bundle publish gate 并读取 exact 存储对象;新增大课 manifest exact-pin 公共可见性门禁;本地 fallback 复用相同事务并实现同内容 no-op。挂起 manifest 时 catalog/detail/download 均不可见,缺失/篡改 ZIP 会生成可加载的新版本。定向回归 6 files / 54 tests、全量 TSC、定向 ESLint 全通过。
- 2026-08-16 已完成课堂 owner 传递边界定位job runner 传给 `generateClassroom` 的 server-only options课堂持久化包装存 owner不将身份字段暴露给生成输入或 Stage/Scene。
- 2026-08-16 账号 owner 竖切已从 job 延伸到 raw classroom后台生成继承 job owner直接课堂写入保留已有 ownerrequired 模式限制 GET/POSTguest/legacy 迁移使用 compare-and-set身份元数据始终位于 Stage/Scene 之外。定向 7 files / 41 tests 通过。
- 2026-08-16 账号 owner 扩展回归已通过10 test files / 57 tests包含 job/classroom 创建、列表、读写、迁移、路由拒绝、大课发布 learner 边界;同批 TSC 和定向 ESLint 通过。
- 2026-08-16 原课堂保护性回归通过87 test files / 937 tests覆盖 interactive iframe 保活、whiteboard 动作、playback 恢复、Quiz、PBL v2 和 audio/TTS。账号元数据改动未进入任何原课堂内核文件。
- 2026-08-16 账号 owner 竖切生产构建通过Next.js 16 编译、TypeScript、52 个静态页面与全部 route 收集完成。仅有项目已存在的 middleware 命名弃用提示,无构建错误。
| Question | Answer |
|---|---|
| Where am I? | Phase 7公网安全网络与身份边界 |
| Where am I going? | 其余 outbound safe-fetch → 产品身份决策 → owner/entitlement/quota → 数据库/对象存储 |
| What's the goal? | 不改原课堂内核,完成麦洛教育大型连续课程与三端能力边界 |
| What have I learned? | 见 `findings.md` |
| What have I done? | 完成大课生成/冻结/精确学习链、三角色与跨进程发布;新增 DNS-pinned 媒体代理、server/source 边界并形成 learner 身份推荐方案 |
## 2026-08-16 生成任务恢复专项规划
- **Status:** in_progress
- 阅读并遵循文件化规划流程,重新核对了当前运行状态与服务日志。
- 确认普通 Python 任务 `Xjk5UcLtOx` 仍在推进(当时为第 5/10 个场景);英语大课程 `S9V3Mm0AWy` 在第 1 个模块因旧进程失联被判定为 stale/failed。
- 区分了“后端进程重启/失联”的证据与“无法仅凭现有日志证明具体是崩溃还是手动重启”的不确定性。
- 已将持久化任务租约、心跳、场景级检查点、大课模块续跑、旧任务兼容、故障演练和验收标准写入 `task_plan.md`,并将证据写入 `findings.md`
- 本轮没有修改生成源码、删除任务记录或中断正在运行的 Python 任务。
- **Next:** 按 R1 → R2 → R3 → R4 实施恢复协议,并先用故障注入和旧数据兼容测试验证,再扩大到真实生成任务。