Skip to content

fix: scope refresh-row disabling to the provider being refreshed#1911

Merged
steipete merged 5 commits into
steipete:mainfrom
hhh2210:fix/scoped-refresh-row-greying
Jul 5, 2026
Merged

fix: scope refresh-row disabling to the provider being refreshed#1911
steipete merged 5 commits into
steipete:mainfrom
hhh2210:fix/scoped-refresh-row-greying

Conversation

@hhh2210

@hhh2210 hhh2210 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Problem

Refreshing one provider disabled the Refresh row for every provider. The controller also used one global manual-refresh task, so a second provider refresh was silently dropped while the first ran.

Change

  • Track manual refresh tasks by global or provider scope.
  • Keep unrelated provider rows interactive and allow independent provider refreshes to run concurrently.
  • Preserve global-refresh exclusivity for merged-overview refreshes.
  • Freeze each provider card at that provider's own refresh start, avoiding stale snapshots inherited from another concurrent refresh.
  • Keep frozen layout and loading subtitles scoped to the provider being refreshed.

Validation

  • swift test --filter 'StatusMenuPersistentRefreshTests|StatusMenuSwitcherRefreshTests|StatusMenuMergedOverviewRefreshTests|StatusMenuClosedPreparationTests' (55 tests)
  • make test (47 shards)
  • make check
  • Codex autoreview: clean

Visual proof

Refreshing Claude leaves unrelated provider rows enabled:

Claude refresh row scoped to Claude Other provider refresh row remains enabled

@clawsweeper

clawsweeper Bot commented Jul 5, 2026

Copy link
Copy Markdown

Codex review: needs real behavior proof before merge. Reviewed July 5, 2026, 10:27 AM ET / 14:27 UTC.

Summary
The branch replaces global manual-refresh state with scoped global/provider tasks, updates menu row gating and frozen-card refresh state, and adds focused menu refresh tests.

Reproducibility: yes. from source inspection: current main checks a single manualRefreshTask before provider-specific state, so any manual refresh makes every persistent Refresh row look busy. I did not run live app validation because this was a read-only review.

Review metrics: 1 noteworthy metric.

  • Touched surface: 6 source files, 4 test files. The fix crosses task tracking, menu-row gating, shutdown cleanup, frozen-card state, and focused menu refresh tests.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🐚 platinum hermit
Result: blocked until stronger real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Replace the contradictory unrelated-provider screenshot with a short recording or before/after screenshots showing one provider refreshing while another provider's Refresh row remains enabled.
  • Redact private account details, email addresses, endpoints, and other sensitive data before posting proof.
  • After updating the PR body, wait for the automatic ClawSweeper re-review or ask a maintainer to comment @clawsweeper re-review if it does not run.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: Screenshots are present, but the unrelated-provider proof still shows the Refresh row greyed out and annotated as wrong; add redacted proof in the PR body so a fresh ClawSweeper review can clear it. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Mantis proof suggestion
A short visible menu capture would directly prove the row-enabled behavior that the current screenshots do not establish. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis visual task: verify that refreshing Claude disables only Claude's Refresh row while Codex/Cursor Refresh rows remain enabled.

Risk before merge

  • [P1] The only merge blocker I found is proof quality: the second screenshot shows the unrelated Cursor Refresh row greyed out and annotated as wrong, so the live after-fix behavior is not convincingly proven.

Maintainer options:

  1. Decide the mitigation before merge
    Land the scoped refresh-task implementation once the PR body includes clear redacted proof showing one provider refreshing while unrelated provider Refresh rows remain enabled.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] The remaining blocker is contributor-supplied real behavior proof, which cannot be produced by an automated repair lane for their setup.

Security
Cleared: The diff changes Swift menu refresh state and tests only; no dependency, secret, CI, release, or supply-chain surface was changed.

Review details

Best possible solution:

Land the scoped refresh-task implementation once the PR body includes clear redacted proof showing one provider refreshing while unrelated provider Refresh rows remain enabled.

Do we have a high-confidence way to reproduce the issue?

Yes from source inspection: current main checks a single manualRefreshTask before provider-specific state, so any manual refresh makes every persistent Refresh row look busy. I did not run live app validation because this was a read-only review.

Is this the best way to solve the issue?

