@@ -419,7 +419,10 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
419419 if ( isElementNotFound && bugDesc . includes ( "@hint=" ) && ! cat . includes ( "[蓝本问题]" ) ) {
420420 lines . push ( ` ⚠️ 归因提示:XPath[@hint='xxx'] 在 Flutter 中不稳定(UiAutomator2 有时无法读取 EditText hint)。建议改用 Semantics label 的 accessibility_id 定位。大概率是【蓝本问题】。` ) ;
421421 }
422- // ── 顽固Bug加强分析(已出现≥2次,即至少3次修复失败)──
422+ // ── 顽固Bug多级递进分析 ──
423+ if ( retryCount === 1 ) {
424+ lines . push ( ` ⚠️ [第2次出现] 此Bug上次已出现过,修复后依然发生。请优先检查:蓝本断言是否本身有误?选择器是否精确对应源码?` ) ;
425+ }
423426 if ( retryCount >= 2 ) {
424427 lines . push ( ` 🚨 [顽固Bug × ${ retryCount + 1 } 次] 此Bug已连续 ${ retryCount + 1 } 次出现,前几次修复均无效。请强制换思路深度分析:` ) ;
425428 lines . push ( ` ① expected 文本/元素在APP当前状态下真的可见/存在吗?(不要假设)` ) ;
@@ -428,6 +431,9 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
428431 lines . push ( ` ④ 如果APP没有后端/数据库,操作后不会有文字反馈,断言应改为验证UI状态变化` ) ;
429432 lines . push ( ` ⑤ 禁止重复使用上一次失败的同一修复方案` ) ;
430433 }
434+ if ( retryCount >= 3 ) {
435+ lines . push ( ` 🚨🚨 [第${ retryCount + 1 } 次·请人工介入] AI已无法独立解决此Bug,建议暂停AI自动修复,手动打开蓝本文件检查断言逻辑,并直接运行APP验证该操作的真实反馈,再决定修复方向。` ) ;
436+ }
431437 } ) ;
432438 } else {
433439 lines . push ( ( report . report_markdown as string || "" ) . substring ( 0 , 1000 ) ) ;
@@ -1860,8 +1866,13 @@ ${commonRules}`;
18601866
18611867 // 存储最后一次报告数据
18621868 let lastReport = null;
1863- // 顽固Bug重试计数:key=签名(步骤号|标题前40字), value=累计出现次数(跨多次测试,不重置)
1864- var bugRetryMap = {};
1869+ // 顽固Bug重试计数:key=签名(步骤号|标题前40字), value=累计出现次数(localStorage持久化,Reload Window不丢失)
1870+ var bugRetryMap = (function() {
1871+ try { return JSON.parse(localStorage.getItem("tp_bug_retry") || "{}"); } catch(e) { return {}; }
1872+ })();
1873+ function saveBugRetryMap() {
1874+ try { localStorage.setItem("tp_bug_retry", JSON.stringify(bugRetryMap)); } catch(e) {}
1875+ }
18651876
18661877 // 复制Bug给AI
18671878 document.getElementById("btnCopyBugs").addEventListener("click", () => {
@@ -2391,6 +2402,7 @@ ${commonRules}`;
23912402 var sig = (bug.step_number || "0") + "|" + (bug.title || "").substring(0, 40);
23922403 bugRetryMap[sig] = (bugRetryMap[sig] || 0) + 1;
23932404 });
2405+ saveBugRetryMap();
23942406 controlSection.classList.add("hidden");
23952407 screenshotSection.classList.add("hidden");
23962408 addLog("测试完成!", "success");
@@ -2417,7 +2429,7 @@ ${commonRules}`;
24172429 resultSection.classList.remove("hidden");
24182430
24192431 // 渲染Bug列表
2420- renderBugs(report.bugs || []);
2432+ renderBugs(report.bugs || [], bugRetryMap );
24212433
24222434 // 渲染步骤详情(自动展开)
24232435 renderSteps(report.steps || []);
@@ -2467,7 +2479,8 @@ ${commonRules}`;
24672479 };
24682480 }
24692481
2470- function renderBugs(bugs) {
2482+ function renderBugs(bugs, retryMap) {
2483+ retryMap = retryMap || {};
24712484 bugList.innerHTML = "";
24722485 bugTotal.textContent = bugs.length;
24732486 if (bugs.length === 0) {
@@ -2479,10 +2492,18 @@ ${commonRules}`;
24792492 const sev = bug.severity || "medium";
24802493 const div = document.createElement("div");
24812494 div.className = "bug-item " + sev;
2495+ var bugSig = (bug.step_number || "0") + "|" + (bug.title || "").substring(0, 40);
2496+ var rc = retryMap[bugSig] || 0;
2497+ var retryBadge = rc >= 3
2498+ ? ' <span style="color:var(--error,#ef4444);font-size:10px;font-weight:600">🚨×' + rc + ' 需人工介入</span>'
2499+ : rc >= 2
2500+ ? ' <span style="color:var(--warning,#f59e0b);font-size:10px">🔁×' + rc + '</span>'
2501+ : '';
24822502 div.innerHTML =
24832503 '<div class="bug-title">' +
24842504 '<span class="severity-badge ' + sev + '">' + sev.toUpperCase() + '</span>' +
24852505 escapeHtml(bug.title || "Bug #" + (i+1)) +
2506+ retryBadge +
24862507 '</div>' +
24872508 (bug.step_number ? '<div class="bug-meta">步骤 #' + bug.step_number + (bug.category ? ' · ' + escapeHtml(bug.category) : '') + '</div>' : '') +
24882509 '<div class="bug-desc">' + escapeHtml((bug.description || "").substring(0, 200)) + '</div>';
0 commit comments