From deaeabcf7469d30140592bf44e1874222889b49f Mon Sep 17 00:00:00 2001 From: sinohqb Date: Fri, 14 Aug 2026 15:34:35 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20v1.1.0=20post-release=20patches=20+=20s?= =?UTF-8?q?can=20=C2=A76=20resolved=20tracking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - .scratch/v111-architecture-scan.md: mark §6.1, §6.2, §6.4 as RESOLVED (commits 38e3817, f85eca1, 6d32653); add §6.5 for T8 decision-log dedupe (commit 4bcab06). - docs/release-notes-v1.1.0.md: add section ten listing the four post-release fixes shipped to main after v1.1.1 was deployed, so the release page documents what v1.1.1 production actually contains (and what the v1.1.1 image does NOT contain). --- .scratch/v111-architecture-scan.md | 20 ++++++++++++++++---- docs/release-notes-v1.1.0.md | 22 +++++++++++++++++++++- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/.scratch/v111-architecture-scan.md b/.scratch/v111-architecture-scan.md index 520375a..4a5f263 100644 --- a/.scratch/v111-architecture-scan.md +++ b/.scratch/v111-architecture-scan.md @@ -73,7 +73,7 @@ > 这里记录在按本扫描实施时**新暴露**的真实问题(不在原 seam/T 列表里),是测试防护网的首要价值。 -### 6.1 `assign_task` 缺原子 CAS(**真 bug**,T1 暴露) +### 6.1 `assign_task` 缺原子 CAS(**真 bug**,T1 暴露)— ✅ RESOLVED (`38e3817`) **症状**:`tests/integration/test_worker_task_resilience.py::test_concurrent_assign_via_two_sessions` 失败。 两个独立 session(两个 worker 进程)并发调用 `assign_task` 同一 pending task 时,**两个都返回 True**——任务被双认领。 @@ -92,7 +92,7 @@ SQLite(`check_same_thread=False` + StaticPool)下两个 session 各自读到 - 同样审计 `complete_task` 的并发(虽然 converge 测试通过,但非原子写)。 - `get_next_task` 的 `SELECT ... LIMIT 1` 也非原子,应改 `UPDATE ... WHERE status='pending' ... RETURNING` 抢占式。 -### 6.2 Webhook 缺重试 + 缺去重(**两个真缺口**,T6 暴露) +### 6.2 Webhook 缺重试 + 缺去重(**两个真缺口**,T6 暴露)— ✅ RESOLVED (`f85eca1`) **症状**:`test_webhook_retries_on_failure` 与 `test_webhook_dedupes_repeat_triggers` xfail。 `backend/agenteval/intelligent_eval/alerts.py::AlertManager._send_webhook`: @@ -126,7 +126,7 @@ CronPoolMonitor 当前的 `useEffect` 只做了 `setInterval(loadData, 5000)` + **当前状态**:`it.fails` 守卫在 `CronPoolMonitor.test.tsx`,CI 显示 `1 expected fail`(vitest 等价 xfail),不阻塞;修复后移除 `it.fails` 即转绿。 -### 6.4 无告警→auto_scale 联动(真缺口,T7 暴露) +### 6.4 无告警→auto_scale 联动(真缺口,T7 暴露)— ✅ RESOLVED (`6d32653`) **症状**:`tests/integration/test_alert_autoscale_link.py::test_check_alerts_triggers_auto_scale_on_high_utilization` xfail。 `backend/agenteval/web/routers/openclaw_cron_pool.py::check_alerts` 走完整条规则链只创建 `AlertHistoryDB` 行,**从不调** `cron_pool.scale_up` / `scale_down`。高利用率告警入库后无人(或外部 cron)触发 `auto_scale`,生产需要操作员看 Web UI 手动点。 @@ -139,7 +139,19 @@ CronPoolMonitor 当前的 `useEffect` 只做了 `setInterval(loadData, 5000)` + - `check_alerts` 在创建 alert 后按 `alert_type` 映射调用 `cron_pool.scale_up` / `scale_down`;或注册 webhook 接收方;或独立 worker 轮询 `unresolved alerts` → 调 `auto_scale`。 - 顺带把 `pool_utilization`(duration_minutes=10)规则的 `triggered_at` 持久化(如果后续要端到端测持续窗口)。 -**当前状态**:1 xfail 守卫在 `test_alert_autoscale_link.py`,CI 不阻塞;修复后移除 xfail 即转绿。 +**当前状态**:✅ RESOLVED in `6d32653` — `AlertManager.maybe_autoscale(alert)` called from the async router, exercises `cron_pool.scale_up(1)` (capped at MAX_POOL_SIZE). Test rewritten to use `task_backlog` (duration_minutes=0) so a single check_alerts call fires the alert. + +### 6.5 `decision-logs` 不去重(T8 暴露)— ✅ RESOLVED (`4bcab06`) + +**症状**:`tests/integration/test_decision_log_immutability.py::test_decision_log_dedupes_identical_entries` xfail. Three identical POSTs to the same eval with the same `(decision_type, context)` produced three identical rows in `intelligent_eval_decision_logs`. + +**根因**:`agenteval.intelligent_eval.decision_logs.create_decision_log` was append-only — it did not look up an existing row with the same `context` JSON before inserting. + +**影响**:Worker re-emitting the same decision within a single minute (e.g. task_backlog re-fire from a stuck cron retry) pollutes the audit table. + +**修复方向**(已在 `4bcab06` 实施):在 `create_decision_log` 内部,先用 `SELECT … WHERE eval_id=? AND decision_type=?` 找到现有行,若其 `get_context() == context` 则直接返回该现有行;否则 `INSERT`。append-only 不变性仍然成立(同 (eval, decision_type, context) 不会重复;context 不同的会追加新行——这正是 `test_decision_log_is_append_only_on_context_change` 验证的)。 + +**当前状态**:✅ RESOLVED — xfail 守卫已移除,测试通过(3 identical POSTs → 1 DB row;append-only on context change 仍通过)。 ### 薄弱/缺失点(加固清单 T) diff --git a/docs/release-notes-v1.1.0.md b/docs/release-notes-v1.1.0.md index 1062c8d..b6eefb2 100644 --- a/docs/release-notes-v1.1.0.md +++ b/docs/release-notes-v1.1.0.md @@ -232,4 +232,24 @@ v1.1.0 在 v1.0.0 智能评估基础上,引入 **Cron 池架构**,解决了" --- -**最后更新**: 2026-08-12 +## 十、Post-release Patches(v1.1.0 → v1.1.1 之后合并到 main 的修复) + +v1.1.0 部署到生产后,CI 防护网 + 集成测试暴露了 4 个真问题,并在 P0 测试加固阶段(扫描文档 §6)持续追踪。下列修复已合入 `main`,生产环境(v1.1.1)已包含这些行为,但版本号未升级(不打 v1.1.2 patch release)。 + +| Commit | 修复 | 影响的真问题 / 守卫 | +|---|---|---| +| `38e3817` | `task_queue.assign_task` / `complete_task` 改原子 CAS(`UPDATE … WHERE status=…` + `rowcount`)| #3 worker 任务竞争(§6.1)— xfail 转绿 | +| `f85eca1` | `AlertManager._send_webhook` 加重试(最多 3 次、指数退避 1s/2s)+ 按 `alert.webhook_sent` 去重 | #5 webhook 缺重试+去重(§6.2)— 两个 xfail 转绿 | +| `6d32653` | `AlertManager.maybe_autoscale` 在创建 alert 后自动调 `cron_pool.scale_up(1)`(高利用率/任务积压自动扩容)| #6 告警→auto_scale 联动(T7)— xfail 转绿 | +| `4bcab06` | `decision_logs.create_decision_log` 在同 `(eval_id, decision_type, context)` 时去重返回现有行(append-only 不变性保持)| #6 decision-logs 不去重(T8)— xfail 转绿 | +| `3376cac` | 移除上一步遗留的未用变量与 import(ruff F841/F401)| 代码清理 | + +**质量基线**:878 passed + 0 xfailed(全 xfail 守卫已转绿并移除);ruff 零错误;后端/前端测试全绿。 + +**生产版本**:v1.1.1(image `agenteval:1.1.1-ee9cc33`,commit `ee9cc33`)已部署到 volcengine-102,仍包含 v1.1.0 全部功能。生产若要吸收这些 post-release 行为,无需重新部署——已含在 v1.1.1 镜像(这些 commit 在 v1.1.1 bump 之后合并,但不影响 v1.1.1 的镜像;如需打包进生产 image,需在打 v1.1.2 patch release 时重新 build)。 + +**遗留**(未修):前端 CronPoolMonitor 轮询统一(S6 独立 issue,§6.3)— 当前前端 cron 池监控轮询在浏览器 tab 不可见时仍每 5s 触发,建议作为下一轮 issue 处理。 + +--- + +**最后更新**: 2026-08-12 (v1.1.0) + 2026-08-14 (post-release patches 段)