Commit Graph

24 Commits

Author SHA1 Message Date
sinohqb
1782b245bf refactor(architecture): deepen campaign runtime modules 2026-08-11 13:18:48 +08:00
sinohqb
864ae2b7fe fix(review): address release correctness findings 2026-08-09 03:20:40 +08:00
sinohqb
62485684ca fix(architecture): enforce lifecycle consistency 2026-08-07 10:59:27 +08:00
sinohqb
c896ab3f71 refactor(architecture): deepen evaluation lifecycle and read model 2026-08-07 03:11:37 +08:00
sinohqb
160332665e refactor(exploration): absorb settlement.py into ExplorationSessionRepository
Some checks failed
CI / test (push) Failing after 12s
将 settlement.py 的 settle_campaign_sessions 函数吸收为
ExplorationSessionRepository.expire_running_sessions 方法。删除浅模块
settlement.py(30 行,接口宽如实现),会话生命周期操作集中在 repository。

- 新增 ExplorationSessionRepository.expire_running_sessions(campaign_id)
- 更新 campaigns.py 和 campaign_runner.py 两个调用点
- 删除 backend/agenteval/exploration/settlement.py
- 所有测试通过,行为不变
2026-08-04 13:28:23 +08:00
sinohqb
42be31dd1f feat(report): add load_campaign_view as unified campaign read model
活动级读模型单一出口:一次取齐报告 / 探索 / 分析 / 对比四大数据源。
markdown handler 从 30 行拼装逻辑缩到 3 行;分析执行器同步迁移。
comparison.py 内部的 8 次 load_campaign_report 调用暂不动(跨请求冗余,
缓存收益有限,改动风险高)。

- 新增 load_campaign_view(session, campaign) -> dict[str, Any]
- 返回 {report, exploration, analysis, comparison} 四键
- 迁移 markdown handler 和分析执行器两个调用点
- 4 个新测试覆盖 view 的组装逻辑
2026-08-04 11:33:45 +08:00
sinohqb
2b6cab6cb2 feat(comparison): unify read model and validation for period comparison
周期对比读模型升位为单一出口(load_comparison_view),GET/POST/markdown
三处调用点统一走同一 view 投影,消除「取数三件套」重复。校验逻辑收敛到
validate_comparison_request,router 捕获映射 400,执行器捕获落 failed 行,
校验顺序权威不再漂移。

- 新增 load_comparison_view:无行返回 status=none + auto_baseline,有行
  返回完整 comparison dict(含 model_name 标签)+ metric_diff
- 新增 validate_comparison_request:活动终态 → 模型 → 基线 → 分析,违
  规抛 ComparisonError
- execute_campaign_comparison 内联校验替换为 validate_comparison_request
  调用,catch ComparisonError 落 failed 行
