Skip to content

Avoid redundant menu-open refreshes - #1277

Merged
steipete merged 1 commit into
steipete:mainfrom
hhh2210:codex/fix-menu-open-latency
Jun 2, 2026
Merged

Avoid redundant menu-open refreshes#1277
steipete merged 1 commit into
steipete:mainfrom
hhh2210:codex/fix-menu-open-latency

Conversation

@hhh2210

@hhh2210 hhh2210 commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Avoids queuing deferred provider refreshes when opening a menu whose visible data is already fresh.
  • Keeps the existing stale/missing-data retry path, still deferred until menu tracking ends.
  • Adds focused coverage for fresh opens vs missing-data opens.

Why

Refs #1235. This follows the existing open-menu refresh direction from #923/#1040/#946: menu-open/background refreshes should stay non-blocking and avoid invalidating or rebuilding the visible NSMenu unless data is actually stale or missing.

Scope note for #1235: 0.32.3 already cached provider brand icons (#1274), and 0.32.2 capped/sped up Codex token scanning. This PR is a separate, additive path: it removes the redundant deferred refresh that 0.32.1's "defer refresh until tracking ends" change queued unconditionally on every open, even when no data was stale or missing.

Evidence

Focused fresh-menu behavior

Command:

swift test --filter 'CodexBarTests.StatusMenuTests/`opening fresh menu does not schedule deferred refresh`()'

Redacted output excerpt:

Build complete! (11.46s)
◇ Test "opening fresh menu does not schedule deferred refresh" started.
✔ Test "opening fresh menu does not schedule deferred refresh" passed after 0.283 seconds.
✔ Test run with 1 test in 1 suite passed after 0.283 seconds.

Missing-data retry behavior preserved

Command:

swift test --filter 'CodexBarTests.StatusMenuTests/`menu open with missing data defers automatic refresh until tracking ends`()'

Redacted output excerpt:

◇ Test "menu open with missing data defers automatic refresh until tracking ends" started.
✔ Test "menu open with missing data defers automatic refresh until tracking ends" passed after 0.343 seconds.
✔ Test run with 1 test in 1 suite passed after 0.344 seconds.

Lint / format gate

Command:

make check

Redacted output excerpt:

SwiftFormat completed in 0.81s.
0/997 files require formatting.
Done linting! Found 0 violations, 0 serious in 996 files.

ClawSweeper status

ClawSweeper's current blocker is real app behavior proof, not patch quality. I kept this PR scoped to the narrow refresh guard and did not push temporary profiling instrumentation or unrelated packaging/widget-project changes. A real macOS app proof should show:

  • Fresh menu open: no deferred provider refresh is queued after close.
  • Missing-data menu open: deferred refresh is still queued after menu tracking ends.

Notes

Maintainer live menu proof

Ran against a freshly packaged CodexBar.app from this branch on June 2, 2026. Prompt-risk settings were temporarily disabled for the run: keychain access disabled, refresh cadence manual, OpenAI Web off, Claude Web extras off, token-cost scanning off, and storage-footprint scanning off. Defaults were restored afterwards and the test app was stopped.

Packaged CLI smoke:

CodexBar.app/Contents/Helpers/CodexBarCLI config validate
Config: OK

Peekaboo proof:

peekaboo menu list-all --json
status item present: codexbar-merged

/usr/bin/time -p peekaboo menu click-extra --title codexbar-merged --json
success: true, clicked_item: codexbar-merged, real 0.16s

Visual check: screenshot showed the merged Overview menu rendered with provider rows and no blocking prompt.

Repeated open / click-away proof:

3 merged-menu opens: 0.14s, 0.15s, 0.17s
3 synthetic outside clicks: 0.12s, 0.13s, 0.15s
All 6 Peekaboo actions returned success: true
Final screenshot showed the menu dismissed.

Runtime sample after settle:

%CPU 0.1, RSS 119632 KB

Copilot AI review requested due to automatic review settings June 2, 2026 11:45

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

Note

Copilot was unable to run its full agentic suite in this review.

Updates menu refresh behavior so provider refresh is deferred only when menu data is missing or stale, and expands test coverage to assert no deferred refresh occurs when opening an already-fresh menu.

