关于 ln-652-transaction-correctness-auditor
专门审查数据库事务正确性、范围及触发器交互的工作者技能。它会生成按严重程度分类的发现和合规评分,但不会修改代码。
主要功能
- 01检查事务边界与提交
- 02审查回滚处理
- 03检查触发器和通知行为
- 04比对事件发布方与订阅方
- 05生成结构化报告和评分
适用场景
- 01审计代码库中的事务处理
- 02查找影响通知的提交缺失
- 03识别范围过宽或拆分过细的事务
MCP 相关
如可用,该技能优先使用 hex-line MCP 读取、搜索和编辑文件,并在引用链或调用路径有帮助时使用 hex-graph。MCP 不可用或不受支持时则使用内置工具。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ levnikolaevich/ claude-code-skills --skill ln-652-transaction-correctness-auditor安装后在 Claude Code 中输入/ln-652-transaction-correctness-auditor确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/audit_output_schema.mdaudit_scoring.mdaudit_summary_contract.mdaudit_worker_core_contract.mdmcp_integration_patterns.mdmcp_tool_preferences.mdtwo_layer_detection.mdreferences/templates/audit_worker_report_template.md详细介绍
**路径:**文件路径(
references/、../ln-*)均相对于此技能目录。
事务正确性审计员(L3 Worker)
**类型:**L3 Worker
专门审计数据库事务模式的正确性、范围和触发器交互的 Worker。
用途与范围
- 审计事务正确性(优先级:高)
- 检查提交模式、事务边界、回滚处理以及触发器/通知语义
- 将结构化发现写入文件,包含严重程度、位置、工作量和建议
- 计算事务正确性类别的合规评分(X/10)
输入
**必须读取:**加载 references/audit_worker_core_contract.md 和 references/mcp_tool_preferences.md。
工具策略:你可能作为独立子 Agent 运行,此时宿主的 AGENTS.md 不在适用范围内,因此读取文件、搜索和编辑时默认优先使用 hex-line MCP。只有在 MCP 行为不明确时才加载 references/mcp_integration_patterns.md。
接收包含以下内容的 contextStore:tech_stack、best_practices、db_config(数据库类型、ORM 设置、触发器/通知模式)、codebase_root、output_dir。
**支持领域感知:**支持 domain_mode 和 current_domain。
当引用链或调用路径能实质性改善事务分析时,优先使用 hex-graph。若可用,则本地代码/配置读取优先使用 hex-line。如果 MCP 不可用、不受支持或未建立索引,则继续使用内置的 Read/Grep/Glob/Bash,并在报告中说明回退情况。
工作流程
检测策略:采用两层检测(候选扫描,然后上下文验证);仅在验证方法不明确时加载 references/two_layer_detection.md。
-
从 contextStore 解析上下文
- 提取 tech_stack、best_practices、db_config、output_dir
- 确定 scan_path
-
发现事务基础设施
- 查找包含触发器的迁移文件(
pg_notify、CREATE TRIGGER、NOTIFY) - 查找会话/事务配置(
expire_on_commit、autocommit、隔离级别) - 梳理受触发器影响的表
- 查找包含触发器的迁移文件(
-
扫描代码库中的违规项
- 跟踪受触发器影响表的 UPDATE 路径
- 分析事务边界(begin/commit 范围)
- 检查提交操作周围的错误处理
-
收集发现,包含严重程度、位置、工作量和建议
-
使用惩罚算法计算评分
-
**编写报告:**按照
references/templates/audit_worker_report_template.md在内存中构建完整的 Markdown 报告,并通过单次 Write 调用写入{output_dir}/ln-652--global.md -
**返回摘要:**向协调器返回最简摘要(参见输出格式)
审计规则(优先级:高)
1. 缺少中间提交
问题: UPDATE 后未提交,但数据库触发器/NOTIFY 依赖事务提交
检测:
- 步骤 1: 在迁移文件中查找触发器:
- 在
alembic/versions/、migrations/中搜索pg_notify|NOTIFY|CREATE TRIGGER|CREATE OR REPLACE FUNCTION.*trigger - 提取:触发器函数名称、表名、触发事件(INSERT/UPDATE)
- 在
- 步骤 2: 查找会更新受触发器影响的表的代码:
- 搜索与触发器表相关的
repo.*update|session\.execute.*update|\.progress|\.status
- 搜索与触发器表相关的
- 步骤 3: 检查连续更新之间是否调用了
commit():- 如果在循环或一系列操作中,对触发器表执行了多次 UPDATE,却未在中间调用
commit(),则 NOTIFY 事件会延迟到最终提交时才触发 - 没有中间提交会导致实时进度跟踪失效
- 如果在循环或一系列操作中,对触发器表执行了多次 UPDATE,却未在中间调用
严重级别:
- 严重: 基于 NOTIFY/LISTEN 的实时功能(SSE、WebSocket)缺少提交
- 高: 会更新物化数据的触发器缺少提交
例外情况: 单个原子操作且没有可观察的中间状态 → 将严重级别从严重下调为中等。若事务范围有文档说明其为有意设计(ADR、架构注释)→ 下调一个级别
建议:
- 在进度里程碑处调用
session.commit()(限频:每达到 N% 或每隔 T 秒) - 或将实时通知移出数据库触发器(使用 Redis pub/sub、进程内事件)
工作量: S-M(添加策略性提交或重新设计通知路径)
2. 事务范围过大
问题: 单个事务包含无关操作,包括耗时较长的外部调用
检测:
- 查找
async with session.begin()或显式事务代码块 - 检查代码块中是否包含外部调用:
await httpx.、await aiohttp.、await requests.、await grpc. - 检查代码块中是否包含文件 I/O:
open(、.read(、.write( - 模式:同一事务中包含数据库写入 + 外部 API 调用 + 另一次数据库写入
严重级别:
- 高: 事务内有外部 HTTP/gRPC 调用(网络延迟期间会占用数据库连接)
- 中等: 事务内有文件 I/O
建议: 拆分为多个事务;使用 Saga/Outbox 模式保证跨服务一致性
工作量: M-L(重新组织事务边界)
3. 事务范围过窄
问题: 逻辑上应为原子操作的操作被拆分到多个提交中
检测:
- 对应当保持原子性的操作多次调用
session.commit() - 模式:创建父实体后提交,再创建子实体并提交(应在单个事务中完成)
- 模式:更新状态与创建审计日志分开提交
严重级别:
- 高: 父子实体分开提交(失败时有产生孤立数据的风险)
- 中等: 相关更新分开提交(失败时状态不一致)
建议: 使用 async with session.begin() 或工作单元模式,将相关操作封装在单个事务中
工作量: M(重新组织提交边界)
4. 缺少回滚处理
问题: 调用 session.commit() 时未妥善处理错误和回滚
检测:
- 查找未置于
try/except代码块或上下文管理器中的session.commit() - 查找位于
try中、但except中没有session.rollback()的session.commit() - 模式:服务方法中直接调用
await session.commit() - 例外:
async with session.begin()会自动回滚(安全)
严重级别:
- 中等: 缺少回滚(失败后会话会处于损坏状态)
- 低: 使用上下文管理器时缺少显式回滚(会自动处理)
建议: 使用 async with session.begin()(自动回滚),或添加显式的 try/except/rollback 模式
工作量: S(使用上下文管理器封装或添加错误处理)
5. 长时间持有事务
内容: 事务在缓慢或阻塞操作期间保持打开状态
检测:
- 衡量作用域:统计事务开始到提交之间的代码行数
- 如果
begin()和commit()之间超过 50 行代码,则标记 - 如果事务中包含对外部服务的
await调用(网络延迟),则标记 - 如果事务中包含
time.sleep()或asyncio.sleep(),则标记
严重程度:
- HIGH: 事务在外部 API 调用期间保持打开状态(存在连接池耗尽风险)
- MEDIUM: 事务跨越超过 50 行代码(逻辑复杂,发生锁竞争的可能性较高)
建议: 尽量缩小事务范围;在开启事务前准备数据,并在数据库操作完成后立即提交
工作量: M(重构代码以缩短事务窗口)
6. 事件频道名称一致性
内容: 发布者的频道/主题名称与订阅者的频道/主题名称不匹配
检测:
- 步骤 1: 收集发布者的频道名称(扩展第 2 阶段的触发器发现):
- 迁移触发器:从
pg_notify('channel_name', ...)、NOTIFY channel_name中提取字符串参数 - 应用代码:在
src/、app/中搜索\.publish\(["']|\.emit\(["']|redis.*publish\(["']|\.send_to\(["'] - 提取:
{channel_name, source_file, source_line, technology}
- 迁移触发器:从
- 步骤 2: 收集订阅者的频道名称:
- PostgreSQL:在应用代码中(不只是迁移文件)搜索
LISTEN\s+(\w+) - Redis:在
src/、app/中搜索\.subscribe\(["']([^"']+) - EventEmitter/WebSocket:在处理程序/监听器目录中搜索
\.on\(["']([^"']+) - 提取:
{channel_name, source_file, source_line, technology}
- PostgreSQL:在应用代码中(不只是迁移文件)搜索
- 步骤 3: 交叉核对发布者与订阅者:
- 完全匹配:
publisher.channel_name == subscriber.channel_name-> 正常 - 近似不匹配:Levenshtein 距离 <= 2,或其中一个是另一个的子串 -> 标记为不匹配
- 孤立发布者:频道存在于发布者中,但不存在于订阅者中 -> 标记为孤立
- 孤立订阅者:频道存在于订阅者中,但不存在于发布者中 -> 标记为孤立
- 完全匹配:
第 2 层上下文分析(强制):
- 如果频道名称来自共享配置常量或环境变量(例如
CHANNEL = os.environ["EVENT_CHANNEL"]),且发布者和订阅者使用相同来源 -> 不属于不匹配 - 如果频道使用动态后缀模式(例如
job_events:{job_id}),且两端使用相同模板 -> 不属于孤立 - 从发布者和订阅者发现结果中排除测试文件(
**/test*/**、**/*.test.*)
严重程度:
- CRITICAL: 频道名称不匹配(近似不匹配:发布者向
job_events发送事件,订阅者却监听job_event) - HIGH: 孤立发布者——事件已发送但从未被消费(如果事件携带状态变更,则存在数据丢失风险)
- MEDIUM: 孤立订阅者——已注册监听器,但未找到发布者(死代码或未来功能)
建议:
- 对于不匹配:统一频道名称,在发布者和订阅者之间共享同一个常量
- 对于孤立发布者:添加订阅者,或移除未使用的 NOTIFY/发布操作
- 对于孤立订阅者:添加发布者,或移除无用的监听器
工作量: S(修复拼写错误/添加常量)到 M(设计缺失的订阅者/发布者)
评分算法
必须阅读: 加载 references/audit_scoring.md。
输出格式
务必阅读: 加载 references/templates/audit_worker_report_template.md。
按照 references/audit_summary_contract.md 编写 JSON 摘要。在托管模式下,调用方会同时传入 runId 和 summaryArtifactPath;在独立模式下,工作器会按照共享契约生成自己的运行专属产物路径。
将报告写入 {output_dir}/ln-652--global.md,并设置 category: "Transaction Correctness",检查项包括:missing_intermediate_commits、scope_too_wide、scope_too_narrow、missing_rollback、long_held_transaction、event_channel_consistency。
按照 references/audit_summary_contract.md 返回摘要。
当 summaryArtifactPath 缺失时,将独立模式的运行时摘要写入 .hex-skills/runtime-artifacts/runs/{run_id}/evaluation-worker/{worker}--{identifier}.json,并可选择在结构化输出中回显相同摘要。
Report written: .hex-skills/runtime-artifacts/runs/{run_id}/audit-report/ln-652--global.md
Score: X.X/10 | Issues: N (C:N H:N M:N L:N)
关键规则
遵循已加载的 references/audit_worker_core_contract.md。
- 不要自动修复: 仅报告
- 先发现触发器: 分析事务模式前,始终先扫描迁移文件中的触发器/NOTIFY
- 考虑 ORM: 检查 ORM 上下文管理器是否会自动回滚(
async with session.begin()是安全的) - 排除测试事务: 不要标记使用手动提交/回滚的测试夹具
- 考虑数据库差异: PostgreSQL 的 NOTIFY 语义与 MySQL 事件调度器不同
完成标准
遵循已加载的 references/audit_worker_core_contract.md。
- contextStore 已成功解析(包括 output_dir)
- 已确定 scan_path
- 已从迁移文件中发现触发器/NOTIFY 基础设施
- 已完成全部 6 项检查:
- 缺少中间提交、范围过宽、范围过窄、缺少回滚、事务持有时间过长、事件通道一致性
- 已收集问题,包含严重程度、位置、工作量和建议
- 已使用惩罚算法计算评分
- 已将报告写入
{output_dir}/ln-652--global.md(通过一次原子 Write 调用) - 已按照契约写入摘要
参考文件
- 审计输出架构:
references/audit_output_schema.md
版本: 1.1.0 最后更新: 2026-03-15