From d32deda49832c9d7c0b826249c6e77e15827b2e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E6=99=BA=E9=B9=8F?= Date: Tue, 8 Sep 2026 22:26:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=AE=BE=E7=BD=AE=E8=A7=86=E5=9B=BE?= =?UTF-8?q?=E8=A7=84=E5=88=99=E6=96=87=E4=BB=B6=E5=90=8D=E5=8F=AF=E7=82=B9?= =?UTF-8?q?=E5=87=BB=E6=89=93=E5=BC=80=20+=20=E6=96=87=E4=BB=B6=E7=BC=BA?= =?UTF-8?q?=E5=A4=B1=E6=8F=90=E7=A4=BA=EF=BC=88i18n=20=E4=B8=89=E8=AF=AD?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _AI_USAGE_LOG.md | 2 ++ src/i18n/messages.ts | 5 +++++ src/views/setupView.js | 7 ++++++- src/views/setupView.ts | 19 +++++++++++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/_AI_USAGE_LOG.md b/_AI_USAGE_LOG.md index 5c92b56..81040ab 100644 --- a/_AI_USAGE_LOG.md +++ b/_AI_USAGE_LOG.md @@ -245,3 +245,5 @@ | 2026-09-07 21:05 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | 不规则内容导入全量手动验证(7 种格式 × 同一 12 条规则基准,重噪声嵌入:项目背景/团队介绍/会议纪要/部署流程/版本历史/反面正面代码示例/wiki 链接/Checklist):素材 7 文件由用户放入 data/import-verification/03-irregular-content/(无 template 轮,严格校验路径不适配不规则内容);用户逐轮手动导入(规则名 irregular-<格式>),AI 逐轮核对落盘并归档至 03-irregular-content/results/。结果 7/7 通过:噪声过滤零失守(背景/纪要/版本历史等未成规则)、反面示例陷阱零触发(Admin@123456/eval 示例未被生成规则)、叙事与规则正确分离、severity 全对、languages 除 yaml 直读外全对。三项跨场景结论:①pptx 降级定性修正——本场景 pptx(45KB 重噪声)languages 零丢失,与场景②丢 6 处、旧 rules_ppt.yaml 大面积缺失合并,证明是高方差而非必然缺陷(02 报告结论据此修正);②去重判断方差实锤——no-hardcoded-credentials 在 xlsx 轮判 overlap(保留,与 custom/no-hardcoded-secret 并存双报)multisheet 轮回归 exact,且 docx 轮 avoid-magic-numbers(id 前缀完全不同)仍被精准标为 custom/no-magic-numbers exact,去重语义性最直接验证;③表格类稳定性跨场景复现——xlsx/multisheet id 再次全对齐基准,multisheet 落盘与场景② multisheet 逐字节一致(fc 0 差异,源文件 15KB 标准 vs 24KB 重噪声完全不同),02-xlsx≡02-multisheet≡03-multisheet 链条成立。自由文本四轮 id 继续逐轮漂移(语义等价)。总报告 data/import-verification/03-irregular-content/result-report.md(无人名);guide.md 场景③状态更新为已完成。无代码变更 | 中间产物:①pptx 轮一度预期复现场景②降级,实测零丢失后推翻原假设并修正定性;②xlsx 轮 overlap 判定曾商榷是否要求用户人工改注,按『AI 方差属设计内弹性、预览人工复核为设计补偿』定性保留原样仅记录 | data/import-verification/03-irregular-content/(素材7件+results/7件归档+result-report.md) data/import-verification/guide.md(状态更新) | GLM-5.3-Flash | | 2026-09-07 21:19 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | 场景② pptx 同文件重测与根因终审(一次调查两阶段,原分两条记录现合并):阶段一·重测复现——用户重导 standard-rules-pptx(归档为 results/standard-rules-pptx-retest.yaml,-retest 后缀防同名冲突),12 条全检出、severity 全对、去重 3 exact 同构;语言留空模式与首测逐字段完全复现(同 6 处留空、类型注解规则同保留 [typescript]、TODO 同无 excludeLanguages),而同期 id 照例漂移(8 条中 7 条不同)——id 生成随机属 AI 层、语言留空确定属文件因素,排除 AI 随机性。阶段二·根因终审——用户提出关键假设『02 pptx 文件中并没有包含语言等信息』,经与插件相同的 officeparser 调用链(OfficeParser.parseOffice→ast.toText)提取两份 pptx 比对证实:02 源文件全文 950 字符不含任何『适用语言/排除语言』标注(severity 有 [error]/[warning]/[info] 前缀,语言没有),03 源文件含成组『严重级别 | 语言』标注及『排除语言:sql』。终案:语言字段差异源于源文件内容差异,AI 两轮行为均正确(源有的正确映射含 excludeLanguages:[sql],源无的按『严禁猜测留空更安全』留空,语义可推的一条正确推断 [typescript]),不存在降级或丢失——源文件没有的数据不能叫丢失。定性演进三版全记录:格式缺陷(02 初稿)→高方差(03 初稿)→文件级提取确定性(重测阶段,被后证推翻)→源文件内容差异(终稿)。两份报告按终稿修正(02 发现 1 重写+结论改写、03 发现 2 重写+结论改写),制作 pptx 素材需语言限定须在幻灯片显式标注。无代码变更 | 中间产物:①定性经三版演进(格式缺陷→高方差→提取层丢失)才到终案,前两版均未实际检验提取文本——教训:假设提取层有损前应先比对提取输出与源内容;②重测归档命名用 -retest 后缀避免与首测同名冲突(防覆盖约定) | data/import-verification/02-standard-formats/results/standard-rules-pptx-retest.yaml(归档) data/import-verification/02-standard-formats/result-report.md(更新×2) data/import-verification/03-irregular-content/result-report.md(更新×2) | GLM-5.3-Flash | | 2026-09-07 22:44 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | 自定义规则审查联动验证(演示定位:团队编码风格/习惯类规则,目标『覆盖全』——测试代码对静态分析与通用 AI 审查双重干净,仅含团队约定违规):新建 data/custom-rule-demo/(脱离 import-verification 场景体系,用户指定);设计 5 条纯团队约定规则(查询方法前缀/DTO 后缀/Result 包装/@author 标注/中文日志)+ TeamStyleService.java 测试代码(5 处无痕埋点,不带提示注释防 AI 照抄);基线经 3 轮迭代收敛(11→4→6,PMD 清零、无 error 级、均为开放性设计 nitpick),迭代中两次设计修正——金额 BigDecimal 规则被通用 AI 原生命中(真实最佳实践不配当团队约定)换为 @author 标注规则,类名 TeamStyleDemo→TeamStyleService 消除 R1『Service 层』歧义;用户导入 team-style-rules(5 条零去重保留)后复审:自定义规则 6 条命中(5/5 规则全覆盖,require-author-tag 双命中系埋点遗漏被规则抓出)、行号全部精准、message 逐字来自规则文件、与 4 条通用 AI 建议独立分区零混淆。关键实证:通用 AI 建议逐轮波动(11→4→6→4)vs 团队规则命中确定精准——『开放性建议 vs 确定性约定检查』为演示核心叙事;通用 AI 与团队规则边界实测划清(金额 BigDecimal 被通用 AI 捕获、@author/中文日志零感知)。基线 7 条规则恢复激活(与 5 条团队规则共存无冲突);结果报告 data/custom-rule-demo/result-report.md(无人名)。无代码变更 | 中间产物:①『AI 零建议』基线目标对非平凡代码不可达,改为『无 error 级+建议均为开放性 nitpick』通过标准;②R4 金额规则被通用 AI 原生捕获后曾考虑构造器注入等替代,最终选 @author(纯约定零感知);③OrderController 埋点漏加 @author 反被规则命中,转化为规则执行力佐证 | data/custom-rule-demo/team-style-rules.yaml(新建) data/custom-rule-demo/TeamStyleService.java(新建,迭代3版) data/custom-rule-demo/result-report.md(新建) .code-review/rules-hold/(基线规则暂存与恢复) | GLM-5.3-Flash | +| 2026-09-08 20:41 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | 设置面板自定义规则列表可点击打开规则文件:webview 新增 openRuleFile 并挂到 .rule-name 的 onclick(与 deleteFile 同风格,删除按钮独立元素不受影响);后端消息 switch 新增 case openRuleFile + openRuleFile 方法(path.join(workspaceRoot,.code-review,rules,fileName) → openTextDocument+showTextDocument,复用 handleAdapterConfig 先例,文件不存在 showWarningMessage);CSS .rule-name 加 cursor:pointer 与 hover 主题蓝下划线;i18n 新增 setup.ruleFileMissing(中/英/日)。验证:eslint 0 error(2 条既有 warning 与本次无关)→ tsc 编译通过 → copy-webview-js 产物含 openRuleFile×2。⚠️本条记录的『验证通过』不实——见 21:22 修正条目 | 无(方案一次批准直接编码,无废弃草稿) | src/views/setupView.js src/views/setupView.ts src/i18n/messages.ts | GLM-5.3 | +| 2026-09-08 21:22 | ① 用户提出 → ② 需求澄清 → ③ 方案设计 → ④ 人类审批 → ⑤ 编码实现 → ⑥ 审查验证 | 修复上条功能实际失效:用户实测点击无反应,排查发现 20:41 对 setupView.js/setupView.ts 各自并行发起 3 个 Edit 调用发生丢失更新竞态——每个编辑基于同一原始快照独立读改写,最后写入者只保留自己那处改动,导致 js 的 onclick 绑定与 window 挂载、ts 的 case 分支与 CSS 共 4 处丢失(仅 js 函数定义与 ts 方法幸存),首次 rg 计数 2 被误读为正常,首个 VSIX 即打包自残缺代码。本次逐个串行补齐 4 处(不同文件可并行):git diff 复核 js +7/-1、ts +19、messages +5 齐全;rg 确认 out/webview/setupView.js 含 42/43/190/365 四处 openRuleFile;lint 0 error → compile 通过 → 重新 package-prod 出包。教训:同一文件多处修改必须串行 Edit,rg -c 计数需与预期处数逐一核对而非仅判断非零 | 中间产物:并行竞态产生的两份残缺文件版本(js 仅含函数定义版、ts 仅含方法版)及据此打出的残缺 VSIX(6137 文件 70.93MB,已被 21:22 重新打包覆盖) | src/views/setupView.js src/views/setupView.ts(补齐 4 处丢失改动) | GLM-5.3 | diff --git a/src/i18n/messages.ts b/src/i18n/messages.ts index 5239415..241e2f5 100644 --- a/src/i18n/messages.ts +++ b/src/i18n/messages.ts @@ -1275,6 +1275,11 @@ const messages: Record> = { en: 'Select template file', ja: 'テンプレートファイルを選択', }, + 'setup.ruleFileMissing': { + 'zh-CN': '规则文件不存在: {0}', + en: 'Rule file not found: {0}', + ja: 'ルールファイルが見つかりません: {0}', + }, 'setup.importingTemplate': { 'zh-CN': '正在导入模板...', en: 'Importing template...', diff --git a/src/views/setupView.js b/src/views/setupView.js index 8795922..0f4d0aa 100644 --- a/src/views/setupView.js +++ b/src/views/setupView.js @@ -39,6 +39,10 @@ vscode.postMessage({ type: 'deleteFile', fileName: fileName }); } + function openRuleFile(fileName) { + vscode.postMessage({ type: 'openRuleFile', fileName: fileName }); + } + var _step1Done = false; var _step2Done = false; var _i18n = {}; @@ -183,7 +187,7 @@ if (msg.ruleFiles && msg.ruleFiles.length > 0) { ruleList.innerHTML = msg.ruleFiles.map(function (f) { return '
' + - '' + escapeHtml(f) + '' + + '' + escapeHtml(f) + '' + '
'; }).join(''); } else { @@ -358,4 +362,5 @@ window.postMsg = postMsg; window.addRule = addRule; window.deleteFile = deleteFile; + window.openRuleFile = openRuleFile; })(); diff --git a/src/views/setupView.ts b/src/views/setupView.ts index f7475e7..c771972 100644 --- a/src/views/setupView.ts +++ b/src/views/setupView.ts @@ -235,6 +235,9 @@ export class SetupViewProvider implements vscode.WebviewViewProvider { case 'saveAndTest': await this.testConnection(); break; + case 'openRuleFile': + await this.openRuleFile(msg.fileName); + break; case 'deleteFile': await this.deleteFile(msg.fileName); await this.pushConfig(); @@ -402,6 +405,20 @@ export class SetupViewProvider implements vscode.WebviewViewProvider { } } + private async openRuleFile(fileName: string): Promise { + const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; + if (!workspaceRoot) {return;} + + const filePath = path.join(workspaceRoot, '.code-review', 'rules', fileName); + if (!fs.existsSync(filePath)) { + vscode.window.showWarningMessage(t('setup.ruleFileMissing', { 0: fileName })); + return; + } + + const doc = await vscode.workspace.openTextDocument(filePath); + await vscode.window.showTextDocument(doc); + } + private async addRule(name: string, useTemplateMode?: boolean): Promise { if (!name.trim()) { return; } @@ -705,7 +722,9 @@ input::placeholder { color: var(--vscode-input-placeholderForeground, var(--vsco font-family: 'SF Mono', Consolas, 'Liberation Mono', Menlo, monospace; color: var(--vscode-foreground); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + cursor: pointer; } +.rule-name:hover { color: var(--vscode-textLink-foreground); text-decoration: underline; } .rule-del { flex-shrink: 0; width: 20px; height: 20px; border-radius: 4px; border: none; background: transparent; color: var(--vscode-descriptionForeground);