Skip to content

fix: making typing start fire-and-forget allows cleanup/idle to run before a persistent typin...#75403

Open
clawsweeper[bot] wants to merge 6 commits into
mainfrom
clawsweeper/clawsweeper-commit-openclaw-openclaw-45b86450795d
Open

fix: making typing start fire-and-forget allows cleanup/idle to run before a persistent typin...#75403
clawsweeper[bot] wants to merge 6 commits into
mainfrom
clawsweeper/clawsweeper-commit-openclaw-openclaw-45b86450795d

Conversation

@clawsweeper

@clawsweeper clawsweeper Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Found one concrete regression: making typing start fire-and-forget allows cleanup/idle to run before a persistent typing indicator has finished starting, so the stop path can no-op and leave the indicator behind.

What ClawSweeper Is Fixing

  • Medium: Pending typing start can outlive cleanup and leave persistent indicators stuck (regression)
    • File: src/channels/typing.ts:79
    • Evidence: onReplyStart now starts fireStart() in the background and returns after one microtask at src/channels/typing.ts:79-87, while fireStop immediately marks the callbacks closed and calls stop at src/channels/typing.ts:90-98. For Feishu, start assigns typingState only after await addTypingIndicator(...) at extensions/feishu/src/reply-dispatcher.ts:176; stop returns without doing anything if typingState is still unset at extensions/feishu/src/reply-dispatcher.ts:183-185. A fast cleanup while addTypingIndicator is still in flight therefore calls stop too early, then the delayed start completes and records a persistent reaction with no later removal.
    • Impact: Feishu typing reactions are explicitly persistent until removed. A quick reply, NO_REPLY, empty-message cleanup, cancellation, or send-policy path can leave a visible typing reaction/indicator on the parent message after the run is already finished.
    • Suggested fix: keep typing start off the reply critical path, but serialize cleanup against the pending start. For example, track the current start promise and, if stop/cleanup happens while it is pending, run stop again after the promise settles when a start actually completed. Alternatively make persistent-indicator channels expose an abortable/pending-aware start helper.
    • Confidence: high

Expected Repair Surface

  • src/channels/typing.ts
  • src/auto-reply/reply/typing.ts
  • src/channels/typing.test.ts

Source And Review Context

Expected validation

  • pnpm check:changed

ClawSweeper already ran:

  • pnpm install was needed because vitest/package.json was missing.
  • pnpm test src/channels/typing.test.ts src/auto-reply/reply/typing-persistence.test.ts src/auto-reply/reply/reply-utils.test.ts passed.
  • pnpm test extensions/feishu/src/reply-dispatcher.test.ts passed.
  • Focused pnpm exec tsx -e ... race probe reproduced the stale persistent-state ordering.

Known review limits:

  • I did not run a live Feishu API test; the finding is based on the current callback ordering and Feishu’s local persistent-reaction state contract.

ClawSweeper Guardrails

  • Re-check the finding against latest main before changing code.
  • Keep the patch to the narrowest behavior change and matching regression coverage.
  • Do not merge automatically; this PR stays for maintainer review.

ClawSweeper 🐠 replacement reef notes:

  • Cluster: clawsweeper-commit-openclaw-openclaw-45b86450795d
  • Source PRs: none
  • Credit: Detected by ClawSweeper commit review for 45b8645.; Original commit author: Ayaan Zaidi.
  • Validation: pnpm check:changed

fish notes: model gpt-5.5, reasoning medium; reviewed against f903926.

@clawsweeper clawsweeper Bot added clawsweeper Tracked by ClawSweeper automation clawsweeper:commit-finding PR created from a ClawSweeper commit finding labels May 1, 2026
@clawsweeper

clawsweeper Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor Author

Codex review: needs changes before merge. Reviewed July 3, 2026, 8:41 PM ET / July 4, 2026, 00:41 UTC.

Summary
The PR tracks pending channel typing starts so cleanup can issue a final stop after a raced start settles and adds regression coverage, while also changing Copilot SDK option and test fields.

PR surface: Source +50, Tests +90. Total +140 across 7 files.

Reproducibility: yes. by source inspection. Current main starts typing in the background while Feishu records removable typingState only after addTypingIndicator resolves, so cleanup can call stop before there is state to remove.

