Files
yingqing/core/qa/function-audit
zycandClaude Fable 5 dcc5d7fe50 fix(billing): 删任务/删项目级联吞 ACTIVE 预留致 reserved_balance 永久冻结(审计 I2)
- 根因: CreditReservation.task 是 OneToOneField(CASCADE), AITask.project 也是 CASCADE
  —— 删项目→级联删任务→ACTIVE 预留行被吞, 账户冻结份额永不归还(实测 4 账户漂移共 ¥42,
  且随删项目持续增长)
- 修法: billing/signals.py 挂 AITask pre_delete, 删除前先 release_credit 释放(级联同样
  触发, release 自带行锁+幂等); apps.py ready() 接线
- 回归测试 x3: 直删任务/删项目级联/已扣费不重复释放
- qa/repair_reserved_drift.py: 存量漂移回填脚本(dry-run 默认, --apply 落 RELEASE 流水),
  已对线上 4 账户执行并复验清零
- qa/function-audit/output: 本轮 18 页模拟点击审计报告(0 真死按钮 0 JS 报错)

验证: 后端测试 213/213 通过, django check 无警告
补齐 aab4d7e: 该提交带走了 signals.py 之外的测试轮改动, 信号挂载点与回归测试在本提交收口

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 13:07:09 +08:00
..

Function Audit · 逐页功能审计

visual-parity像素,这里比行为:把每个页面在真实 React 路由里打开, 逐个真实点击所有可交互元素,报出「点了没反应」的死交互(假按钮)。

完整说明见 skill:.claude/skills/page-function-audit/SKILL.md

快速开始

# 0. 先起前后端(见 skill)。后端必须 .venv/bin/python。
# 1. 装依赖(复用 visual-parity 的 playwright)
cd AirShelf/core/qa/function-audit && npm install
# 2. 跑
node audit.mjs                  # 全量(最准,慢)
node audit.mjs --only account   # 单页(改完复验)
node audit.mjs --mode quick     # 粗扫(快)
# 3. 读报告
open output/summary.md          # 全页一览,看 dead 列
open output/<page>.audit.md     # 单页 DEAD 表

判定口径

  • works — 点了有反应(URL/浮层/自身状态/网络/DOM 五路任一变)
  • dead — 点了五路全无反应 → 真缺陷,优先修(多半没接 onClick)
  • 🛑 error — 点击抛 JS 异常
  • ◷ noop-active — 点的是已选中 tab/chip,本该无反应,忽略
  • ⏭ skipped — 破坏性按钮(删除/充值/生成…)不自动点,人工验
  • 🔍 missing — 设计稿 /exact 有、React 没渲染(启发式,人工过)

参数

参数 默认 说明
--mode isolated isolated=逐元素 reload(准);quick=不 reload(快)
--only (全部) 逗号分隔页名子串,如 --only account,pipeline
--include-pointer off 额外把 cursor:pointer 的 div 当候选
--headed off 看着浏览器跑
--settle 700 点击后观察窗口 ms
--token / --email / --password 演示账号 登录态来源
--base http://127.0.0.1:5173 前端地址