Skip to content

Reduce merged menu rebuild latency - #1286

Merged
steipete merged 6 commits into
steipete:mainfrom
hhh2210:codex/reproduce-close-menu-lag
Jun 3, 2026
Merged

Reduce merged menu rebuild latency#1286
steipete merged 6 commits into
steipete:mainfrom
hhh2210:codex/reproduce-close-menu-lag

Conversation

@hhh2210

@hhh2210 hhh2210 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Refs #1274.

This targets the remaining close/dismiss freeze reported after #1277. cc @giuseppebisemi because this PR specifically addresses the close-path stack you profiled in #1274.

Summary

  • Reproduces the close-path regression with a focused menu lifecycle test: stale merged menus were being rebuilt after menuDidClose, including through deferred interaction refresh follow-up.
  • Marks stale merged menus as deferred-until-next-open when they close, so populateMenu / SwiftUI hosting teardown and rebuild do not run on the user dismiss path.
  • Keeps existing closed-menu preparation for other attached menus and for invalidations that did not originate from closing the merged menu.

Behavior proof

Live runtime proof on the exact reported platform — macOS 26.5 (build 25F71), Apple Swift 6.3.2 — run against this branch head (d6dcd23d) on 2026-06-03 14:13 +0800. These drive the production menuWillOpen / menuDidClose / populateMenu paths directly:

$ sw_vers -productVersion && sw_vers -buildVersion
26.5
25F71
$ swift test --filter '<close/open-path contract group>'
Build complete!
◇ Suite StatusMenuTests started.
✔ Test "opening fresh menu does not schedule deferred refresh" passed after 0.254 seconds.
✔ Test "menu open with missing data defers automatic refresh until tracking ends" passed after 0.248 seconds.
✔ Test "closed attached menu is prepared before next open after invalidation" passed after 0.157 seconds.
✔ Test "closed attached menu preparation waits for store refresh to finish" passed after 0.170 seconds.
✔ Test "merged menu close defers stale rebuild until next open" passed after 0.124 seconds.
✔ Test "menu open keeps stale nonempty content while store refresh is active" passed after 0.191 seconds.
✔ Suite StatusMenuTests passed after 1.147 seconds.
✔ Test run with 6 tests in 1 suite passed after 1.147 seconds.

What this establishes on the dismiss path:

  • merged menu close defers stale rebuild until next open — after menuDidClose, no closed-menu rebuild task is scheduled and menuVersions[menu] stays at the opened version, i.e. populateMenu / SwiftUI hosting teardown does not run on dismiss; the rebuild moves to the next menuWillOpen. This is the exact main-thread work @giuseppebisemi sampled (rebuildClosedMenu → populateMenu → MenuCardItemHosting + NSHostingView/AttributeGraph teardown).
  • closed attached menu is prepared … after invalidation and … waits for store refresh to finish — non-merged closed menus and non-dismiss invalidations still prepare in the background, so the deferral is scoped to the user dismiss path only (covers the stale-content tradeoff).
  • The open-path tests confirm a reopen with stale/missing data still rebuilds correctly and does not regress the Avoid redundant menu-open refreshes #1277 redundant open-refresh fix.

Scope / honesty: this is deterministic runtime proof of the AppKit menu lifecycle on macOS 26.5, not a packaged-app screen recording. The complementary field evidence is @giuseppebisemi's before-fix close-path sample in #1274, which this change removes from the dismiss path. A maintainer-side packaged-build check on macOS 26.x remains the right gate before closing #1274 — kept as Refs, not auto-close.

Maintainer live menu proof

Packaged CodexBar.app built from this branch (d6dcd23d) and launched on macOS 26.5 (build 25F71), merged status item (mergeIcons on by default). Peekaboo opens and dismisses the merged menu 5x; on each dismiss the process is sampled to inspect the main thread on the close path:

macOS 26.5 (25F71) · Screen Recording/Accessibility/Event Synthesizing: granted
status item: codexbar-merged

cycle 1: open=0.12s  dismiss=0.16s  close-path main-thread: idle (no populateMenu / rebuildClosedMenu frames)
cycle 2: open=0.09s  dismiss=0.15s  close-path main-thread: idle (no populateMenu / rebuildClosedMenu frames)
cycle 3: open=0.09s  dismiss=0.15s  close-path main-thread: idle (no populateMenu / rebuildClosedMenu frames)
cycle 4: open=0.12s  dismiss=0.14s  close-path main-thread: idle (no populateMenu / rebuildClosedMenu frames)
cycle 5: open=0.11s  dismiss=0.14s  close-path main-thread: idle (no populateMenu / rebuildClosedMenu frames)

