Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(macos): keep the Talk overlay visible when a present interrupts its dismissal - #132565

Closed
HuzaifaChaudary wants to merge 4 commits into
openclaw:mainfrom
HuzaifaChaudary:fix/talk-overlay-dismissal-generation
Closed

fix(macos): keep the Talk overlay visible when a present interrupts its dismissal#132565
HuzaifaChaudary wants to merge 4 commits into
openclaw:mainfrom
HuzaifaChaudary:fix/talk-overlay-dismissal-generation

Conversation

@HuzaifaChaudary

@HuzaifaChaudary HuzaifaChaudary commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Closes #127645

What Problem This Solves

Fixes an issue where users who dismiss the Talk overlay and immediately bring it back would end up with Talk still enabled but nothing on screen. The overlay is Talk's only operator-visible surface, so once it is hidden this way there is no indication the mode is still running.

It needs only a quick dismiss then present, inside the 160 ms dismissal animation.

Why This Change Was Made

Dismissal starts a fade and used to leave model.isVisible true until the animation completed. A present arriving during that window therefore saw the panel as already visible, took the path that only repositions and orders it front, and never brought the alpha back up. The dismissal completion then ran and hid the panel regardless, so the newer presentation lost.

Visibility is now released when the dismissal starts, so a present during the fade takes the first-present path and animates the panel back in on its own. Each dismissal carries a transition id, and its completion hides the panel only if it still owns it.

That is the shape QuickChatController already uses, which rotates a transitionID on present and dismiss and checks it in its dismissal completion. The ownership decision is a pure function so it can be tested directly, the way VoiceWakeOverlayController.evaluateToken is.

User Impact

Dismissing and immediately re-opening Talk keeps the overlay on screen. Talk can no longer end up enabled with its panel hidden, which previously needed a restart of the mode to recover from.

No visual change to either animation on its own. TalkOverlayView reads phase, level and isPaused, not isVisible, so releasing visibility earlier does not alter what is drawn during the fade.

Evidence

The reported sequence as a test, present -> dismiss -> present, then waiting out the 160 ms fade so the interrupted completion has run.

On 651c1ec2 before the change:

✘ Test "a present during the dismissal fade survives the old completion" recorded an issue
  at TalkOverlayDismissalTests.swift:49:9:
  Expectation failed: (controller.model.isVisible → false) == true

which is the terminal visible=False (expected True) from the issue. After:

✔ Test "a dismissal completion hides only for the transition it started for" passed
✔ Test "each dismissal is judged against its own transition" passed
✔ Test "a present during the dismissal fade survives the old completion" passed after 0.559 seconds
✔ Test run with 3 tests in 1 suite passed

Full swift test for apps/macos, same machine, same run conditions:

tests suites failures
clean 651c1ec2 1890 197 3
this branch 1893 198 3

Same three, TalkMLXSpeechSynthesizerTests, AppStateIsolationTests and CLIInstallerTests. They fail on a clean checkout here too and are unrelated to this change, all three environment dependent, around helper process reaping, an app profile and a temp CLI install. The counts differ by exactly the 3 tests and 1 suite added here.

swiftformat --lint --config config/swiftformat reports 0/2 files require formatting. swiftformat is the pinned 0.62.1; my swiftlint is 0.65.1 against the pinned 0.65.0, so treat the lint result as indicative rather than the pinned check.


disclaimer: this contribution was prepared with the assistance of an ai agent. i traced the present and dismiss paths and both call sites myself, confirmed the failing sequence on a clean checkout before changing anything, and ran the suites and formatter above locally.


On the cancelled macos-swift job

ci-gate is red here because macos-swift was cancelled, not because it failed an assertion. It ran 14:49 to 15:19 and was stopped at the thirty minute mark.

I get the same shape locally. A full swift test on apps/macos reaches about 1,880 passing tests and then stops making progress with 68 outstanding, printing:

SWIFT TASK CONTINUATION MISUSE: wait() leaked its continuation without resuming it.

None of the outstanding tests are in this area. They are gateway, relay, node lifecycle and update orchestration. The suite holding the largest group of them passes on its own on this branch in well under a second:

✔ Test run with 25 tests in 1 suite passed after 0.367 seconds.   (UpdateOrchestrationTests)

What this branch adds, run on its own:

✔ Test run with 6 tests in 3 suites passed after 1.135 seconds.   (--filter TalkOverlay)

Two of those three suites are the probes, and it is worth being explicit about them since they are the only thing here that could plausibly hold a CI runner. Both return before constructing anything at all unless an environment variable is set, which CI does not set:

guard let dir = ProcessInfo.processInfo.environment["OPENCLAW_TALK_PROBE_DIR"] else { return }
guard let dir = ProcessInfo.processInfo.environment["OPENCLAW_TALK_SHOT_DIR"] else { return }

No window, no panel, no screenshot on a runner. That is why the filtered run above finishes in a second with all six counted.

I cannot re-run the job myself and I cannot compare against another PR, because this is currently the only open pull request where macos-swift is not skipped. So I am not claiming it is repo wide, only that I could not find anything in this branch that accounts for it and that everything this branch touches finishes fast in isolation. Happy to be pointed at whatever I have missed.

…ts dismissal

dismiss started a 160ms fade and left isVisible true until the completion. a
present arriving inside that window therefore saw the panel as already visible,
took the branch that only moves and orders it front, and did not bring the alpha
back. the old completion then ran and hid the panel anyway

so talk could stay enabled with nothing on screen, which is the sequence in the
report, present dismiss present then the old completion

visibility is now given up when dismiss starts, so a present during the fade
takes the first present path and animates the panel back in itself. each
dismissal carries a transition id and its completion only hides the panel if it
still owns it. the already visible path restores alpha as well

this follows quick chat, which rotates a transitionID and checks it in its
dismissal completion, and the decision is a pure function so it can be tested
the way VoiceWakeOverlayController.evaluateToken is
Copilot AI lite review requested due to automatic review settings August 29, 2026 11:47
@clawsweeper

clawsweeper Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@clawsweeper clawsweeper Bot added merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. P2 Normal backlog priority with limited blast radius. 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 Aug 29, 2026
@clawsweeper

clawsweeper Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed August 29, 2026, 3:16 PM ET / 19:16 UTC.

ClawSweeper review

What this changes

This PR prevents an old Talk-overlay fade-out completion from hiding a panel that was presented again during the fade.

Merge readiness

⚠️ Ready for maintainer review - 3 items remain

The patch is a correct, bounded repair for a current macOS Talk-overlay race; it should remain open pending a fresh successful exact-head macOS CI run.

Priority: P2
Reviewed head: 0075bc361e4ed2364cf6bd9a89ccd2501a99545e

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) Strong focused visual and regression evidence supports a clean local lifecycle repair; exact-head macOS CI is the remaining merge gate.
Proof confidence 🦞 diamond lobster (5/6) ✨ media proof bonus Sufficient (screenshot): The changed production owner is TalkOverlayController; the supplied before/after visual artifacts show its interrupted-dismissal outcome, while the added screen-capture probe drives the real AppKit panel and the contributor supplied the corresponding visible/alpha output after the fix.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (screenshot): The changed production owner is TalkOverlayController; the supplied before/after visual artifacts show its interrupted-dismissal outcome, while the added screen-capture probe drives the real AppKit panel and the contributor supplied the corresponding visible/alpha output after the fix.
Evidence reviewed 7 items Current-main defect remains: Current main retains the pre-fix behavior: dismiss starts the fade while visibility remains true until its completion; the PR changes that owner boundary and adds the transition check.
Repair is at the lifecycle owner: The changed controller releases visibility at dismiss start, assigns a dismissal identity, and only orders the panel out when that identity remains current.
Caller and animation callee checked: TalkModeController presents or dismisses this controller when Talk enablement changes; OverlayPanelFactory runs the 160 ms fade and schedules its completion.
Findings None None.
Security None None.

How this fits together

Talk Mode drives an AppKit overlay panel when the operator enables or disables Talk. The overlay controller converts those requests into panel animations, whose asynchronous completion must respect the latest visibility intent.

flowchart LR
A[Talk Mode toggle] --> B[Talk mode controller]
B --> C[Talk overlay controller]
C --> D[Present or dismiss animation]
D --> E[Current transition check]
E --> F[Visible Talk panel]
Loading

Before merge

  • Resolve merge risk (P1) - macos-swift was cancelled on this exact head, so the required macOS CI gate has not yet demonstrated a green result even though the focused contributor evidence is positive.
  • Resolve merge risk (P1) - The bug fix is net +35 production lines; the transition identity is justified by asynchronous completion ownership, but it should remain the sole local mechanism for this panel.
  • Complete next step (P2) - A maintainer needs to restore the cancelled exact-head macOS CI gate; no focused repair action is indicated by this review.
Agent review details

Security

None.

PR surface

Other +209. Total +209 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 0 0 0 0
Tests 0 0 0 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 4 212 3 +209
Total 4 212 3 +209

Review metrics

Metric Value Why it matters
Production versus test LOC production +35, tests/proof +174 The production growth establishes explicit ownership for an asynchronous panel completion; the added tests and probes cover both the state transition and visible panel result.

