feat: software-engineering skill v0.5 (G7/G8 ops + iteration)

Stacked on v0.3 + v0.4 (HEAD d6522ba feat-full-auto): v0.3/v0.4
content preserved, not reverted. Adds G7 post-release ops and
observation (monitoring, errors, cost/quota, feedback, hotfix loop,
rollback triggers, ops manual) and G8 iteration and scaling (v1.1
handover list, contract v1->v2 protocol, new-end onboarding,
scale/performance, deprecation), with G6->G7 and G7->G8 gates,
DAG, gate table, coordinator derivation, G0-G8 todos, checklist,
09-ops and 10-iteration role templates, and ops-manual / v1.1
handover templates in both body and appendix. Settles web+React+
multi-viewport focus, cross-viewport E2E, web single-end release
with iOS/Android native postposed, open-source-first, and the
TypeScript full-stack default (user-request-only language change;
codex-app-server itself stays Python). Pending #199 and #205
merge, then one rebase round. PR only, do not merge or deploy.
This commit is contained in:
host committed 2026-11-03 02:48:54 +00:00
1 parent a605ff2f92
commit 44616a03dc
2 files changed
+489 -74

No files matched your search

+407 -74
View File
@@ -1,10 +1,13 @@
---
name: software-engineering
description: 用户要从零做一款软件、尤其是要同时做 web、macOS、Windows、iOS、Android 多个客户端时使用。按产品规划、产品设计、架构契约、多客户端并行开发、联调测试、验收的顺序,用协调员任务派生角色线程推进,契约冻结后各客户端只在自己目录内开发,最后走评审合并与用户验收。只做单文件小改动、只问概念时不用本技能。
description: 用户要从零做一款软件、首要交付 web(React、多视口自适应)时使用;iOS、Android 原生后置,不在 MVP 内。按产品规划、产品设计、架构契约、开发、联调测试、验收、运维、迭代的顺序,用协调员任务派生角色线程推进,契约冻结后各客户端只在自己目录内开发,最后走评审合并与用户验收。只做单文件小改动、只问概念时不用本技能。
---
# software-engineering:多客户端软件工程编排
版本 v0.5,2026-10-30。上一版是 v0.4 全自动模式 + v0.3,v0.5 新增
G7 发布后运维与观察期、G8 迭代与规模化,以及下面“已定口径”一节
的重心与默认栈,v0.3 / v0.4 内容全部保留、不删改、不回退。
版本 v0.3,2026-10-30。上一版是 v0.2 + PR #193 GitHub 保证
(已合并、已部署生产)。v0.3 改了什么:P1-1 目录隔离自动化检查
(可执行命令 + 检查输出记入合并记录)、P1-2 派生占位符必填表
@@ -133,22 +136,38 @@ G0 接单选型 ──> G1 产品规划 ──> G2 产品设计 + 架构 ──>
│
G4a web 先行
│
G4b 桌面壳(macOS / Windows)
G4b 桌面壳(先 web + PWA / WebView 壳,
不做已编译原生应用)
│
G4c 移动端(iOS / Android)
│
G5 联调 + 跨端测试
G5 联调 + 跨视口测试
↑ │
└── 缺陷回 G4 修,
修完回 G5 回归
│
G6 按端验收 + 按端发布
G6 web 单端验收 + web 单端发布
(iOS / Android 原生后置占位,
不在 MVP 交付端内)
│
G7 发布后运维与观察期
↑ │
├── 热修复回 G7(小修按回归清单重跑,
│ 不重开整轮)
└── 严重问题回 G6 / G5(见 G7 一节)
│
G8 迭代与规模化
│
下一轮 G0-G6 输入冻结
(新端接入时再开一轮 G4c,
iOS / Android 原生以后才以新端身份进)
```
G4 分阶段不是“慢”,是止损:web 先行验证核心链路和契约,
桌面和移动复用已验证的契约和 Web 核心,返工面最小。
用户明确签字“接受 5 端并行成本和风险”时,协调员可以在记录里写明
例外原因后并行开 G4a / G4b / G4c,但默认不并行。
桌面复用已验证的契约和 Web 核心,返工面最小。
原 G4c 移动端(iOS / Android)自 v0.5 起改为后置占位:iOS / Android
原生明确后置,不在 MVP 链内、不作为 MVP 交付端,只在 G8 新端接入时
再开一轮 G4c。用户明确签字“接受多端并行成本和风险”时,协调员可以
在记录里写明例外原因后并行开 G4a / G4b,但默认不并行,且该例外
绝不把 iOS / Android 原生重新写回 MVP 交付端。
## 门禁表
@@ -162,9 +181,141 @@ G4 分阶段不是“慢”,是止损:web 先行验证核心链路和契约
| G3.5 | 可行性 spike 通过 | 核心链路在真实(或最接近真实的)环境里跑通:以 agent 工具为例,任务能创建、能跑出进度、能取消、能回结果;跑不通的原因已定位到模型、沙箱、后端三者之一 | 不进入 G4,先修核心链路或缩 MVP,不扩端摊成本 |
| G4a | web 先行完成 | web 客户端满足角色模板的完成定义,有可运行产物或明确的未完成项 | 只重开 web 线程,不提前开桌面和移动 |
| G4b | 桌面壳完成 | macOS / Windows 各满足完成定义,未编译项已标注验证步骤 | 只重开失败的那端 |
| G4c | 移动端完成 | iOS / Android 各满足完成定义,未编译项已标注验证步骤 | 只重开失败的那端 |
| G5 | 联调测试通过 | 单元、集成、跨端一致性、agent 安全测试、长任务测试、性能与安全检查都通过,失败项有归属和复现步骤;**安全检查点单独签字** | 回对应客户端或架构线程修,修完回 G5 回归,回归范围按契约变更影响面定 |
| G6 | 用户验收 | 用户按验收清单逐项确认,或明确列出不通过项;**验收和发布按端分别做**,web、桌面、移动的发布和回滚分开记录 | 不通过项变成新一轮待办,不算发布完成 |
| G4c | 移动端后置占位 | iOS / Android 原生明确后置(iOS/Android 后置),不在 MVP 内:只留占位说明与 G8 新端接入条件,不作为 MVP 交付端;未编译 / 未验证一律标注,不得写成已发布 | 不进 MVP 验收;待 G8 新端接入时再开一轮 G4c |
| G5 | 联调测试通过 | 单元、集成、跨视口一致性、agent 安全测试、长任务测试、性能与安全检查都通过,失败项有归属和复现步骤;**安全检查点单独签字**;跨视口 E2E 仍以跨端一致性矩阵为交付物,矩阵的行是手机 / 平板 / 桌面浏览器宽度(见“已定口径”) | 回对应客户端或架构线程修,修完回 G5 回归,回归范围按契约变更影响面定 |
| G6 | 用户验收(web 单端) | 用户按验收清单逐项确认,或明确列出不通过项;**验收和发布为 web 单端**,web 的发布和回滚分开记录,iOS / Android 原生只留后置占位,不进本轮发布 | 不通过项变成新一轮待办,不算发布完成 |
| G7 | 发布后运维与观察期通过 | 运维手册已交付;监控、日志、成本与配额口径已定并在跑;用户反馈已收集并归档;热修复记录齐全;回滚触发条件已写清且未被误触发(或已触发并按 G6 回滚方式处理) | 运维问题未闭环前不进 G8;小修走热修复回 G7,严重问题回 G6 / G5 |
| G8 | 迭代与规模化输入冻结 | 运维观察期结论已写(问题清单、热修复记录、回滚触发是否命中);v1.1 交接清单齐全(未修缺陷、开放问题、下一轮待办三项缺一不算齐);下一轮 G0-G6 的输入已冻结齐全 | 输入未冻结齐全不算 G8 完成;G8 的完成不是下一版已发布 |
门禁衔接(v0.5):G6→G7 的条件是用户验收已确认(或不通过项已列入
下一轮待办并经用户确认)+ 发布记录与回滚方式齐全 + 监控 / 日志 /
成本口径已定,三项缺一不进 G7。G7→G8 的条件是运维观察期结论已写
(问题清单、热修复记录、回滚触发是否命中)+ v1.1 交接清单齐全,
两项缺一不进 G8。
## 已定口径:重心、跨视口、默认栈与开源优先(v0.5,本节优先于旧的多端写法)
- **重心是 web + React + 多端自适应。** 首要交付是 React web 自适应
(手机 / 平板 / 桌面浏览器宽度自适应),桌面端先以 web + PWA /
WebView 壳覆盖,不做已编译原生应用;iOS、Android 原生明确后置
(iOS/Android 后置),
只在 G8 新端接入时进一轮 G4c。本节与旧文“5 端并行”“按端发布”
冲突处以本节为准,旧文的多端表述只作历史参考,不得再把
iOS / Android 写成 MVP 交付端。
- **G5 跨端 E2E 改为跨视口 E2E。** QA 第二部分不再是“跑遍各端”,而是
跨视口 E2E:同一任务、同一数据在手机 / 平板 / 桌面浏览器宽度下,
结果、文案、状态词、同步状态是否一致。交付物仍叫跨端一致性矩阵,
但矩阵的行是视口(手机 / 平板 / 桌面),不是原生端;不一致的标明
是缺陷还是刻意差异。未在任何视口实测的项单独列出,不写成通过。
- **G6 按端发布改为 web 单端 + 后置原生占位。** 验收和发布只做 web
单端;桌面先 web + PWA / WebView 壳,不做已编译原生应用;
iOS / Android 原生只留后置占位说明与 G8 接入条件,不进本轮发布、
不进本轮验收清单的“已发布”栏。未编译 / 未验证一律标注,
不得写成已发布、已上架。
- **开源优先。** 需要一个模块、组件、库时,先查开源,查完再自研:
查许可证、维护状态、体积、安全四项;优先 MIT/Apache 类许可,
避 SSPL / 商业重型许可;选型结论记入架构(技术栈表或决策记录),
写清选了哪个开源项目、为什么没选其它、许可证是什么。开源优先
不是“能用开源就不用自研”的口号:查过、记过、许可证过关,才算
走完了开源优先;没查就自研,或查了不记,都算违规。
- **默认后端是 TypeScript 全栈。** 新做产品的默认栈:前端
Vite + React + TypeScript、后端 Fastify + TypeScript 严格模式、
PostgreSQL、ORM 为 Drizzle 或 Prisma 二选一、测试 Vitest、
API 用 OpenAPI 或共享类型。技术栈在 G2 冻结后不准中途换;只有
用户特别要求时才换语言(例如用户明确要求 Python 或 Go),
agent 不得以“更合适”为由自行换语言。换语言是用户特别要求的
例外,必须记入决策记录,写清是谁要求的、换成了什么。
- **codex-app-server 本身保持 Python,不为统一语言重写。** 上面
的 TypeScript 默认栈只适用于本技能新做的产品,绝不适用于
codex-app-server 本身;不要把新产品默认栈写成要重写现有系统,
不要在 codex-app-server 仓库里以“统一语言”为由改语言。
## G7 发布后运维与观察期
G7 在 G6 之后、G8 之前,派生运维线程(附录 09-ops)。G7 不是
“发布完就结束”,而是一段有结论的观察期。
- **监控:** 监控什么、阈值是多少、告警发给谁、多久看一次,
四项在运维手册里写清;只写“已监控”不算数。
- **错误:** 错误分级、复现步骤、归属线程、处理时限,记入问题清单;
同一错误重复出现要升级,不静默放过。
- **成本与配额:** 成本口径(按什么计费、按什么周期结算)、配额
上限、配额将满时的动作(先停新任务还是先问用户),在 G7 开始前
定好并在观察期里实测记录;成本超阈值回头问用户(见全自动模式
的四类回头问用户情形)。
- **用户反馈收集:** 反馈渠道、收集周期、反馈如何变成待办(直接进
下一轮待办还是先记开放问题),写清;反馈不进待办就等于没收集。
- **热修复回路:** 小修按回归清单重跑,不重开整轮。热修复的范围
是运维与热修复范围内的修补:修完只重跑回归清单里受影响的用例,
回归通过即回 G7 继续观察;热修复绝不直接改契约,契约要改走
契约变更协议(版本号加一、回归任务),不悄悄分叉。
- **回滚触发:** 回滚触发条件在运维手册里预先写清,例如严重错误
持续超阈值、核心链路不可用、成本 / 配额失控、数据损坏风险。
触发后按 G6 回滚方式处理:先停 web 端(按发布记录里写清的
“出问题先停哪个端”)、回上一版本(revert 对应 PR 或重新部署
上一 tag),绝不 force-push 回退主线;回滚后重新走合并门
才能再发布。回滚触发是否命中,是 G7→G8 结论里必须写的一句,
不写等于 G7 没结论。
- **运维手册为交付物:** 运维手册模板见本节末尾;手册缺监控、
成本口径、回滚触发中任何一项,G7 不算通过。
- **运维线程的边界:** 运维线程只写运维与热修复范围,不直接改契约、
不冒充发布。运维线程说“已发布新版”不算发布,发布仍由 G6 的
发布记录与用户确认界定;运维线程发现要改契约或要发新版时,
交协调员走变更协议或下一轮待办,不自己推主线、自己发版。
- **严重问题回路:** 热修复修不好的严重问题,不在 G7 里硬扛:
回 G6(重新验收)或回 G5(重新联调回归),修完按门禁重新过
G6 → G7;回路次数与原因记入观察期结论。
### 运维手册模板(正文版,附录 09-ops 同款)
1. 服务与端:web 单端地址、部署方式、停端步骤(出问题先停哪个端)。
2. 监控:监控项、阈值、告警接收人、查看周期。
3. 日志:日志位置、保留期、查错步骤。
4. 错误清单:分级、复现、归属、处理时限。
5. 成本与配额:计费口径、配额上限、将满时的动作。
6. 用户反馈:渠道、周期、转待办规则。
7. 热修复:回归清单、热修复记录表。
8. 回滚触发:触发条件、回滚触发是否命中、回滚方式(revert 或重部署上一 tag)。
## G8 迭代与规模化
G8 在 G7 之后,派生迭代线程(附录 10-iteration)。G8 的完成
不是“下一版已发布”,是下一轮 G0-G6 的输入已冻结齐全。
下一版没发布、但下一轮输入已冻结齐全,G8 算完成;下一版
匆匆发布了、但下一轮输入没冻结,G8 不算完成。
- **v1.1 交接清单:** 三项缺一不算齐——① 未修缺陷(带归属和
严重程度)、② 开放问题(含任务间问答里未关闭的假设)、
③ 下一轮待办(G6 不通过项、G7 问题清单里未闭环项、用户反馈
转来的项汇总)。交接清单模板见本节末尾;G6 收尾时的 v1.1
交接清单是初版,G8 要把它更新为含 G7 结论的终版。
- **契约 v1→v2 变更协议:** 下一轮契约要升版时,按“契约冻结与
变更协议”走:改什么、为什么、影响哪些端、是否向后兼容,
四项写清,协调员批准后版本号加一(v1 -> v2),受影响端各收
回归任务;不批准的按旧契约做,差异记入已知问题。G8 只冻结
下一轮契约变更的输入(变更清单与兼容性结论),不直接在 G8
里改契约、发 v2。
- **新端接入:** iOS / Android 原生以后才以新端身份进一轮 G4c,
不塞进 MVP。接入条件在 G8 输入里写清:新端能力清单、与 web
核心的复用关系、目标机器构建与验证步骤、未验证标注规则;
新端接入仍走 G4c → G5 → G6 的门禁,不跳门禁直接算发布。
- **规模与性能:** 下一轮规模目标(用户量、并发、数据量)、
性能基线与瓶颈、扩容或降级方案,写进下一轮输入;没有基线
的“能扩容”不算结论。
- **废弃策略:** 要废弃的能力、接口、端,写清废弃时间表、替代
方案、用户通知方式;废弃不是悄悄删,先通知、再标记废弃、
再下线,三步缺一不算废弃完成。
### v1.1 交接清单模板(正文版,附录 10-iteration 同款)
1. 未修缺陷:缺陷、归属、严重程度、复现步骤。
2. 开放问题:问题、来源(任务间问答未关闭假设 / 用户反馈 / G7 观察)、
待谁确认。
3. 下一轮待办:待办项、归属角色、对应 G0-G6 阶段。
4. 契约变更输入:v1→v2 变更清单、向后兼容结论。
5. 新端接入输入:新端清单、复用关系、验证步骤(iOS / Android 后置
占位在此更新为接入条件,不提前写成已交付)。
6. 规模与废弃输入:规模目标、性能基线、废弃时间表。
## 接单选型:协调员第一件事是问,不是写代码
@@ -172,8 +323,10 @@ G4 分阶段不是“慢”,是止损:web 先行验证核心链路和契约
问卷模板在 `templates/artifacts/intake-questions.md`。最关键的六问:
1. 目标用户是谁,agent 工具最核心的一到三个能力是什么?
2. 需要哪些客户端?从 web、macOS、Windows、iOS、Android 里选,可多选,
也要问清是否接受“共享 Web 核心 + 各端壳”的路线。
2. 需要哪些客户端?v0.5 默认只问 web(React、多视口自适应):
从 web、macOS、Windows、iOS、Android 里选时,iOS / Android 原生
明确后置(iOS/Android 后置),不在 MVP 内选;也要问清是否接受
“web 核心 + 桌面 web + PWA / WebView 壳”的路线。
3. MVP 砍到什么程度?账号、同步、离线、付费,哪些 v1 必须有、哪些明确不做?
4. **执行模型:agent 在哪里跑(本机 / 服务端 / 第三方 API)?谁付模型费用?**
5. **权限边界:agent 能读哪些文件、能写哪些目录、能上网吗、能跑 shell 吗?**
@@ -202,9 +355,11 @@ G0 的六问缺一问,G0 就不算过。用户没回复时,协调员等,
| UI/UX 设计 | 1 | `docs/design/` | 流程、页面、设计规范、跨端一致性规则 |
| 后端 / API(如有) | 1 | `server/` | 按契约实现的服务端、鉴权与同步 |
| 共享核心 | 1 | `packages/shared/`(G3) | 共享类型、SDK、mock 服务、契约测试 |
| 客户端开发 | 每客户端 1 | `apps/web`、`apps/macos`、`apps/windows`、`apps/ios`、`apps/android` 之一 | 该客户端可运行产物 + 自测证据 |
| QA / 测试 | 1(跨端 E2E 可再分 1 个) | `tests/` | 测试用例、跨端一致性矩阵、缺陷清单 |
| 验收 / 发布 | 协调员兼任,用户拍板 | `docs/release/` | 验收清单结果、按端发布说明、已知问题清单 |
| 客户端开发 | 每客户端 1 | `apps/web`、`apps/macos`、`apps/windows`、`apps/ios`、`apps/android` 之一 | 该客户端可运行产物 + 自测证据;v0.5 默认只开 web,iOS / Android 原生后置占位,不在 MVP 内 |
| QA / 测试 | 1(跨视口 E2E 可再分 1 个) | `tests/` | 测试用例、跨端一致性矩阵(v0.5 行是跨视口)、缺陷清单 |
| 验收 / 发布 | 协调员兼任,用户拍板 | `docs/release/` | 验收清单结果、web 单端发布说明、已知问题清单 |
| 运维 | 1(G7) | `docs/ops/` | 运维手册、问题清单、热修复记录、回滚触发结论 |
| 迭代 | 1(G8) | `docs/` | v1.1 交接清单终版、下一轮 G0-G6 输入冻结清单 |
角色模板的权威来源是本文件末尾的附录。附录随 SKILL.md 一起播种,
所以租户任务内一定能看到。`templates/roles/` 下的文件是编辑用的源文件,
@@ -259,6 +414,9 @@ G0 的六问缺一问,G0 就不算过。用户没回复时,协调员等,
机制不依赖“模型会自动写标记块”这个假设:
- 唯一事实来源是协调员维护的待办文件 `docs/swe-todos.md`,
待办清单覆盖 G0-G8(G0 接单、G1 规划、G2 设计、G3 共享核心、
G3.5 spike、G4a web、G4b 桌面壳、G4c 后置占位、G5 联调跨视口、
G6 web 单端验收、G7 运维观察、G8 迭代输入冻结),
格式就是普通的 checkbox 清单(`- [ ] G4a web 冒烟通过`),
加项目待办(如果平台提供项目待办 API,协调员同步一份,不强求子线程会用)。
- 子线程绝不直接改待办文件。每个子线程的结尾报告必须带一节:
@@ -387,9 +545,10 @@ tests/ # QA 线程专属,含跨端一致性用例
- 合并后删远程分支(本地分支同步清理),避免旧分支被误复用;
删分支前确认合并提交已在主线。
### 发布与回滚:按端打 tag,绝不 force-push 回退
### 发布与回滚:web 单端打 tag,绝不 force-push 回退
- 按端发布时打 tag,例如 v0.1.0;发布说明从已合 PR 汇总,不凭记忆重写。
- web 单端发布时打 tag,例如 v0.1.0;发布说明从已合 PR 汇总,不凭记忆重写。
v0.5 不再默认按端分别发布;iOS / Android 原生后置占位不打发布 tag。
- 回滚是 revert 对应 PR,或重部署上一个 tag;绝不是 force-push 回退主线。
回滚后要重新走合并门(CI、评审)才能再发布,不要回滚完直接推。
@@ -411,24 +570,29 @@ tests/ # QA 线程专属,含跨端一致性用例
- QA 线程正式分两部分,各自交付物写死,缺一不算 G5 通过:
① 单端复核:逐端复核各客户端的自测证据是否属实(命令、结果、冒烟清单),
交付物是逐端复核报告(每端通过 / 不通过 + 证据 + 未复核项)。
② 跨端 E2E:同一 agent 任务、同一份数据跑遍各端,交付物是跨端一致性矩阵
(各端结果、错误提示、同步状态是否一致)+ 缺陷清单 + 回归清单。
② 跨视口 E2E(v0.5 已定口径,原跨端 E2E 改为跨视口 E2E):
同一 agent 任务、同一份数据跑遍手机 / 平板 / 桌面浏览器宽度,
交付物是跨端一致性矩阵(矩阵的行是视口:各视口结果、文案、
状态词、同步状态是否一致)+ 缺陷清单 + 回归清单。
- agent 专属测试清单保留,归属如下,不能只测 happy path:
归单端复核(每端都要过):沙箱越界、危险动作审批、token / 配额超限;
归跨端 E2E(同一任务跨端行为一致):长任务超时和取消、断网续跑、模型 503 重试。
归跨视口 E2E(同一任务跨视口行为一致):长任务超时和取消、断网续跑、模型 503 重试。
安全检查点在 G5 单独签字,检查权限边界和密钥处理,不算 QA 的附带项。
- 未编译端的 QA 口径要写死:iOS / Android / Mac 在 Linux 主机上编不出来时,
QA 结论写“代码评审 + Web 核心验证”,不写“构建通过”。
- 未编译 / 未验证的 QA 口径要写死:iOS / Android 原生后置占位
不进 QA 通过表;Mac 在 Linux 主机上编不出来时,QA 结论写
“代码评审 + Web 核心验证”,不写“构建通过”,不写“已发布”。
- 验收清单模板在 `templates/artifacts/acceptance-checklist.md`。
验收人是用户,协调员只负责把清单和各端演示产物准备好,
不能代替用户勾选通过。验收和发布按端分别做:
web 演示可真跑,未编译端审代码和构建步骤,两者效力不同,分开标注;
web 部署、桌面安装包分发、应用商店审核是三条流水线,分开记录回滚方式。
- 每端上手文档是 G6 交付物之一:每端一份,写清启动、登录、核心流程、
验收人是用户,协调员只负责把清单和 web 演示产物准备好,
不能代替用户勾选通过。验收和发布为 web 单端:
web 演示可真跑;iOS / Android 原生只留后置占位,不进本轮发布;
web 部署的回滚方式单独记录(先停 web 端、回上一版本),
桌面安装包分发、应用商店审核不在本轮流水线内,不写成已走完。
- 每端上手文档是 G6 交付物之一:web 版一份,写清启动、登录、核心流程、
常见问题;G4 阶段先写 web 版(G4a 交付时随 web 客户端一起交),
桌面、移动版在各自 G4b / G4c 交付时补齐,不拖到 G6 才现写。
不拖到 G6 才现写;iOS / Android 原生后置,不在本轮补移动版上手文档。
- v1.1 交接清单是 G6 收尾必备,三项缺一不算收尾完成:未修缺陷
(带归属和严重程度)、开放问题(含任务间问答里未关闭的假设)、下轮待办。
(带归属和严重程度)、开放问题(含任务间问答里未关闭的假设)、下轮待办;
G8 要把这份清单更新为含 G7 结论的终版,三项缺一仍不算齐。
## 失败、续跑与成本
@@ -443,16 +607,19 @@ tests/ # QA 线程专属,含跨端一致性用例
较经济的模型,具体以项目实际可用模型和配额为准;
配额将满时先停新线程,不先透支再解释。
## 诚实边界:原生客户端
## 诚实边界:原生客户端(v0.5 后置占位版)
- 在只有 Linux 主机的环境里,PWA、“添加到主屏幕”、WebView 壳是能做能测的;
真原生 iOS 需要 Xcode、Android 需要 Android SDK、已编译的 Mac 应用
需要 Mac 环境,这些在当前 Linux VM 上编不出、测不了。
- 所以客户端角色模板里有明确要求:编不出来的平台,交付物是
Web 核心 + 该端壳代码 + 在目标机器上的构建步骤,并明确标注
“未在目标机器上编译验证”,绝不能把“代码写完了”写成“应用已发布”。
- 路线选择(真原生 / 跨平台壳 + Web 核心)必须在 G0 由用户定,
不能由某个客户端线程中途自己改路线。
- v0.5 后置占位:iOS / Android 原生不在 MVP 内,交付物不是
“Web 核心 + 该端壳代码 + 在目标机器上的构建步骤”,而是后置占位说明:
写清该端以后才接入、接入条件是什么、目标机器验证步骤待 G8 新端接入时
再定,并明确标注“未编译 / 未验证、未发布”。旧的“壳代码 + 构建步骤”
写法自 v0.5 起废止,不得再把 iOS / Android 写成 MVP 交付端,
绝不能把“代码写完了”写成“应用已发布”。
- 路线选择(web + PWA / WebView 壳,iOS / Android 原生后置)必须在 G0
由用户定,不能由某个客户端线程中途自己改路线、自己把原生端加回 MVP。
## 校验(协调员每过一个门禁自查一次)
@@ -470,11 +637,23 @@ tests/ # QA 线程专属,含跨端一致性用例
发布打 tag 了吗,回滚方案是 revert 或重部署上一 tag、而不是 force-push 吗?
密钥进代码、commit、命令行了吗?.gitignore 在首 commit 前检查了吗?
- 验收清单是不是用户亲手确认的?有没有一项是协调员替用户勾的?
- 分阶段走了吗?G3.5 没过就开了 G4b / G4c 吗?
- 分阶段走了吗?G3.5 没过就开了 G4b 吗?G4c 是不是仍被写成了 MVP 交付端?
- v0.3 新增项:派生校验表 8 项全填且贴进了提示词吗?精简包所含章节
在提示词里列出了吗?QA 单端复核报告和跨端一致性矩阵都齐了吗?
agent 测试清单归属对吗?决策记录是只追加的 `docs/decisions.md` 吗?
web 版上手文档在 G4a 交了吗?v1.1 交接清单三项齐了吗?
- v0.5 新增项:G6→G7 的条件齐了吗(用户验收已确认或不通过项已列入
下一轮待办并经用户确认 + 发布记录与回滚方式齐全 + 监控 / 日志 /
成本口径已定)?G7 运维手册齐了吗,热修复是不是只按回归清单重跑、
回滚触发是否命中写了吗?G7→G8 的条件齐了吗(运维观察期结论已写 +
v1.1 交接清单齐全)?G8 结论是不是“下一轮 G0-G6 输入已冻结齐全”,
而不是“下一版已发布”?跨视口 E2E 的矩阵行是不是手机 / 平板 / 桌面
视口?开源优先查过许可证、维护状态、体积、安全并记入架构了吗,
选型是不是优先 MIT/Apache、避 SSPL?默认栈是不是 TypeScript 全栈
(Vite + React + TypeScript、Fastify + TypeScript 严格模式、
PostgreSQL、Drizzle 或 Prisma 二选一、Vitest),G2 冻结后有没有
未经用户特别要求就换语言?iOS / Android 是不是仍写成后置占位,
未编译 / 未验证有没有标注为未发布?
有一项为否,就停在当前门禁,不进入下一阶段。
## 附录:角色模板(播种随附版)
@@ -488,7 +667,10 @@ tests/ # QA 线程专属,含跨端一致性用例
本附录同时是 v0.4 全自动模式的一部分:正文的“全自动模式”一节
(FULL_AUTO_ENABLED、一次授权、CI 自动修复、回滚)已同步进
协调员章节,正文与附录不一致就是不合格。
(附录正文由生成脚本从 `templates/roles/` 原样拼接,见 CHANGELOG。)
本附录同时是 v0.5 版的一部分:正文的 G7、G8、“已定口径”
(跨视口 E2E、开源优先、TypeScript 全栈、iOS / Android 后置)
已同步进协调员、QA、验收、运维、迭代章节,正文与附录不一致
就是不合格。
---
@@ -513,10 +695,18 @@ full-auto-executor + installation id。质量门禁全部自动且阻塞合并
## 你必须先做的事
1. 按 `software-engineering` 技能的 G0 问卷问清:目标用户、核心能力、
客户端清单、MVP 范围、技术路线(真原生 / 跨平台壳 + Web 核心),
以及 agent 类产品的执行模型、权限边界、审批模型。六问缺一问,G0 不算过。
客户端清单、MVP 范围、技术路线(v0.5:web + PWA / WebView 壳,
iOS / Android 原生后置),以及 agent 类产品的执行模型、权限边界、
审批模型。六问缺一问,G0 不算过。
用户确认前,不派生任何开发线程。用户没回复时你等,不按假设推进。
2. 建待办文件 `docs/swe-todos.md`:G0 到 G6 每个阶段的任务、负责人(角色)、
已定口径(v0.5,正文“已定口径”一节同步于此):重心是 web + React
+ 多端自适应;默认后端是 TypeScript 全栈(Vite + React + TypeScript、
Fastify + TypeScript 严格模式、PostgreSQL、Drizzle 或 Prisma 二选一、
Vitest、OpenAPI 或共享类型),G2 冻结后不准中途换,只有用户特别要求
时才换语言,agent 不得以“更合适”为由换;开源优先(先查开源,查
许可证、维护状态、体积、安全,优先 MIT/Apache,避 SSPL / 商业重型,
选型记入架构);codex-app-server 本身保持 Python,不为统一语言重写。
2. 建待办文件 `docs/swe-todos.md`:G0 到 G8 每个阶段的任务、负责人(角色)、
完成定义。之后所有状态以这份待办为准,不以对话为准。
你是待办文件的唯一写作者,子线程只在结尾报告里写 TODO-UPDATE,
你核对证据后才勾选。不要虚构任何待办标记语法,不要依赖模型会自动写标记块。
@@ -542,16 +732,30 @@ full-auto-executor + installation id。质量门禁全部自动且阻塞合并
在 G3 阶段就参与契约测试,不要等到 G4 才对接。
- G3.5:可行性 spike。核心链路真跑通(agent 工具就是任务能创建、能跑出进度、
能取消、能回结果)才能扩端,跑不通先修核心或缩 MVP。
- G4a:web 先行 1 个线程。G4b:桌面壳 macOS / Windows 各 1 个线程。
G4c:移动端 iOS / Android 各 1 个线程。用户明确签字接受并行成本和风险时,
才可以在记录里写明例外原因后并行开 G4b / G4c。
- G5:QA 分单端复核和跨端 E2E,安全检查点单独签字。
- G4a:web 先行 1 个线程。G4b:桌面壳 1 个线程(先 web + PWA / WebView 壳,
不做已编译原生应用)。G4c:v0.5 起为后置占位,不在 MVP 内派生;
iOS / Android 原生以后才以新端身份在 G8 接入时再开一轮 G4c。
用户明确签字接受并行成本和风险时,才可以在记录里写明例外原因后
并行开 G4a / G4b,该例外绝不把 iOS / Android 原生重新写回 MVP 交付端。
- G5:QA 分单端复核和跨视口 E2E,安全检查点单独签字。
单端复核交付物是逐端复核报告(每端通过 / 不通过 + 证据 + 未复核项),
归单端复核的 agent 测试:沙箱越界、危险动作审批、token / 配额超限;
跨端 E2E 交付物是跨端一致性矩阵 + 缺陷清单 + 回归清单,
归跨端 E2E 的 agent 测试:长任务超时和取消、断网续跑、模型 503 重试。
两部分交付物缺一不算 G5 通过。
- G6:你按端分别准备验收清单和演示产物,交用户逐项确认;发布和回滚也按端分开记。
跨视口 E2E 交付物是跨端一致性矩阵(矩阵的行是手机 / 平板 / 桌面浏览器宽度:
同一任务、同一数据在各视口结果、文案、状态词、同步状态是否一致)
+ 缺陷清单 + 回归清单,归跨视口 E2E 的 agent 测试:长任务超时和取消、
断网续跑、模型 503 重试。两部分交付物缺一不算 G5 通过。
(旧文“跨端 E2E 跑遍各端”自 v0.5 起改为跨视口 E2E,矩阵名保留、行改为视口。)
- G6:你为 web 单端准备验收清单和演示产物,交用户逐项确认;
发布和回滚为 web 单端记录;iOS / Android 原生只留后置占位,不进本轮发布。
- G7:运维线程 1 个(附录 09-ops),交付运维手册、问题清单、热修复记录、
回滚触发结论。门禁衔接 G6→G7 的条件是用户验收已确认(或不通过项
已列入下一轮待办并经用户确认)+ 发布记录与回滚方式齐全 + 监控 /
日志 / 成本口径已定,三项缺一不进 G7。
- G8:迭代线程 1 个(附录 10-iteration),交付 v1.1 交接清单终版与
下一轮 G0-G6 输入冻结清单。门禁衔接 G7→G8 的条件是运维观察期结论已写
(问题清单、热修复记录、回滚触发是否命中)+ v1.1 交接清单齐全,
两项缺一不进 G8;G8 的完成不是下一版已发布,是下一轮 G0-G6 的输入
已冻结齐全。
## 你的合并规则(评审与执行拆分)
@@ -593,6 +797,8 @@ full-auto-executor + installation id。质量门禁全部自动且阻塞合并
每个门禁一份简短判定:过了哪个门、证据是什么、下一阶段派生哪几个线程、
有什么风险和未完成项。G6 的交付物是用户确认过的验收清单,不是你自己勾的清单。
G7 的交付物是运维手册与观察期结论(含热修复记录、回滚触发是否命中);
G8 的交付物是 v1.1 交接清单终版与下一轮 G0-G6 输入冻结清单,不是下一版发布证明。
---
@@ -694,10 +900,21 @@ full-auto-executor + installation id。质量门禁全部自动且阻塞合并
6. 错误 taxonomy:至少区分模型失败、工具失败、用户取消、超时、权限拒绝、配额超限,
每个错误给固定错误码和各端统一提示文案,同一错误在各端不得换名字。
7. 技术栈表:每端用什么栈、共享核心用什么语言、壳用什么方案,冻结后不擅自换栈。
v0.5 默认栈(正文“已定口径”同步于此):前端 Vite + React + TypeScript、
后端 Fastify + TypeScript 严格模式、PostgreSQL、Drizzle 或 Prisma 二选一、
测试 Vitest、API 用 OpenAPI 或共享类型;G2 冻结后不准中途换,只有
用户特别要求时才换语言,agent 不得以“更合适”为由换。
开源优先:每个模块先查开源(许可证、维护状态、体积、安全),优先
MIT/Apache,避 SSPL / 商业重型,选型记入技术栈表或决策记录。
边界:codex-app-server 本身保持 Python,不为统一语言重写;上面
的 TypeScript 默认栈只适用于本技能新做的产品。
8. 每端能力矩阵:后台执行、通知、文件权限等能力在每端是否提供、受什么限制,
做不到的端写明降级方案,不写“全端一致”蒙过去。
做不到的端写明降级方案,不写“全端一致”蒙过去;v0.5 默认矩阵只有
web 视口(手机 / 平板 / 桌面),iOS / Android 原生后置占位,不列为已提供端。
9. 跨端一致性规则:同一数据、同一任务在各端应该表现一致的地方列出来,
差异处要说明是刻意差异还是待统一。
差异处要说明是刻意差异还是待统一;v0.5 下“各端”首先指跨视口
(手机 / 平板 / 桌面浏览器宽度),规则是同一任务、同一数据在各视口
结果、文案、状态词、同步状态是否一致。
10. 共享核心分层:共享逻辑(状态机、事件解析、重试策略)归共享核心线程;
各端适配器(token 存法、通知、文件权限)归各客户端线程,不要混成一层。
@@ -788,10 +1005,13 @@ TODO-UPDATE 要求,缺一项就不发任务)。派生提示词里的精简
按目标机器的构建步骤交付。没有 Mac 编译环境时,明确标注未验证。
- **Windows**:同 macOS,路线以 G0 为准。安装包、窗口行为、系统托盘
等如在 MVP 内要实现,如不在要写进已知问题,不假装有。
- **iOS**:同上。没有 Xcode 环境时,交付物是 Web 核心 + iOS 壳代码
+ 在 Mac 上的构建步骤,并标注“未在真机 / 模拟器上编译验证”。
- **Android**:同上。没有 Android SDK 环境时,交付物是 Web 核心 +
Android 壳代码 + 构建步骤,并标注“未编译验证”。
- **iOS**(v0.5 后置占位,iOS/Android 后置):不在 MVP 内,不派生本端
开发线程;只留后置占位说明(以后才接入、接入条件待 G8 新端接入时
再定),并标注“未编译 / 未验证、未发布”。旧的“Web 核心 + iOS 壳代码
+ 在 Mac 上的构建步骤”写法自 v0.5 起废止,不得再把 iOS 写成 MVP 交付端。
- **Android**(v0.5 后置占位,iOS/Android 后置):同 iOS,不在 MVP 内;
只留后置占位说明,并标注“未编译 / 未验证、未发布”。旧的
“Web 核心 + Android 壳代码 + 构建步骤”写法自 v0.5 起废止。
## 交付前自测(缺一项不算完成)
@@ -867,7 +1087,7 @@ agent 类产品还要参与 G3.5 可行性 spike:任务能创建、能跑出
## 附录角色:06-qa(来源 templates/roles/06-qa.md)
# 角色模板:QA / 测试(单端复核 + 跨端 E2E,可分 2 个线程)
# 角色模板:QA / 测试(单端复核 + 跨视口 E2E,可分 2 个线程)
## 只能写
@@ -881,12 +1101,14 @@ agent 类产品还要参与 G3.5 可行性 spike:任务能创建、能跑出
QA 正式分两部分,各自交付物写死,缺一不算 G5 通过:
① 单端复核:逐端复核各客户端的自测证据是否属实,交付物是逐端复核报告
(每端通过 / 不通过 + 证据 + 未复核项);
② 跨端 E2E:同一 agent 任务、同一份数据跑遍各端,交付物是跨端一致性矩阵
(各端结果、文案、状态词、同步状态是否一致;不一致的标明是缺陷还是刻意差异)
② 跨视口 E2E(v0.5 已定口径,原跨端 E2E 改为跨视口 E2E):
同一 agent 任务、同一份数据跑遍手机 / 平板 / 桌面浏览器宽度,
交付物是跨端一致性矩阵(矩阵的行是视口:各视口结果、文案、
状态词、同步状态是否一致;不一致的标明是缺陷还是刻意差异)
+ 缺陷清单 + 回归清单。
2. agent 专属测试(缺一项不算测完),归属如下:
归单端复核(每端都要过):沙箱越界、危险动作审批、token / 配额超限;
归跨端 E2E(同一任务跨端行为一致):长任务超时和取消、断网续跑、模型 503 重试。
归跨视口 E2E(同一任务跨视口行为一致):长任务超时和取消、断网续跑、模型 503 重试。
4. 安全检查点(G5 单独签字):权限边界是否按契约实现、密钥是否外泄、
agent 是否能读工作目录外文件。安全检查不算 QA 的附带项。
5. 缺陷清单:每个缺陷写清复现步骤、影响客户端、严重程度、归属线程。
@@ -895,14 +1117,15 @@ agent 类产品还要参与 G3.5 可行性 spike:任务能创建、能跑出
## 未编译端的口径
iOS / Android / Mac 在 Linux 主机上编不出来时,你的结论写
“代码评审 + Web 核心验证”,不写“构建通过”。没测的端和用例单独列出,
iOS / Android 原生后置占位不进 QA 通过表,标注“未编译 / 未验证、
未发布”;Mac 在 Linux 主机上编不出来时,你的结论写
“代码评审 + Web 核心验证”,不写“构建通过”。没测的视口和用例单独列出,
不要把“没测”写成“通过”。
## 完成定义
- 所有 PRD 验收标准都有对应测试用例,不是只测了 happy path。
- 跨端矩阵已覆盖全部已选客户端,缺失的端要写明为什么没测。
- 跨端矩阵已覆盖手机 / 平板 / 桌面全部视口,缺失的视口要写明为什么没测。
- 缺陷清单已交协调员,严重缺陷未修好前不建议进入验收。
## 禁止
@@ -922,16 +1145,18 @@ iOS / Android / Mac 在 Linux 主机上编不出来时,你的结论写
1. 按 `templates/artifacts/acceptance-checklist.md` 生成本项目的验收清单,
每一项对应 PRD 里的一条验收标准,不额外加、不悄悄删。
2. 每个已选客户端准备一份演示产物:怎么启动、测哪个核心流程、
已知问题是什么、哪些平台未编译验证。web 演示可真跑,
未编译端审代码和构建步骤,两者效力不同,分开标注,不能混成一张“通过”表。
3. 发布说明草稿,按端分别写:新能力、已知问题、回滚方式
(至少写清“出问题先停哪个端”)。web 部署、桌面安装包分发、
应用商店审核是三条流水线,分开记录,不要写成一次全上。
4. 每端上手文档:每端一份,写清启动、登录、核心流程、常见问题;
web 版在 G4a 交付时先交,桌面、移动版在各自 G4b / G4c 交付时补齐。
2. 为 web 单端准备一份演示产物:怎么启动、测哪个核心流程、
已知问题是什么、哪些平台未编译验证。web 演示可真跑;
iOS / Android 原生只留后置占位,不进本轮演示产物,不混成一张“通过”表。
3. 发布说明草稿,web 单端写:新能力、已知问题、回滚方式
(至少写清“出问题先停 web 端”)。web 部署的回滚方式单独记录;
桌面安装包分发、应用商店审核不在本轮流水线内,不写成已走完。
4. 上手文档:web 版一份,写清启动、登录、核心流程、常见问题;
web 版在 G4a 交付时先交,不拖到 G6 才现写;iOS / Android 原生后置,
不在本轮补移动版上手文档。
5. v1.1 交接清单:未修缺陷(带归属和严重程度)、开放问题
(含任务间问答里未关闭的假设)、下轮待办;三项缺一不算 G6 收尾完成。
(含任务间问答里未关闭的假设)、下轮待办;三项缺一不算 G6 收尾完成;
G8 要把它更新为含 G7 结论的终版,三项缺一仍不算齐。
## 用户确认规则
@@ -951,8 +1176,9 @@ iOS / Android / Mac 在 Linux 主机上编不出来时,你的结论写
## 按端发布与回滚(验收)
- 发布按端分别做:每端发布时打 tag,例如 v0.1.0;
发布说明从已合 PR 汇总,不凭记忆重写;发布记录里写清端、tag、PR 号、执行人。
- v0.5 起发布为 web 单端:web 发布时打 tag,例如 v0.1.0;
发布说明从已合 PR 汇总,不凭记忆重写;发布记录里写清端(web)、tag、PR 号、执行人;
iOS / Android 原生后置占位不打发布 tag。
- 回滚是 revert 对应 PR,或重部署上一个 tag;绝不是 force-push 回退主线;
回滚后重新走合并门(CI、评审)才能再发布。
- 合并记录复核:PR 号、合并提交 hash、CI 运行链接、执行人缺一项,
@@ -991,3 +1217,110 @@ iOS / Android / Mac 在 Linux 主机上编不出来时,你的结论写
- 不在共享逻辑里写某端专属代码,专属逻辑留给各端适配器。
- 不改契约迎合实现;实现不了契约时向协调员提变更请求。
---
## 附录角色:09-ops(来源 templates/roles/09-ops.md,v0.5 新增)
# 角色模板:运维(G7,1 个线程)
你是 G7 发布后运维与观察期的运维线程。你的产出是运维手册、
问题清单、热修复记录、回滚触发结论。你只写运维与热修复范围,
不直接改契约、不冒充发布。
## 只能写
`docs/ops/`(运维手册、问题清单、热修复记录)。`contracts/`、
业务代码、他人目录对你只读;想改契约走协调员的变更协议,
想发新版交协调员走下一轮待办,不自己推主线、自己发版。
## 产出(G7)
1. 运维手册:与正文“G7 发布后运维与观察期”末尾的运维手册模板
同款,含服务与端、监控、日志、错误清单、成本与配额、
用户反馈、热修复、回滚触发八项,缺一项 G7 不算通过。
监控要写清监控项、阈值、告警接收人、查看周期;成本与配额
要写清计费口径、配额上限、将满时的动作;用户反馈要写清
渠道、周期、转待办规则。
2. 问题清单:错误分级、复现步骤、归属线程、处理时限;同一错误
重复出现要升级,不静默放过。
3. 热修复记录:每次热修复写清修了什么、按回归清单重跑了哪些
用例、结果是什么;热修复只按回归清单重跑,不重开整轮。
4. 回滚触发结论:回滚触发条件是否命中写成一句话;命中时按
G6 回滚方式处理(先停 web 端、revert 对应 PR 或重新部署上一 tag,
绝不 force-push),并重新走合并门才能再发布。
5. 观察期结论:问题清单、热修复记录、回滚触发是否命中三项齐全,
才交协调员判定 G7→G8;结论缺一项,G8 不开。
## 热修复与严重问题回路
- 小修走热修复回 G7:修完只重跑回归清单里受影响的用例,
通过即回 G7 继续观察。
- 严重问题回 G6 / G5:热修复修不好的,交协调员回 G6 重新验收
或回 G5 重新联调回归,修完按门禁重新过 G6 → G7,不在 G7 里硬扛。
## 完成定义与禁止
- 运维手册八项齐全;观察期结论三项齐全;结尾报告带 TODO-UPDATE。
- 禁止:不直接改契约、不冒充发布、不把“已观察”写成“已发布新版”、
不把未验证写成已验证;未编译 / 未验证一律标注未发布。
- 已定口径同步(v0.5):本线程不改默认栈与重心;默认栈仍是
TypeScript 全栈(Vite + React + TypeScript、Fastify + TypeScript
严格模式、PostgreSQL、Drizzle 或 Prisma 二选一、Vitest),
只有用户特别要求时才换语言;开源优先仍适用(先查开源,查许可证、
维护状态、体积、安全,优先 MIT/Apache,避 SSPL);跨视口 E2E
的矩阵行仍是手机 / 平板 / 桌面视口;iOS/Android 后置仍是后置占位,
不在本轮运维里把原生端写回交付端。
---
## 附录角色:10-iteration(来源 templates/roles/10-iteration.md,v0.5 新增)
# 角色模板:迭代(G8,1 个线程)
你是 G8 迭代与规模化的迭代线程。你的产出是 v1.1 交接清单终版
与下一轮 G0-G6 输入冻结清单。G8 的完成不是下一版已发布,
是下一轮 G0-G6 的输入已冻结齐全。
## 只能写
`docs/`(v1.1 交接清单、下一轮输入清单、决策记录提议)。
业务代码、契约对你只读;契约升版走变更协议,不直接改契约发 v2。
## 产出(G8)
1. v1.1 交接清单终版:与正文“G8 迭代与规模化”末尾的
v1.1 交接清单模板同款,三项缺一不算齐——① 未修缺陷
(带归属和严重程度)、② 开放问题(含任务间问答里未关闭的
假设、G7 观察问题、用户反馈)、③ 下一轮待办(G6 不通过项、
G7 未闭环项、用户反馈转来的项汇总);另附契约变更输入、
新端接入输入、规模与废弃输入。
2. 契约 v1→v2 变更协议输入:改什么、为什么、影响哪些端、
是否向后兼容四项写清,交协调员批准后才升版;G8 只冻结输入,
不直接改契约、发 v2。
3. 新端接入输入:iOS / Android 原生以后才以新端身份进一轮 G4c,
不塞进 MVP;写清新端能力清单、与 web 核心的复用关系、
目标机器构建与验证步骤、未验证标注规则;iOS/Android 后置
占位在此更新为接入条件,不提前写成已交付。
4. 规模与性能输入:下一轮规模目标、性能基线与瓶颈、扩容或降级方案;
没有基线的“能扩容”不算结论。
5. 废弃策略输入:要废弃的能力、接口、端,写清废弃时间表、
替代方案、用户通知方式;先通知、再标记废弃、再下线。
6. 门禁衔接:G7→G8 的条件是运维观察期结论已写(问题清单、
热修复记录、回滚触发是否命中)+ v1.1 交接清单齐全;G8 完成时
交协调员一份“下一轮 G0-G6 输入已冻结齐全”的结论,结论里
不写“下一版已发布”。
## 完成定义与禁止
- v1.1 交接清单三项齐全;下一轮输入清单已冻结;结尾报告带 TODO-UPDATE。
- 禁止:不把 G8 完成写成下一版已发布;不直接改契约;不把新端
接入写成 MVP 已交付;未编译 / 未验证一律标注未发布。
- 已定口径同步(v0.5):重心仍是 web + React + 多端自适应;
跨视口 E2E 仍是手机 / 平板 / 桌面视口;开源优先仍适用
(先查开源,查许可证、维护状态、体积、安全,优先 MIT/Apache,
避 SSPL);默认栈仍是 TypeScript 全栈(Vite + React + TypeScript、
Fastify + TypeScript 严格模式、PostgreSQL、Drizzle 或 Prisma 二选一、
Vitest、OpenAPI 或共享类型),G2 冻结后不准中途换,只有
用户特别要求时才换语言;codex-app-server 本身保持 Python,
不为统一语言重写。
@@ -0,0 +1,82 @@
"""software-engineering 技能 v0.5:G7/G8 关键词断言(轻量)。
只断言正文与附录都含有 v0.5 的关键概念,不逐字背诵全文:
版本号与上一版、G7 运维与 G8 迭代、运维手册与 v1.1 交接清单、
热修复与回滚触发、跨视口 E2E、开源优先与许可证口径、
TypeScript 默认栈与用户特别要求例外、iOS/Android 后置。
正文改了附录没同步时,附录部分就会失败。
门禁衔接断言单独检查:G6→G7 与 G7→G8 的条件词必须同时
出现在正文门禁表附近与附录协调员章节。
角色断言检查附录含 09-ops 与 10-iteration 章节标题。
"""
import unittest
from pathlib import Path
SKILL = Path(__file__).resolve().parents[1] / "skills" / "software-engineering" / "SKILL.md"
# 正文与附录都要有的关键词(词形与技能正文一致)
BOTH = ("v0.5", "G7", "G8", "运维手册", "v1.1 交接清单",
"热修复", "回滚触发", "跨视口", "开源优先", "MIT/Apache",
"SSPL", "TypeScript", "Fastify", "Drizzle 或 Prisma",
"Vitest", "用户特别要求", "iOS/Android 后置")
# 门禁衔接:正文与附录协调员章都要出现
GATES = ("G6→G7", "G7→G8")
class SoftwareEngineeringG7G8TestCase(unittest.TestCase):
def test_g7g8_in_body_and_appendix(self):
text = SKILL.read_text(encoding="utf-8")
main, sep, appendix = text.partition("## 附录:角色模板")
self.assertTrue(sep, "appendix marker missing")
self.assertIn("v0.4", main, "header must name the previous version")
self.assertIn("全自动模式", main, "header must keep v0.4 full-auto content")
self.assertIn("v0.3", main, "header must keep v0.3 content")
for kw in BOTH:
self.assertIn(kw, main, kw)
self.assertIn(kw, appendix, "appendix: " + kw)
def test_gate_transitions_in_body_and_coordinator(self):
text = SKILL.read_text(encoding="utf-8")
main, sep, appendix = text.partition("## 附录:角色模板")
self.assertTrue(sep, "appendix marker missing")
# 附录协调员章:从 00-coordinator 到下一个附录角色标题之间
coord_start = appendix.index("00-coordinator")
coord_end = appendix.index("## 附录角色:01-", coord_start)
coordinator = appendix[coord_start:coord_end]
for kw in GATES:
self.assertIn(kw, main, kw)
self.assertIn(kw, coordinator, "coordinator appendix: " + kw)
# 门禁条件词:G6→G7 侧与 G7→G8 侧的关键条件
self.assertIn("用户验收已确认", main)
self.assertIn("用户验收已确认", coordinator)
self.assertIn("运维观察期结论已写", main)
self.assertIn("运维观察期结论已写", coordinator)
self.assertIn("回滚触发是否命中", main)
self.assertIn("回滚触发是否命中", coordinator)
def test_g7g8_roles_in_appendix(self):
text = SKILL.read_text(encoding="utf-8")
_, sep, appendix = text.partition("## 附录:角色模板")
self.assertTrue(sep, "appendix marker missing")
self.assertIn("## 附录角色:09-ops", appendix)
self.assertIn("## 附录角色:10-iteration", appendix)
self.assertIn("下一轮 G0-G6", appendix)
self.assertIn("不是下一版已发布", appendix)
self.assertIn("不直接改契约", appendix)
def test_g7g8_templates_in_body_and_appendix(self):
text = SKILL.read_text(encoding="utf-8")
main, sep, appendix = text.partition("## 附录:角色模板")
self.assertTrue(sep, "appendix marker missing")
self.assertIn("运维手册模板", main)
self.assertIn("运维手册模板", appendix)
self.assertIn("v1.1 交接清单模板", main)
self.assertIn("v1.1 交接清单模板", appendix)
self.assertIn("未修缺陷", main)
self.assertIn("未修缺陷", appendix)
if __name__ == "__main__":
unittest.main()