- Overview: full-width stacked cards (basic info as two aligned rows,
plan, user input with seeds in fixed-height right column, sessions)
- Basic info labels fixed-width right-aligned for vertical alignment
- Add "已显示全部内容" end marker and increase drawer tab bottom
padding (16px → 24px) so content no longer looks cut off
- Row 1: basic info (span=8) + plan (span=16) with virtual users in
2-column grid and time distribution as a table
- Row 2: user input in one row (goal/intent/role/seeds), seeds area
enlarged with no height cap for full JSON display
- Row 3: session progress full-width with progress bar in header
- Drawer width: 1000px → 1200px for more content space
- Overview tab: move user input to full-width bottom section
- Seeds JSON area: maxHeight 160px → 300px with better padding
- Unify font sizes: 13px body, 12px labels/tags throughout
- Fix progress calculation to use estimated_sessions consistently
- Show estimated session progress in list (completed/estimated with running count)
- Improve user input layout with scrollable sections for long text
- Remove 50-item limit on activity feed, show all events
- Enhance lifecycle steps and time distribution chart styling
- Add pagination to decision log table (20/50/100 per page)
- Unify font sizes across drawer tabs (12/13/14px scale)
- _supplement_decision_logs: executing evals missing a decision log get a
platform-derived execute_session (deficit) or start_analysis (all sessions
done) entry. Audit backfill only — records observable state, does not change
agent execution. Called each scan tick after requeue+scan.
- t480 legacy cron workers (5) disabled: superseded by platform-triggered
headless agent (plan C); they kept firing every minute and failing on
Channel-required.
openclaw gateway fails to start when trusted-proxy and a shared token are
both configured (mutually exclusive). The env var was re-introduced on every
deploy because deploy-t480.sh rsyncs the repo compose file. Remove it so the
gateway runs in trusted-proxy mode; the agenteval proxy authenticates via
x-forwarded-user.
openclaw agent has no cron state; a bare 'agenteval-intelligent-worker'
message made the worker skill decide then 'wait for the next tick',
deadlocking (task assigned, session never created). The trigger message now
demands '立即完成当前任务,不要等待下一节拍' and, when all sessions are
done, delegates to agenteval-intelligent-analyst. Verified end-to-end on
t480: 1h-window eval went executing -> session (2 real turns) -> close ->
report -> completed, fully agent-driven, no external IM channel.
OpenClaw cron requires a channel (announce->last fail-closed); webchat is a
Control-UI feature, not an addressable channel, and platform-side static
execution would degrade the intelligent eval into a static evaluation.
Solution (plan C): the platform keeps the scan loop and, when the queue has
a pending task, invokes the headless agent:
docker exec openclaw-eval openclaw agent --agent main \
-m agenteval-intelligent-worker --json
--deliver defaults to false, so no cron delivery channel is involved. The
worker skill runs unchanged under the OpenClaw agent (LLM decisions +
evaluator/analyst skills). Verified headless invocation returns ok.
scan_and_enqueue_tasks had no scheduler: the OpenClaw Worker wakes every
minute but the platform never enqueued executing evals, so the queue was
always empty. lifespan now starts an asyncio background task that scans
executing intelligent evals every 60s (aligned with the Worker wake),
cancelled cleanly on shutdown. Verified by a new startup test (879 total).
- NaN root cause: report.scores is nested { overall, dimensions: {...} };
the old code treated every value as a number, so Number({object}) → NaN.
Now: dimScores from scores.dimensions, overall prefers scores.overall.
- Header summary cards restyled: icon + colored big number + responsive
(xs=12 md=6), colored score (>0.8 green / 0.6-0.8 amber / else red).
- usePolling gains a pauseWhenHidden option (default true): the timer
pauses while the document is hidden (background tab / minimised) and
resumes with an immediate reload on returning to visible. Callers keep
owning their initial fetch, so no duplicate first request.
- CronPoolMonitor now delegates its 5s poll to the shared usePolling hook
(initial load stays in its own useEffect); removes the bespoke
setInterval + manual visibility gap.
- CronPoolMonitor.test: visibility guard now passes (3/3), removing the
previous it.fails. Frontend suite: 18/18; tsc clean; backend 878.
Resolves scan §6.3.
- .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).
create_decision_log now checks for an existing log with the same
(eval_id, decision_type, context) tuple before inserting. If found, it
returns the existing row's dict instead of appending a duplicate. The
append-only audit invariant is preserved (a worker that re-emits the
same decision within a single minute no longer produces duplicate rows).
Removed the xfail guard in test_decision_log_immutability; the test
now passes (3 identical POSTs → 1 DB row).
AlertManager gains an optional openclaw_client. check_alerts records
each newly created alert and AlertManager.maybe_autoscale (called
from the async router for each alert) invokes cron_pool.scale_up(1).
scale_up itself caps at MAX_POOL_SIZE so repeated invocations are safe.
Removed the xfail guard in test_alert_autoscale_link; rewrote the test
to use task_backlog (duration_minutes=0) so a single check_alerts call
fires an alert and triggers auto-scale.