Root-cause cluster

Relationship: fixed_by_candidate
Canonical: #127645
Summary: This PR is the candidate repair for the canonical Talk-overlay dismissal race report.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge-risk options

Maintainer options:

  1. Decide the mitigation before merge
    Keep the local transition-identity repair and land it once the exact-head macOS suite completes successfully, without introducing a second overlay-state mechanism.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Technical review

Best possible solution:

Keep the local transition-identity repair and land it once the exact-head macOS suite completes successfully, without introducing a second overlay-state mechanism.

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

Yes. Current main retains the pre-fix controller sequence, and the supplied focused regression run and before/after visual evidence exercise present → dismiss → present through the 160 ms completion.

Is this the best way to solve the issue?

Yes. The lifecycle owner now records the latest visibility intent and rejects stale completion work, matching the established Quick Chat approach rather than compensating in a caller.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 86b9cf728895.

Labels

Label justifications:

  • P2: The PR repairs a reproducible macOS Talk UI reliability defect with a limited surface area.
  • 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 (screenshot): The changed production owner is TalkOverlayController; the supplied before/after visual artifacts show its interrupted-dismissal outcome, while the added screen-capture probe drives the real AppKit panel and the contributor supplied the corresponding visible/alpha output after the fix.
  • proof: sufficient: Contributor real behavior proof is sufficient. The changed production owner is TalkOverlayController; the supplied before/after visual artifacts show its interrupted-dismissal outcome, while the added screen-capture probe drives the real AppKit panel and the contributor supplied the corresponding visible/alpha output after the fix.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The changed production owner is TalkOverlayController; the supplied before/after visual artifacts show its interrupted-dismissal outcome, while the added screen-capture probe drives the real AppKit panel and the contributor supplied the corresponding visible/alpha output after the fix.

Evidence

What I checked:

Likely related people:

  • steipete: Peter Steinberger authored the recent Talk-mode feature work and the mainline history around the affected controller. (role: recent macOS Talk and overlay feature owner; confidence: high; commits: 311f5bfbaa5c, 20816f676f37; files: apps/macos/Sources/OpenClaw/TalkModeController.swift, apps/macos/Sources/OpenClaw/TalkOverlay.swift)
  • fellanH: Felix Hellström authored prior Voice Wake overlay lifecycle work, an adjacent implementation using completion ownership guards. (role: adjacent overlay lifecycle contributor; confidence: medium; commits: 58ae5582f4cd; files: apps/macos/Sources/OpenClaw/VoiceWakeOverlayController+Session.swift)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Obtain a successful exact-head macos-swift run before merging.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
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.

Workflow

  • 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.

History

Review history (4 earlier review cycles)
  • reviewed 2026-08-29T11:52:05.770Z sha 662c113 :: needs real behavior proof before merge. :: none
  • reviewed 2026-08-29T12:05:23.763Z sha 3c97b53 :: needs real behavior proof before merge. :: none
  • reviewed 2026-08-29T12:21:41.954Z sha 2d09b0d :: needs real behavior proof before merge. :: none
  • reviewed 2026-08-29T15:01:58.774Z sha 0075bc3 :: needs maintainer review before merge. :: none

review asked for proof at the surface the operator actually sees, since the
model flag is not that. the panel is readable now, setter still file private,
and the test checks alphaValue and isVisible on the real NSPanel after the fade
that present interrupted has finished

on the base it reports alphaValue 0.0 and isVisible false, so the panel is
transparent and ordered out while talk is still enabled. that is the reported
symptom measured on the object the animation was driving
@HuzaifaChaudary

Copy link
Copy Markdown
Contributor Author

thanks, the ask was fair. the flag i was asserting is not what an operator sees, so it did not settle the question.

pushed 3c97b53c, which asserts the panel itself. window is readable now, setter still file private, and the test checks alphaValue and isVisible on the real NSPanel after the fade that present interrupted has finished.

on the base, with only present -> dismiss -> present and then waiting out the 160 ms:

✘ "the panel itself is left visible and opaque after the interrupted fade"
    Expectation failed: (panel?.alphaValue → 0.0) == (1 → 1.0)
    Expectation failed: (panel?.isVisible → false) == true
    Expectation failed: (controller.model.isVisible → false) == true

so the panel is fully transparent and ordered out while Talk is still enabled. that is the reported symptom measured on the object the dismissal animation was driving, not on the flag. on this branch all four pass.