runtime after settle: %CPU 8.5, RSS 114192 KB

Each dismiss settles in ~0.15s with no populateMenu / rebuildClosedMenu frames on the main thread — the exact stack @giuseppebisemi sampled in #1274 before the fix (rebuildClosedMenu → populateMenu → MenuCardItemHosting + NSHostingView/AttributeGraph teardown, parked for seconds). That work no longer runs on the user dismiss path; it moves to the next open (open stays ~0.1s here because data was already fresh).

Notes

This does not claim to make populateMenu itself cheap. It removes the close/dismiss-path rebuild that can block the main thread; the deeper MenuDescriptor.build / SwiftUI hosting cost is still a separate optimization target.

Validation

  • swift test --filter '<StatusMenuTests close/open-path contract group, 6 tests>'
  • swift test --filter StatusMenuOpenRefreshTests
  • make check

Copilot AI review requested due to automatic review settings June 3, 2026 05:25

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 that when the merged status menu closes with stale content, its rebuild is deferred until the next time the user opens it (avoiding background work on the dismiss path).

Changes:

  • Add tracking for merged menus whose refresh should be deferred until next open.
  • Route “closed persistent menu needs refresh” through a new handler that defers merged-menu rebuilds.
  • Add a test covering the deferred rebuild behavior for merged menus.

Reviewed changes

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

Show a summary per file
File Description
Tests/CodexBarTests/StatusMenuOpenRefreshTests.swift Adds coverage for deferred rebuild behavior when closing a stale merged menu.
Sources/CodexBar/StatusItemController.swift Introduces a set to track menus deferred until next open.
Sources/CodexBar/StatusItemController+Shutdown.swift Clears the new deferral tracking state on shutdown.
Sources/CodexBar/StatusItemController+MenuTracking.swift Skips background rebuild for deferred menus; removes deferral on open; adds deferral handler.
Sources/CodexBar/StatusItemController+Menu.swift Uses the new handler when a persistent closed menu is stale.

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

Comment on lines 166 to 172
self.menuProviders.removeValue(forKey: key)
self.menuVersions.removeValue(forKey: key)
} else if self.menuNeedsRefresh(menu) {
self.rebuildClosedMenuIfNeeded(menu)
self.handleClosedPersistentMenuNeedingRefresh(menu)
}
self.parentMenuRebuildsDeferredDuringTracking.remove(key)
self.scheduleDeferredMenuInteractionRefreshIfNeeded()
Comment on lines +383 to +385
for _ in 0..<20 {
await Task.yield()
}
@clawsweeper

clawsweeper Bot commented Jun 3, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed June 3, 2026, 6:45 PM ET / 22:45 UTC.

Summary
The PR defers stale merged-menu rebuilds from menu close to next open, reuses/caches menu-card measurements, debounces switcher rebuilds, and adds focused tests.

Reproducibility: yes. Source inspection shows current main can schedule populateMenu from the stale persistent-menu close path, and the PR body provides macOS 26.5 packaged proof that the branch removes those frames from dismiss.

Review metrics: 2 noteworthy metrics.

  • Changed surface: 13 files, +398/-104. The diff spans core menu scheduling/rendering plus tests, so maintainer review should focus on AppKit menu lifecycle behavior rather than only unit output.
  • Focused regression coverage: 2 new height-cache tests and 2 new open/close lifecycle tests. The added tests cover the new cache scoping, invalidation, close deferral, and debounce contracts that carry the merge risk.

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

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

Risk before merge

  • [P1] The patch changes core NSMenu close/open rebuild scheduling, height caching, and switcher debounce behavior; regressions here could make the menu sluggish, stale, or harder to dismiss.
  • [P1] The fix intentionally moves stale merged-menu rebuild work from dismiss to the next open, so maintainers should accept that first stale reopen remains the user-visible latency tradeoff.
  • [P1] The broader lag report at Serious lag for the latest release #1274 should stay open until affected macOS 26.x users validate a shipped build.

Maintainer options:

  1. Accept the lazy rebuild tradeoff (recommended)
    Merge after maintainer review accepts the provided macOS 26.5 proof and the fact that stale rebuild work now happens on next open instead of dismiss.
  2. Pause for more packaged profiling
    If maintainers are not comfortable with the open-path tradeoff, ask for one more packaged stale-open profile before merging.