Review metrics: 2 noteworthy metrics.

  • Copilot SDK Field Drift: 2 option renames, 1 fixture shape change. The PR changes SDK-facing field names while the pinned dependency still exposes the current-main names.
  • Shared Typing Helper Contract: 1 SDK-exposed helper behavior changed. createTypingCallbacks is re-exported through the channel SDK surface, so duplicate final cleanup behavior matters beyond Feishu.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🌊 off-meta tidepool
Patch quality: 🧂 unranked krab
Result: blocked by patch quality or review findings.

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

Rank-up moves:

  • Restore baseDirectory, suppressResumeEvent, and Date timestamp fixture semantics for the pinned Copilot SDK.
  • Get maintainer acceptance or a narrower design for the shared duplicate-stop typing contract.
  • Attach live Feishu proof or apply an explicit proof override before landing.

Proof path suggestion
A visible Feishu proof would materially verify that the persistent reaction is removed after cleanup races a pending start. Mantis is currently scoped to Telegram, Discord, and web UI chat proof, so it is not the right proof path for this surface.
Use maintainer screenshot/manual proof, browser or Playwright proof, Crabbox where appropriate, or normal local artifact proof instead.

Risk before merge

  • [P1] The PR head passes Copilot SDK option names that @github/[email protected] does not consume, so Copilot auth and session state can fall back to the wrong home or resume behavior.
  • [P1] The shared SDK-exposed typing helper would allow one duplicate final stop after a raced successful start; maintainers should explicitly accept that compatibility change for third-party channel users.
  • [P1] The Feishu race is source-proven, but there is still no live Feishu proof or explicit proof override showing the persistent reaction is removed after fast cleanup.

Maintainer options:

  1. Restore The Pinned SDK Contract (recommended)
    Revert the Copilot option-name and hook timestamp drift while preserving the pending-start typing cleanup fix and regression tests.
  2. Accept Shared Cleanup Semantics
    Maintainers may explicitly accept that the SDK-exposed typing helper can send one final cleanup stop after a raced successful start settles.
  3. Pause For Feishu Proof
    Pause merge until a live Feishu run or explicit proof override confirms the persistent reaction is removed after fast cleanup.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Drop the unrelated Copilot SDK API-name edits from this PR and restore extensions/copilot/harness.ts, extensions/copilot/harness.test.ts, extensions/copilot/src/runtime.ts, extensions/copilot/src/runtime.test.ts, and extensions/copilot/src/hooks-bridge.test.ts to current-main SDK semantics while keeping the pending-start typing cleanup fix and tests.

Next step before merge

  • [P2] A narrow automated repair can restore the pinned Copilot SDK option and test contracts while preserving the typing cleanup fix; maintainer proof and shared-helper acceptance remain after that repair.

Security
Needs attention: The diff introduces a concrete Copilot auth/session isolation concern by passing SDK options that the pinned dependency does not recognize.

Review findings

  • [P1] Restore Copilot home to baseDirectory — extensions/copilot/src/runtime.ts:368
  • [P1] Use suppressResumeEvent for resumed SDK sessions — extensions/copilot/harness.ts:271
  • [P2] Keep hook fixtures on Date timestamps — extensions/copilot/src/hooks-bridge.test.ts:8
Review details

Best possible solution:

Land a narrow typing cleanup fix after restoring the pinned Copilot SDK contract and deciding or validating the shared typing-helper duplicate-stop behavior.

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

Yes, by source inspection. Current main starts typing in the background while Feishu records removable typingState only after addTypingIndicator resolves, so cleanup can call stop before there is state to remove.

Is this the best way to solve the issue?

No for the current head. The typing-layer fix is plausible, but the branch must drop unrelated Copilot SDK contract drift before maintainers judge the shared cleanup semantics and Feishu proof gap.

Full review comments:

  • [P1] Restore Copilot home to baseDirectory — extensions/copilot/src/runtime.ts:368
    The pinned @github/[email protected] option is baseDirectory, and the SDK sets COPILOT_HOME only from that field. Passing copilotHome here leaves OpenClaw's normalized per-agent Copilot home unused, so SDK auth and session state can fall back to the default location.
    Confidence: 0.96
  • [P1] Use suppressResumeEvent for resumed SDK sessions — extensions/copilot/harness.ts:271
    resumeSession takes suppressResumeEvent, not disableResume, in the pinned SDK. Leaving this field renamed means history compaction resumes can emit the resume event again and reintroduce the side effects this option was suppressing.
    Confidence: 0.94
  • [P2] Keep hook fixtures on Date timestamps — extensions/copilot/src/hooks-bridge.test.ts:8
    The SDK hook input contract has timestamp: Date, but this fixture now passes 0. That makes the hook test fixture drift from the SDK-derived handlers and can fail type-checking instead of proving the real hook shape.
    Confidence: 0.9