i have not attached a recording. this is a headless assertion of the same two properties a screenshot would be showing, alphaValue and isVisible, and it is exact and re-runnable where a screenshot is neither. if you would still rather have the video i can build the app and capture Talk being re-enabled mid dismissal, just say so and i will add it rather than assume this substitutes.

on the rank-up note about inlining evaluateDismissal, i kept it deliberately. VoiceWakeOverlayController.evaluateToken is the same shape, a one-use ownership decision pulled out so it can be asserted directly, and VoiceWakeOverlayControllerTests tests it that way. happy to inline it if you would rather not carry the precedent twice, the interrupted-fade tests do not depend on it being separate.

check result
TalkOverlayDismissalTests on this branch 4 passed
the same tests on the base 2 failed, 4 issues, including panel alpha and ordering
swiftformat --lint --config config/swiftformat 0/2 files require formatting, pinned 0.62.1

review wants proof at the surface an operator sees, and this machine has no
display access so screencapture cannot run here. this renders the real overlay
view instead and composites it at the panels own alphaValue, drawing nothing at
all when the panel is ordered out, which is what reaches the screen

it is off unless OPENCLAW_TALK_PROBE_DIR is set, so it does nothing in ci, and a
maintainer can run it on both revisions and get the same two images
@HuzaifaChaudary

Copy link
Copy Markdown
Contributor Author

proof attached, and one limitation stated up front so you can judge whether it clears the gate.

i cannot run screencapture here. it returns could not create image from display, this machine has no display access, so a recording of the running app is not something i can produce. rather than leave it at test output i rendered the surface instead.

TalkOverlayRenderProbe (2d09b0d8) drives the real TalkOverlayController through present, dismiss, present, waits past the 160 ms fade, then renders the real overlay view and composites it at the panel's own alphaValue, drawing nothing when the panel is ordered out. that composite is what reaches the screen.

after present after the interrupted dismissal
base base presented base gone
this branch fixed presented fixed still there

the second base frame is empty. Talk is still enabled, and the panel is transparent and ordered out:

base    PROBE 1-presented:                    visible=true  alpha=1.0
base    PROBE 2-after-interrupted-dismissal:  visible=false alpha=0.0
branch  PROBE 1-presented:                    visible=true  alpha=1.0
branch  PROBE 2-after-interrupted-dismissal:  visible=true  alpha=1.0

the first frame is byte identical across base and branch, 173,915 bytes both, so the ordinary present is untouched. the second is 107,299 bytes on base against 174,156 on the branch, and that difference is the orb.

the probe is in the branch and does nothing unless OPENCLAW_TALK_PROBE_DIR is set, so ci is unaffected and you can reproduce both columns:

OPENCLAW_TALK_PROBE_DIR=/tmp/shots swift test --filter TalkOverlayRenderProbe

if this still does not meet the native proof gate, say so and i will ask the machine owner to run the app and capture Talk being re-enabled mid dismissal. i would rather be told it is insufficient than have you infer i tried to pass a rendered composite off as a screenshot, which is why the method is spelled out above.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. labels Aug 29, 2026
@HuzaifaChaudary

Copy link
Copy Markdown
Contributor Author

understood, and i have run out of what i can do about it from here, so rather than push a fifth revision at the same gate let me say where it stands and ask a maintainer to decide.

what is blocking is not the patch. both re-reviews put patch quality at 🐚 platinum hermit and confirmed the defect on current main, the repair, the caller boundary and the sibling precedent. it is the proof tier, and the remaining ask is a capture from the running app.

i cannot produce one. screencapture on this machine returns could not create image from display, there is no display access, and that is not something i can work around from inside a test process. i took it as far as rendering the real view composited at the panel's real alpha, which the review credited as visibly distinguishing base from branch, and that moved the rating but not the gate.

so the honest position: this needs someone with a running OpenClaw install to open Talk, dismiss it and re-enable inside the fade, and record it. i am happy for that to be a maintainer, or i can ask the owner of this machine to set the app up and capture it, which will take a little longer.

the question i actually want answered: is a native capture required from outside contributors who do not have the app running, or is it a gate you apply to work that changes UI you can already exercise? if it is required regardless, say so and i will get the recording rather than keep substituting for it. if the evidence already here is enough for a human reviewer, this is ready.

not asking anyone to lower a bar. asking which bar applies, so i stop guessing at it.

screen recording is granted on this machine now, so the panel can be captured
where it actually renders rather than composited from the view

screencapture is called with -l<windowNumber>, so the frame is the overlay panel
and nothing else on the display. all four come out 880x880, the 440pt panel at
2x, against 2704x1756 for a full grab

off unless OPENCLAW_TALK_SHOT_DIR is set, same as the render probe
@HuzaifaChaudary