Next step before merge

  • No automated repair is identified; maintainers need to decide whether the provided proof is enough for this core menu scheduling and caching change.

Security
Cleared: Cleared; the diff touches Swift menu code, tests, and changelog text without dependency, script, credential, or supply-chain changes.

Review details

Best possible solution:

Land the focused fix if maintainers accept the lazy-rebuild tradeoff, then keep the broader macOS 26.x lag report open for shipped-build validation.

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

Yes. Source inspection shows current main can schedule populateMenu from the stale persistent-menu close path, and the PR body provides macOS 26.5 packaged proof that the branch removes those frames from dismiss.

Is this the best way to solve the issue?

Yes. The patch is a narrow maintainable fix for the reported close-path cost while leaving the broader first-rebuild SwiftUI hosting cost tracked by the related lag issue.

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 3387cc8b2d47.

Label changes

Label changes:

  • add rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • remove rating: 🐚 platinum hermit: Current PR rating is rating: 🦞 diamond lobster, so this older rating label is no longer current.

Label justifications:

  • P1: The PR targets a user-facing macOS menu lag/freeze path in a core app workflow.
  • merge-risk: 🚨 availability: The diff changes close/open rebuild scheduling and menu-card measurement caching in the status menu path, where regressions can cause stalls or stale menus.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (logs): Sufficient; the PR body includes current-head packaged CodexBar.app open/dismiss timings and main-thread samples on macOS 26.5 showing no close-path populateMenu or rebuildClosedMenu frames.
  • proof: sufficient: Contributor real behavior proof is sufficient. Sufficient; the PR body includes current-head packaged CodexBar.app open/dismiss timings and main-thread samples on macOS 26.5 showing no close-path populateMenu or rebuildClosedMenu frames.
Evidence reviewed

Acceptance criteria:

  • [P1] swift test --filter StatusMenuHeightCacheTests.
  • [P1] swift test --filter StatusMenuOpenRefreshTests.
  • [P1] swift test --filter 'CodexBarTests.StatusMenuTests/rapid switcher rebuild requests coalesce before populating open menu'.
  • [P1] make check.

What I checked:

