"""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()