- router 三处迁移:GET /comparison、POST /comparison、markdown 导出
- 删除 build_comparison_payload(已吸收进 load_comparison_view)
- 8 个新测试覆盖读模型三态 + 校验五错
2026-08-04 10:49:14 +08:00
sinohqb
38849d46f1 refactor(repository): narrow atomic updates for patrol/cancel/scheduler writes
全行 update 逼着调用方承诺「持有最新完整快照」,巡检水位、活动取消、
调度循环三方并发写入会互相覆盖(后写者抹掉先写者的 summary/status)。
CampaignRepository 新增三个窄口径原子操作:touch_patrol_watermark、
mark_cancelled、save_scheduler_state,各自只写自己的列;三处调用点迁移。
2026-08-04 03:39:42 +08:00
sinohqb
f8d8450b1e refactor(report): unify campaign report loading behind one read model
「活动报告取数三件套」此前在报告/markdown/分析/对比等 7 处手写重复,
唯一深化产物 build_campaign_report_dict 被锁在周期对比私有角落。
升位为 report.py 的 load_campaign_report(session, campaign) 单一出口
(探索线 summarize_campaign_exploration 同口径),并把 8 处
scenario_names 推导式收敛为 ScenarioRepository.name_map() 窄方法。
纯结构重排、零行为变更,572 项测试全绿。
2026-08-04 03:30:29 +08:00
sinohqb
ef4c094082 refactor(exploration): share one fetch+aggregate helper across outlets
report, markdown and analysis each repeated the
summarize_exploration(repo.list_by_campaign(...)) shape; collapse it
into summarize_campaign_exploration so the aggregation has one home.
2026-08-04 02:48:59 +08:00
sinohqb
62f7031b5b feat(exploration): expire dangling sessions on campaign finalize 2026-08-04 01:23:37 +08:00
sinohqb
2484c207af feat(exploration): findings flow into report, analysis and export
Exploration sessions aggregate into a single exploration summary
(session counts, goal-achievement rate, issue lists from experience
records, judge conclusions when reviewed) that feeds three exits:
the campaign report gains an exploration dimension, the v0.7 analysis
stage-two input gains the summary (stats only, never full dialogues),
and the Markdown export appends a findings appendix after analysis and
comparison. With no exploration data every output stays unchanged.
2026-08-03 19:16:33 +08:00
sinohqb
53afb9b5d1 feat(campaigns): exploration seed set and budget config per campaign
v0.9 ticket 02. Campaigns now carry an exploration seed set (seed
personas × seed goals — the comparability unit for exploratory
evaluation) and an optional budget override, stored as JSON columns
isomorphic to plan. Empty seeds normalize to null, marking the campaign
as opted out of exploration. resolve_budget merges per-field overrides
into platform defaults; enforcement stays server-side. The create form
gains seed lists and budget inputs (minutes → seconds), submitting null
when left empty.
2026-08-03 17:52:25 +08:00
sinohqb
14b09e1ac6 feat(campaigns): 周期对比纳入 Markdown 导出,活动导出排版重优化
- 导出端点解析评测对象名与 completed 周期对比行(基线元信息、分析模型、现算机械 diff),渲染 `## 周期对比` 附录(趋势 + 指标变化表 + 问题演变 + 建议落实),紧跟智能分析之后;非 completed 则完全无痕
- 头部排版重优化:状态中文化、窗口与时段人类可读(24h、0h–1h)、友好时间戳、头部补评测对象名、「正式线」/「加速调试线 ×N」措辞(加速线附注压缩后实际耗时);Run 级导出不动
- 测试:渲染器黄金断言更新 + 附录/头部/缺省用例,集成测试新增导出含对比、无对比行、failed 行三例
2026-08-03 15:13:11 +08:00
sinohqb
1e55a21649 feat(comparison): v0.8 周期对比 — 计划指纹自动基线配对、机械指标 diff 与 LLM 演进叙述
正式线活动分析完成后自动链式生成对比;报告抽屉新增「周期对比」区块
(趋势徽章、指标 delta 表、问题演变、建议追踪,无自动基线时手动选择)。
版本号升至 0.8.0。
2026-08-03 13:32:48 +08:00
sinohqb
5d04455664 feat(campaigns): auto-trigger analysis and include it in markdown export
The scheduler loop enqueues the analysis task when a realtime campaign
completes; accelerated or cancelled campaigns and a missing analysis
model skip silently. The campaign markdown export appends the analysis
appendix (overall, problems, narratives, suggestions) when a completed
analysis exists.
2026-08-03 02:25:07 +08:00
sinohqb
15c542d92c feat(analysis): two-phase campaign analysis agent with storage and API
Add the analysis role's execution path: a two-phase orchestration
(per-scenario diagnosis gathered in parallel, then a synthesis pass)
that reads the existing campaign report aggregation plus capped failure
samples, validates the LLM's JSON against the report schema, and strips
fabricated run/scenario references before persisting. Results upsert one
row per campaign (generating/completed/failed) with the model config
snapshot; GET/POST /api/campaigns/{id}/analysis expose the state machine,
guarding non-terminal campaigns and missing analysis models with 400s.
2026-08-03 02:06:29 +08:00
sinohqb
c63236f671 feat(campaign): support per-campaign analysis model override
Campaigns can pin an analysis model config instead of following the
global analysis default. Creation validates the referenced config
exists (400 otherwise); the create form offers enabled chat configs
with the global default as the fallback option.
2026-08-03 01:53:13 +08:00
sinohqb
8bc5aa6979 feat(campaign): add per-Run timeline seam + endpoint
build_campaign_timeline flattens a campaign's child Runs into offset-sorted
per-Run entries (distinct from the report's 12-bucket aggregation), reusing a
shared _run_window_offset口径 so both views place a run identically. Exposes
GET /campaigns/{id}/timeline and the api.ts type/call. (v0.6 ticket 06)
2026-07-31 16:49:04 +08:00
sinohqb
f285738f6d refactor(report): split report generation from pure rendering
report.py mixed DB-reading generation with string formatting: the four
render_*_report(run_id, session) functions each re-fetched via
generate_report, so the HTML/Markdown/JSON formatting was welded to storage
and could not be unit-tested from a plain dict. Extract the formatting into a
new pure report_render module whose renderers take the already-built report
dict (no session, no storage import). Migrate every caller to generate-then-
render, delete the old coupled renderers with no back-compat shim, and drop
the _aggregate_runs middle-man alias in favour of metrics.aggregate_runs.
2026-07-31 10:19:04 +08:00
sinohqb
7ed765726f feat(campaigns): live list progress, polling, and richer drill-down
Embed compact progress (completed/planned total + overall pass_rate,
reusing the report's aggregation) into GET /campaigns so the list drops
its N+1 report fetch. Poll list and open report drawer every 5s while the
tab is active and a campaign is still running. Show scenario version and
trigger source tags in the child-run drill-down.
2026-07-30 15:35:18 +08:00
sinohqb
f433ebb970 feat(campaigns): dual-axis periodic report (time trend + capability)
Add generate_campaign_report: a pure aggregator over a campaign's child Runs
producing a time-trend axis (Runs bucketed by service-window position) and a
capability-summary axis (grouped by scenario), each carrying pass_rate /
availability / latency. pass_rate keeps the single-Run case-level meaning and
counts execution failures as 0.0 (ADR-0002); time_scale only places Runs into
window-time buckets and never alters any figure. Engine summary now records
avg_latency_ms to feed the latency axis.

Expose GET /api/campaigns/{id}/report (structured) and .../report/markdown
(reusing the existing Markdown export path). Adds "可用性/Availability" to the
domain glossary.
2026-07-30 13:55:32 +08:00
sinohqb
8910fd17e0 feat(campaigns): durable scheduler loop with restart recovery and cancel
Add a thin async loop (run_campaign_loop) that ticks on real wall-clock time,
maps elapsed×time_scale to a window offset via the pure decide_schedule, spawns
due child Runs, and marks the campaign COMPLETED at window end. All authority
lives in the DB (started_at, spawned_indices, status), so the app lifespan can
resume every RUNNING campaign on startup without double-spawning and stop all
loops gracefully on shutdown. A failing plan entry is skipped and recorded
rather than wedging the campaign.

Creating a campaign now starts its loop; POST /api/campaigns/{id}/cancel stops
further spawning (completed child Runs are kept); GET /api/campaigns/{id}
reports live progress (window offset, spawned/completed Run counts).
2026-07-30 13:33:10 +08:00
sinohqb
e4404f1fa2 feat(campaigns): add Campaign persistence and create/query API
Introduce the 评估活动 (Campaign) aggregate above Run: a single-target,
service-cycle window driving a static plan. Adds Campaign/CampaignPlanEntry
models, CampaignDB table, nullable eval_runs.campaign_id, CampaignRepository,
Alembic migration, and POST/GET /api/campaigns with validation.

Ticket 01 of v0.6; no scheduling or child-run spawning yet (ADR-0003 v1).
2026-07-30 11:56:19 +08:00