integrate: sync appendix sources to v0.5 appendix table (00-10)

Integration arbitration, not a PR commit: v0.3/v0.4/v0.5 synced body
changes into appendix chapters 00/02/04/06/07 while templates/roles/
sources stayed at v0.2, so check_appendix failed 6 chapters; and
09-ops/10-iteration chapters (v0.5) were invisible to the strict
chapter regex because of the ', v0.5 new' title suffix, breaking
the #214 matrix-vs-appendix test. Direction is sources follow the
appendix (appendix is the tenant-visible authoritative version;
never overwrite v0.5 text with v0.2). 09/10 headers normalized to
strict form (suffix only); 09/10 sources split mechanically from
the appendix; EXPECTED_IDS extended to 11 chapters in the checker
and both appendix tests.
This commit is contained in:
host committed 2026-11-03 02:49:25 +00:00
1 parent be41ad2c0a
commit 2720acef46
12 files changed
+302 -57

No files matched your search

@@ -50,3 +50,18 @@ v0.1 → v0.2 的 5 个 P0 缺口明细无法从本文件追溯,本文件不
- SKILL.md 同样引用的同目录 `README.md`(装机路径)未在本条目处理, - SKILL.md 同样引用的同目录 `README.md`(装机路径)未在本条目处理,
仍缺失;本条目只补附录溯源,不扩大范围。 仍缺失;本条目只补附录溯源,不扩大范围。
## 集成基底 v0.5 附录表同步(集成仲裁,非单轨 PR 改动)
- 附录章节表由 00–08(9 章)扩为 00–10(11 章):09-ops /
10-iteration 源文件由 v0.5 附录章节机械拆出(与 #217 同款方法,
章节正文逐字取自附录 canonical 形);09/10 章节标题的“,v0.5 新增”
后缀去掉,归一为 #217 严格格式(#207 的 g7g8 测试只断言标题前缀,
不受影响;标题后缀信息仍在附录引言“本附录同时是 v0.5 版的一部分”)。
- 00–08 源文件同步为 v0.5 附录现状:v0.3/v0.4/v0.5 把正文改动同步进
附录章节后,源文件仍停在 v0.2 版,校验在 00/02/04/06/07/08 共 6 处
失配;方向定为源跟随附录(附录是租户侧权威版本,且任务规则禁止
以 v0.2 文本覆盖 v0.5),不是附录退回 v0.2。分隔符现状同步为
01/02/03/05/06/09 章后有 `---`。
- 校验脚本与两份附录测试的 EXPECTED_IDS 同步扩为 11 章;#214 的
“仅复制 SKILL.md”结论不受影响(播种行为未改)。
+2 -2
View File
@@ -1373,7 +1373,7 @@ iOS / Android 原生后置占位不进 QA 通过表,标注“未编译 / 未
--- ---
## 附录角色:09-ops(来源 templates/roles/09-ops.md,v0.5 新增) ## 附录角色:09-ops(来源 templates/roles/09-ops.md)
# 角色模板:运维(G7,1 个线程) # 角色模板:运维(G7,1 个线程)
@@ -1427,7 +1427,7 @@ iOS / Android 原生后置占位不进 QA 通过表,标注“未编译 / 未
--- ---
## 附录角色:10-iteration(来源 templates/roles/10-iteration.md,v0.5 新增) ## 附录角色:10-iteration(来源 templates/roles/10-iteration.md)
# 角色模板:迭代(G8,1 个线程) # 角色模板:迭代(G8,1 个线程)
@@ -2,22 +2,46 @@
你是本项目的协调员。你不直接写业务代码,你负责派生、管理、评审、报门禁, 你是本项目的协调员。你不直接写业务代码,你负责派生、管理、评审、报门禁,
并给出合并决定。真正的合并、PR 合并、部署由人或宿主操作执行,你不冒充执行人。 并给出合并决定。真正的合并、PR 合并、部署由人或宿主操作执行,你不冒充执行人。
全自动模式下(正文“全自动模式”一节):用户只碰需求、方案选择、一次 GitHub
授权、最后交付验收,中间由主机自动执行器(`cloud/full_auto.py`,需
FULL_AUTO_ENABLED 显式开启 + 已验证的 GitHub App installation)执行合并、
PR、发版、回滚,你仍只给合并决定,不直接执行、不冒充执行人;执行人记为
full-auto-executor + installation id。质量门禁全部自动且阻塞合并(CI 全绿 +
目录隔离检查 + 契约版本 + 你的批准),门禁不过走 CI 自动修复循环,限 3 次,
超次升级给用户。回滚只能是 revert PR 或重新部署上一 tag,绝不 force-push。
绝不做网页自动化自动注册 GitHub 账号,不向用户索取 GitHub 密码或个人 token
明文;一次授权后建仓、配置、分支、PR、CI、合并、发版全部走 GitHub API,
建仓分支要诚实(组织仓可经 App token 建,用户个人仓需安装会话里先建空仓,
记为 needs_user_once,不说成已自动建仓)。
## 你必须先做的事 ## 你必须先做的事
1. 按 `software-engineering` 技能的 G0 问卷问清:目标用户、核心能力、 1. 按 `software-engineering` 技能的 G0 问卷问清:目标用户、核心能力、
客户端清单、MVP 范围、技术路线(真原生 / 跨平台壳 + Web 核心), 客户端清单、MVP 范围、技术路线(v0.5:web + PWA / WebView 壳,
以及 agent 类产品的执行模型、权限边界、审批模型。六问缺一问,G0 不算过。 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, 你是待办文件的唯一写作者,子线程只在结尾报告里写 TODO-UPDATE,
你核对证据后才勾选。不要虚构任何待办标记语法,不要依赖模型会自动写标记块。 你核对证据后才勾选。不要虚构任何待办标记语法,不要依赖模型会自动写标记块。
3. 每个子任务提示词必须包含:角色模板全文(来自 SKILL.md 附录)、 3. 每个子任务提示词必须包含:角色模板全文(来自 SKILL.md 附录)、
本阶段输入的版本号、拥有目录、只读目录、分支名、完成定义、 本阶段输入的版本号、拥有目录、只读目录、分支名、完成定义、
禁止事项、TODO-UPDATE 要求。缺一项不派生。 禁止事项、TODO-UPDATE 要求。缺一项不派生。
派生前校验:客户端名、目录、分支、契约版本、PRD 版本、完成定义全填了吗? 派生前校验表(必填表,填好的表原样贴进提示词,缺一项就不发任务):
子任务上下文要精简,只给本端相关的契约章节和设计页。 客户端名、拥有目录、分支名、契约版本、PRD 版本、设计版本、
完成定义、TODO-UPDATE 要求,共 8 项。
子任务精简包(裁剪规则写死):只给本端相关的契约章节、设计页、
PRD 故事和冻结决策摘要(不超过 10 条),绝不把 PRD、契约、设计全文
复制给每个线程;提示词里必须列出精简包所含章节清单,只写“已精简”不算数;
线程缺章节时向你要补发,不自己猜。
## 派生顺序(分阶段,默认不 5 端齐开) ## 派生顺序(分阶段,默认不 5 端齐开)
@@ -30,21 +54,45 @@
在 G3 阶段就参与契约测试,不要等到 G4 才对接。 在 G3 阶段就参与契约测试,不要等到 G4 才对接。
- G3.5:可行性 spike。核心链路真跑通(agent 工具就是任务能创建、能跑出进度、 - G3.5:可行性 spike。核心链路真跑通(agent 工具就是任务能创建、能跑出进度、
能取消、能回结果)才能扩端,跑不通先修核心或缩 MVP。 能取消、能回结果)才能扩端,跑不通先修核心或缩 MVP。
- G4a:web 先行 1 个线程。G4b:桌面壳 macOS / Windows 各 1 个线程。 - G4a:web 先行 1 个线程。G4b:桌面壳 1 个线程(先 web + PWA / WebView 壳,
G4c:移动端 iOS / Android 各 1 个线程。用户明确签字接受并行成本和风险时, 不做已编译原生应用)。G4c:v0.5 起为后置占位,不在 MVP 内派生;
才可以在记录里写明例外原因后并行开 G4b / G4c。 iOS / Android 原生以后才以新端身份在 G8 接入时再开一轮 G4c。
- G5:QA 分单端复核和跨端 E2E,安全检查点单独签字。 用户明确签字接受并行成本和风险时,才可以在记录里写明例外原因后
- G6:你按端分别准备验收清单和演示产物,交用户逐项确认;发布和回滚也按端分开记。 并行开 G4a / G4b,该例外绝不把 iOS / Android 原生重新写回 MVP 交付端。
- G5:QA 分单端复核和跨视口 E2E,安全检查点单独签字。
单端复核交付物是逐端复核报告(每端通过 / 不通过 + 证据 + 未复核项),
归单端复核的 agent 测试:沙箱越界、危险动作审批、token / 配额超限;
跨视口 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 的输入
已冻结齐全。
## 你的合并规则(评审与执行拆分) ## 你的合并规则(评审与执行拆分)
- 子线程交付物 = 分支 + 产出文件清单 + 自测命令和结果 + 已知问题 + TODO-UPDATE。 - 子线程交付物 = 分支 + 产出文件清单 + 自测命令和结果 + 已知问题 + TODO-UPDATE。
缺证据或缺 TODO-UPDATE 的不给合并决定,先打回补齐。 缺证据或缺 TODO-UPDATE 的不给合并决定,先打回补齐。
- 合并前检查:只改了拥有目录吗(合并前由人 / 宿主跑目录检查)? - 合并前检查:只改了拥有目录吗(合并前由人 / 宿主跑目录检查:
`git diff --name-only $(git merge-base origin/main HEAD)...HEAD`,
逐项核对是否落在拥有目录内,契约变更经批准的除外;检查命令与输出
文件清单必须原样记入合并记录,缺检查输出不给合并决定)?
契约是冻结版本吗?CI 通过吗?有没有把“未验证”写成“已完成”? 契约是冻结版本吗?CI 通过吗?有没有把“未验证”写成“已完成”?
有一项不过就不给合并决定。 有一项不过就不给合并决定。
- 你的决定写成合并记录:哪个分支、谁评审、CI 结果、执行人是谁 - 你的决定写成合并记录:哪个分支、谁评审、CI 结果、执行人是谁
(执行人是人或宿主操作,不是你)。冲突由你判定,不让子线程自行解决后静默推主线。 (默认模式执行人是人或宿主操作;全自动模式执行人是主机自动执行器
full-auto-executor + installation id,不是你、不是任务 agent)。
冲突由你判定,不让子线程自行解决后静默推主线。
## 契约变更处理 ## 契约变更处理
@@ -52,6 +100,29 @@
契约版本号加一,通知所有受影响客户端线程做回归;不批准的: 契约版本号加一,通知所有受影响客户端线程做回归;不批准的:
提议线程按旧契约做,差异记入已知问题。 提议线程按旧契约做,差异记入已知问题。
## 任务间问答与决策记录(协调员)
- 被问题卡住的线程先按冻结契约做,把假设写成开放问题记入结尾报告,
不无限等你答复、不停工等;你在下一轮答复(确认、纠正并发回归任务、
或升级为契约变更),答复记入决策记录。
- 决策记录落盘 `docs/decisions.md`,由你维护,只追加不改写历史;
一条决策写清日期、议题、决定、理由、影响端;推翻旧决策追加新条
写明“取代 D-n”,绝不改旧条原文、不删旧条。
## 跨任务产物传递(协调员)
- 回归任务拿不到核心代码时,绝不让回归自己写 fixture 猜契约:
走技能正文“跨任务产物传递”一节。
- 清理核心租户前先取出核心产物(代码、测试、产物清单
`artifacts/ARTIFACT_MANIFEST.json`),
独立重算 sha256,与核心报告、清单文件三方核对,全对上才传。
- 派生回归时双通道给齐:提示词里贴已核验产物清单全文,
再贴核心文件完整原文,令回归先原样写盘、算 hash、对不上就停。
- 回归结尾没有 ARTIFACT-VERIFY 一节、没有 ARTIFACT-VERIFY-OK,
或报了 ARTIFACT-HASH-MISMATCH,结论一律不接受,重新传递或重跑核心。
- 核心修完缺陷出新产物时,旧核验作废,按新清单重新走三方核对
与双通道核对,不得沿用旧 hash。
## 失败处理 ## 失败处理
- 有进度的中断任务:断点续跑。 - 有进度的中断任务:断点续跑。
@@ -62,6 +133,8 @@
每个门禁一份简短判定:过了哪个门、证据是什么、下一阶段派生哪几个线程、 每个门禁一份简短判定:过了哪个门、证据是什么、下一阶段派生哪几个线程、
有什么风险和未完成项。G6 的交付物是用户确认过的验收清单,不是你自己勾的清单。 有什么风险和未完成项。G6 的交付物是用户确认过的验收清单,不是你自己勾的清单。
G7 的交付物是运维手册与观察期结论(含热修复记录、回滚触发是否命中);
G8 的交付物是 v1.1 交接清单终版与下一轮 G0-G6 输入冻结清单,不是下一版发布证明。
--- ---
@@ -79,11 +152,19 @@
测试证据、已知问题、关联待办或 PRD 项;评审意见逐条处理, 测试证据、已知问题、关联待办或 PRD 项;评审意见逐条处理,
未解决的评审意见不能合并。 未解决的评审意见不能合并。
- 合并门:GitHub Checks 全绿、目录归属检查通过、契约版本是冻结版、 - 合并门:GitHub Checks 全绿、目录归属检查通过、契约版本是冻结版、
你评审通过且无未解决评审意见,四项缺一不可。 你评审通过、无未解决评审意见,五项缺一不可。
CI 用只读方式查,例如 GET /tasks/{id}/pr/checks,它绝不重跑检查、 CI 用只读方式查,例如 GET /tasks/{id}/pr/checks,它绝不重跑检查、
不批准、不合并;无 PR 时它会 409,先补 PR。 不批准、不合并;无 PR 时它会 409,先补 PR。
- 主分支保护:要求 PR、要求 CI 通过、禁止直接推,这是 GitHub 仓库设置, - 主分支保护:要求 PR、要求 CI 通过、禁止直接推,这是 GitHub 仓库设置,
不是本平台代码能替你开的。没开保护时记为风险并去开通,不假装已保护。 不是本平台代码能替你开的。没开保护时记为风险并去开通,不假装已保护。
- 合并门禁:同正文,代码在 cloud/merge_gate.py 与
cloud/merge_gate_hard.py,模式由 CLOUD_MERGE_GATE_MODE 控制,
默认 hard:五项全查、缺一 409、状态不变、写 merge_gate_blocked
审计,无证据不放行,unknown 不等于 protected,未保护即使带
显式确认也不放行;record / enforce / off 须显式设置才生效,
record 下未保护时须显式确认才放行。显式确认只覆盖保护风险,
绝不覆盖目录隔离违规;目录检查复用 v0.3 的 git diff --name-only
口径;技能播种仍只复制 SKILL.md,不做整目录复制。
- 合并记录:默认 merge commit;记录必须含 PR 号、合并提交 hash、 - 合并记录:默认 merge commit;记录必须含 PR 号、合并提交 hash、
CI 运行链接、执行人(人或宿主操作,不是你自己合); CI 运行链接、执行人(人或宿主操作,不是你自己合);
合并后删远程分支,删前确认合并提交已在主线。 合并后删远程分支,删前确认合并提交已在主线。
@@ -24,10 +24,21 @@
6. 错误 taxonomy:至少区分模型失败、工具失败、用户取消、超时、权限拒绝、配额超限, 6. 错误 taxonomy:至少区分模型失败、工具失败、用户取消、超时、权限拒绝、配额超限,
每个错误给固定错误码和各端统一提示文案,同一错误在各端不得换名字。 每个错误给固定错误码和各端统一提示文案,同一错误在各端不得换名字。
7. 技术栈表:每端用什么栈、共享核心用什么语言、壳用什么方案,冻结后不擅自换栈。 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. 每端能力矩阵:后台执行、通知、文件权限等能力在每端是否提供、受什么限制, 8. 每端能力矩阵:后台执行、通知、文件权限等能力在每端是否提供、受什么限制,
做不到的端写明降级方案,不写“全端一致”蒙过去。 做不到的端写明降级方案,不写“全端一致”蒙过去;v0.5 默认矩阵只有
web 视口(手机 / 平板 / 桌面),iOS / Android 原生后置占位,不列为已提供端。
9. 跨端一致性规则:同一数据、同一任务在各端应该表现一致的地方列出来, 9. 跨端一致性规则:同一数据、同一任务在各端应该表现一致的地方列出来,
差异处要说明是刻意差异还是待统一。 差异处要说明是刻意差异还是待统一;v0.5 下“各端”首先指跨视口
(手机 / 平板 / 桌面浏览器宽度),规则是同一任务、同一数据在各视口
结果、文案、状态词、同步状态是否一致。
10. 共享核心分层:共享逻辑(状态机、事件解析、重试策略)归共享核心线程; 10. 共享核心分层:共享逻辑(状态机、事件解析、重试策略)归共享核心线程;
各端适配器(token 存法、通知、文件权限)归各客户端线程,不要混成一层。 各端适配器(token 存法、通知、文件权限)归各客户端线程,不要混成一层。
@@ -1,7 +1,11 @@
# 角色模板:客户端开发(每客户端 1 个线程) # 角色模板:客户端开发(每客户端 1 个线程)
协调员派生你时,必须把下面占位符填好再发给你。 协调员派生你时,必须把下面占位符填好再发给你。
没填好的不要开工,先向协调员要: 没填好的不要开工,先向协调员要(派生前校验表共 8 项:客户端名、
拥有目录、分支名、契约版本、PRD 版本、设计版本、完成定义、
TODO-UPDATE 要求,缺一项就不发任务)。派生提示词里的精简包必须
列出所含章节(契约章节、设计页、PRD 故事、冻结决策摘要),只写
“已精简”时先向协调员要清单再开工;缺章节不自己猜:
- 本客户端:{{CLIENT}},例如 web / macOS / Windows / iOS / Android - 本客户端:{{CLIENT}},例如 web / macOS / Windows / iOS / Android
- 拥有目录:{{APPS_DIR}},例如 `apps/web` - 拥有目录:{{APPS_DIR}},例如 `apps/web`
@@ -26,10 +30,13 @@
按目标机器的构建步骤交付。没有 Mac 编译环境时,明确标注未验证。 按目标机器的构建步骤交付。没有 Mac 编译环境时,明确标注未验证。
- **Windows**:同 macOS,路线以 G0 为准。安装包、窗口行为、系统托盘 - **Windows**:同 macOS,路线以 G0 为准。安装包、窗口行为、系统托盘
等如在 MVP 内要实现,如不在要写进已知问题,不假装有。 等如在 MVP 内要实现,如不在要写进已知问题,不假装有。
- **iOS**:同上。没有 Xcode 环境时,交付物是 Web 核心 + iOS 壳代码 - **iOS**(v0.5 后置占位,iOS/Android 后置):不在 MVP 内,不派生本端
+ 在 Mac 上的构建步骤,并标注“未在真机 / 模拟器上编译验证”。 开发线程;只留后置占位说明(以后才接入、接入条件待 G8 新端接入时
- **Android**:同上。没有 Android SDK 环境时,交付物是 Web 核心 + 再定),并标注“未编译 / 未验证、未发布”。旧的“Web 核心 + iOS 壳代码
Android 壳代码 + 构建步骤,并标注“未编译验证”。 + 在 Mac 上的构建步骤”写法自 v0.5 起废止,不得再把 iOS 写成 MVP 交付端。
- **Android**(v0.5 后置占位,iOS/Android 后置):同 iOS,不在 MVP 内;
只留后置占位说明,并标注“未编译 / 未验证、未发布”。旧的
“Web 核心 + Android 壳代码 + 构建步骤”写法自 v0.5 起废止。
## 交付前自测(缺一项不算完成) ## 交付前自测(缺一项不算完成)
@@ -66,5 +73,12 @@
契约版本、测试证据、已知问题、关联待办或 PRD 项。没有 PR 号不算完成。 契约版本、测试证据、已知问题、关联待办或 PRD 项。没有 PR 号不算完成。
- 合并门由协调员判定:Checks 全绿、目录归属通过、契约版本是冻结版、 - 合并门由协调员判定:Checks 全绿、目录归属通过、契约版本是冻结版、
评审通过且无未解决意见;你不自己合并、不绕过评审推主线。 评审通过且无未解决意见;你不自己合并、不绕过评审推主线。
- 合并门禁:同正文,模式由 CLOUD_MERGE_GATE_MODE 控制,默认
hard:五项全查、缺一 409、状态不变、写 merge_gate_blocked 审计,
无证据不放行,unknown 不等于 protected,未保护即使带显式确认
也不放行;record 须显式设置才生效,未保护时须显式确认才放行;
显式确认只覆盖保护风险,绝不覆盖目录隔离违规;目录检查复用
v0.3 的 git diff --name-only 口径;技能播种仍只复制 SKILL.md,
不做整目录复制。
- 安全:密钥、口令、token 绝不进代码、commit、命令行、PR 正文; - 安全:密钥、口令、token 绝不进代码、commit、命令行、PR 正文;
需要调用 GitHub 时 token 只进子进程环境,不写进示例命令。 需要调用 GitHub 时 token 只进子进程环境,不写进示例命令。
@@ -1,4 +1,4 @@
# 角色模板:QA / 测试(单端复核 + 跨端 E2E,可分 2 个线程) # 角色模板:QA / 测试(单端复核 + 跨视口 E2E,可分 2 个线程)
## 只能写 ## 只能写
@@ -9,30 +9,44 @@
## 产出 ## 产出
1. 测试用例:按 PRD 验收标准写,每个用例写清前置条件、步骤、期望结果。 1. 测试用例:按 PRD 验收标准写,每个用例写清前置条件、步骤、期望结果。
单端复核先复核各客户端的自测证据,跨端 E2E 再做下面的矩阵,不要一个人包全端。 QA 正式分两部分,各自交付物写死,缺一不算 G5 通过:
2. 跨端一致性矩阵:同一个 agent 任务、同一份数据,在已选各端的结果、 ① 单端复核:逐端复核各客户端的自测证据是否属实,交付物是逐端复核报告
文案、状态词、同步状态是否一致;不一致的标明是缺陷还是刻意差异。 (每端通过 / 不通过 + 证据 + 未复核项);
3. agent 专属测试(缺一项不算测完):沙箱越界、危险动作审批、 ② 跨视口 E2E(v0.5 已定口径,原跨端 E2E 改为跨视口 E2E):
长任务超时和取消、断网续跑、模型 503 重试、token / 配额超限。 同一 agent 任务、同一份数据跑遍手机 / 平板 / 桌面浏览器宽度,
交付物是跨端一致性矩阵(矩阵的行是视口:各视口结果、文案、
状态词、同步状态是否一致;不一致的标明是缺陷还是刻意差异)
+ 缺陷清单 + 回归清单。
2. agent 专属测试(缺一项不算测完),归属如下:
归单端复核(每端都要过):沙箱越界、危险动作审批、token / 配额超限;
归跨视口 E2E(同一任务跨视口行为一致):长任务超时和取消、断网续跑、模型 503 重试。
4. 安全检查点(G5 单独签字):权限边界是否按契约实现、密钥是否外泄、 4. 安全检查点(G5 单独签字):权限边界是否按契约实现、密钥是否外泄、
agent 是否能读工作目录外文件。安全检查不算 QA 的附带项。 agent 是否能读工作目录外文件。安全检查不算 QA 的附带项。
5. 缺陷清单:每个缺陷写清复现步骤、影响客户端、严重程度、归属线程。 5. 缺陷清单:每个缺陷写清复现步骤、影响客户端、严重程度、归属线程。
6. 回归清单:契约从 v1 升到 v2 时,哪些用例必须重跑;G5 缺陷修完回 G5 回归, 6. 回归清单:契约从 v1 升到 v2 时,哪些用例必须重跑;G5 缺陷修完回 G5 回归,
回归范围按契约变更影响面定,不是每次都全量重测。 回归范围按契约变更影响面定,不是每次都全量重测。
7. 跨任务产物传递:回归第 0 步永远是核对,不是跑测试。
按协调员给的已核验产物清单与文件原文原样写盘,跑 `sha256sum`
逐项比对;全对上写 ARTIFACT-VERIFY-OK 才能跑同一份核心代码
与核心测试;任一文件对不上就停,报 ARTIFACT-HASH-MISMATCH,
不跑测试、不写 fixture、不猜契约。补测只能 import 核心模块,
不能复制核心实现,不能写功能等价的 fixture 冒充核心代码。
## 未编译端的口径 ## 未编译端的口径
iOS / Android / Mac 在 Linux 主机上编不出来时,你的结论写 iOS / Android 原生后置占位不进 QA 通过表,标注“未编译 / 未验证、
“代码评审 + Web 核心验证”,不写“构建通过”。没测的端和用例单独列出, 未发布”;Mac 在 Linux 主机上编不出来时,你的结论写
“代码评审 + Web 核心验证”,不写“构建通过”。没测的视口和用例单独列出,
不要把“没测”写成“通过”。 不要把“没测”写成“通过”。
## 完成定义 ## 完成定义
- 所有 PRD 验收标准都有对应测试用例,不是只测了 happy path。 - 所有 PRD 验收标准都有对应测试用例,不是只测了 happy path。
- 跨端矩阵已覆盖全部已选客户端,缺失的端要写明为什么没测。 - 跨端矩阵已覆盖手机 / 平板 / 桌面全部视口,缺失的视口要写明为什么没测。
- 缺陷清单已交协调员,严重缺陷未修好前不建议进入验收。 - 缺陷清单已交协调员,严重缺陷未修好前不建议进入验收。
## 禁止 ## 禁止
- 不替开发线程改代码“顺手修掉”,修了就测不出原缺陷。 - 不替开发线程改代码“顺手修掉”,修了就测不出原缺陷。
- 不把“没测”写成“通过”。没测的端和用例要单独列出。 - 不把“没测”写成“通过”。没测的端和用例要单独列出。
- 不在 hash 未核对通过时跑测试,不用自己写的 fixture 冒充核心代码。
@@ -6,12 +6,18 @@
1. 按 `templates/artifacts/acceptance-checklist.md` 生成本项目的验收清单, 1. 按 `templates/artifacts/acceptance-checklist.md` 生成本项目的验收清单,
每一项对应 PRD 里的一条验收标准,不额外加、不悄悄删。 每一项对应 PRD 里的一条验收标准,不额外加、不悄悄删。
2. 每个已选客户端准备一份演示产物:怎么启动、测哪个核心流程、 2. 为 web 单端准备一份演示产物:怎么启动、测哪个核心流程、
已知问题是什么、哪些平台未编译验证。web 演示可真跑, 已知问题是什么、哪些平台未编译验证。web 演示可真跑;
未编译端审代码和构建步骤,两者效力不同,分开标注,不能混成一张“通过”表。 iOS / Android 原生只留后置占位,不进本轮演示产物,不混成一张“通过”表。
3. 发布说明草稿,按端分别写:新能力、已知问题、回滚方式 3. 发布说明草稿,web 单端写:新能力、已知问题、回滚方式
(至少写清“出问题先停哪个端”)。web 部署、桌面安装包分发、 (至少写清“出问题先停 web 端”)。web 部署的回滚方式单独记录;
应用商店审核是三条流水线,分开记录,不要写成一次全上。 桌面安装包分发、应用商店审核不在本轮流水线内,不写成已走完。
4. 上手文档:web 版一份,写清启动、登录、核心流程、常见问题;
web 版在 G4a 交付时先交,不拖到 G6 才现写;iOS / Android 原生后置,
不在本轮补移动版上手文档。
5. v1.1 交接清单:未修缺陷(带归属和严重程度)、开放问题
(含任务间问答里未关闭的假设)、下轮待办;三项缺一不算 G6 收尾完成;
G8 要把它更新为含 G7 结论的终版,三项缺一仍不算齐。
## 用户确认规则 ## 用户确认规则
@@ -31,8 +37,9 @@
## 按端发布与回滚(验收) ## 按端发布与回滚(验收)
- 发布按端分别做:每端发布时打 tag,例如 v0.1.0; - v0.5 起发布为 web 单端:web 发布时打 tag,例如 v0.1.0;
发布说明从已合 PR 汇总,不凭记忆重写;发布记录里写清端、tag、PR 号、执行人。 发布说明从已合 PR 汇总,不凭记忆重写;发布记录里写清端(web)、tag、PR 号、执行人;
iOS / Android 原生后置占位不打发布 tag。
- 回滚是 revert 对应 PR,或重部署上一个 tag;绝不是 force-push 回退主线; - 回滚是 revert 对应 PR,或重部署上一个 tag;绝不是 force-push 回退主线;
回滚后重新走合并门(CI、评审)才能再发布。 回滚后重新走合并门(CI、评审)才能再发布。
- 合并记录复核:PR 号、合并提交 hash、CI 运行链接、执行人缺一项, - 合并记录复核:PR 号、合并提交 hash、CI 运行链接、执行人缺一项,
@@ -0,0 +1,49 @@
# 角色模板:运维(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 后置仍是后置占位,
不在本轮运维里把原生端写回交付端。
@@ -0,0 +1,48 @@
# 角色模板:迭代(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,
不为统一语言重写。
@@ -10,10 +10,10 @@ source, then re-issue the appendix through the skill's own track),
never a silent rewrite by this script. never a silent rewrite by this script.
What it checks, in order: What it checks, in order:
1. SKILL.md contains the appendix intro and exactly the nine 1. SKILL.md contains the appendix intro and exactly the eleven
chapters 00..08, in order, each with a source note naming its own chapters 00..10, in order, each with a source note naming its own
templates/roles/<id>.md file. templates/roles/<id>.md file.
2. templates/roles/ contains exactly those nine source files: 2. templates/roles/ contains exactly those eleven source files:
a missing source fails, an unexpected extra file fails. a missing source fails, an unexpected extra file fails.
3. Each source, in canonical form, equals the matching appendix 3. Each source, in canonical form, equals the matching appendix
chapter in canonical form (see canonical() below). chapter in canonical form (see canonical() below).
@@ -27,9 +27,10 @@ and its appendix chapter -- anything else is a failure):
templates/roles/<id>.md)") exists only in SKILL.md; it is templates/roles/<id>.md)") exists only in SKILL.md; it is
derived from the file name, not stored in the source. derived from the file name, not stored in the source.
b. One inter-chapter separator line "---": in the current SKILL.md b. One inter-chapter separator line "---": in the current SKILL.md
it appears after chapters 01/02/03/05/06 only. Chapters it appears after chapters 01/02/03/05/06/09 only. Chapters
00/04/07 end with their GitHub subsection and run straight into 00/04/07 end with their GitHub subsection and run straight into
the next heading with no separator, and 08 is the end of file. the next heading with no separator, and 10-iteration is the end
of file.
The check strips at most one trailing separator; it does NOT The check strips at most one trailing separator; it does NOT
normalise SKILL.md to a uniform separator, so the current normalise SKILL.md to a uniform separator, so the current
inconsistency stays visible and untouched. inconsistency stays visible and untouched.
@@ -62,7 +63,8 @@ from pathlib import Path
EXPECTED_IDS = ["00-coordinator", "01-product-manager", "02-architect", EXPECTED_IDS = ["00-coordinator", "01-product-manager", "02-architect",
"03-designer", "04-client-developer", "05-backend", "03-designer", "04-client-developer", "05-backend",
"06-qa", "07-acceptance", "08-shared-core"] "06-qa", "07-acceptance", "08-shared-core",
"09-ops", "10-iteration"]
CHAPTER_RE = re.compile( CHAPTER_RE = re.compile(
r"^## 附录角色:(\d{2}-[a-z0-9-]+)" r"^## 附录角色:(\d{2}-[a-z0-9-]+)"
+10 -8
View File
@@ -8,14 +8,15 @@ script. The appendix was therefore unverifiable -- a drifted chapter
would pass CI silently. would pass CI silently.
This file pins the repair, and nothing else: This file pins the repair, and nothing else:
- tools/check_appendix.py passes on the real pack (all nine chapters - tools/check_appendix.py passes on the real pack (all eleven
match their templates/roles/ sources, CHANGELOG present and chapters match their templates/roles/ sources, CHANGELOG present
mentioning templates/roles/); and mentioning templates/roles/);
- the same script FAILS (nonzero exit) on a temp copy with a source - the same script FAILS (nonzero exit) on a temp copy with a source
deleted, a source tampered, or an extra source added -- so a future deleted, a source tampered, or an extra source added -- so a future
"source missing" or "appendix drifted" state cannot slip through; "source missing" or "appendix drifted" state cannot slip through;
- --emit output is exactly the nine headings plus the nine source - --emit output is exactly the eleven headings plus the eleven
bodies, so the spliced form is itself derived from the sources. source bodies, so the spliced form is itself derived from the
sources.
Scope guard: these tests never edit SKILL.md or the sources. A Scope guard: these tests never edit SKILL.md or the sources. A
failure here is an editorial decision for the skill's own track failure here is an editorial decision for the skill's own track
@@ -38,7 +39,8 @@ SCRIPT = SKILL_DIR / "tools" / "check_appendix.py"
EXPECTED_IDS = ["00-coordinator", "01-product-manager", "02-architect", EXPECTED_IDS = ["00-coordinator", "01-product-manager", "02-architect",
"03-designer", "04-client-developer", "05-backend", "03-designer", "04-client-developer", "05-backend",
"06-qa", "07-acceptance", "08-shared-core"] "06-qa", "07-acceptance", "08-shared-core",
"09-ops", "10-iteration"]
def _run(skill_dir=None): def _run(skill_dir=None):
@@ -66,7 +68,7 @@ class AppendixProvenanceTestCase(unittest.TestCase):
self.assertEqual( self.assertEqual(
result.returncode, 0, result.returncode, 0,
"校验脚本应在真实包上通过,stderr:%s" % result.stderr) "校验脚本应在真实包上通过,stderr:%s" % result.stderr)
self.assertIn("9 chapters match", result.stdout) self.assertIn("11 chapters match", result.stdout)
def test_missing_source_fails(self): def test_missing_source_fails(self):
skill = _temp_skill_copy(self) skill = _temp_skill_copy(self)
@@ -110,7 +112,7 @@ class AppendixProvenanceTestCase(unittest.TestCase):
/ (cid + ".md")).read_text(encoding="utf-8") / (cid + ".md")).read_text(encoding="utf-8")
expected_parts.append(heading + "\n\n" + source.rstrip("\n")) expected_parts.append(heading + "\n\n" + source.rstrip("\n"))
self.assertEqual(result.stdout, "\n\n".join(expected_parts) + "\n", self.assertEqual(result.stdout, "\n\n".join(expected_parts) + "\n",
"--emit 输出须恰为 9 章标题 + 9 份源正文") "--emit 输出须恰为 11 章标题 + 11 份源正文")
if __name__ == "__main__": if __name__ == "__main__":
+6 -4
View File
@@ -11,7 +11,8 @@ asserting two chapters (00-coordinator, 08-shared-core) exist in the
seeded file -- a dropped middle chapter (01..07) would pass CI silently. seeded file -- a dropped middle chapter (01..07) would pass CI silently.
The bidirectional assertion previously discussed on the #209 track is The bidirectional assertion previously discussed on the #209 track is
unmerged, so main does not have it; this file supplies it on the main unmerged, so main does not have it; this file supplies it on the main
base (skill text v0.2, 9 appendix chapters 00..08). base (skill text v0.2, 9 appendix chapters 00..08;
integrated text is v0.5, 11 appendix chapters 00..10).
What "bidirectional" means here, concretely (all derived from SKILL.md What "bidirectional" means here, concretely (all derived from SKILL.md
itself, no new semantics invented): itself, no new semantics invented):
@@ -25,8 +26,8 @@ itself, no new semantics invented):
merge-gate / PR-number rules but no literal "GitHub" word, so the merge-gate / PR-number rules but no literal "GitHub" word, so the
test must not demand that word there); test must not demand that word there);
- body role-matrix role names == appendix role-title names as sets - body role-matrix role names == appendix role-title names as sets
(order differs: matrix order vs numeric 00..08 order, so set, not (order differs: matrix order vs numeric 00..10 order, so set, not
list, comparison), and appendix ids are exactly 00..08 in order. list, comparison), and appendix ids are exactly 00..10 in order.
CI: .github/workflows/host-verify.yml and release.yml both run CI: .github/workflows/host-verify.yml and release.yml both run
`python3 -m unittest discover -s cloud/tests -v`, so this test_*.py `python3 -m unittest discover -s cloud/tests -v`, so this test_*.py
@@ -55,7 +56,8 @@ SKILL_PATH = (REPO_ROOT / "cloud" / "skills" / "software-engineering"
EXPECTED_IDS = ["00-coordinator", "01-product-manager", "02-architect", EXPECTED_IDS = ["00-coordinator", "01-product-manager", "02-architect",
"03-designer", "04-client-developer", "05-backend", "03-designer", "04-client-developer", "05-backend",
"06-qa", "07-acceptance", "08-shared-core"] "06-qa", "07-acceptance", "08-shared-core",
"09-ops", "10-iteration"]
# Chapter -> keywords that chapter must carry for the GitHub guarantee # Chapter -> keywords that chapter must carry for the GitHub guarantee
# the body claims is "同样写进了附录的协调员、客户端、验收章节". # the body claims is "同样写进了附录的协调员、客户端、验收章节".