execution-safety.md 11 KB

# 执行安全:审计、防线、清单、确认

本 reference 覆盖执行阶段的安全保障机制,收口于 Step 2(规划门禁)、Step 3(执行)。 引用以下机制(顺序对应执行流程):


规划门禁(PLAN-GATE,Step 2 启用)

复杂任务在进入修改阶段前必须通过。Trivial Fix(单文件 ≤ 1 行,无结构变更;或 ≤3 文件且每文件 ≤5 行、无结构变更)可跳过;虽通过但触发异常 → 强制中止。

☐ 1. 是否已遍历所有用户定制 / 人工干预文件?
☐ 2. 是否已覆盖所有相关依赖模块?
☐ 3. 外部系统 / 接口影响已评估?
☐ 4. 新引入库的许可证兼容性已确认?
☐ 5. 命令行 / 脚本参数完整无硬编码路径?
☐ 6. 数据库迁移回滚方案已就绪?
☐ 7. 测试集已选定或确认无需新测试?
☐ 8. 性能敏感路径已标注(需基准对比)?
☐ 9. 批量范围已确认(文件数 / 记录数 / 受影响 API 数)?
☐ 10. 回滚 / 恢复机制已定义?
☐ 11. 安全漏洞扫描已预判(SQL注入/XSS/路径遍历/信息泄露)?
☐ 12. 并发 / 竞态 / 幂等场景已考虑?
☐ 13. 方案已回读确认格式无乱码/截断?
☐ 14. 自动跳过项已注原因?
☐ 15. 中断点与恢复路径已标注?

写码前实码确认

修改或生成代码前,必须完成:

  1. 读文件:read_file 目标文件,确认上下文、编码、插入位置
  2. 搜索关联:search_content 在项目中搜关键函数名/类名/表名,确认无遗漏引用
  3. 冲突检查:确认当前文件无正在进行中的未合并变更

三项均完成后才允许进入修改操作。跳过任一项 → 退回 Step 2。


审计修复分离

适用于代码审查、Bug 诊断、重构建议等场景:

  • 审计阶段:只读操作,收集证据(问题清单、堆栈、日志、复现步骤),禁止修改任何文件
  • 修复阶段:审计阶段结束后,输出结构化诊断结论,经确认后才进入修改

两阶段不可交叉。审计未完成前改代码 → 视为未完成审计,退回重做。

审计输出格式(修复阶段的前置输入):

## 审计结论
- 问题定位: {文件:行号}
- 根因分类: {框架行为/配置/缓存/竞态/逻辑错误/...}
- 影响范围: {受影响模块/功能}
- 修复方向: {最小改动方案}
- 验证方式: {如何确认修复有效}

不卡死计数器

同一诊断点在当前 session 内连续失败 ≥ 3 次 → 触发:

  1. 暂停当前方向的修复尝试
  2. 列出 2-3 条替代方案(不同策略,非参数微调)
  3. 说明各方案的成本、风险与验证方式
  4. 交用户选择后继续

禁止行为:同参数微调绕过计数器;换一句等价表述重试同一思路。


澄清策略分级(高 / 中 / 低,Step 2 引用)

SKILL.md Step 2 要求「业务规则 / 验收口径不明时,按澄清策略分级决定是否补问」。本节能级定义,执行时据此判定问不问、问多少,消除此前「分级」仅被引用无定义导致的决策点悬空。

三级判定标准

| 级别 | 触发条件(满足任一即归入该级) | 执行动作 | | - | - | - | | 高级 | ① 业务规则不明且错判有业务后果(如默认渠道 / 默认状态 / 计费口径写错会出脏数据);② 涉及生产配置 / 数据库写入 / 权限 / 凭证 / 不可回滚操作;③ 多利益方视角未区分优先级;④ 验收口径直接决定"做对了没"却未给出 | 先问关键问题再执行,最多 3 问;不假设、不默认。用户未回前不进入修改。降级例外(仅限非 DDL 的代码改动):若该操作具备可靠回滚点(.bak / 事务 / 版本化,且环境已启用 .bak 自动备份 hook)且影响可局部化,由高级降为中级——给默认假设 + 显式标注"如不符合请纠正",允许先执行后纠,不阻塞(仍保留 SELF-AUDIT / 回滚兜底)。破坏性操作(DDL / 删除 / 覆盖 / 批量写)一律不降级,强制走 delivery-assurance.md「确认超时默认规则」的确认流,优先级高于本降级例外 | | 中级 | ① 有合理默认但不同默认会导致实现差异(如返回 0 / 0.0 / 抛异常、分页用游标 vs offset);② 范围边界(是否连带改调用方)未确认;③ 性能 / 兼容性约束可推断但需对齐 | 先提案再纠:给带权衡的推荐方案——列出候选方案 + 各自 trade-off + 推荐项 + 明确假设标注("如不符合请纠正"),用户可在交付前纠正;不阻塞执行。仅对无候选方案的低歧义点给单一默认值 | | 低级 | ① 纯信息查询 / 只读评估;② 目标明确、范围小、风险低、有最小验证闭环;③ 口径可无歧义从上下文推出 | 直接假设并继续,无需单列确认;交付时说明假设即可 |

分级判定顺序

  1. 先判高级:命中任意高级条件 → 进高级。
  2. 高级降级检查:高级命中且满足「非 DDL 的代码改动 + 可逆(有 .bak / 事务 / 版本化回滚,且环境已启用 .bak 自动备份 hook)+ 影响局部化」→ 降为中级(给默认 + 标注可纠正,不阻塞);命中 DDL / 删除 / 覆盖 / 批量写 / 不可逆 / 影响全局 / 涉生产配置 / 涉凭证隐私 → 维持高级硬卡,并转 delivery-assurance.md 确认超时规则处理。
  3. 否则判中级:命中任意中级条件 → 进中级,先提案再纠(带 trade-off 的推荐方案 + 假设标注)。
  4. 否则 → 低级:直接执行。

