Skip to content

fix(status): filter stale task rows from status cards#58810

Merged
vincentkoc merged 4 commits into
mainfrom
status-tasks-main-audit
Apr 1, 2026
Merged

fix(status): filter stale task rows from status cards#58810
vincentkoc merged 4 commits into
mainfrom
status-tasks-main-audit

Conversation

@vincentkoc

Copy link
Copy Markdown
Member

Summary

  • Problem: /status and session_status were reading raw retained task rows, so stale completed tasks could keep showing up as if they were still the relevant session context.
  • Why it matters: users checking current status can miss active work, or see misleading stale task context after cleanup has not swept yet.
  • What changed: added a cleanup-aware task status snapshot, routed both status surfaces through it, preferred active tasks, and only surfaced recent failures when no active work remains.
  • What did NOT change (scope boundary): this does not change task creation, retention policy, or maintenance sweep behavior.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Root Cause / Regression History (if applicable)

  • Root cause: both status surfaces built their task line from raw retained registry rows instead of a cleanup-aware view.
  • Missing detection / guardrail: there was no shared status-specific snapshot helper that excluded expired rows and prioritized active tasks.
  • Prior context (git blame, prior PR, issue, or refactor if known): task status surfaces were added before a dedicated status snapshot layer existed.
  • Why this regressed now: task retention and task-linked status became useful enough that stale completed rows were visible to users in normal /status checks.
  • If unknown, what was ruled out: this was not a task maintenance sweep failure alone; the UI path itself was reading the wrong view.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/auto-reply/reply/commands-status.test.ts, src/agents/openclaw-tools.session-status.test.ts
  • Scenario the test should lock in: stale completed tasks should not headline status when no active visible work remains, and recent failures should only surface when active tasks are absent.
  • Why this is the smallest reliable guardrail: both user-visible status surfaces share the same summary semantics, and these tests assert those semantics directly.
  • Existing test that already covers this (if any): none.
  • If no new test is added, why not: N/A.

User-visible / Behavior Changes

  • /status prefers active session-linked tasks over stale completed rows.
  • session_status follows the same cleanup-aware task view.
  • Recent failures are still visible, but only when there is no active work to show.
  • Changelog entry included under Unreleased > Fixes. Thanks @vincentkoc.

Diagram (if applicable)

Before:
[/status] -> [raw retained tasks] -> [stale completed row may headline]

After:
[/status] -> [cleanup-aware task snapshot] -> [active tasks first | else recent failure | else recent completion]

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local worktree
  • Model/provider: N/A
  • Integration/channel (if any): chat /status, session_status
  • Relevant config (redacted): default local dev config

Steps

  1. Create retained completed task rows and at least one active task linked to a session.
  2. Run the chat /status path or the session_status tool.
  3. Compare the task headline before and after the snapshot filtering.

Expected

  • Active task context is shown first.
  • Expired/stale completed rows do not headline status.
  • Recent failures only appear when no active work remains.

Actual

  • Verified by targeted tests below.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: /status active-vs-stale behavior, session_status active-vs-recent-failure behavior.
  • Edge cases checked: expired retained rows excluded even before maintenance sweep; recent failures still visible when there is no active work.
  • What you did not verify: live channel smoke across every chat transport.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: status hides a terminal task a user still wanted to inspect.
    • Mitigation: openclaw tasks remains the full ledger/operator surface; this change only narrows the status summary view.

AI-assisted: yes. Targeted tests and local pnpm check run.

@vincentkoc vincentkoc self-assigned this Apr 1, 2026
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: M maintainer Maintainer-authored PR labels Apr 1, 2026
@vincentkoc
vincentkoc marked this pull request as ready for review April 1, 2026 07:03
@greptile-apps

greptile-apps Bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces a buildTaskStatusSnapshot helper in src/tasks/task-status.ts and routes both the /status command and the session_status tool through it, so stale completed/succeeded tasks no longer headline the status output. Active tasks take priority; recent terminal tasks (within a 5-minute window) are surfaced only when no active work remains; everything else is silently excluded.

Key changes:

  • task-status.ts (new): cleanup-aware snapshot — filters expired rows, separates active from recent-terminal, computes recentFailureCount independently.
  • task-owner-access.ts: thin wrapper buildTaskStatusSnapshotForRelatedSessionKeyForOwner delegates to the new helper.
  • session-status-tool.ts and commands-status.ts: both formatSessionTaskLine implementations replaced raw list iteration with snapshot fields; headline now uses active/failure/recently-finished states instead of the old flat "N active · M total" for all tasks.
  • Tests: commands-status.test.ts uses real task-registry helpers (completeTaskRunByRunId, failTaskRunByRunId) for high-fidelity coverage; openclaw-tools.session-status.test.ts uses an inline mock that simplifies the snapshot logic — the mock omits the 5-minute recency window and the [...active, ...recentTerminal] merge, which creates a small fidelity gap for future test authors (see inline comment).