Copy link
Copy Markdown
Contributor Author

screen recording is granted on this machine now, so here is the capture you asked for. real panel, on screen, photographed with screencapture.

after present after the interrupted dismissal
base base presented base gone
this branch fixed presented fixed still there

the second base frame is the empty one. Talk is still enabled and its only visible surface is gone.

base    SHOT 1-presented:                    windowNumber=97949 visible=true  alpha=1.0
base    SHOT 2-after-interrupted-dismissal:  windowNumber=97949 visible=false alpha=0.0
branch  SHOT 1-presented:                    windowNumber=97943 visible=true  alpha=1.0
branch  SHOT 2-after-interrupted-dismissal:  windowNumber=97943 visible=true  alpha=1.0
file size
base, presented 95,877 bytes
base, after the interrupted dismissal 17,492 bytes
branch, presented 95,902 bytes
branch, after the interrupted dismissal 96,598 bytes

on scope, since this is a real display. the capture is screencapture -x -o -l<windowNumber>, restricted to the Talk panel's own window. all four frames are 880x880, which is the 440pt panel at 2x. a full grab on this machine is 2704x1756. nothing else that was on screen is in these images, and that was deliberate rather than incidental.

TalkOverlayScreenshotProbe is in the branch at 0075bc36 and does nothing unless OPENCLAW_TALK_SHOT_DIR is set, so ci is unaffected:

OPENCLAW_TALK_SHOT_DIR=/tmp/shots swift test --filter TalkOverlayScreenshotProbe

it drives TalkOverlayController rather than launching the menu bar app, so if the gate specifically means the shipped app with Talk mode running end to end, this still is not that and i would rather you tell me than assume it passes. what it is, is the real panel in the real window server, photographed, showing the reported sequence.

@clawsweeper clawsweeper Bot added proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. proof: sufficient ClawSweeper judged the real behavior proof convincing. 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: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Aug 29, 2026
steipete added a commit that referenced this pull request Sep 2, 2026
* fix(macos): preserve Talk panel after interrupted dismissal

Record desired visibility at the overlay owner and fence animation completion
with the current presentation token. Remove the redundant nested task.

Rewrites #132565; fixes #127645. Actual signed AppKit before/after proof and
Swift Testing regression cover re-presentation and ordinary dismissal.

Co-authored-by: Huzaifa Iftikhar <[email protected]>

* test(macos): await Talk overlay animation completion

* test(macos): check Talk visibility intent synchronously

Keep immediate visibility intent in the native test suite and retain separate signed AppKit evidence for animation completion. Avoid an unbounded animation wait in the CLI test runner.

* test(macos): retain native Talk overlay race proof

---------

Co-authored-by: Huzaifa Iftikhar <[email protected]>
@steipete

steipete commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

The canonical repair landed in #135731 as 1bf5fb68d389, and I verified that commit is on main. Closing this overlapping proposal as superseded, with Huzaifa Iftikhar's contributor credit preserved in the landed commit.

The Talk controller now records visibility intent immediately and gives each transition its own token. An old dismissal completion cannot hide a newer presentation. The shared animation factory remains unchanged, and removing the redundant nested task keeps the repair at net +1 production line, versus +35 in the original proposal.

The signed synthetic AppKit fixture fails all three rapid-reopen checks when only the token guard is removed; the repaired controller passes all three reopen and all three normal-dismiss checks. Source hashes bind that pre-commit execution to the final committed inputs. The synchronous regression and final-head CI, including Swift tests and the release build, pass. The opt-in AppKit proof is timed native coverage, not a full operator microphone session; details and earlier CI failures are retained in #135731.

@steipete steipete closed this Sep 2, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Sep 3, 2026
…#135731)

* fix(macos): preserve Talk panel after interrupted dismissal

Record desired visibility at the overlay owner and fence animation completion
with the current presentation token. Remove the redundant nested task.

Rewrites openclaw#132565; fixes openclaw#127645. Actual signed AppKit before/after proof and
Swift Testing regression cover re-presentation and ordinary dismissal.

Co-authored-by: Huzaifa Iftikhar <[email protected]>

* test(macos): await Talk overlay animation completion

* test(macos): check Talk visibility intent synchronously

Keep immediate visibility intent in the native test suite and retain separate signed AppKit evidence for animation completion. Avoid an unbounded animation wait in the CLI test runner.

* test(macos): retain native Talk overlay race proof

---------

Co-authored-by: Huzaifa Iftikhar <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: macos App: macos P2 Normal backlog priority with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: M 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.

A stale macOS Talk dismissal animation can hide a newer presentation

3 participants