Yes, the scoped task map with explicit global/provider exclusivity is the narrow maintainable fix for the reported menu-state bug. The remaining gap is proof quality, not a visible code defect.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 9ad35deb6a89.

Label changes

Label justifications:

  • P2: This is a normal scoped UI/state bug fix for manual refresh behavior with limited blast radius.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: Screenshots are present, but the unrelated-provider proof still shows the Refresh row greyed out and annotated as wrong; add redacted proof in the PR body so a fresh ClawSweeper review can clear it. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. Screenshots are present, but the unrelated-provider proof still shows the Refresh row greyed out and annotated as wrong; add redacted proof in the PR body so a fresh ClawSweeper review can clear it.
Evidence reviewed

What I checked:

Likely related people:

  • steipete: Current-main blame for the manual refresh task, persistent refresh-row gate, and refresh monitor points to Peter Steinberger, and the PR head also includes maintainer commits in this same area. (role: recent area contributor; confidence: high; commits: e437044c32ba, b28a4537c30d, ea52f67410af; files: Sources/CodexBar/StatusItemController+Actions.swift, Sources/CodexBar/StatusItemController+PersistentMenuActions.swift, Sources/CodexBar/MenuCardRefreshMonitor.swift)
  • hhh2210: Prior merged history shows hhh2210 introduced manual refresh in-flight feedback across the same controller/menu files, so they are relevant beyond opening this PR. (role: introduced adjacent behavior; confidence: high; commits: d1c96c3ac4a6, 0be735b25a97; files: Sources/CodexBar/StatusItemController+Actions.swift, Sources/CodexBar/StatusItemController+PersistentMenuActions.swift, Tests/CodexBarTests/StatusMenuPersistentRefreshTests.swift)
  • elijahfriedman: Recent merged menu-refresh and action-row work touched the same menu behavior surface, making this a useful secondary routing candidate if the row presentation details need follow-up. (role: adjacent area contributor; confidence: medium; commits: fb8473fe6551, 0260a9a70706; files: Sources/CodexBar/StatusItemController+PersistentMenuActions.swift, Tests/CodexBarTests/StatusMenuPersistentRefreshTests.swift)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (5 earlier review cycles)
  • reviewed 2026-07-05T13:13:58.669Z sha ae0d184 :: needs real behavior proof before merge. :: [P2] Preserve existing frozen cards when merging
  • reviewed 2026-07-05T13:18:07.713Z sha ae0d184 :: needs real behavior proof before merge. :: [P2] Preserve existing frozen cards when merging
  • reviewed 2026-07-05T13:34:44.086Z sha 7ac1b3c :: needs real behavior proof before merge. :: [P2] Preserve existing frozen cards when merging | [P2] Block global refresh while provider refreshes run | [P3] Make test refresh accessors unambiguous
  • reviewed 2026-07-05T13:40:43.394Z sha b7b7c20 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-05T14:07:16.360Z sha d57954e :: needs real behavior proof before merge. :: none

@hhh2210 hhh2210 marked this pull request as ready for review July 5, 2026 13:12
Copilot AI review requested due to automatic review settings July 5, 2026 13:12

Copilot AI 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.

Pull request overview

This PR fixes the status menu’s “Refresh” row gating so manual refresh is scoped to the provider being refreshed (instead of disabling refresh UI globally), while still supporting a true global refresh for ⌘R / merged overview.

Changes:

  • Replace the single global manualRefreshTask with scoped manualRefreshTasks keyed by .global vs .provider(UsageProvider).
  • Update refresh-in-flight checks so only the active provider’s menu/tab greys out during its own refresh (global refresh still greys all).
  • Update MenuCardRefreshMonitor and refresh-row tests to reflect per-provider manual refresh behavior and allow concurrent provider refreshes.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