Overall correctness: patch is incorrect
Overall confidence: 0.96

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 24dba4b44a5b.

Label changes

Label justifications:

  • P2: This is a bounded user-visible channel cleanup regression fix with limited blast radius, not an emergency runtime outage.
  • merge-risk: 🚨 compatibility: The PR changes an SDK-exposed typing helper contract and rewrites Copilot SDK option names without updating the pinned dependency.
  • merge-risk: 🚨 auth-provider: Passing an unrecognized Copilot home option can make SDK credential state use the default global location instead of OpenClaw's per-agent home.
  • merge-risk: 🚨 session-state: The Copilot home and resume flag drift can mis-associate or unexpectedly resume SDK-backed session state during history compaction.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🌊 off-meta tidepool and patch quality is 🧂 unranked krab.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Not applicable: This is a ClawSweeper-authored replacement PR, so the external contributor proof gate does not apply; maintainers still need live Feishu proof or an explicit override before merge.
Evidence reviewed

PR surface:

Source +50, Tests +90. Total +140 across 7 files.

View PR surface stats
Area Files Added Removed Net
Source 3 63 13 +50
Tests 4 98 8 +90
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 7 161 21 +140

Security concerns:

  • [medium] Copilot home may fall back to global state — extensions/copilot/src/runtime.ts:368
    Using copilotHome instead of the pinned SDK's baseDirectory can leave the runtime without OpenClaw's normalized per-agent Copilot home, so credentials and sessions may use the SDK default location.
    Confidence: 0.9

Acceptance criteria:

  • [P1] node scripts/run-vitest.mjs src/channels/typing.test.ts extensions/copilot/src/runtime.test.ts extensions/copilot/harness.test.ts extensions/copilot/src/hooks-bridge.test.ts.
  • [P1] pnpm check:test-types.
  • [P1] pnpm lint:extensions:bundled.
  • [P1] pnpm check:changed.

What I checked:

  • Repository policy read: Root AGENTS.md plus the scoped src/channels and extensions guides were read; the dependency-contract and shared channel SDK boundary guidance affected this review. (AGENTS.md:1, 24dba4b44a5b)
  • Current main still backgrounds typing start: onReplyStart starts fireStart in the background and returns after one microtask, while fireStop can close and send stop before that start settles. (src/channels/typing.ts:97, 24dba4b44a5b)
  • Feishu persistent state is assigned after async start: Feishu assigns typingState only after addTypingIndicator resolves, and stop returns when typingState is still unset, so a fast cleanup can miss the later persistent reaction. (extensions/feishu/src/reply-dispatcher.ts:219, 24dba4b44a5b)
  • Feishu reaction add/remove contract: addTypingIndicator creates the persistent reaction and removeTypingIndicator is a no-op without a reaction id, matching the reported stale-reaction failure mode. (extensions/feishu/src/typing.ts:123, 24dba4b44a5b)
  • Typing helper is SDK-exposed: createTypingCallbacks is re-exported through the plugin SDK channel outbound surface, so changed duplicate-stop behavior can affect third-party channel users, not only Feishu internals. (src/plugin-sdk/channel-outbound.ts:30, 24dba4b44a5b)
  • PR head changes shared cleanup semantics: The PR head tracks pending starts and allows sendStop(true) after a raced successful start settles, which addresses the Feishu race but changes the shared helper contract. (src/channels/typing.ts:66, cdcce22c1f29)

Likely related people:

  • obviyus: Authored the merged change that kept typing indicators off the reply critical path, which made the cleanup-before-start-settles race possible. (role: introduced behavior under review; confidence: high; commits: 45b86450795d; files: src/channels/typing.ts, src/channels/typing.test.ts, src/auto-reply/reply/typing.ts)
  • ramrajprabu: Authored the merged Copilot runtime PR that introduced the runtime, harness, hooks bridge, and pinned SDK integration whose option contracts this PR changes. (role: Copilot runtime feature contributor; confidence: high; commits: f3cfd752d330; files: extensions/copilot/src/runtime.ts, extensions/copilot/harness.ts, extensions/copilot/src/hooks-bridge.ts)
  • arkyu2077: Authored the merged Feishu typing keepalive change documenting that Feishu reactions persist until explicitly removed, directly adjacent to this cleanup race. (role: Feishu typing lifecycle contributor; confidence: medium; commits: 46df7e242138; files: extensions/feishu/src/reply-dispatcher.ts, extensions/feishu/src/typing.ts)
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.