与意图三分法的关系

本分级只决定「澄清动作强度」,不替代意图三分法(信息查询 / 简单任务 / 复杂任务)对执行模式的判定。典型组合:

  • 高级 + 复杂任务 → 先澄清后方案,双门槛。
  • 中级 + 简单任务 → 给默认标注后快速通道执行。
  • 低级 + 信息查询 → 直接回答,不写文件。

反模式(真实执行易踩)

  • 澄清过度:低级任务却反复追问 → 触发对话流异常边界「澄清过度」,进快速通道。
  • 澄清不足:高级条件已命中却未确认即执行 → 触发「澄清不足」,下调自主度补问。
  • 伪分级:把"想偷懒不问"包装成低级 → 凡涉库 / 权限 / 生产配置一律不得降为低级,安全闸门优先。

批量修改 7 防线

批量修改(同操作影响 ≥ 3 文件或 ≥ 10 处修改点)时启用:

| 防线 | 动作 | 失败处置 | | - | - | - | | 1. 预检 | 全局 lint(含 PHPStan/ESLint 等),确保基线干净 | FAIL → 修复后重跑 | | 2. 试点 | 取 3-5 个代表性文件,试改 | 任意 FAIL → 调整规则后重试,上限 2 次 | | 3. 备份 | 改前 cp → .bak(保留最近 3 个历史版本 .bak / .bak.1 / .bak.2),范围对齐批量计划 | 不可跳过 | | 4. 批量执行 | 按计划逐文件执行 | 输出 [OK/SKIP/ROLLBACK] 逐文件日志 | | 5. 后检 | 全局 lint,与前基线对比 | 新增问题 → 回退 | | 6. MD5 校验 | 预期外变更文件输出 MD5 对比 | 标注差异来源 | | 7. 回读确认 | 抽查 3-5 个文件,确认修改点正确 | 不一致 → 整批回退 |

回退规则:ROLLBACK 总量 > 20% → 整批回退。回退方式:倒序 .bak 恢复(.bak 为最新备份,.bak.1 次之,.bak.2 最旧)。


清单化质量自审

代码交付前逐条自审(收口于 SELF-AUDIT § 代码质量):

☐ 异常处理完备(try-catch / 错误返回 / 边界条件)
☐ 硬编码常量已提取
☐ SQL / 外部输入已参数化
☐ 输出已转义(XSS / 模板引擎)
☐ 敏感信息不入日志/返回值
☐ 文件操作含路径白名单校验
☐ 超时/重试已设置上限
☐ 并发/竞态场景已处理
☐ 接口幂等性已保证(写操作)
☐ 注释与代码一致(无过期注释)

安全红线清单

文件操作、数据访问、用户输入处理等场景必须逐条对照:

☐ SQL 参数化(无字符串拼接用户输入)
☐ 输出转义(HTML / JS / URL 上下文)
☐ 文件路径白名单 / 拒绝 ../ 穿越
☐ 上传类型白名单 + 大小限制
☐ 敏感信息不入前端(密钥/Token/内部路径)
☐ CSRF Token(状态变更操作)
☐ 权限校验后端兜底(前端校验仅为 UX)
☐ 错误信息不泄露内部细节
☐ 第三方依赖版本已知漏洞已排查
☐ 日志不含密码/Token/身份证号

session_memory 标识(id)生成规则(Step 0 / Step 6 引用)

SKILL.md Step 1.1 Layer 2(L86 区)读取 {YYYYMMDD}/session_memory_{session-id}.jsonl、Step 6(L240)写入同名文件;首次会话无 session-id 时由 Step 0 探测阶段生成(见下生成规则),兜底读取取当日最大时间戳 jsonl。为避免跨会话恢复时找不到对应文件,本节能级统一 session-id 的生成与存储约定:

生成规则

  • 格式:session-id = YYYYMMDD-HHmm。
  • 生成时机:本次会话首次进入 Step 0(新会话加载 / 探测阶段) 即生成并写入当日 daily.md 顶部 session-id: {YYYYMMDD-HHmm} 行(唯一真相源);若 daily.md 无此行(旧会话 / 首次),取当日目录下时间戳最大的 session_memory_*.jsonl 兜底(见下读取规则)。
  • 存储:写进当日 daily.md 顶部一行 session-id: {YYYYMMDD-HHmm},作为唯一真相源。
  • 读取:Step 0 恢复时,先读 {YYYYMMDD}/daily.md 顶部的 session-id 行,再据该值定位 session_memory_{session-id}.jsonl;若 daily.md 无此行(旧会话 / 首次),则取当日目录下文件名时间戳最大的 session_memory_*.jsonl。

收敛要点

  • 单日多会话:各自有独立 session-id,互不覆盖。
  • 续做定位:用户说"继续"时,按 daily.md 记录的 session-id 精确恢复,不依赖猜测文件名。
  • 无历史:探测失败 → 正常进入意图识别,不阻塞(与 Step 1.1 触发规则一致)。

对接点

| 文件 | Step | 说明 | | - | - | - | | delivery-assurance.md | Step 5 | SELF-AUDIT 引用质量自审清单与安全红线清单 | | error-ledger.md | Step 6 | 踩坑若涉及批量/安全/质量模式,新坑即录 | | software-project.md | Step 3/Step 5 | 项目总控的验收引用交付检查清单 | | code-generation.md | 第〇步 | 复杂代码生成前判定需否安全红线预检 | | SKILL.md | Step 2 / Step 0 / Step 6 | 澄清策略分级定义、session-id 生成规则(消悬空引用) |