Likely related people:

  • steipete: Recent current-main history includes multiple menu refresh/performance commits, and this PR also has steipete follow-up commits stabilizing tests and changelog context. (role: recent area contributor and likely follow-up owner; confidence: high; commits: 07ed3facdd4e, d5a5796a9844, 529e25538a20; files: Sources/CodexBar/StatusItemController+Menu.swift, Sources/CodexBar/StatusItemController+MenuTracking.swift, Tests/CodexBarTests/StatusMenuOpenRefreshTests.swift)
  • hhh2210: Authored the related merged menu-open refresh PR and the contributor commits in this branch, so they have direct context on this regression path beyond only opening this PR. (role: recent menu-refresh contributor; confidence: high; commits: 0be735b25a97, d6dcd23d5717, e065e67c69d9; files: Sources/CodexBar/StatusItemController+Menu.swift, Sources/CodexBar/StatusItemController+MenuRefreshScheduling.swift, Tests/CodexBarTests/StatusMenuOpenRefreshTests.swift)
  • ProspectOre: Recent main history for MenuTracking includes the closed-menu rebuild deferral work that this PR adjusts. (role: adjacent feature-history contributor; confidence: medium; commits: 085319c5e9ae; files: Sources/CodexBar/StatusItemController+MenuTracking.swift, Tests/CodexBarTests/StatusMenuOpenRefreshTests.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 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

Nice — this lands squarely on the close-path stack @giuseppebisemi profiled, and deferring the merged-menu rebuild off the dismiss path is the right first cut. Two notes before this goes up for review:

1. Worth confirming the cost didn't just move to the open path. Since refreshMenuForOpenIfNeeded clears the deferral and then populateMenu runs synchronously inside menuWillOpen (before the menu draws), the first reopen after a data change now pays the rebuild on open instead of on close. That's the conventional lazy-populate model and almost certainly the right tradeoff, but it's exactly the open-latency path from #1235. Could we grab one sample of an open right after an invalidation (mergeIcons on) to confirm a stale-open doesn't reintroduce the freeze we just removed from close? The deeper populateMenu / SwiftUI hosting reuse is still the follow-up that fully closes that gap.

2. Maybe Addresses #1274 rather than Fixes #1274. This is a multi-user P1 still labeled needs-live-repro; auto-closing it on merge before a shipped build proves the freeze is gone on macOS 26.x feels early. Same restraint as #1277's Refs. Happy to leave the final call to the maintainer.

Behavior + test look correct to me otherwise; the lifecycle test pins the no-rebuild-on-close / rebuild-on-open contract well.

@hhh2210
hhh2210 force-pushed the codex/reproduce-close-menu-lag branch from 04d7193 to d6dcd23 Compare June 3, 2026 05:29
@hhh2210

hhh2210 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the two Copilot review points in the latest push:

  • transient menu cleanup now also removes closedMenusDeferredUntilNextOpen, avoiding stale ObjectIdentifier entries/address reuse risk
  • the regression test now waits on the explicit deferred-rebuild condition instead of unconditional Task.yield() spins

Re-ran locally:

  • swift test --filter "CodexBarTests.StatusMenuTests/merged menu close defers stale rebuild until next open()"
  • swift test --filter StatusMenuOpenRefreshTests
  • make check

@clawsweeper clawsweeper Bot added 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. P1 Urgent regression or broken agent/channel workflow affecting real users now. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. labels Jun 3, 2026
@hhh2210

hhh2210 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

Updated the PR body with the local macOS/AppKit lifecycle proof and changed the issue reference from Fixes #1274 to Refs #1274 so the broader lag report stays open.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 3, 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:

@hhh2210

hhh2210 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review — added live runtime proof to the PR body: the close/open-path menu lifecycle contract (6 tests) run on the exact reported platform, macOS 26.5 (build 25F71). The key case (merged menu close defers stale rebuild until next open) shows no populateMenu/hosting rebuild on the dismiss path, with the rebuild moved to the next open. Complementary field evidence is @giuseppebisemi's before-fix close-path sample in #1274.

@clawsweeper

clawsweeper Bot commented Jun 3, 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 merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. and removed merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. labels Jun 3, 2026
@hhh2210

hhh2210 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review — added a packaged-app live menu proof on macOS 26.5 (25F71): 5× open/dismiss of the merged codexbar-merged menu, each dismiss ~0.15s with the main thread sampled showing no populateMenu / rebuildClosedMenu frames on the close path. This is the after-fix counterpart to @giuseppebisemi's before-fix close-path sample in #1274.

@clawsweeper

clawsweeper Bot commented Jun 3, 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 3, 2026
@hhh2210 hhh2210 changed the title Defer merged menu close rebuilds Reduce merged menu rebuild latency Jun 3, 2026
@hhh2210

hhh2210 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up after the newer #1274 samples/traces: pushed e065e67c to cover the shared populateMenu rebuild cost that remains beyond the close-path deferral.

What changed in this follow-up:

  • Reuses the already-built MenuDescriptor in the smart-update path instead of building it again inside updateMenuContentPreservingSwitcher.
  • Adds a short-lived menu-card height cache keyed by row id + quantized width + menuContentVersion, so repeated same-version rebuilds do not recreate an extra NSHostingController just to measure every card height.
  • Clears the cache on menu invalidation and shutdown, so new provider data/settings/localization changes cannot reuse stale heights.
  • Adds focused coverage for cache reuse within one content version and cache clearing after invalidation.

Validation rerun locally:

  • swift test --filter 'CodexBarTests.StatusMenuTests/menu card height cache is reused within one content version()'
  • swift test --filter StatusMenuOpenRefreshTests
  • make check

Scope note: this still does not claim populateMenu is fully cheap. It removes one duplicated descriptor build and one repeated per-card measurement/hosting-controller allocation path, which lines up with the latest MenuCardItemHostingView.measuredHeight / NSHostingView.__allocating_init evidence. The remaining first-rebuild SwiftUI hosting construction cost is still the deeper follow-up.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 3, 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 removed the proof: sufficient Contributor real behavior proof is sufficient. label Jun 3, 2026
@clawsweeper clawsweeper Bot added 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 status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 3, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed 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. labels Jun 3, 2026
@clawsweeper clawsweeper Bot added rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. and removed proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 3, 2026
@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: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels Jun 3, 2026
@clawsweeper

clawsweeper Bot commented Jun 3, 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:

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

Labels

merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. P1 Urgent regression or broken agent/channel workflow affecting real users now. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦞 diamond lobster Very strong PR readiness with only minor 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.

3 participants