diff --git a/governance/GOVERNANCE.yaml b/governance/GOVERNANCE.yaml new file mode 100644 index 0000000..2c492e5 --- /dev/null +++ b/governance/GOVERNANCE.yaml @@ -0,0 +1,166 @@ +version: 1 +org: Cloudbird-Software +# ============================================================================ +# 组织治理总声明(single source of truth) +# 读法(AI): 本文件声明"治理什么"(intent)与"验证方式"(verify), +# platform 段声明"在某平台怎么实现"。迁移平台 = 改 platform 段, +# intent/verify 不动。所有字段机器可判定,无散文。 +# strength: enforced=平台强制 | monitored=自动检测漂移 | advisory=约定 +# ============================================================================ +risk_posture: # 全部措施的优先级依据 + - customer_upgrade_failure # 客户本地部署,升级/回滚炸=收入损失 + - llm_behavior_drift # 产品核心是 LLM + - fake_tests # agent 生成测试的同义反复风险 + - supply_chain # 公开仓库,依赖即攻击面 + - identity_scope # agent 凭据过度授权 + +domains: + + source_control: + measures: + - id: BP-1 + intent: "默认分支仅经 PR+squash 进入;禁删/force-push;线性历史" + strength: enforced + platform: {github: {mechanism: org-ruleset, name: main-protection, definition: rulesets/main-protection.json}} + verify: {method: drift-check, frequency: weekly} + exception: [AI_Web_School, .github] + - id: BP-2 + intent: "合并前置:唯一 required check = gate(聚合检查)" + strength: enforced + platform: {github: {mechanism: ruleset-required-status, context: gate}} + verify: {method: negative-test, frequency: weekly, see: T-11} + - id: BP-3 + intent: "发布标签 v* 不可删除/覆盖" + strength: enforced + platform: {github: {mechanism: org-ruleset, name: release-tags, definition: rulesets/release-tags.json}} + verify: {method: drift-check, frequency: weekly} + - id: BP-4 + intent: "仓库基线:squash-only、合并删分支、auto-merge 开、wiki/projects 关" + strength: enforced + platform: {github: {mechanism: repo-settings, apply: apply.sh#step5}} + verify: {method: drift-check, frequency: weekly} + - id: BP-5 + intent: "成员不可建仓;成员默认权限 read" + strength: enforced + platform: {github: {mechanism: org-settings, fields: [members_can_create_repositories=false, default_repository_permission=read]}} + + ci_gate: + measures: + - id: CI-1 + intent: "每 PR:lint+arch+test+hygiene+dep-review 聚合为 gate" + strength: enforced + platform: {github: {mechanism: reusable-workflows, repo: CI-Workflows, caller: template-service/.github/workflows/ci.yml}} + - id: CI-2 + intent: "Actions 仅允许:github 官方+已验证+白名单(zizmor/astral-sh/dependabot/docker/softprops/org 自有)" + strength: enforced + platform: {github: {mechanism: actions-permissions, state: expected-state.json#actions_policy}} + verify: {method: drift-check, frequency: weekly} + - id: CI-3 + intent: "GITHUB_TOKEN 默认只读;不允许 Actions 批准 PR" + strength: enforced + platform: {github: {mechanism: workflow-permissions, state: expected-state.json#actions_policy}} + - id: CI-4 + intent: "工作流安全静态审计(zizmor medium+ 拦截)" + strength: enforced + platform: {github: {mechanism: hygiene-job, part_of: CI-1}} + + supply_chain: + measures: + - id: SC-1 + intent: "CodeQL 告警 medium+ 阻断合并" + strength: enforced + platform: {github: {mechanism: org-ruleset, name: codeql-gate, definition: rulesets/codeql-gate.json}} + - id: SC-2 + intent: "安全配置(GitHub recommended)为全部新仓默认" + strength: enforced + platform: {github: {mechanism: code-security-default, config_id: 17, scope: all}} + verify: {method: apply-idempotent, note: "API 只写,读不到,由 apply.sh 每次强制"} + - id: SC-3 + intent: "依赖周更;minor/patch 过 gate 自动合并;major 留人" + strength: enforced + platform: {github: {mechanism: dependabot+automerge, config: "template-service/.github/dependabot.yml + workflows/automerge.yml"}} + - id: SC-4 + intent: "构建产物附 provenance attestation + SBOM" + strength: enforced + platform: {github: {mechanism: release-workflow, uses: actions/attest-build-provenance, sbom: policy/testing.yaml#T-07}} + + agent_identity: + measures: + - id: AG-1 + intent: "agent 写仓库唯一身份 = App(cloudbrid-agent);权限 contents/issues/PRs:write,无 workflows/administration" + strength: enforced + platform: {github: {mechanism: github-app, id: 4632704, state: expected-state.json#github_app}} + verify: {method: drift-check, frequency: weekly} + - id: AG-2 + intent: "App 令牌:单仓库作用域、1h 过期、磁盘不落长期凭据" + strength: enforced + platform: {github: {mechanism: script, entry: scripts/gh-app-token.sh}} + - id: AG-3 + intent: "App 受全部 ruleset 约束(无 bypass);CI 合并用 App 令牌(触发下游 workflow)" + strength: enforced + verify: {method: negative-test, frequency: weekly, see: T-11} + - id: AG-4 + intent: "App 安装范围 selected;新仓初始化自动挂载" + strength: monitored + platform: {github: {mechanism: installation, add_repo: scripts/new-repo-init.sh#step3}} + + release: + measures: + - id: RL-1 + intent: "production 环境:人工审批 + 仅受保护分支可部署" + strength: enforced + platform: {github: {mechanism: environment, name: production, apply: new-repo-init.sh#step2}} + + governance_meta: + measures: + - id: GM-1 + intent: "期望状态落盘;周漂移检测;漂移自动开 issue" + strength: monitored + platform: {github: {mechanism: workflow, file: .github/workflows/governance-drift.yml, cron: "Mon 03:00 UTC"}} + verify: {method: self, state: expected-state.json} + - id: GM-2 + intent: "配置变更走 PR→合并→apply.sh(禁止网页手改)" + strength: advisory + - id: GM-3 + intent: "政策文件机器可判定(本目录);agent 按需读取,不常驻上下文" + strength: advisory + files: [policy/languages.yaml, policy/testing.yaml] + + context_governance: + measures: + - id: CG-1 + intent: "AGENTS.md ≤30 行索引型:命令+硬规则+索引表;细节在按需读文件" + strength: advisory + - id: CG-2 + intent: "基建路径(.github/ Makefile arch 配置)变更显式归属 owner" + strength: advisory + platform: {github: {mechanism: CODEOWNERS, file: .github/CODEOWNERS}} + - id: CG-3 + intent: "agent 工具/技能定义放仓库不放本地(可审计防漂移)" + strength: advisory + +flows: + new_repo: + steps: + - {cmd: "gh repo create / --template /template-service --public --clone"} + - {cmd: "bash new-repo-init.sh ", effects: [BP-4, RL-1, AG-4]} + - {pr: "首PR:按 policy/languages.yaml 选型 + dep-cruise 边界规则 + 模块 AGENTS.md"} + rewrite_project: # 如 Go 重写 + rules: + - {step: 1, action: "走 new_repo 流程建仓(不塞旧仓)"} + - {step: 2, action: "骨架 PR 先行:目录+边界 lint 规则+空实现", gate: CI-1} + - {step: 3, action: "模块逐 PR,各带契约测试", limit: "每 PR 单一模块"} + - {step: 4, action: "旧系统立即抓 golden fixtures(不可逆)", policy: R-06} + - {step: 5, action: "差分 job 进 gate", policy: T-09} + - {step: 6, action: "mutation 周跑盯 score", policy: T-10} + - {step: 7, action: "v2 发布走环境审批+升级/回滚测试", policies: [RL-1, R-01..R-05]} + +portability: + neutral: [intent, strength, verify, risk_posture, flows] # 平台无关,直接搬运 + platform_bound: # 迁移时需重写映射的机制 + org-ruleset: {gitlab: protected-branches+push-rules, gitea: branch-protection} + code-security-default: {gitlab: dependency-scanning+sast-templates} + github-app: {gitlab: project-access-token+deploy-tokens, generic: fine-grained-pat} + environment: {gitlab: protected-environments} + reusable-workflows: {gitlab: includes, generic: shared-ci-scripts} + migration_rule: "换平台 = 重写 platform 段 + apply/drift 脚本;intent/verify/flows 原样保留" diff --git a/governance/language-policy.md b/governance/language-policy.md deleted file mode 100644 index 1c7f5ba..0000000 --- a/governance/language-policy.md +++ /dev/null @@ -1,55 +0,0 @@ -# 组织语言生态政策(agent 按需读取) - -> 本文件是组织级政策,不放在任何仓库的 AGENTS.md 里(惜上下文)。 -> agent 在以下场景必须读它:新建项目、新增模块选型、引入新依赖、写架构文档。 -> 违规 = gate 拦截或 PR 打回。最后更新: 2026-08。 - -## 分层选型 - -| 层 | 允许 | 禁止 | 为什么(选型理由) | -|---|---|---|---| -| 主力应用/服务 | Go(服务/CLI 优先);受约束的 TypeScript(需要前端同构时) | Rust/Java/C++/新语言 | 训练数据海量、写法单一、编译反馈快——LLM 产出可靠 | -| LLM/Prompt 层 | BAML + Python | 裸 prompt 字符串拼接 | BAML 是"深接口"的教科书实现:prompt 即类型化契约 | -| 数据层 | SQL + 类型生成(如 sqlc / kysely) | 重 ORM(Prisma/Hibernate 类) | SQL 是史上最成功的深接口 DSL;重 ORM 挡住 agent 对生成的控制 | -| 配置/基建 | 声明式(Terraform / Compose) | 脚本化基建(bash 造 infra) | 无逻辑 = AI 不会写错 | -| 验证层 | property-based test(fast-check/proptest)+ schema 契约 + dependency-cruiser 依赖规则 | 只写 happy-path 单测 | 这是组织的真正护城河 | - -## 每层的硬性要求 - -1. **Go**:`gofmt` 零 diff;错误必须显式处理(`errcheck` 进 gate);模块入口 `cmd/`,包间禁止循环依赖。 -2. **TypeScript**:`strict: true`;禁止 `any`(eslint 进 gate);跨模块只 import 入口 `index.ts`(depcruise 检查)。 -3. **BAML**:prompt 改动必须跑 golden test(输入→输出快照);禁止在 TS/Go 里内嵌 prompt 字符串。 -4. **SQL**:迁移文件只增不改(up + down);查询经类型生成器,禁止手写拼接。 -5. **Terraform/Compose**:`plan`/`config -q` 进 CI;禁止 `local` 值参与资源命名。 -6. **验证层**:对外接口必须有 property-based test;`.dependency-cruiser.cjs` 的 TODO 边界规则在模块落地当周补全。 - -## 测试深度分级(何时上重武器) - -原则:**gate 快(PR 反馈 <5 分钟),重的放周跑**。三级测试按项目阶段递进: - -| 级别 | 工具/手法 | 放哪 | 什么时候上 | -|---|---|---|---| -| 基础:单测+属性测试+golden | vitest/fast-check(TS)、go test(Go) | gate(每个 PR) | 一律必须 | -| **差分测试**:旧实现 vs 新实现,同输入比输出 | golden fixtures + 双实现回放 harness | gate(重写项目专用 job) | **重写/替换现有系统时必须**;LLM 输出对比版本升级时同法 | -| **mutation 测试**:注入变异看测试能否杀死 | Stryker(TS)/ go-mutesting(Go) | 每周定时 job,不进 gate | agent 写了大量测试后必上——AI 写的测试容易同义反复(断言"代码做了什么"而非"应该做什么"),mutation score 是唯一照妖镜。score 低于 60% 的模块 = 测试在演戏 | -| 金丝雀发布:小流量灰度 | 需要流量切分+指标+回滚的在线基建 | 不适用 | **不上**:产品是客户本地部署(Release 附件交付),没有可切流量。替代:release 后跑 smoke test(下载附件验证可运行) | - -判定规则: -- 重写项目:差分测试是 gate 的一部分(不是可选项) -- 任何项目:mutation 每周跑,score 趋势入周报;比单次绝对值重要 -- 金丝雀:等有托管服务再说,现阶段用 release smoke 替代 - -## 新仓库初始化(agent 必须遵循) - -``` -gh repo create Cloudbird-Software/ --template Cloudbird-Software/template-service --public --clone -cd && bash <(curl -sS https://raw.githubusercontent.com/Cloudbird-Software/.github/main/scripts/new-repo-init.sh) -``` - -然后第一个 PR:按本层表选型填 `.dependency-cruiser.cjs` 的 TODO 规则 + 建模块 AGENTS.md。 -语言一旦选定,中途换语言 = 重新立项,不是重构。 - -## 违规处理 - -- gate 拦住的(lint/depcruise/类型)→ agent 自行修复,不许绕过 -- gate 拦不住的(选型违规、引入 ORM)→ PR 打回,理由引用本文件对应行 diff --git a/governance/policy/languages.yaml b/governance/policy/languages.yaml new file mode 100644 index 0000000..591b9fb --- /dev/null +++ b/governance/policy/languages.yaml @@ -0,0 +1,61 @@ +version: 1 +# 语言生态政策(机器可判定)。规则 ID 可被 gate/PR review 引用。 +# enforcement: gate=CI拦截, review=人工/agent审查引用ID打回, policy=约定 +layers: + application: + allowed: + - {language: go, when: "default"} + - {language: typescript, when: "frontend-isomorphic only", requires: [TS-1, TS-2]} + forbidden: [rust, java, csharp, cpp, new_language_without_org_approval] + rationale: "训练数据海量、写法单一、编译反馈快 → LLM 产出可靠" + llm_prompt: + allowed: [{language: baml}, {language: python}] + forbidden: [prompt_string_interpolation_in_code] + rationale: "BAML = 类型化 prompt 契约(深接口)" + data: + allowed: + - {storage: sql, requires: [SQL-1, SQL-2]} + forbidden: [heavy_orm] + heavy_orm_examples: [prisma, hibernate, gorm-auto-migrate] + rationale: "SQL 是深接口 DSL;重 ORM 挡住 agent 对生成的控制" + infrastructure: + allowed: [terraform, docker_compose] + forbidden: [bash_provisioning] + rationale: "无逻辑 = AI 不会写错" + verification: + required: [property_based_test, schema_contract, dependency_boundary_lint] + forbidden: [happy_path_only] + rationale: "组织护城河" + +rules: + - {id: GO-1, lang: go, rule: "gofmt 零 diff", enforcement: gate} + - {id: GO-2, lang: go, rule: "errcheck 通过(错误显式处理)", enforcement: gate} + - {id: GO-3, lang: go, rule: "入口在 cmd/,包间无循环依赖", enforcement: gate} + - {id: GO-4, lang: go, rule: "go test -race 通过", enforcement: gate} + - {id: GO-5, lang: go, rule: "goleak 无 goroutine 泄漏", enforcement: gate, when: "long_running_process"} + - {id: TS-1, lang: typescript, rule: "strict: true", enforcement: gate} + - {id: TS-2, lang: typescript, rule: "禁 any(eslint)", enforcement: gate} + - {id: TS-3, lang: typescript, rule: "跨模块仅 import 入口 index.ts(depcruise)", enforcement: gate} + - {id: BAML-1, lang: baml, rule: "prompt 变更必须过 golden test", enforcement: gate} + - {id: SQL-1, lang: sql, rule: "迁移只增不改(up+down 成对)", enforcement: review} + - {id: SQL-2, lang: sql, rule: "查询经类型生成器,禁手写拼接", enforcement: review} + - {id: INFRA-1, lang: infra, rule: "terraform plan / compose config -q 进 CI", enforcement: gate} + - {id: INFRA-2, lang: infra, rule: "local 值禁止参与资源命名", enforcement: review} + +dependency_policy: + approval_required: true + proposal_format: [name, purpose, license, stdlib_alternative] + forbidden_licenses: [AGPL-3.0, GPL-3.0, SSPL] + enforcement: review + +project_invariants: + - {id: MOD-1, rule: "每模块一个 public entry", check: make_arch} + - {id: MOD-2, rule: "entry 不导出内部实现类型", check: review} + - {id: MOD-3, rule: "模块 ≤3000 行,超限拆分", check: review} + - {id: MOD-4, rule: "生成代码独立目录,禁手改", check: review} + - {id: MOD-5, rule: "depcruise 边界规则随模块落地当周补全", check: gate} + - {id: IF-1, rule: "接口标准:LLM 仅凭签名+一行注释可零样本正确使用", check: review} + +language_change: + rule: "语言选定后更换 = 重新立项,不属重构" + enforcement: policy diff --git a/governance/policy/testing.yaml b/governance/policy/testing.yaml new file mode 100644 index 0000000..b1747ce --- /dev/null +++ b/governance/policy/testing.yaml @@ -0,0 +1,62 @@ +version: 1 +# 测试政策(机器可判定)。状态机: active | on_rewrite | on_llm_product | triggered | rejected。 +# placement: gate=每PR | weekly=定时 | pre_release | manual | none +principles: + - "gate <5min;重的周跑" + - "每个测试必须映射到风险敞口之一: customer_upgrade_failure | llm_behavior_drift | fake_tests" + +active_now: + - {id: T-01, name: unit_property_golden, tools: "vitest+fast-check | go test", placement: gate} + - {id: T-02, name: race_detection, tool: "go test -race", placement: gate, applies: go} + - {id: T-03, name: goroutine_leak, tool: goleak, placement: gate, applies: go, when: long_running_process} + - {id: T-04, name: fuzz_seed, tool: "go test -fuzz", placement: "gate(short) + weekly(deep)", when: "parser/importer/protocol code"} + - {id: T-05, name: doc_examples, tool: "go Example functions", placement: gate, applies: go} + - {id: T-06, name: license_scan, tool: license-checker, placement: gate} + - {id: T-07, name: sbom, tool: syft, placement: release} + - {id: T-08, name: flaky_governance, tool: none, + rule: "重跑一次过≠通过;同测试两次飘→隔离+issue,修复后回归"} + - {id: T-09, name: differential, tool: "golden fixtures + 双实现回放", + placement: gate, note: "重写项目 = gate 必选项"} + - {id: T-10, name: mutation, tools: "stryker | go-mutesting", placement: weekly, + threshold: "score<60% 的模块 = fake_tests 风险", trend: "趋势比绝对值重要"} + - {id: T-11, name: governance_canary, rule: "App 令牌直推 main 必须被拒;被接受=报警", + placement: weekly, risk: "守门人自身失效", note: "唯一自指的测试"} + +on_rewrite_project: # Go 重写落地时激活 + - {id: R-01, name: upgrade_path, rule: "旧版本→新版本真机升级+smoke", placement: pre_release} + - {id: R-02, name: rollback, rule: "升级后回滚数据无损", placement: pre_release} + - {id: R-03, name: migration_idempotent, rule: "up/down 在真实数据快照验证", placement: pre_release} + - {id: R-04, name: config_compatibility, rule: "旧配置喂新二进制行为可预期", placement: pre_release} + - {id: R-05, name: fresh_install_smoke, rule: "干净环境装 Release 附件", placement: post_release} + - {id: R-06, name: capture_golden_now, rule: "旧系统删除前抓输入/输出 fixtures(不可逆操作,立即执行)"} + +on_llm_product: # LLM 输出进产品时激活 + - {id: L-01, name: eval_harness, tool: promptfoo, placement: "gate(小回归集)+weekly(全量)"} + - {id: L-02, name: semantic_golden, rule: "embedding 距离阈值判漂移,禁精确 diff", placement: gate} + - {id: L-03, name: metamorphic, examples: [输入重排→结果集等价, 重试→幂等], placement: gate, + rationale: "LLM 无 oracle,测不变关系"} + - {id: L-04, name: adversarial_corpus, rule: "注入/越狱语料", placement: weekly} + - {id: L-05, name: cost_latency_budget, rule: "token成本+p95延迟趋势报警", placement: weekly} + - {id: L-06, name: model_upgrade_differential, rule: "换模型=换实现,golden 集对比", placement: on_change} + +triggered: # 触发式;防止"听起来好就上" + - {id: G-01, name: contract_api_drift, tools: "oapi-diff|pact", trigger: first_public_api, placement: gate} + - {id: G-02, name: integration_real_deps, tool: testcontainers, trigger: sql_layer_landed, placement: gate} + - {id: G-03, name: bench_regression, tools: "go bench+benchstat", trigger: data_intensive_path, placement: weekly} + - {id: G-04, name: dast, tool: nuclei, trigger: compose_stack_stable, placement: weekly} + - {id: G-05, name: iac_scan, tool: checkov, trigger: terraform_in_use, placement: weekly} + - {id: G-06, name: load_test, tool: k6, trigger: customer_perf_complaint, placement: manual} + - {id: G-07, name: state_model_test, tools: "rapid|fast-check", trigger: complex_state_entity} + - {id: G-08, name: error_path_coverage, trigger: first_public_api, placement: gate} + +rejected: # 翻案需新证据;引用 revisit_when + - {id: X-01, name: coverage_threshold_gate, reason: "数字可游戏", alternative: T-10_mutation, revisit_when: "mutation 不可用的语言"} + - {id: X-02, name: canary_release, reason: "客户本地部署无在线流量", alternative: R-05_smoke, revisit_when: hosted_service} + - {id: X-03, name: chaos_engineering, reason: "无 k8s 舰队", alternative: "失败模式写单测(磁盘满/断网/超时)", revisit_when: multi_node_prod} + - {id: X-04, name: formal_tla, reason: "无调度器/共识组件", revisit_when: "写分布式协调组件"} + - {id: X-05, name: soak_test, reason: "投入产出失衡", alternative: "T-03+G-03", revisit_when: "客户报内存类问题"} + - {id: X-06, name: a11y_i18n, reason: "无 UI", revisit_when: "有 Web UI"} + +existing: # 勿重复建设 + [unit_property_golden, differential(T-09 已active), mutation(T-10), codeql, zizmor, + dependency_review, hygiene, dependabot_automerge, provenance_attestation, governance_drift] diff --git a/governance/testing-policy.md b/governance/testing-policy.md deleted file mode 100644 index 52efb1f..0000000 --- a/governance/testing-policy.md +++ /dev/null @@ -1,71 +0,0 @@ -# 组织测试政策(决策记录 2026-08) - -> 加法穷举 + 减法裁决的完整记录。想引入新测试时先读本文件:已否决的有否决理由,待定的有触发条件。 -> 原则:gate 快(PR <5 分钟)重的周跑;每个测试必须对应一个真实风险敞口。 - -## 三大风险敞口(裁决的排序依据) - -1. **客户升级炸**:产品是客户本地部署(Release 附件交付),升级/回滚/迁移是收入保护 -2. **LLM 行为悄悄变差**:产品核心是 LLM,无 eval 即盲飞 -3. **agent 写的测试演戏**:同义反复测试比没测试更危险(mutation score 是照妖镜) - -## 立即生效(gate,近零成本) - -| 测试 | 工具/手法 | 说明 | -|---|---|---| -| 竞态检测 | `go test -race` | Go 并发 bug 最难排查,检测器免费 | -| goroutine 泄漏 | uber-go/goleak | 服务类项目一个 import | -| Fuzz 种子 | `go test -fuzz`(短跑)+ 周 cron 深跑 | 解析器/导入器/协议处理必备;语料入库 | -| 文档即测试 | Go Example 函数 | 文档代码段进 CI,防文档腐烂 | -| 许可证扫描 | license-checker | 政策(禁 AGPL/GPL-3/SSPL)自动化 | -| SBOM | syft 附 Release | 已有 provenance attestation,补齐供应链 | -| Flaky 治理 | 流程规则 | 重跑一次过≠通过;两次飘=隔离+issue,修好才回 | - -## 重写项目落地时生效(release 前置) - -| 测试 | 说明 | -|---|---| -| 升级路径测试 | 旧版本→新版本真机升级+smoke(客户模拟) | -| 回滚测试 | 升级后回滚,数据无损 | -| 迁移测试 | up+down 在真实数据快照上,幂等验证 | -| 配置兼容 | 旧版配置文件喂新版二进制,行为可预期 | -| 全新安装 smoke | 干净环境装 Release 附件,模拟客户第一天 | - -## LLM 输出进产品时生效 - -| 测试 | 放哪 | 说明 | -|---|---|---| -| Eval harness(promptfoo 类) | 小回归集进 gate,全量周跑 | prompt/模型变更必须过 | -| 语义 golden | gate | embedding 距离阈值判漂移,不做精确 diff | -| 蜕变测试 | gate | LLM 无 oracle:输入重排结果集等价、重试幂等 | -| 对抗语料库 | 周跑 | 注入/越狱样本,LLM 产品的安全测试 | -| 成本/延迟预算 | 周跑趋势 | token 成本+p95 延迟回归报警 | -| 模型升级差分 | 变更时 | 换模型=换实现,同 golden 集对比 | - -## 触发式(写明触发器,防止"听起来好就上") - -| 测试 | 触发器 | 工具 | -|---|---|---| -| 契约测试+API 漂移 | 第一个对外 API | oapi-diff / Pact | -| 真实依赖集成 | SQL 层落地 | testcontainers | -| 基准回归 | 出现数据密集路径 | Go bench + benchstat 周跑趋势 | -| DAST | compose 栈稳定 | Nuclei 周跑 | -| IaC 扫描 | Terraform 真实使用 | checkov | -| 压测 | 客户报性能问题 | k6 手动 | -| 状态机模型测试 | 出现复杂状态实体 | rapid (Go) / fast-check (TS) | -| 治理金丝雀 | —(直接上,周跑) | 自动验证 App 直推 main 被 ruleset 拒;守门人自身的健康检查 | - -## 明确否决(含理由,翻案需新证据) - -| 测试 | 否决理由 | 替代 | -|---|---|---| -| 覆盖率门槛 gate | 数字可游戏;AI 时代尤其假 | mutation score 趋势 | -| 金丝雀发布 | 客户本地部署,无在线流量可切 | release smoke | -| 混沌工程全套 | 无 k8s 舰队;投入产出失衡 | 失败模式写成单测(磁盘满/断网/超时) | -| TLA+/形式化 | 无调度器/共识类组件 | — | -| 长跑 soak | 重投入 | goleak + bench 趋势覆盖大部分意图 | -| a11y/i18n 测试 | 无 UI | 出现 UI 再议 | - -## 已有(勿重复建设) - -单测+属性测试+golden(gate)|差分测试(重写项目 gate 必选项)|mutation 周跑|CodeQL|zizmor|dependency review|hygiene(大文件/密钥文件)|Dependabot+automerge|provenance attestation|治理漂移检测周跑