Changes:

  • Gate deferred refresh scheduling behind a “missing or stale menu data” check.
  • Add a new test for “fresh menu” open behavior and adjust/extend the existing deferred-refresh test scenario.

Reviewed changes

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

File Description
Tests/CodexBarTests/StatusMenuOpenRefreshTests.swift Adds/renames tests to validate deferred refresh is (not) scheduled depending on whether menu data is present.
Sources/CodexBar/StatusItemController+Menu.swift Changes open-menu refresh scheduling to defer refresh only when menu content is stale or missing.

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

Comment on lines 1112 to 1120
// Queue refresh work only when visible menu data is missing or stale. AppKit menu tracking is modal;
// starting provider refreshes while it is active can make the menu feel frozen and can block keyboard
// focus from returning.
if self.menuNeedsDelayedRefreshRetry(for: menu) {
self.deferMenuInteractionRefreshIfNeeded()
}
let key = ObjectIdentifier(menu)
self.menuRefreshTasks[key]?.cancel()
self.menuRefreshTasks[key] = Task { @MainActor [weak self, weak menu] in
Comment on lines +45 to +54
for _ in 0..<20 {
await Task.yield()
}
#expect(providerRefreshCount == 0)
#expect(!controller.deferredMenuInteractionRefreshPending)

controller.menuDidClose(menu)
for _ in 0..<40 {
await Task.yield()
}
@clawsweeper

clawsweeper Bot commented Jun 2, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed June 2, 2026, 9:01 AM ET / 13:01 UTC.

Summary
The branch guards open-menu deferred provider refreshes behind missing or stale visible provider data and updates status-menu tests for fresh-data and missing-data menu opens.

Reproducibility: yes. for the source-level behavior: current main unconditionally marks a deferred provider refresh on menu open, and the PR test split covers fresh-data and missing-data paths. I did not independently reproduce the macOS lag live during this read-only review.

Review metrics: 1 noteworthy metric.

  • Patch scope: 2 files changed, 63 added, 4 removed. The diff is narrowly limited to menu refresh scheduling and focused status-menu regression coverage.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

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

Rank-up moves:

  • none.

Risk before merge

Maintainer options:

  1. Decide the mitigation before merge
    Merge the narrow refresh guard after normal maintainer check review, while keeping Bug: Menu bar dropdown remains unresponsive on macOS despite changelog fixes #1235 open for any remaining menu-lag investigation.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • No ClawSweeper repair lane is needed; the remaining action is normal maintainer review, check gating, and merge timing.

Security
Cleared: The diff only changes Swift menu-refresh logic and focused tests; no dependency, build, signing, credential, or supply-chain surface changed.

Review details

Best possible solution:

Merge the narrow refresh guard after normal maintainer check review, while keeping #1235 open for any remaining menu-lag investigation.

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

Yes for the source-level behavior: current main unconditionally marks a deferred provider refresh on menu open, and the PR test split covers fresh-data and missing-data paths. I did not independently reproduce the macOS lag live during this read-only review.

Is this the best way to solve the issue?

Yes; this is a narrow fix for the redundant refresh path because it gates only provider refresh deferral and preserves the existing missing/stale retry behavior. The broader linked performance report should remain open for residual lag work.

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 9e6557cc6fa6.

Label changes

Label justifications:

  • P1: The PR targets a live menu responsiveness regression affecting the app's primary menu bar workflow.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body includes sufficient after-fix real behavior proof from a freshly packaged app using CLI validation, Peekaboo live menu output, repeated timings, and runtime sampling.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes sufficient after-fix real behavior proof from a freshly packaged app using CLI validation, Peekaboo live menu output, repeated timings, and runtime sampling.
Evidence reviewed

What I checked:

  • Repository policy read: AGENTS.md was read fully; its guidance on focused SwiftPM tests, avoiding Keychain-prompting validation, and using bundle-level proof for UI/runtime behavior informed this review. (AGENTS.md:1, 9e6557cc6fa6)
  • Current main behavior: Current main registers the menu as open, then calls scheduleOpenMenuRefresh; inside that scheduler it unconditionally calls deferMenuInteractionRefreshIfNeeded before the delayed stale/missing-data retry check. (Sources/CodexBar/StatusItemController+Menu.swift:1111, 9e6557cc6fa6)
  • PR production diff: The PR keeps the delayed menu refresh task but wraps the immediate deferred provider refresh in menuNeedsDelayedRefreshRetry(for:), so fresh visible data no longer queues a post-close store refresh. (Sources/CodexBar/StatusItemController+Menu.swift:1111, d06226ec0cf4)
  • Regression coverage: The PR splits the original menu-open refresh test into a fresh-data case that expects no deferred refresh and a missing-data case that clears the Codex snapshot and expects the deferred background refresh to remain. (Tests/CodexBarTests/StatusMenuOpenRefreshTests.swift:9, d06226ec0cf4)
  • Test fixture context: makeCodexStore seeds a fresh Codex usage snapshot by default, which makes the new fresh-menu test exercise the no-missing-data path; the PR explicitly clears that snapshot for missing-data retry tests. (Tests/CodexBarTests/StatusMenuTests.swift:34, 9e6557cc6fa6)
  • Real behavior proof: The PR body includes after-fix packaged-app proof: CodexBarCLI config validation, Peekaboo menu list/open output, repeated open and click-away timings, a final dismissed-menu check, and a runtime CPU/RSS sample. (d06226ec0cf4)

Likely related people:

  • steipete: GitHub path history shows multiple recent menu-refresh source and test commits by this account, including menu refresh reduction, deferral until close, background rebuild stalls, and visible menu rebuild coalescing. (role: recent area contributor; confidence: high; commits: 07ed3facdd4e, d5a5796a9844, 482f1da5adbb; files: Sources/CodexBar/StatusItemController+Menu.swift, Sources/CodexBar/StatusItemController+MenuInteractionRefresh.swift, Tests/CodexBarTests/StatusMenuOpenRefreshTests.swift)
  • ProspectOre: The most recent GitHub path-history entry before this PR touched the same menu source and open-refresh test file for closed-menu rebuild deferral during refresh. (role: recent adjacent contributor; confidence: medium; commits: 085319c5e9ae; files: Sources/CodexBar/StatusItemController+Menu.swift, Tests/CodexBarTests/StatusMenuOpenRefreshTests.swift)
  • anirudhvee: Recent merged history touched open-menu provider switcher behavior and the same status menu controller path, making this person a useful secondary routing candidate for open-menu interaction regressions. (role: adjacent open-menu contributor; confidence: low; commits: 904549557ec1; files: Sources/CodexBar/StatusItemController+Menu.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.

@hhh2210
hhh2210 force-pushed the codex/fix-menu-open-latency branch from 01af59e to 715dd2c Compare June 2, 2026 11:48
@clawsweeper clawsweeper Bot added 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. P1 Urgent regression or broken agent/channel workflow affecting real users now. labels Jun 2, 2026
@hhh2210

hhh2210 commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 2, 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.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jun 2, 2026
@hhh2210
hhh2210 force-pushed the codex/fix-menu-open-latency branch from 715dd2c to d06226e Compare June 2, 2026 12:40
@hhh2210

hhh2210 commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 2, 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.

Re-review progress:

@steipete

steipete commented Jun 2, 2026

Copy link
Copy Markdown
Owner

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 2, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Command router queued. I will update this comment with the next step.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed 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. labels Jun 2, 2026
@hhh2210

hhh2210 commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

Adding context as the author: I did a fair amount of local testing before settling on this narrow refresh-gate. I also tried a couple of other angles first — profiling populateMenu per stage to confirm where the residual closed-menu cost actually sits, and deliberately ruling out the cheap-but-wrong levers (bumping refresh frequency / keeping the animation frame-rate high), since those trade battery for responsiveness without removing the main-thread synchronous work. After building and running the packaged branch app locally with Claude Code active, I can no longer reproduce the laggy/unresponsive dropdown from the original report. Agreed it stays scoped to the redundant-refresh path and shouldn't be treated as fully closing #1235.

@steipete
steipete merged commit 0be735b into steipete:main Jun 2, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P1 Urgent regression or broken agent/channel workflow affecting real users now. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Menu bar dropdown remains unresponsive on macOS despite changelog fixes

3 participants