BonfireAI/candyfactory-quality
GitHub: BonfireAI/candyfactory-quality
一个聚合式代码质量门禁套件,通过统一的本地与 CI 检查流程及棘轮基线机制,确保所有仓库持续满足可度量的质量标准。
Stars: 0 | Forks: 0
# candyfactory-quality — 测量套件
[](LICENSE)
[](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, 安全规则引擎, 开发工具, 开源框架, 持续集成, 无后门, 逆向工具