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

96 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 审核时预生成修复 + 展开问题即显示 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 }``LinterFix``originalText?``LinterDiagnostic``aiFix?: AiFixSnippet` |
| `src/ai/schema.ts` | `CustomRuleResult``AIFinding``TranslatedDiagnostic` 加可选 `fix?: AiFixSnippet` |
| `src/ai/engine.ts` | 三语 promptzh/en/ja)的 `customRuleResults`/`findings`/`translatedDiagnostics` 输出格式加 `fix` 字段(含"原文逐字、不含行号前缀"说明);`runAIReview`/`runMethodReview` 解析容错保留 `fix` |
| `src/merger/merger.ts` | `MergeInput``code?`;映射 `staticDiagnostics` 时从 `code``fix.range` 切片补 `fix.originalText`;映射 `customRuleResults` 时带 `aiFix` |
| `src/activation/commands.ts` | 所有 `mergeResults` 调用点传 `document.getText()` 作为 `code``refreshAfterFix` 重建时保留 `aiFix``findCustomIssue`/`findAIIssue`/`fixAll``fix` |
| `src/fix/fixPrompt.ts` | `ReviewIssueInput``fix?: AiFixSnippet` |
| `src/fix/customFixEngine.ts` | `aiFixReviewIssue` 开头尝试预生成片段直接应用,失败进实时循环 |
| `src/fix/aiFixEngine.ts` | `aiFixDiagnostic` 开头尝试预生成片段直接应用 |
| `src/utils/diff.ts`(新建) | 轻量行级 diff(LCS),返回 `{type:'del'\|'add'\|'same', text}[]` |
| `src/panel/webview.ts` | 展开区渲染行级 diff`.diff-del` 红 / `.diff-add` 绿 + CSS);三列表构造 detailHtml 时并入 diffsuggestion 与 diff 同时展示 |
## 核心逻辑
### 预生成片段直接应用(两个修复引擎开头共用模式)
```ts
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 渲染
```ts
// 提取每条问题的修复片段
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 lint``npm run compile``npm test`
- 手动验证:custom / AI findings / linter 无 autofix 三条路径的"展开即见 diff"与"点修复免等待"
- 修改代码后再点修复应回退实时
- fixAll 批量场景多数问题秒过,个别失败回退实时