Tests/CodexBarTests/StatusMenuSwitcherRefreshTests.swift Adds coverage ensuring provider refresh only greys its own tab and global refresh greys all.
Tests/CodexBarTests/StatusMenuPersistentRefreshTests.swift Reworks refresh gating assertions and adds concurrency test for parallel provider refresh starts.
Sources/CodexBar/StatusItemController+Shutdown.swift Cancels and clears all scoped manual refresh tasks on shutdown; resets monitor state.
Sources/CodexBar/StatusItemController+PersistentMenuActions.swift Scopes isRefreshActionInFlight(for:) to the provider’s own manual refresh task (or global).
Sources/CodexBar/StatusItemController+MenuTracking.swift Treats any scoped manual refresh task as “menu data refresh in flight.”
Sources/CodexBar/StatusItemController+Actions.swift Introduces ManualRefreshScope and stores manual refresh tasks per scope when starting refresh.
Sources/CodexBar/StatusItemController.swift Replaces manualRefreshTask/manualRefreshProvider storage with scoped manualRefreshTasks plus test accessors.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Sources/CodexBar/StatusItemController.swift Outdated
Comment thread Sources/CodexBar/StatusItemController+Actions.swift
@clawsweeper clawsweeper Bot added proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal priority bug or improvement with limited blast radius. labels Jul 5, 2026
@hhh2210

hhh2210 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Updated the PR body with local menu-state proof from b7b7c20e and removed the ambiguous Cursor screenshot that showed the failing state. The proof now points to the specific row-gating tests and the current CI status.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 5, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@steipete steipete force-pushed the fix/scoped-refresh-row-greying branch from b7b7c20 to f562916 Compare July 5, 2026 13:49
@clawsweeper clawsweeper Bot added proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. labels Jul 5, 2026
hhh2210 and others added 5 commits July 5, 2026 07:16
Refreshing one provider greyed out — and single-flighted — the Refresh
row for every provider, so the menu implied the others were refreshing
when they were not.

Replace the single global `manualRefreshTask` with a per-scope map
(`.global` for the all-providers ⌘R/overview refresh, `.provider(p)`
for a single provider). The disable gate now reflects only the target
provider's own refresh (a global refresh still disables every row), and
`startManualRefresh` guards per scope so different providers can refresh
concurrently instead of one blocking the rest. `MenuCardRefreshMonitor`
tracks in-flight providers as a set plus a global flag.

Rewrites the refresh-row tests that encoded the old blanket behavior and
adds coverage for scoped greying and concurrent per-provider refreshes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…er overlap

- MenuCardRefreshMonitor: keep an already-refreshing provider's frozen card when a
  second provider's refresh re-supplies models (old-wins merge), so the first card
  no longer jumps mid-refresh — the artifact the freeze exists to prevent.
- startManualRefresh: make a .global refresh mutually exclusive with any per-provider
  one (and vice versa); two different providers still refresh concurrently.
- Merged-overview Refresh row now reflects any in-flight manual refresh, including a
  per-provider refresh's post-fetch status/token tail, instead of flickering.
- Make the test-only manualRefreshTask / manualRefreshProvider accessors return a value
  only when unambiguous (global, or exactly one task), else nil; move them to +Actions.
- Add tests: concurrent frozen-card retention, and overview-busy-through-tail + global
  refresh exclusion.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@steipete steipete force-pushed the fix/scoped-refresh-row-greying branch from d57954e to ea52f67 Compare July 5, 2026 14:19
@steipete steipete merged commit e3c2ade into steipete:main Jul 5, 2026
10 checks passed
@steipete

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Landed after maintainer hardening. Thank you, @hhh2210!

Final proof on exact contributor head ea52f67410afdf534ffb41b52ebb414c97f2f4d0:

  • GitHub CI: all 10 checks green, including all four macOS shards, both Linux builds, lint, changes, GitGuardian, and the aggregate lint-build-test gate.
  • Focused regression proof: swift test --filter 'StatusMenuPersistentRefreshTests|StatusMenuSwitcherRefreshTests|StatusMenuMergedOverviewRefreshTests|StatusMenuClosedPreparationTests' — 55 tests passed.
  • Full local suite: make test — all 47 shards passed.
  • Repository checks: make check — 0 format/lint violations; documentation, locales, and repository gates passed.
  • Final maintainer review: no accepted or actionable findings.

The landed version scopes in-flight refresh state and frozen menu snapshots per provider, preserves global-refresh exclusivity, permits independent provider refreshes, rejects stale completions, and adds regression coverage that distinguishes each provider's own refresh-start snapshot.

Squash merge: e3c2adeb53a1930f7bd19f76d871699097cf280b

Changelog credit: 45b000c135b06a69c982b2ed09df35563b2e2350

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants