Files
codex-app-server/cloud/tests/test_software_engineering_g7g8.py
host 44616a03dc 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.
2026-11-03 02:48:54 +00:00

83 lines
4.0 KiB
Python
Raw Permalink 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.
"""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()