Files
memind/docs/production-release-guardian.md
T
john 473ad80882
Memind CI / Test, build, and release guards (push) Has been cancelled
fix: route portal canary through isolated edge tunnel
2026-07-26 20:30:56 +08:00

726 lines
38 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.
# 生产发布守门员
> 适用目标:生产 `103` Portal runtime 及其共享链路。
> 规则状态:已确认为生产发布的强制验收规范。
> 当前实施状态:187 场景机器目录、fail-closed 执行器、artifact 哈希、机器报告校验和发布脚本上传前硬阻断已经落地;业务场景自动化仍在分批补齐。任何未实现项保持 `unknown` 并阻断发布,在 187 项全部通过或合法豁免前,不得宣称生产发布已经通过本守门员。
## 1. 目标
本守门员将生产发布从“运行若干测试后人工判断”升级为绑定同一源码和同一产物的可审计硬闸门:
1. 只有完整、干净、可追溯的 `main` 可以成为候选版本。
2. 同一个 `main` commit 构建出的同一个 runtime artifact,必须完成本文规定的全部适用场景。
3. 结果必须满足 `failed=0``skipped=0``cleanup_failed=0`
4. 确实不受影响的场景只能标记为经过审核的 `not_applicable`,不能用 `skip`、口头说明或发布参数绕过。
5. 即使机器闸门全部通过,仍须取得用户针对“发布 103”动作本身的明确批准。
6. 未获得批准时,禁止上传、切换 runtime、重启服务或执行任何生产写操作。
## 2. 核心术语
| 术语 | 含义 |
|---|---|
| Candidate commit | 已进入远端 `main`、CI 通过、准备构建发布包的完整 Git SHA |
| Candidate artifact | 由 Candidate commit 构建的 Portal runtime 包及其 SHA256 |
| Scenario family | 本文定义的一条业务或运行时场景;可包含多个参数化 case |
| Deterministic case | 不依赖真实外部模型输出、可以稳定重复的单元或集成测试 |
| Live canary | 在隔离或预生产环境调用真实 LLM、图片、搜索等服务的最小验证 |
| `not_applicable` | 有完整影响证明并经审核后,确认本次发布不适用的场景状态 |
| Gate report | 绑定 commit、artifact 和环境指纹的机器可读验收报告 |
| Release approval | 所有闸门通过后,用户对本次 103 发布作出的明确授权 |
## 3. 发布硬规则
### 3.1 允许发布的唯一条件
以下条件必须同时成立:
- Candidate commit 位于完整 `main`,工作区干净,不落后 `origin/main`
- Candidate commit 已在远端 CI 通过,且没有未合并的关键变更。
- Candidate artifact 的 SHA256 与 Gate report 完全一致。
- 所有适用场景均为 `passed`
- 没有 `failed``skipped``blocked``unknown` 或未执行场景。
- 所有 `not_applicable` 均具有有效的影响评估和审核记录。
- 测试数据和临时资源清理完成。
- Gate report 未过期;默认有效期不超过 4 小时。
- 103 只读预检通过。
- 用户再次明确批准本次 103 发布。
任何一项不满足,发布脚本必须在上传 artifact 之前退出。
### 3.2 永远不可豁免的场景
下列场景不允许标记为 `not_applicable`
- `REL-*` 全部发布、升级、备份和回滚场景。
- `AUTH-01``AUTH-04``AUTH-05``AUTH-06`
- `CHAT-01``CHAT-02``CHAT-06``CHAT-07``CHAT-08``CHAT-09``CHAT-11``CHAT-12``CHAT-13``CHAT-15`
- `MEM-08``MEM-13``MEM-14``MEM-15``MEM-16`
- `FILE-07` 附件跨用户隔离。
- `PAGE-08``PAGE-09``PAGE-10``PAGE-12`
- `DATA-06``DATA-10``DATA-12`
- `AGENT-10``AGENT-11`
- `WX-09``WX-13`
- `BILL-02``BILL-03``BILL-04`
- `MS-01``MS-03``MS-04`
- `COMP-01``COMP-04` 既有生产数据兼容场景。
- `CFG-08` 模型配置兼容场景。
- `COMP-08``COMP-09`
### 3.3 `not_applicable` 的判定
只有同时满足以下条件,才允许将场景标记为 `not_applicable`
1. 本次 diff 不触达该场景映射的代码、配置、数据库对象、依赖、运行时打包清单或公共契约。
2. 本次 diff 不触达共享入口,包括 `server.mjs`、鉴权、会话、数据库初始化、runtime 构建、goosed 配置、worker、代理、公共环境变量。
3. 场景所依赖的生产功能处于明确关闭状态,并且“关闭状态行为”已经通过测试。
4. 影响分析能够列出 changed paths、依赖链和不受影响的理由。
5. 审核人对该 Candidate commit 作出明确确认。
每条豁免记录必须包含:
```json
{
"scenario_id": "SEARCH-04",
"status": "not_applicable",
"commit_sha": "<full sha>",
"reason": "生产 GitHub Search 功能关闭,且本次变更不触达搜索配置或共享网关",
"changed_paths_checked": ["..."],
"dependency_evidence": ["..."],
"reviewed_by": "<reviewer>",
"reviewed_at": "<ISO-8601>"
}
```
如果无法确定是否受影响,默认必须执行,不得豁免。
## 4. 分层闸门
| Gate | 名称 | 环境 | 主要产物 | 失败处理 |
|---|---|---|---|---|
| G0 | 源码与 CI | 本地 + Git 远端 | commit 证明、CI 状态 | 阻断 |
| G1 | 确定性测试 | 隔离本地副本 | 单元/集成/回归结果 | 阻断 |
| G2 | API 全栈场景 | 隔离全栈 | 场景报告、数据库和文件断言 | 阻断 |
| G3 | 浏览器场景 | 隔离全栈 | Playwright 报告、截图、控制台日志 | 阻断 |
| G4 | 真实服务 Canary | 预生产 | LLM/图片/搜索/Deep Search 结果 | 阻断 |
| G5 | 升级与回滚演练 | 脱敏生产快照 | 升级、持久化、回滚证据 | 阻断 |
| G6 | 103 只读预检 | 生产只读 | 健康、任务、锁、空间、备份检查 | 阻断 |
| G7 | 人工批准 | 发布前 | 明确批准记录 | 未批准不得发布 |
| G8 | 发布后烟雾与自动回滚 | 生产 | 最小业务验收 | 失败立即回滚 |
G8 不能替代 G0-G7;发布后健康检查也不能为发布前缺失的场景补票。
## 5. 测试环境和数据隔离
### 5.1 禁止测试连接生产
全场景执行器必须在代码层拒绝以下目标:
- `58.38.22.103`
- `m.tkmind.cn`
- 生产 MySQL、PostgreSQL、Redis、SearXNG、Deep Search 和图片服务地址
- 生产用户工作区、发布目录和对象存储
G6 仅允许明确列出的只读检查;不得创建会话、页面、订单、问卷、记忆、充值或 Agent Run。
### 5.2 隔离要求
每次执行必须使用:
- 唯一 `run_id`
- 独立测试数据库或独立 schema
- 独立用户工作区和公开页根目录
- 专用普通用户 A、普通用户 B、creator、developer、admin、低余额用户
- 专用微信绑定账号和模拟支付数据
- 独立 Portal、MindSpace、goosed、worker 端口
- 可控的 LLM、图片、搜索 Stub,以及单独的真实服务 Canary 凭据
测试结束必须删除或归档:
- 测试会话和 Agent Run
- 用户记忆
- 上传附件和生成图片
- MindSpace 页面、缩略图和 Conversation Package
- Page Data dataset、policy 和测试行
- 计费、充值、微信和 Plaza 测试记录
- 临时数据库/schema、容器、进程和日志
清理失败等同测试失败。
## 6. 场景用例标准
每个场景文件必须具备:
```yaml
id: MEM-02
name: 新会话召回用户偏好
gate: G2
owners: [memory, chat]
impact_paths:
- memory-v2*.mjs
- chat-intent-router.mjs
preconditions:
- user_a 已保存一条确定性偏好
steps:
- 新建会话
- 使用不同措辞询问偏好
assertions:
- 路由启用 memory_recall
- 回复包含目标事实
- 不包含 user_b 的记忆
cleanup:
- 删除本次测试记忆和会话
evidence:
- API 响应
- memory query trace
- database assertion
production_regression_refs:
- PRC-MEM-001
```
LLM 场景不得只断言固定文案,应优先断言:
- 路由、skill、tool 和 Provider 选择
- 工具请求/响应是否真实发生
- 数据库、文件和 artifact 是否正确产生
- 数字结果和标准 fixture 是否一致
- 用户可见结果是否包含关键事实和可访问链接
- 不应出现的敏感信息、内部提示和旧资产是否缺失
## 7. 场景目录
以下共 19 个场景包、187 个场景族。每个场景族可以在场景文件中继续扩展参数化 case,但不得减少本文要求。
### 7.1 发布与运行时(11
- **REL-01**:候选来源必须是干净、非 detached 的完整 `main`;记录完整 SHA。
- **REL-02**:候选不落后 `origin/main`,已进入远端且 CI 通过,没有未合并关键变更。
- **REL-03**:同一 commit 可重复生成可追踪的 manifest 和 runtime artifact SHA256。
- **REL-04**artifact 必需文件完整,不包含开发垃圾、运行态数据、源码备份或密钥。
- **REL-05**:前端和 runtime 不包含 localhost、错误内网地址或错误公共域名。
- **REL-06**:使用生产同构配置冷启动,数据库初始化和 Portal 健康检查通过。
- **REL-07**:从脱敏生产数据库快照升级,DDL 成功、数据保留且重复启动幂等。
- **REL-08**9 个 goosed、worker、Portal 和隧道全部指向并识别新 runtime。
- **REL-09**:注入启动或健康检查失败后,完整恢复旧 live 目录和旧 release。
- **REL-10**:活动任务排空、备份一致、上传中断和切换前失败均不影响当前版本。
- **REL-11**:启用扩展及 runtime 的依赖闭包完整;每个打包的 MCP 模块都存在,并能在生产同构容器内实际启动。
### 7.2 登录、账号和权限(8)
- **AUTH-01**:正确账号密码登录,返回合法 Cookie 和用户信息。
- **AUTH-02**:错误密码、连续错误尝试和限流行为正确。
- **AUTH-03**Portal 重启后合法会话状态符合配置,不出现幽灵登录。
- **AUTH-04**:登出清除 Cookie,旧 Cookie 无法访问受保护 API。
- **AUTH-05**:用户 A 无法访问用户 B 的会话、附件、页面和私有数据。
- **AUTH-06**:普通用户无法访问管理员接口或提升自身权限。
- **AUTH-07**:访问策略 `off``enforce` 和 kill switch 三种模式符合预期。
- **AUTH-08**:路径穿越、XSS、SQL 注入和敏感配置泄露防护有效。
### 7.3 聊天、会话和流式恢复(15)
- **CHAT-01**:普通问候进入 Direct Chat 并返回用户可见回复。
- **CHAT-02**:页面、文件和工具任务进入 Agent 路径。
- **CHAT-03**:实时信息问题进入 Web Search,而不是使用过期直接回答。
- **CHAT-04**:多轮任务及“继续/确认”保持在原 Agent 会话。
- **CHAT-05**:明确新会话与自动复用会话的行为正确。
- **CHAT-06**Finish 与最终消息正确 merge,不丢用户或助手消息。
- **CHAT-07**SSE 中断后按 Portal 游标续播,不重放、不漏事件。
- **CHAT-08**Portal replay ID 不直接作为 Goose `Last-Event-ID`
- **CHAT-09**SSE 不可用时,轮询能够恢复 Agent 最终状态和消息。
- **CHAT-10**:重复请求、失败重试、取消和损坏 tool history 修复正确。
- **CHAT-11**:已有活动请求时再次发送消息,排队、取消或新建会话的行为明确,不暴露原始技术错误,也不丢失任一请求。
- **CHAT-12**:兼容历史消息契约,包括 `userVisible`/`agentVisible` 字段和 legacy、非 UUID request ID。
- **CHAT-13**:只有助手消息、Finish、会话快照和规范化消息全部持久化且顺序、时间一致后,任务才允许标记成功。
- **CHAT-14**:用户纠正“不是这个文件/对象”时,本轮纠正覆盖过期上下文,真实任务不会被 routing、skill 或内部提示覆盖。
- **CHAT-15**:快照中的每条用户可见文本都同步到规范化消息表,单字回复、Finish 边界和恢复流程均不得静默丢消息。
### 7.4 用户记忆与记忆召回(16)
- **MEM-01**:用户明确要求“记住”后成功保存偏好。
- **MEM-02**:新会话能够准确召回已保存偏好。
- **MEM-03**:换一种表达仍能通过语义检索召回正确记忆。
- **MEM-04**:能够召回历史会话中的具体事实和讨论主题。
- **MEM-05**:偏好变更时新值生效,不同时注入冲突的新旧内容。
- **MEM-06**:用户要求遗忘后,后续无法继续召回目标记忆。
- **MEM-07**:无关问题不注入无关记忆。
- **MEM-08**:两个用户的长期记忆和历史会话完全隔离。
- **MEM-09**:敏感信息遵循披露、保存、拒绝和删除策略。
- **MEM-10**:候选记忆、确认、晋升、过期和作用域生命周期正确。
- **MEM-11**Memory V2 不可用时按配置降级到 legacy,核心聊天仍可用。
- **MEM-12**:大量记忆按相关性和 token 限额截断,并保留来源追踪。
- **MEM-13**routing prompt、Memory Context、skill/tool 指令和系统模板不得被提取为用户记忆。
- **MEM-14**:单条证据消息的记忆提取数量和 fan-out 有硬上限,异常输入不能生成数百或数千条记忆。
- **MEM-15**:重复处理同一证据保持幂等,精确和语义重复均被去重,且每条记忆必须保留合法 evidence/source。
- **MEM-16**:用户纠正、遗忘或删除的内容,不能被 episodic、legacy 或上下文重摄取重新写回。
### 7.5 文件和附件基础能力(8)
- **FILE-01**:图片上传、预览、关联会话并可被 Agent 读取。
- **FILE-02**XLSX 上传、解析和附件选择正确。
- **FILE-03**:CSV 的编码、分隔符、中文字段和空值解析正确。
- **FILE-04**PDF、DOCX 文本抽取和文件元数据正确。
- **FILE-05**:多附件的选择、顺序、取消选择和会话复用正确。
- **FILE-06**:损坏文件、错误 MIME、超限文件和不支持格式明确拒绝。
- **FILE-07**:附件访问令牌过期后失效,跨用户访问被拒绝。
- **FILE-08**:生成文件、公开 URL、下载按钮和微信原生交付均指向真实可下载 artifact,访问令牌和权限正确。
### 7.6 根据图片生成页面(8)
- **IMGPG-01**:单张产品或风景图片生成响应式页面。
- **IMGPG-02**:截图经过视觉识别和 OCR 后生成结构相符的页面。
- **IMGPG-03**:多张图片按用户指定顺序生成图集或内容页面。
- **IMGPG-04**:图片与文字要求共同决定页面结构、文案和风格。
- **IMGPG-05**:页面引用合法上传资产,不包含本地绝对路径或失效 URL。
- **IMGPG-06**:公开页、封面、缩略图、OG 和分享链接完整。
- **IMGPG-07**:后续修改文案或布局时保留原图片和页面地址。
- **IMGPG-08**:图片不可读或用户无权限时明确失败,不伪造识别结果。
### 7.7 Excel/CSV 分析并生成页面(12
- **XLS-01**:单工作表生成指标摘要和可访问页面。
- **XLS-02**:多工作表关联分析得到 fixture 规定的结果。
- **XLS-03**:公式、日期、货币和百分比计算与标准答案一致。
- **XLS-04**:合并单元格、空行、脏数据和重复数据处理正确。
- **XLS-05**:页面 KPI 和图表数值可追溯到 Excel 原始数据。
- **XLS-06**:大文件分页、采样、超时和内存限制符合阈值。
- **XLS-07**XLSX、XLS、CSV 支持范围和降级提示准确。
- **XLS-08**:后续对话修改分析维度,无需重新上传文件。
- **XLS-09**:页面保留原文件下载入口和数据来源说明。
- **XLS-10**Excel 私有数据默认不公开,用户之间严格隔离。
- **XLS-11**:约 5MB、多工作表 Excel 在 xlsx 工具超时时安全降级,数字经过验证并仍能交付真实 artifact。
- **XLS-12**:新 Excel 能增量更新已有数据看板,保留页面身份、既有数据和用户已确认的纠正。
### 7.8 页面生成和 AI 配图(13)
- **PAGE-01**:纯文字需求生成公开页面并返回可访问链接。
- **PAGE-02**:长内容整理为适合阅读和分享的富页面。
- **PAGE-03**:视觉类页面自动判断是否需要配图。
- **PAGE-04**:强制生图必须使用本轮新生成资产。
- **PAGE-05**:用户明确不要图片时不得调用生图。
- **PAGE-06**:生图失败时如实报告,不使用旧图冒充成功。
- **PAGE-07**:主图、卡片封面和缩略图复用合法资产,避免重复生成。
- **PAGE-08**`edit_file` 修改必须 materialize 到 `public/*.html`
- **PAGE-09**:多页面任务只更新本轮相关页面,不污染其他页面。
- **PAGE-10**:文件名冲突、canonical、CSP、公开链接和域名正确。
- **PAGE-11**:复合每日资讯页同时覆盖当日新闻、天气、市场/股票、知识卡片、权威引用、合规说明和可访问公开页。
- **PAGE-12**:首次缺少公开 HTML、artifact 或必要交付物时只允许一次有界自修复;仍缺失则形成正确失败终态。
- **PAGE-13**:独立生图请求不得被强制转成页面;用户说“换一个”时必须产生本轮新位图,不能复用旧资产。
### 7.9 Page Data、问卷和业务后台(13
- **DATA-01**AI 使用调查完成页面、dataset、提交和后台查看。
- **DATA-02**:客户下单系统前台提交和后台管理完整。
- **DATA-03**:供应商数据上报、校验和后台查看完整。
- **DATA-04**TKMind 功能偏好调查完成交付。
- **DATA-05**:儿童问卷新增饮食字段且保留历史数据。
- **DATA-06**:匿名前台可以按 policy 提交,后台必须登录。
- **DATA-07**:新增、查询、修改、删除和字段校验正确。
- **DATA-08**HTML 使用 `updateRow`/`deleteRow` 时权限自动匹配。
- **DATA-09**:验证码、重复提交、重放和限流有效。
- **DATA-10**dataset、page policy 和 workspace 绑定一致。
- **DATA-11**remote 模式同步,storage 缺失时回退 workspace。
- **DATA-12**:跨用户、SQL 注入、越权字段和审计日志验证通过。
- **DATA-13**:不完整 schema 能安全修复并重新绑定,覆盖缺字段、重复 `created_at`、误判只读、禁用软删、legacy API/client/localStorage 和过期页面版本。
### 7.10 搜索和 Deep Search8
- **SEARCH-01**:实时信息通过 Web Search 获取并提供可验证来源。
- **SEARCH-02**SearXNG 查询和结果解析正确。
- **SEARCH-03**:网页 Reader 抽取正文并处理失败页面。
- **SEARCH-04**GitHub Search 启用和禁用状态符合配置。
- **SEARCH-05**Deep Search 使用真实 LLM 网关完成最小研究任务。
- **SEARCH-06**:密钥不匹配时明确返回鉴权失败,不能以 health 200 代替功能成功。
- **SEARCH-07**:搜索超时、取消和 Provider fallback 正确。
- **SEARCH-08**:容器内 loopback 地址正确重写为 host gateway。
### 7.11 Agent、goosed、worker 和代码执行(11
- **AGENT-01**:普通 Agent 任务可由 goosed 成功执行。
- **AGENT-02**:并发任务分配和 session affinity 正确。
- **AGENT-03**Portal 与 worker runtime/build identity 匹配。
- **AGENT-04**identity 不匹配时 fail closed,不误领任务。
- **AGENT-05**:任务重试、幂等和重复消费防护正确。
- **AGENT-06**worker 重启后任务恢复或形成明确失败终态。
- **AGENT-07**:获得授权的用户可以执行 Aider 开发任务。
- **AGENT-08**:未授权用户和非允许 task type 被拒绝。
- **AGENT-09**:代码产物正确交付,不能逃逸用户工作区。
- **AGENT-10**:扩展启动兼容目标数据库方言、PostgreSQL role 权限和模块路径;Page Data 扩展失败不能拖垮非数据任务。
- **AGENT-11**:超时、心跳过期或 worker 重启后任务恰好恢复或终结一次,只产生一个终态和一份用户可见结果。
### 7.12 日程和提醒(5
- **SCHED-01**:按照用户时区创建提醒。
- **SCHED-02**:模糊时间要求澄清,不擅自确定错误时间。
- **SCHED-03**:修改和取消提醒正确。
- **SCHED-04**worker 只发送一次,失败重试不重复通知。
- **SCHED-05**:服务重启后提醒仍存在并按计划执行。
### 7.13 微信渠道(13
- **WX-01**:签名和连通性验证正确。
- **WX-02**:重复消息 ID 不重复执行。
- **WX-03**:绑定用户聊天及用户数据隔离正确。
- **WX-04**:页面交付返回正确公开链接。
- **WX-05**:图片需求发送微信原生图片消息。
- **WX-06**:服务号页面使用本轮新缩略图,缺失时按规则修复。
- **WX-07**OAuth 回调、return URL 和 state 校验正确。
- **WX-08**:支付通知签名、幂等和渠道隔离通过沙箱数据验证。
- **WX-09**:每条入站消息最终进入 done 或 failed,长期 processing 记录能够自动恢复或关闭。
- **WX-10**:仅图片的历史和内容能为纯文本模型安全归一化,图片后的文字追问不会触发 `image_url` 400。
- **WX-11**:微信 45047 响应次数和 45015 时间窗口错误可恢复,不重复发送,并在下一次被动回复机会完成交付。
- **WX-12**AMR 语音转换及 ASR 成功链路可用,转换或识别失败时给出明确用户提示。
- **WX-13**:微信页面交付为原子组合:真实页面 artifact、本轮封面、摘要、品牌标记和可发送公开链接缺一不可。
### 7.14 计费、额度和充值(7)
- **BILL-01**:免费、订阅和管理员权益计算正确。
- **BILL-02**Direct Chat 和 Agent 分别只扣费一次。
- **BILL-03**:失败、取消和超时任务不重复扣费。
- **BILL-04**SSE 重连和消息重放不重复结算。
- **BILL-05**:并发任务下余额扣减保持原子性。
- **BILL-06**:充值回调签名和幂等正确。
- **BILL-07**:余额不足时拒绝执行且不创建残留任务。
### 7.15 MindSpace 和交付物(9
- **MS-01**MindSpace `/health``/mindspace/v1/contract` 正常。
- **MS-02**local/remote adapter 的核心行为一致。
- **MS-03**:公开页访问、canonical、OG 和分享正确。
- **MS-04**:页面同步、缩略图和 workspace fallback 正确。
- **MS-05**Conversation Package 创建、校验和历史回填正确。
- **MS-06**:DOCX 和长图下载可用,链接不指向本地地址。
- **MS-07**:内容扫描、CSP 和危险脚本处理正确。
- **MS-08**:删除、清理和 purge 不留下孤立资源。
- **MS-09**PDF/DOCX 生成不依赖运行时联网下载字体,真实文件可下载,并可通过原生或直接链路交付。
### 7.16 Plaza 集成(5
- **PLAZA-01**:页面发布到 Plaza 后内容和链接正确。
- **PLAZA-02**:发现、搜索和 SEO 数据正确。
- **PLAZA-03**:点赞、评论、关注和权限正确。
- **PLAZA-04**:推荐和排序在固定 fixture 下稳定。
- **PLAZA-05**:页面删除或转私密后不再公开访问。
### 7.17 配置、功能开关和可观测性(8)
- **CFG-01**Orchestrator 关闭时不成为 Portal 启动或请求依赖。
- **CFG-02**Orchestrator shadow 模式不改变用户结果。
- **CFG-03**kill switch 可以立即阻断新的受控执行。
- **CFG-04**Analytics 关闭时零上报,开启时上下文正确。
- **CFG-05**System Disclosure 的 shadow/enforce 行为正确。
- **CFG-06**:环境变量迁移到数据库配置且重复执行幂等。
- **CFG-07**:日志、指标和审计可追踪,且不泄露密钥和用户隐私。
- **CFG-08**:活动 Provider 接受全部已配置数据库模型;模型目录升级时自动迁移或明确拒绝 legacy 配置,不把无效模型带入运行。
### 7.18 浏览器和移动端(8)
- **UI-01**:桌面端登录、聊天和历史记录完整。
- **UI-02**:移动端聊天、流式消息和 Finish 完整。
- **UI-03**:图片、Excel 和其他附件上传交互正确。
- **UI-04**:页面预览、修改、发布和分享流程正确。
- **UI-05**:公开 Page Data 表单可以真实提交并看到结果。
- **UI-06**:空状态、加载、错误、重试和禁用状态完整。
- **UI-07**:刷新、前进后退和重新进入会话不丢状态。
- **UI-08**:无控制台错误、无布局重叠,并通过基础可访问性检查。
### 7.19 生产兼容、故障恢复和性能(9)
- **COMP-01**:脱敏生产旧会话升级后可以继续聊天。
- **COMP-02**:现有公开页面升级后仍可访问且内容未损坏。
- **COMP-03**:现有 Page Data 数据、policy 和表单升级后仍可使用。
- **COMP-04**:现有用户记忆升级后仍可召回。
- **COMP-05**:单个 goosed 容器故障时隔离并恢复。
- **COMP-06**:数据库短暂不可用后服务能够恢复并保持一致性。
- **COMP-07**:图片、搜索或记忆 Provider 故障不拖垮核心聊天。
- **COMP-08**:并发聊天、文件分析和页面生成满足延迟、错误率和资源泄漏阈值。
- **COMP-09**:每次候选发布都在隔离环境回放脱敏生产回归语料库,且执行器从代码层禁止连接生产。
## 8. 既有场景迁移
现有 `scenarios/*.json` 场景必须保留,并映射到新编号:
| 既有场景 | 新场景 |
|---|---|
| `ai-usage-survey` | DATA-01 |
| `customer-order-system` | DATA-02 |
| `dev-logout` | AUTH-04 |
| `john2-suzhou-page` | PAGE-01、MS-03 |
| `john4-children-hobby-diet-update` | DATA-05 |
| `supplier-data-report` | DATA-03 |
| `suzhou-page` | PAGE-01、PAGE-08 |
| `tkmind-feature-survey` | DATA-04 |
| `event-registration-page-data` | DATA-06、DATA-07、DATA-10 |
| `event-registration-page-data-repair` | DATA-07、DATA-10、DATA-11 |
现有执行器只支持 `login``logout``chat`。实施时至少增加:
- `seed``cleanup`
- `grant``revoke`
- `upload``select_asset`
- `disconnect_stream``reconnect_stream`
- `assert_memory`
- `assert_page`
- `assert_dataset`
- `assert_billing`
- `assert_audit`
- `restart_service`
- `inject_fault`
- `browser`
- `rollback`
## 9. 自动化命令和报告接口
当前已提供以下入口:
```bash
npm run test:release-gate:unit
npm run test:release-gate:deterministic -- --artifact .runtime/portal
npm run test:release-gate:scenarios -- --artifact .runtime/portal
npm run test:release-gate:browser -- --artifact .runtime/portal
npm run test:release-gate:providers -- --artifact .runtime/portal
npm run test:release-gate:upgrade -- --artifact .runtime/portal
npm run test:release-gate:all -- --artifact .runtime/portal
npm run verify:release-gate-report -- --artifact .runtime/portal
```
`test:release-gate:all` 生成:
```text
.release-gate/<full-commit-sha>/
├── report.json
├── report.md
├── junit.xml
├── artifact.sha256
├── environment.json
├── scenarios/
├── screenshots/
├── logs/
└── partials/
```
当前执行器从本文解析并校验 187 个连续唯一编号。现有自动化 suite 已为 184
个场景提供逐项业务断言,仓库/候选检查另直接判定 `REL-01``REL-02`
`REL-04`,共 187 个场景都有自动判定能力。未执行 mode 仍为 `unknown`
缺少 active 脱敏回归 fixture 时 `COMP-09` 明确失败;候选不等于 `origin/main`
或缺少成功 CI 证据时 `REL-02` 明确失败。任何不完整证据都会让完整闸门返回非零,
这是发布保护而不是测试故障。精确分组覆盖、命令和扩展方式见
[自动发布闸门实现说明](release-gate-automation.md)。
`report.json` 至少包含:
```json
{
"schema_version": 1,
"commit_sha": "<full sha>",
"branch": "main",
"artifact_sha256": "<sha256>",
"started_at": "<ISO-8601>",
"completed_at": "<ISO-8601>",
"expires_at": "<ISO-8601>",
"environment_fingerprint": "<sha256>",
"summary": {
"required": 187,
"passed": 187,
"not_applicable": 0,
"failed": 0,
"skipped": 0,
"blocked": 0,
"unknown": 0,
"cleanup_failed": 0
},
"scenarios": [],
"exemptions": [],
"approved_for_release": false
}
```
如果存在合法 `not_applicable``required` 仍为 187,且必须满足:
```text
passed + not_applicable = required
failed = skipped = blocked = unknown = cleanup_failed = 0
```
## 10. 发布脚本的最终阻断点
### 10.0 用户级灰度前置条件
用户级灰度入口由 `scripts/release-portal-canary-prod.sh` 安装:稳定 Portal 保持 8081
候选 Portal 使用 18081,候选 goosed 使用 18015,身份路由器使用 18082105 使用独立
19082 反向隧道访问路由器。活动 nginx 上游在脚本备份、`nginx -t` 和健康检查后,才允许
从稳定 `58.38.22.103:8081` 切到 `127.0.0.1:19082`。灰度身份必须
使用不可变用户 ID、唯一用户名或微信绑定账号标识;禁止按显示昵称(包括“唐”)匹配。未命中、
身份解析失败或候选不可用必须自动回落稳定版本。
完整契约和回滚入口见 [103 用户级灰度发布](release-canary-103.md),对应测试至少包括
`release-gate/canary-routing.test.mjs``memind-canary-proxy.test.mjs`
`release-gate/release-script.test.mjs`。测试通过不代表已经部署;103 灰度仍须绑定同一
commit、artifact 和 Gate report,并完成备份、只读预检及人工批准。
`scripts/release-portal-runtime-prod.sh` 会替换 8081 live 目录。它只用于同一候选完成灰度
验收后的全量晋升;在晋升证据校验完成前继续硬阻断非 dry-run,不能拿灰度入口替代晋升批准。
`scripts/release-portal-runtime-prod.sh` 必须按以下顺序执行:
1. `check-release-ready.sh`
2. 获取完整 `main` SHA 和远端 CI 状态
3. 构建 Candidate artifact
4. 计算 artifact SHA256
5. 读取对应 Gate report
6. 校验 commit、artifact、环境、有效期和场景汇总
7. 校验全部 `not_applicable` 记录
8. 执行 103 只读预检
9. 请求本次发布的明确人工批准
10. 批准后才允许上传
以下情况必须直接退出:
- 使用 `--skip-tests`
- 使用范围绕过变量
- report 不存在、过期或解析失败
- commit 或 artifact SHA 不一致
- 任一场景失败、跳过、未知或清理失败
- 豁免记录缺少审核信息
- 103 有活动任务且未完成排空
- 备份、磁盘空间、数据库锁或回滚预检失败
当前脚本已在任何 103 SSH、上传或切换之前执行 `verify-release-gate-report.mjs`,并硬拒绝 `--skip-tests``ALLOW_PORTAL_RELEASE_SCOPE_BYPASS``ALLOW_MINDSPACE_PUBLIC_LINK_ISSUES`。Gate report 绑定 `.runtime/portal` 的排序目录树 SHA256;打包后的传输压缩包另行记录自身 SHA256。
## 11. 发布后的最小保护
生产切换后立即执行只产生最小业务影响的烟雾验证:
- Portal 本地和公网健康检查
- 登录与登出
- 新建最小聊天并收到回复
- SSE 终态
- 读取一张既有公开页
- 读取一个既有 Page Data 页面
- MindSpace health/contract
- 9 个 goosed、worker 和隧道状态
- 日志中无数据库迁移、鉴权、循环重启和大面积 5xx
任何一项失败,必须自动回滚到 Gate report 记录的旧 release,并保存失败证据。
## 12. 审核与维护
1. 新增生产功能时,必须同时新增场景或明确映射到已有场景。
2. 删除场景必须说明对应生产功能已删除,并经过审核。
3. 事故修复必须把复现路径加入本守门员或 `docs/regression-guards/`
4. 场景实现不能只检查 HTTP 200,必须验证真实业务结果。
5. 任何脚本都不得自动把失败改成 `not_applicable`
6. 发布人不能单独审批自己提出的豁免。
7. Gate report 和发布 manifest 应按 release ID 归档。
8. 本文、`PRODUCTION_RELEASE_RULES.md` 和发布脚本的规则必须保持一致。
## 13. 生产失败回归语料库
### 13.1 2026-07-26 只读审计基线
以下数字仅用于说明场景来源和风险优先级,是一次性时间点证据,不是生产实时不变量,也不能替代发布前重新验证:
| 对象 | 审计结果 | 对应守卫重点 |
|---|---:|---|
| 注册用户 / 有聊天用户 | 122 / 70 | 用户隔离、旧数据兼容、长尾任务 |
| 会话快照 / 快照消息 | 739 / 16,628 | Finish、恢复、消息顺序、历史契约 |
| 规范化消息 | 10,009 | 快照与规范化消息一致性 |
| 快照中未进入规范化表的用户或助手文本 | 824 | CHAT-13、CHAT-15 |
| Agent Run | 1,297,失败 1088.33%) | 故障分类、终态、恢复与真实交付 |
| 当前生产版本以来 Agent Run(自 2026-07-23 17:48:55 +08:00 | 42,失败 819.05% | 当前版本 P0 回归样本 |
| 微信消息 | 1,701,失败 245,仍 processing 17 | 微信终态、窗口限制、图片和交付 |
| 当前生产版本以来微信消息(自 2026-07-23 17:48:55 +08:00 | 78,失败 13 | 当前版本 P0 微信回归样本 |
| 活跃记忆 / 有 evidence 的记忆 | 8,709 / 418 | 来源追踪和异常扩张 |
| 缺少 evidence/source 的活跃记忆 | 3,457 | MEM-15 |
| 单条 evidence 最大记忆数 | 1,019 | MEM-14 |
| 精确重复组 / 额外重复记录 | 164 / 182 | MEM-15 |
| 疑似内部提示型记忆 | 13 | MEM-13、MEM-16 |
Agent 失败按规范化根因聚类后,至少覆盖以下 14 类 fixture
| 根因 | 审计计数 | 场景映射 |
|---|---:|---|
| Page Data schema、绑定或扩展错误 | 33 | DATA-10、DATA-13、AGENT-10 |
| 心跳过期或 stale run | 12 | AGENT-11 |
| 已有活动请求冲突 | 10 | CHAT-11 |
| 缺少公开页或交付物 | 9 | PAGE-12、FILE-08、WX-13 |
| 工具或任务超时 | 7 | XLS-11、AGENT-11 |
| Finish / 终态代码异常 | 7 | CHAT-06、CHAT-13、CHAT-15 |
| 生图工具或结果异常 | 7 | PAGE-04、PAGE-06、PAGE-13 |
| 数据库 role / 权限错误 | 6 | AGENT-10 |
| 历史消息契约异常 | 5 | CHAT-12 |
| 数据库方言错误 | 4 | AGENT-10 |
| runtime 模块缺失 | 4 | REL-11、AGENT-10 |
| request ID 格式异常 | 2 | CHAT-12 |
| 数据库连接池耗尽 | 1 | AGENT-11、COMP-08 |
| worker 重启中断 | 1 | AGENT-11 |
### 13.2 回归语料结构
建议在实现阶段建立以下目录;本节只定义契约,不代表目录或执行器已经创建:
```text
scenarios/production-regressions/
├── agent-run/
├── page-data/
├── memory/
├── wechat/
├── files/
└── manifests/
```
每个 fixture 必须包含:
- 稳定 ID,例如 `PRC-AGENT-001`,以及映射的 guardian scenario ID。
- 脱敏后的用户意图和最小合成输入,不保存原始聊天全文。
- 规范化失败签名、触发能力、依赖和故障注入条件。
- 预期终态、用户可见结果、数据库/文件断言和清理断言。
- 受控审计批次 ID、不可逆且不可反查用户的证据摘要、首次发现版本和修复版本,用于审计追踪。
- `contains_personal_data=false`、隐私审核人和审核时间。
严禁写入 Git 或 Gate report
- 原始用户聊天、记忆正文、附件内容或生产数据库快照。
- 姓名、邮箱、手机号、OpenID、Cookie、token、密钥、内部用户 ID 和可反查标识。
- 生产文件 URL、workspace 路径或能够重新定位用户资源的哈希。
### 13.3 从生产失败晋升为回归用例
1. 对生产只做授权范围内的只读聚合;原始数据留在受控环境。
2. 按语义根因去重,不能简单地把每条失败记录复制成一个测试。
3. 用合成用户、合成文件和最小输入重建失败,替换全部身份和业务内容。
4. 完成隐私审核,确认无法从 fixture 反推出用户或原始任务。
5. 将 fixture 映射到至少一个场景 ID;新能力或新根因必须新增场景。
6. 在隔离环境复现旧版本失败,并验证修复版本通过,保存确定性证据。
7. 当前版本审计发现的 8 个 Agent 失败和 13 个微信失败必须先去重、脱敏并进入 P0 回归清单。
未完成脱敏、无法稳定重建或仍依赖生产数据的记录,保留为待分析证据,不能伪装成已覆盖测试。
### 13.4 闸门判定
- `COMP-09` 每次发布强制执行,不能标记为 `not_applicable`
- 回归语料库中的全部 active fixture 必须通过;`failed``skipped``unknown` 和未执行均阻断。
- fixture 只能使用隔离数据库、合成账号、Stub 或独立 Canary,执行器必须拒绝生产地址和凭据。
- 新生产事故或用户任务失败在归因后必须进入回归待办;修复关闭前必须落为可回放 fixture 或给出经审核的不可自动化理由。
- 历史 fixture 只在对应功能已删除且完成审核后才能退役,不能因为不稳定或失败而删除。
### 13.5 首批强制参数化 case
场景族通过不等于只跑一条 happy path。首批实现必须至少包含下表参数;同一行可以由多个 fixture 覆盖,但报告必须能反查到每个参数的执行证据:
| 场景 | 必测参数 |
|---|---|
| CHAT-11 | active request 下排队、取消、新会话;前一任务成功、失败、超时三种终态 |
| CHAT-12 | legacy `userVisible`/`agentVisible`、非 UUID request ID、缺失可选字段、损坏 tool history |
| CHAT-13、CHAT-15 | 单字回复、Finish 同批到达、Finish 先后乱序、SSE 断线、轮询恢复、重复同步 |
| MEM-13 至 MEM-16 | routing/skill/tool prompt、无 evidence、单证据超量、重复摄取、语义重复、纠正、遗忘、legacy 回灌 |
| FILE-08 | 登录下载、公开下载、token 过期、跨用户、按钮 URL、微信 media/link 交付 |
| XLS-11、XLS-12 | 约 5MB、多 sheet、工具超时、降级解析、数字校验、已有看板增量更新、用户纠正保留 |
| PAGE-11 至 PAGE-13 | 搜索 Provider 失败不得伪造来源;缺 HTML/artifact/封面/摘要/品牌;强制生图无工具、无有效位图及“换一个” |
| DATA-13 | `survey_page_should_not_be_read_only`、缺 page-data client、legacy API、localStorage、缺字段、重复 `created_at`、禁用软删、过期页面版本 |
| AGENT-10、AGENT-11 | SQLite/MySQL/PostgreSQL 方言、role 权限、模块缺失、连接池耗尽、timeout、stale heartbeat、worker restart |
| WX-09 至 WX-13 | 重复 callback 不重复执行/扣费、stale processing、图片历史 + 文字追问、45047、45015、AMR/ASR 失败、原子页面交付 |
| MS-09 | 无网络字体、缺字体、PDF/DOCX 生成失败、文件不存在、直接下载和原生渠道交付 |
| CFG-08 | 当前模型、legacy 模型、未知模型、Provider 切换、目录升级迁移,例如无效 `deepseek-chat` 到有效目录项 |
| COMP-09 | 每个 active 生产回归 fixture、生产地址拒绝、生产凭据拒绝、清理失败 |
任何参数缺少结果时,对应场景状态必须为 `failed``unknown`,不能只用场景族中的其他 case 通过来覆盖。