[ISSUE-0047] 第 9 轮 agent — 质量分可配置 v0.10.66 3 处漏¶
v0.10.66 提交后立刻让第 9 轮独立 agent 审查 — 找出 1 个误判 + 3 处真漏:
- 🔴 误判(已 verify):agent 担心 search.ts 在 background,但实际通过 useRequest 在 main page React 端调用,与 main-layout 共享 module bundle。
- 🟡 race(真):first dataRun 可能赶在 main-layout init 完之前
- 🔴 真:用户在 Settings 改完权重 → cachedConfig 更新了,但已渲染的 DataView 不会 re-fetch → 不刷新
- 🟡 真:
qualityConfigItem.setValue漏 catch — 保存失败静默
修¶
1. init 幂等 + 返回 promise(防 race)¶
let initPromise: Promise<void> | null = null;
export function initQualityConfigCache(): Promise<void> {
if (initPromise) return initPromise;
initPromise = (async () => { ... })();
return initPromise;
}
export function ensureQualityConfigReady(): Promise<void> {
return initQualityConfigCache();
}
2. apiLocalDataList client-sort 前 await ready¶
防 first dataRun 用旧默认值排错序。
3. DataView 订阅 qualityConfigItem.watch → 即时重刷¶
useEffect(() => {
const unsub = qualityConfigItem.watch(() => {
getTableData();
});
return () => unsub();
}, []);
用户改完 Settings 切回数据 tab → 立刻按新算法刷新(不必手动点刷新)。
4. Settings setValue 加 catch¶
qualityConfigItem.setValue(next).catch((e) => {
notice.error(`保存质量分配置失败:${e?.message || '未知错误'}`);
});
storage quota / 隐私模式失败时用户能看到,不再静默丢。
元洞察 — Sync Cache 模式的结构性裂缝¶
第 9 轮 agent 指出(即便误判 search.ts context)一个通用问题:
Sync cache 模式有结构性裂缝:UI context 装的 cache + watch 无法保护其它 context 的同一函数调用。
应对模板:
1. cache 初始化做成幂等 + lazy — 任何 caller 都可以 await ensureXxxReady()
2. storage.watch 不只更新 cache 还要触发 UI 重渲 — 否则 cache 新了但视图旧
3. storage.setValue 永远 catch — 防 quota / 隐私模式静默吞错
第 9 轮 agent 价值¶
| Agent 判断 | 我的 verify | 价值 |
|---|---|---|
| 🔴 search.ts in background → cache 不共享 | 误判 — 实际在 main page | 但勾起的"防御性思考"对的 |
| 🔴 watcher 不触发 re-render → DataView 不刷新 | 真 | 修了 |
| 🟡 first dataRun race | 真 | 修了 |
| 🟡 setValue 漏 catch | 真 | 修了 |
| 🟢 多个 watcher 单例 | 无害 | 跳过 |
4/5 valid。误判 1 个 — 但提出的元洞察(多 context 双初始化)依然有用, 未来碰到 SW 调 computeQualityScore 时就要双初始化。
audit_grep¶
audit_grep:
- pattern: "initQualityConfigCache\\(\\)[^.]"
description: "init 应该幂等 + 返回 promise,不应 fire-and-forget — 调用者
应 await ensureQualityConfigReady() 或忽略 promise(main-layout useEffect 可忽略)"