BonfireAI/candyfactory-quality

GitHub: BonfireAI/candyfactory-quality

一个聚合式代码质量门禁套件,通过统一的本地与 CI 检查流程及棘轮基线机制,确保所有仓库持续满足可度量的质量标准。

Stars: 0 | Forks: 0

# candyfactory-quality — 测量套件 [![License](https://img.shields.io/badge/license-Apache--2.0-5fd4c4)](LICENSE) [![Python](https://img.shields.io/badge/python-3.12+-5fb8ff)](pyproject.toml) **一个聚合的质量运行器,使得 `local == CI`。** 可观测、棘轮化、内部试用 —— 每个 CandyFactory 仓库(以及每次 Bonfire burn)都要通过的质量门禁。 这是每个 CandyFactory 仓库共享的单一质量门禁。本套件是 **BubbleGum Law** 的 可执行部分 —— *代码保持可度量的形态,而维持它的法则自带粘性*。约定源自工厂的量规,而不是 某个 agent 第一次下载的随便什么包。 ## 两个面 1. **The sticky intro** (认知面) —— `src/cf_quality/data/sticky-intro.md` 是法则的规范 简短介绍,套件会将其挂载到每个消费者仓库中。任何 扫描仓库的模型在阅读时就会摄取该法则。在强制 边界之外,它充当文件中最强烈的建议;这就是它的 职责。这里的副本是 canon ADR 0030 §9(v2 块, 根据 ADR 自身的文本,它取代了 ADR 0029 的 v1 块;有关出处和内容哈希,请参见 `src/cf_quality/data/sticky-intro.SOURCE.md`)的 **declared mirror**。 2. **The gate** (机械面) —— 在 CandyFactory CI 内部以及 Bonfire burn 中,法则是可执行且具有否决性的。描述用于教导;它永远不能替代 门禁。 ## 门禁组件 (console scripts) | Command | 门禁内容 | |---|---| | `cf-file-budget` | 新文件 ≤ 500 行;在 `file-budget.json` 中被设定为基线的违规项将被冻结,仅允许缩减。 | | `cf-sticky-check` | 仓库携带标准的 sticky intro,逐字节与本套件的镜像保持一致。 | | `cf-mirror-check` | 跨仓库副本是已声明的镜像 (`MIRRORS.md`);未声明的偏差将失败。 | | `cf-recursion-check` | 递归必须带有声明的边界,否则失败。 | | `cf-exemptions` | 受门禁控制的抑制项 —— `# noqa: C901`/`PLR0915` (形式), `# noqa: S###`/`# nosec B###` (安全), `# noqa: BLE###` (Elegance) —— 必须追溯到 `exemptions.json` 中合理的条目;裸的/一刀切的和自行签发的抑制项将失败,且注册表中锚点不再可解析的条目(删除的文件、重命名的 symbol、移除的抑制项)也会失败。Style codes (E/F/I/UP/B) 依赖于 ruff + review。 | 预算锚定于度量,绝不凭空发明:CC ≤ 10 per function, ≤ 50 statements per function,新文件 ≤ 500 行,0 个新增 type 错误。现有 代码被设定为基线,并且只能缩减 (ratchet —— 永远不进行全局重构)。 本套件适用自身的预算:其 ruff/mypy config 在本仓库上强制执行的 正是门禁对消费者执行的规则,并且失败会抛出 typed errors (`cf_quality.errors.GateError` / `GateViolation`),这符合 Elegance Law。 ## 消费者快速入门 ``` pip install candyfactory-quality # or: pip install -e ../candyfactory-quality ``` 使用约 10 行的调用存根(自动生成,切勿手动编辑)在 CI 中挂载门禁: ``` # .github/workflows/quality.yml name: quality-gate on: push: {branches: [main]} pull_request: {branches: [main]} jobs: gate: uses: BonfireAI/candyfactory-quality/.github/workflows/quality-gate.yml@ secrets: inherit ``` 首日基线生成(第一次运行在结构上直接变绿;每个基线 都带有一个有日期的 ratchet 工单,因此 green-by-baseline 永远不会变成 green-forever): ``` cf-file-budget init # freeze existing >500-line files at measured size mypy src | mypy-baseline sync complexipy src --snapshot-create # cognitive-complexity floor (second metric) ``` 这里的 `--snapshot-create` 不是可选的,并且光秃秃的 `complexipy src` 永远不是 正确的命令:存在 snapshot 时,工具自身的 *passing* compare 会重写 下限(在固定的 5.6.0 版本上测得 —— 参见 `configs/BASELINE-CONVENTIONS.md` §1)。 在仓库根目录下运行它;snapshot 会存放在 CWD 中,而不是在分析的路径中。 ## 开发 ``` python3 -m venv .venv && .venv/bin/pip install -e '.[dev]' .venv/bin/cf-gate # THE local gate — the exact battery CI runs ``` `cf-gate` 是镜像 CI 的单一命令:它是 workflow 调用的 同一个 console script (`.github/workflows/quality-gate.yml` 和 `self-ci.yml` 各自运行一个 `cf-gate` 步骤),因此本地通过的 `cf-gate` 意味着 CI 中也会通过 —— 相同的量规、相同的 config、相同的判定。它运行 **每一个** 门禁阶段 (ruff check, ruff format, `cf-*` 门禁, 贯穿 baseline ratchet 的 mypy, 贯穿 snapshot ratchet 的 complexipy, pytest),收集每一个判定并 **聚合** 它们:它不会在第一次遇到红灯时停止,因此单次运行 会报告整个失败面板,然后根据最差的判定退出 (`2` setup error · `1` violations · `0` clean)。它会自动解析声明的 布局并从已安装的套件中加载其量规 config —— 无需传递任何 flag。 在迭代时,各个工具仍然可以用于专注的单门禁运行: ``` .venv/bin/pytest .venv/bin/ruff check . .venv/bin/mypy src ``` 但是 `cf-gate` 是标准的本地门禁 —— 只有它能完全复现 CI (每一个阶段,相同的聚合判定)。工具行为测试 (complexipy snapshot 语义,mypy-baseline set-difference) 记录在 `docs/tool-spikes.md` 中。
标签:Python, SOC Prime, 安全规则引擎, 开发工具, 开源框架, 持续集成, 无后门, 逆向工具