Files
2026Technology-Competition/docs/superpowers/specs/2026-08-22-pregen-fix-design.md
T
范智鹏 9c676e46e6 feat: AI 修复预生成 + 审查面板 diff 预览两步确认 + SQLFluff 行号修复 + PMD 内置规则精简
- AI 修复预生成:静态/custom/AI 条目审查时预生成修复片段(originalText/newText),展开问题即显示行级 diff,无预生成时展示占位提示,匹配失败回退实时 LLM 生成

- 修复前 diff 预览:侧边新建编辑器组打开内置 diff,确认后写入(两步确认),不覆盖当前文件

- fix: sqlfluff 在 jinja 标签位于注释内时 JJ01 JSON 缺失 end_line_no/end_line_pos,适配器 Range 构造产生 NaN 被 VSCode 交换 start/end 导致行号 LNaN;新增 resolveSqlFluffRange 兜底 + 面板/report 行号 Number.isFinite 防御

- fix: 从 PMD 内置 ruleset 移除 5 条实际不可触发规则(AvoidAssertAsIdentifier、AvoidEnumAsIdentifier、AccessorClassGeneration、AccessorMethodGeneration、LoosePackageCoupling),内置配置 274→269 条全部可触发,同步 static-rules.json 与翻译脚本

- docs: README/DESIGN 更新
2026-08-25 21:58:14 +08:00

4.7 KiB
Raw Blame History

审核时预生成修复 + 展开问题即显示 diff

日期:2026-08-22 状态:已批准

目标

  1. 审核时 AI 为三类问题(custom 规则问题、AI 深度审查发现、linter 无 autofix 诊断)预生成可直接应用的修复片段 { originalText, newText }
  2. 点击面板"修复"按钮直接从报告取片段匹配应用,无需再调 LLM;匹配失败自动回退实时 AI 修复。
  3. 面板展开问题时,直接以行级 -/+ 对比显示修复前后代码(所有可修复问题,含 linter 自带 fix)。
  4. fixAll 采用"预生成片段优先,失败回退实时"策略,不做偏移修正。

数据流

审核(发现 + 预生成修复片段) → 面板
   ├─ 点修复 → 直接匹配应用(免等待) → 失败 → 回退实时 LLM
   └─ 展开问题 → 行级 -/+ diff 立即渲染

关键决策

决策点 结论
预生成覆盖 custom + AI findings + linter 无 autofix 诊断
匹配失败 回退实时 AI 修复
点击修复 保留 diff 预览确认,内容来自预生成片段
展开 diff 形式 行级 -/+ 对比(红删/绿增)
展开 diff 范围 所有可修复问题(含 linter 自带 fix)
fixAll 策略 预生成片段优先,失败回退实时,不做偏移修正
兼容性 fix/aiFix 字段可选,缺失则该问题无预生成修复/diff,行为不变

文件变更

文件 变更
src/types.ts 新增 AiFixSnippet { originalText; newText }LinterFixoriginalText?LinterDiagnosticaiFix?: AiFixSnippet
src/ai/schema.ts CustomRuleResultAIFindingTranslatedDiagnostic 加可选 fix?: AiFixSnippet
src/ai/engine.ts 三语 promptzh/en/ja)的 customRuleResults/findings/translatedDiagnostics 输出格式加 fix 字段(含"原文逐字、不含行号前缀"说明);runAIReview/runMethodReview 解析容错保留 fix
src/merger/merger.ts MergeInputcode?;映射 staticDiagnostics 时从 codefix.range 切片补 fix.originalText;映射 customRuleResults 时带 aiFix
src/activation/commands.ts 所有 mergeResults 调用点传 document.getText() 作为 coderefreshAfterFix 重建时保留 aiFixfindCustomIssue/findAIIssue/fixAllfix
src/fix/fixPrompt.ts ReviewIssueInputfix?: AiFixSnippet
src/fix/customFixEngine.ts aiFixReviewIssue 开头尝试预生成片段直接应用,失败进实时循环
src/fix/aiFixEngine.ts aiFixDiagnostic 开头尝试预生成片段直接应用
src/utils/diff.ts(新建) 轻量行级 diffLCS),返回 {type:'del'|'add'|'same', text}[]
src/panel/webview.ts 展开区渲染行级 diff.diff-del 红 / .diff-add 绿 + CSS);三列表构造 detailHtml 时并入 diffsuggestion 与 diff 同时展示

核心逻辑

预生成片段直接应用(两个修复引擎开头共用模式)

const p = diag.fix ?? diag.aiFix;
if (p?.originalText && p?.newText) {
  const i = currentText.indexOf(p.originalText);
  if (i !== -1) {
    const next = currentText.slice(0, i) + p.newText + currentText.slice(i + p.originalText.length);
    if (next !== currentText) {
      appliedFixes.push({ originalText: p.originalText, newText: p.newText, line });
      return dryRun ? { success: true, appliedFixes, newText: next }
                     : applyWorkspaceEdit(document, next, appliedFixes);
    }
  }
}
// 匹配失败 → 继续现有 for 循环(实时 LLM)

展开 diff 渲染

// 提取每条问题的修复片段
linter: d.fix?.originalText + d.fix?.text     // 或 d.aiFix
custom: d.aiFix
ai:     f.fix
// 生成行级 diff HTML
diffHtml = computeLineDiff(originalText, newText)
  .map(l => `<div class="diff-${l.type}">${esc(l.text)}</div>`).join('')

fixAll 策略

逐条串行处理:每条问题先尝试预生成片段在当前累积文本 currentText 上匹配,命中则直接应用(不调 LLM);失败或无片段则走现有实时修复。完成后保留批量 diff 预览 + 应用确认。

影响与风险

  • 审核输出变长(三个来源都输出 fix),token/耗时略增——换取点修复零等待 + 展开即见 diff
  • linter 原文片段依赖 code 全文切片;refreshAfterFix 需传当前文本,否则 diff 基于旧文本(匹配失败会回退,体验无损)
  • 自写 diff 仅行级对比,不做字符级高亮

验证

  • npm run lintnpm run compilenpm test
  • 手动验证:custom / AI findings / linter 无 autofix 三条路径的"展开即见 diff"与"点修复免等待"
  • 修改代码后再点修复应回退实时
  • fixAll 批量场景多数问题秒过,个别失败回退实时