@clawsweeper

clawsweeper Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor Author

🦞🔧
ClawSweeper applied a repair to this PR branch.

Repair: kept the fix on this contributor branch instead of opening a replacement PR.
Validation: pnpm check:changed; pnpm lint; pnpm check:test-types
Updated head: cdcce22c1f29
Run: https://github.com/openclaw/clawsweeper/actions/runs/27732590681

Current state: exact-head review queued immediately; GitHub checks and the review verdict gate final merge.

Automerge progress:

  • 2026-05-31 05:03:00 UTC review requested repair a5f5ddb7830f (structured ClawSweeper needs-human verdict with repairable P-severity findings...)
  • 2026-06-18 01:43:56 UTC review requested repair 13725651dca8 (structured ClawSweeper needs-human verdict with repairable P-severity findings...)
  • 2026-06-18 02:58:06 UTC review queued cdcce22c1f29 (after repair)

@clawsweeper
clawsweeper Bot force-pushed the clawsweeper/clawsweeper-commit-openclaw-openclaw-45b86450795d branch from f903926 to a5f5ddb Compare May 1, 2026 04:46
@barnacle-openclaw

Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@barnacle-openclaw barnacle-openclaw Bot added the stale Marked as stale due to inactivity label May 30, 2026
@clawsweeper clawsweeper Bot added the rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. label May 30, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the stale Marked as stale due to inactivity label May 31, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. and removed rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels May 31, 2026
@clawsweeper
clawsweeper Bot force-pushed the clawsweeper/clawsweeper-commit-openclaw-openclaw-45b86450795d branch 2 times, most recently from 73cb4c5 to 1372565 Compare May 31, 2026 05:28
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: needs maintainer proof decision A ClawSweeper-authored PR needs a maintainer proof capture or override decision. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels May 31, 2026
@clawsweeper

clawsweeper Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor Author

ClawSweeper status: this ClawSweeper-authored replacement PR is blocked on real behavior proof.

Reviewed head: 13725651dca881de7d288f8ebab6a930b9c79c0f
Proof status: not_applicable
Updated: 2026-06-17T11:47:40.076Z

Maintainer decision needed:

  • capture real behavior proof for this head
  • apply proof: override if the proof requirement should be waived
  • pause or close the replacement if proof should not be pursued

@clawsweeper clawsweeper Bot added status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. status: needs maintainer proof decision A ClawSweeper-authored PR needs a maintainer proof capture or override decision. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed status: needs maintainer proof decision A ClawSweeper-authored PR needs a maintainer proof capture or override decision. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jun 15, 2026
@clawsweeper clawsweeper Bot added the status: needs maintainer proof decision A ClawSweeper-authored PR needs a maintainer proof capture or override decision. label Jun 18, 2026
@clawsweeper

clawsweeper Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

ClawSweeper status: this ClawSweeper-authored replacement PR is blocked on real behavior proof.

Reviewed head: cdcce22c1f2928c177a2e7533faf1d5f9f0b96cf
Proof status: not_applicable
Updated: 2026-07-02T10:55:07.231Z

Maintainer decision needed:

  • capture real behavior proof for this head
  • apply proof: override if the proof requirement should be waived
  • pause or close the replacement if proof should not be pursued

Possible manual Mantis/desktop proof suggestion:

@openclaw-mantis visual task: verify a Feishu persistent typing reaction is removed when cleanup runs before typing start settles.

@clawsweeper clawsweeper Bot added status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. status: needs maintainer proof decision A ClawSweeper-authored PR needs a maintainer proof capture or override decision. and removed status: needs maintainer proof decision A ClawSweeper-authored PR needs a maintainer proof capture or override decision. status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 18, 2026
@clawsweeper clawsweeper Bot added status: needs maintainer proof decision A ClawSweeper-authored PR needs a maintainer proof capture or override decision. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. and removed status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. status: needs maintainer proof decision A ClawSweeper-authored PR needs a maintainer proof capture or override decision. status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. labels Jun 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clawsweeper:commit-finding PR created from a ClawSweeper commit finding clawsweeper Tracked by ClawSweeper automation extensions: copilot merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: S status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants