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