feat(ui): show background tasks live in the web Control UI#100789
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9a0a5c1efc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 37473b082b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Codex review: needs changes before merge. Reviewed July 6, 2026, 9:33 AM ET / 13:33 UTC. Summary PR surface: Source +1522, Tests +455, Docs +6, Other +2. Total +1985 across 70 files. Reproducibility: yes. the review findings are source-reproducible from the current PR head. The affected paths are Review metrics: 2 noteworthy metrics.
Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Copy recommended automerge instructionNext step before merge
Maintainer decision needed
Security Review findings
Review detailsBest possible solution: Keep the standalone Tasks route and read-scoped task event shape, but fix terminal-only Recent fetching, terminal updatedAt semantics, stable pagination, and stale-cancel guards before maintainer product sign-off. Do we have a high-confidence way to reproduce the issue? Yes, the review findings are source-reproducible from the current PR head. The affected paths are Is this the best way to solve the issue? No, not yet: the standalone page and task event are a maintainable direction, but the current implementation is not the best mergeable shape until the task-ledger edge cases are fixed with focused regression coverage. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 25a7708f19ca. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +1522, Tests +455, Docs +6, Other +2. Total +1985 across 70 files. View PR surface stats
Acceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (3 earlier review cycles)
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9225028df6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0bf8e26c07
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
ea07e6c to
09abc4c
Compare
6294fea to
214851a
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 214851ae80
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (!active || !recent) { | ||
| throw new Error(t("tasksPage.invalidResponse")); | ||
| } | ||
| const tasks = mergeTaskLists(recent, active); |
There was a problem hiding this comment.
Prefer the fresher task snapshot when merging
When a queued/running task finishes while these two tasks.list requests are in flight, the active-filtered response can contain the old running row while the unfiltered response contains the newer completed row. Because this call passes recent before active and mergeTaskLists lets later lists overwrite earlier entries, the stale active copy wins and the page can move a just-completed task back into Active until another refresh/event happens; choose the row with the newest updatedAt/terminal status instead of relying on query order.
Useful? React with 👍 / 👎.
|
The four review-bot findings raised on the final head (terminal-row ranking via stale |
…100789) * feat(gateway): broadcast task ledger changes as task events * feat(ui): add background Tasks page to Control UI * fix(gateway): address tasks page review findings * fix(ui): surface tasks.cancel refusals on the Tasks page * fix(gateway): guard stale task observer disposal against replacement gateways * chore: satisfy lint and docs-map gates for tasks page * test(gateway): await async agent unsub in stale-dispose test
…100789) * feat(gateway): broadcast task ledger changes as task events * feat(ui): add background Tasks page to Control UI * fix(gateway): address tasks page review findings * fix(ui): surface tasks.cancel refusals on the Tasks page * fix(gateway): guard stale task observer disposal against replacement gateways * chore: satisfy lint and docs-map gates for tasks page * test(gateway): await async agent unsub in stale-dispose test
What Problem This Solves
OpenClaw tracks background work (subagent spawns, cron executions, ACP runs, gateway-dispatched CLI and media runs) in the task registry, but the only surfaces are the CLI (
openclaw tasks list) and the chat/tasksboard. The web Control UI has no way to see what detached work is running, whether it succeeded, or to cancel a stuck task.Closes #100706.
Why This Change Was Made
Operators watching an agent fan out subagents from the dashboard are blind to that work today. The gateway already exposes
tasks.list/tasks.get/tasks.cancel, and the task registry already has an (unused in prod) observer seam — so the web UI can get a live task ledger without polling by broadcasting registry changes the same way the cron page consumes thecronevent.User Impact
task({action: "upserted"|"deleted"|"restored", ...}) emitted from task registry changes with the same bounded publicTaskSummarymapping the RPC handlers use. No polling; a manual Refresh button and reconnect refetch cover the rest.docs/automation/tasks.mdgains a Control UI subsection;docs/web/control-ui.mdlists the Tasks page.Live screenshots (real gateway, real OpenAI
gpt-5.5agent runs):Active tasks while three spawned subagents run — status chips, runtime chips, cancel buttons:
After cancelling a running subagent from the UI — the pushed
taskevent moves the row to Recent as Cancelled ("Cancelled by operator."), completed subagents show their terminal summaries:Evidence
Implementation notes:
src/gateway/server-methods/task-summary.ts: publicTaskSummarymapping + closedTaskEventPayloadunion extracted fromserver-methods/tasks.tsso RPC responses and the broadcast share one bounded mapping (status text sanitized/truncated, runtime statuses translated to the ledger vocabulary,lost→failed).src/gateway/server-runtime-subscriptions.ts: registers the task-registry observer lazily at startup and broadcaststaskevents withdropIfSlow; disposal wired throughserver-runtime-handles.ts→server.impl.ts→server-close.ts."task"added toGATEWAY_EVENTS; iOS/Android allowlisted inscripts/protocol-event-coverage.allowlist.json(no mobile consumer yet).ui/src/pages/tasks/:data.ts(defensive normalization, deterministic sort, active/recent partition, event merge),tasks-page.ts(gateway lifecycle, push events, cancel),view.ts(sections/rows from existing list/chip styles).pnpm ui:i18n:syncregenerated locale bundles.Verification:
--devprofile) with a real OpenAIgpt-5.5agent: prompts spawned subagents viasessions_spawn; the page showed queued/running rows live (pushed events, no refresh), completed tasks moved to Recent with terminal summaries, and clicking Cancel on a running subagent cancelled it (tasks.cancel) and re-rendered it as Cancelled via the pushed event — see screenshots above.pnpm test ui/src/pages/tasks src/gateway/server-runtime-subscriptions.test.ts src/gateway/server-methods/tasks.test.ts ui/src/i18n(Testbox): green, including the mocked-gateway Playwright e2e (tasks.e2e.test.ts: sections render, pushed completion moves rows, cancel request asserted).pnpm tsgo+pnpm tsgo:test:ui+pnpm tsgo:test:src(Testbox): green.node scripts/check-protocol-event-coverage.mjs: green (30 gateway events, task allowlisted for both mobile clients).pnpm ui:i18n:check: green after locale sync.gpt-5.5): clean.Review rounds
Six review findings (Codex autoreview + the GitHub Codex review bot) were verified and fixed on this branch before landing:
tasks.listpage → dedicated queued/running query merged over page one (mergeTaskLists).taskbroadcast dropped by the gateway broadcaster (missingEVENT_SCOPE_GUARDSentry) →task: [READ_SCOPE]+ scope-guard regression test; re-proven live (13 rows pushed to an open page with zero extratasks.listcalls).tasks.listnow pages by last activity (taskUpdatedAt) with a regression test.tasks.cancelisoperator.write) → gated onhasOperatorWriteAccess.tasks.cancelrefusals (successful responses withcancelled: false+reason) were silent → surfaced as errors (normalizeTasksCancelResult).Final Codex autoreview on the branch: clean (no actionable findings).