Confidence Score: 5/5

Safe to merge — production logic is correct and well-tested; only a minor test-mock fidelity gap remains.

All production-path changes are logically correct: expired tasks are properly gated, active tasks are prioritised, and failures surface only when no active work remains. The higher-fidelity tests in commands-status.test.ts use the real registry and lock in both key scenarios. The single P2 finding is a test-mock shortcut that does not affect any production code path.

The inline mock in src/agents/openclaw-tools.session-status.test.ts (lines 219–223) diverges from the real snapshot logic; worth tightening before adding more session-status tests that rely on it.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/openclaw-tools.session-status.test.ts
Line: 219-223

Comment:
**Test mock diverges from real `buildTaskStatusSnapshot` in two ways**

The inline mock at lines 219 and 223 differs from the actual implementation in `task-status.ts` in two meaningful ways:

1. **Recency window not applied**: when `active.length === 0` the mock sets `recentTerminal = tasks` (every task, regardless of age), but the real function keeps only tasks within `TASK_STATUS_RECENT_WINDOW_MS` (5 min). A future test that sets up stale failures (>5 min old) with no active tasks will pass here but return an empty snapshot in production.

2. **`visible` is narrower than reality**: the mock uses `visible = active` when `active.length > 0`, while the real code uses `visible = [...active, ...recentTerminal]`. This means `totalCount` in the mock equals `activeCount`, while the real implementation would include any co-existing recent terminal tasks, giving a higher `totalCount`.

Neither divergence affects the two new tests (the stale task is 15 min old so it would also be excluded by the real recency filter, and the failure test has no active tasks), but they create a gap where incorrect future tests could silently pass.

Consider either: (a) importing and calling the real `buildTaskStatusSnapshot` on the mock's task list (passing a stable `now` so the age math is deterministic), or (b) adding a third test that covers the active-tasks-plus-recent-failure combination to lock in the `totalCount` behaviour.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "Merge branch 'main' into status-tasks-ma..." | Re-trigger Greptile

Comment thread src/agents/openclaw-tools.session-status.test.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e6dee43112

ℹ️ 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".

Comment thread src/auto-reply/reply/commands-status.ts
@vincentkoc
vincentkoc merged commit 340c99d into main Apr 1, 2026
9 checks passed
@vincentkoc
vincentkoc deleted the status-tasks-main-audit branch April 1, 2026 07:19

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2025b73963

ℹ️ 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".

Comment thread src/tasks/task-status.ts
Comment on lines +50 to +52
const reconciled = tasks
.map((task) => reconcileTaskRecordForOperatorInspection(task))
.filter((task) => !isExpiredTask(task, now));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep status snapshots free of reconciliation side effects

buildTaskStatusSnapshot now runs every task through reconcileTaskRecordForOperatorInspection, so each /status and session_status render can execute liveness reconciliation logic that was previously limited to operator/maintenance views. For active subagent/cli tasks older than the grace period, that path calls loadSessionStore synchronously (src/tasks/task-registry.maintenance.ts:80-84), which adds O(N) blocking disk I/O to chat status rendering and can transiently project a running task to lost if the store read misses. This means status cards may become slow or briefly report false recent failures under heavier task loads.

Useful? React with 👍 / 👎.

@vincentkoc

Copy link
Copy Markdown
Member Author

Follow-up landed on main in cfa307b

This addresses the status-snapshot review concern:

  • buildTaskStatusSnapshot() no longer calls reconcileTaskRecordForOperatorInspection(), so /status and session_status stay free of maintenance/reconciliation side effects and avoid synchronous session-store reads during status rendering
  • added a unit test locking in that old active tasks stay active in status snapshots

I also folded in the small display-safety follow-up so task status lines truncate long unlabeled task prompts/details instead of dumping raw prompt text.

steipete pushed a commit to Mlightsnow/openclaw that referenced this pull request Apr 1, 2026
* fix(status): filter stale task rows

* test(status): use real task snapshot semantics

* fix(status): prefer failure task context in recent failures
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
* fix(status): filter stale task rows

* test(status): use real task snapshot semantics

* fix(status): prefer failure task context in recent failures
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
* fix(status): filter stale task rows

* test(status): use real task snapshot semantics

* fix(status): prefer failure task context in recent failures
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
* fix(status): filter stale task rows

* test(status): use real task snapshot semantics

* fix(status): prefer failure task context in recent failures
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 24, 2026
* fix(status): filter stale task rows

* test(status): use real task snapshot semantics

* fix(status): prefer failure task context in recent failures
Nachx639 pushed a commit to Nachx639/clawdbot that referenced this pull request Jun 17, 2026
* fix(status): filter stale task rows

* test(status): use real task snapshot semantics

* fix(status): prefer failure task context in recent failures
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling maintainer Maintainer-authored PR size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

session_status leaks stale task context in chat (/status shows old completed jobs)

1 participant