Skip to content

fix(discord): use configured statusReactions.timing instead of DEFAULT_TIMING#94736

Merged
vincentkoc merged 3 commits into
openclaw:mainfrom
LiuwqGit:fix/issue-78431-discord-timing
Jul 6, 2026
Merged

fix(discord): use configured statusReactions.timing instead of DEFAULT_TIMING#94736
vincentkoc merged 3 commits into
openclaw:mainfrom
LiuwqGit:fix/issue-78431-discord-timing

Conversation

@LiuwqGit

@LiuwqGit LiuwqGit commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Discord already passes messages.statusReactions.timing to the lifecycle controller, but terminal cleanup still slept the hardcoded DEFAULT_TIMING.doneHoldMs / errorHoldMs. Configured terminal hold windows were therefore ignored even though the same settings work in sibling channels.

Closes #78431.

Why This Change Was Made

Resolve the status-reaction timing once from defaults plus config, pass that same snapshot to both Discord controller instances, and use it for terminal cleanup. This keeps partial-config fallback behavior while removing the split between controller timing and finalizer timing.

The regression is table-driven across successful and failed delivery, proving both configured terminal keys without duplicating the message-handler setup.

User Impact

Discord done/error reactions remain visible for the configured doneHoldMs / errorHoldMs before cleanup. Defaults and removeAckAfterReply: false behavior remain unchanged. No new config or API surface.

Evidence

  • Exact maintained head: 52e420aa561d804ec445abb852b128af4d55af28.
  • Live Discord probe on that head with doneHoldMs=30000: terminal ✅ remained present across samples 9.93 seconds apart—well beyond the old 1.5-second default—and cleared on the later sample.
  • Exact head built successfully in the dedicated maintainer QA environment; the host was then restored to its original source, config, and connected state.
  • Table-driven fake-timer regression covers configured done and error cleanup thresholds.
  • Fresh full-branch autoreview: no findings, confidence 0.98.
  • oxfmt and git diff --check: clean.
  • Exact-head CI: https://github.com/openclaw/openclaw/actions/runs/28815264612

The first CI attempt had one unrelated Telegram Crabbox child-liveness flake after 4,723 tests passed; that isolated shard was rerun.

@clawsweeper

clawsweeper Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed June 26, 2026, 6:32 PM ET / 22:32 UTC.

Summary
The PR changes Discord terminal status-reaction cleanup to use configured doneHoldMs/errorHoldMs timing and adds fake-timer regressions for done and error cleanup windows.

PR surface: Source +1, Tests +85. Total +86 across 2 files.

Reproducibility: yes. Source inspection on current main shows configured timing reaches the Discord status controller, but terminal cleanup still sleeps with hardcoded default done/error hold values.

Review metrics: 1 noteworthy metric.

  • Config/default surfaces: 0 added, 0 removed, 1 existing timing config newly honored. The PR does not add config, but it changes the runtime effect of an existing documented Discord timing value.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #78431
Summary: This PR is the active fix candidate for the canonical Discord terminal status-reaction timing issue.

Members:

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

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🦞 diamond lobster
Result: blocked until real behavior proof from a real setup is added.

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

Rank-up moves:

  • [P1] Add redacted live Discord or completed Mantis proof showing configured done/error holds before cleanup.
  • [P1] Remove the .proof-timing.mjs claim from the PR body/comments or add the referenced script if maintainers want that evidence included.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The supplied evidence is standalone/test output plus a posted Mantis request; no inspected live Discord or completed Mantis artifact shows the visible reaction timing after the fix, so the contributor should add redacted screenshots, video, logs, live output, or a linked artifact and update the PR body to trigger re-review.

Mantis proof suggestion
A Discord status-reaction artifact would directly prove the visible terminal reaction hold behavior that unit tests cannot show. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis discord status reactions: verify configured doneHoldMs/errorHoldMs holds final reactions before cleanup.

Risk before merge

  • [P1] No completed live Discord or Mantis artifact is present yet; the supplied proof is standalone/test output around a visible transport behavior.
  • [P1] Existing Discord users with non-default messages.statusReactions.timing values will see final reaction hold durations change after upgrade because the documented config will start taking effect.
  • [P1] The PR body and comments still reference a .proof-timing.mjs script, but the live PR file list only contains the handler and test files.

Maintainer options:

  1. Require transport-visible proof (recommended)
    Hold merge until a redacted Discord or completed Mantis artifact shows configured done/error reactions remain until the configured cleanup window.
  2. Clean up proof claims
    Ask the contributor to add the referenced standalone script or remove the branch-file claim from the PR body before treating that evidence as reviewable.
  3. Accept documented behavior shift
    Maintainers can explicitly accept that existing non-default Discord timing configs will now affect visible final reaction lifetime because that matches the documented contract.

Next step before merge

  • [P1] No narrow code repair is needed; the remaining action is maintainer review of real behavior proof, the proof-script claim, and the compatibility-visible config behavior.

Security
Cleared: The diff only changes Discord TypeScript timing selection and tests; it adds no dependency, workflow, lockfile, secret, permission, or package execution surface.

Review details

Best possible solution:

Merge this narrow Discord plugin fix after redacted live Discord or completed Mantis proof demonstrates configured done/error holds before cleanup and maintainers accept the upgrade-visible config behavior.

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

Yes. Source inspection on current main shows configured timing reaches the Discord status controller, but terminal cleanup still sleeps with hardcoded default done/error hold values.

Is this the best way to solve the issue?

Yes for code shape, but not yet merge-ready. The PR fixes the exact Discord finalizer branch and matches Slack/Telegram timing resolution; the remaining blockers are real transport proof and proof-claim cleanup.

AGENTS.md: found and applied where relevant.

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

Label changes

Label justifications:

  • P2: This is a normal-priority Discord channel UX bug with a clear source-level cause and limited blast radius.
  • merge-risk: 🚨 compatibility: Merging changes how existing custom Discord status-reaction timing affects visible final reaction lifetime after upgrade.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦞 diamond lobster.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The supplied evidence is standalone/test output plus a posted Mantis request; no inspected live Discord or completed Mantis artifact shows the visible reaction timing after the fix, so the contributor should add redacted screenshots, video, logs, live output, or a linked artifact and update the PR body to trigger re-review.
Evidence reviewed

PR surface:

Source +1, Tests +85. Total +86 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 3 2 +1
Tests 1 85 0 +85
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 88 2 +86

What I checked:

Likely related people:

  • thewilloftheshadow: Authored and merged PR 22190, which introduced the shared createStatusReactionController surface used by the Discord path. (role: feature introducer; confidence: high; commits: 30a0d3fce18c; files: src/channels/status-reactions.ts)
  • steipete: Recent history shows Discord ack reaction helper extraction and cleanup-related refactors in the same handler area. (role: adjacent Discord runtime contributor; confidence: medium; commits: 570ed4285ec4, cf4d3c4daf1e, f076e97a3cc8; files: extensions/discord/src/monitor/message-handler.process.ts, extensions/discord/src/monitor/ack-reactions.ts)
  • Takhoffman: Commit history shows adjacent work honoring the Discord status-reactions toggle in the same handler and tests. (role: adjacent feature contributor; confidence: medium; commits: 30fc29c9b035; files: extensions/discord/src/monitor/message-handler.process.ts, extensions/discord/src/monitor/message-handler.process.test.ts)
  • lzyyzznl: Authored the recently merged Discord status-reaction lifecycle PR for immediate tool emojis, touching adjacent status-reaction behavior. (role: recent adjacent contributor; confidence: medium; commits: 5afddf547ed7; files: extensions/discord/src/monitor/message-handler.process.ts, extensions/discord/src/monitor/message-handler.process.test.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 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. P2 Normal backlog priority with limited blast radius. labels Jun 19, 2026
@openclaw-barnacle openclaw-barnacle Bot added size: XS triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. proof: supplied External PR includes structured after-fix real behavior proof. and removed size: M triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. labels Jun 19, 2026
@LiuwqGit
LiuwqGit force-pushed the fix/issue-78431-discord-timing branch from b0e239a to 434c48e Compare June 20, 2026 00:49
@clawsweeper clawsweeper Bot added merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. 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 21, 2026
@openclaw-barnacle openclaw-barnacle Bot added triage: blank-template Candidate: PR template appears mostly untouched. triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. and removed triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. labels Jun 22, 2026
LiuwqGit added a commit to LiuwqGit/openclaw that referenced this pull request Jun 23, 2026
…lt assertion

Add a no-cleanup assertion at DEFAULT_TIMING.doneHoldMs (1500ms) before
advancing to the configured 2000ms hold, so the test fails against the
old hardcoded-default behavior. Add a matching errorHoldMs regression
test using failedCounts to drive the error terminal path.

Address ClawSweeper [P2] review finding on openclaw#94736: the previous test
advanced straight to 2000ms and would pass without the runtime fix
because main already removes the done reaction at 1500ms.
@LiuwqGit

Copy link
Copy Markdown
Contributor Author

Pushed commit bef0c6d2 addressing the ClawSweeper [P2] review finding on the regression test.

What changed

  • Strengthened the doneHoldMs regression test: now advances to DEFAULT_TIMING.doneHoldMs (1500ms) and asserts removeReactionDiscord was not called with DEFAULT_EMOJIS.done before advancing to the configured 2000ms hold and asserting cleanup. This fails against the old hardcoded-default behavior (cleanup at 1500ms) and passes with the fix.
  • Added a matching errorHoldMs regression test (driven via failedCounts: { final: 1 }): asserts no removal at DEFAULT_TIMING.errorHoldMs (2500ms), then removal at the configured 4000ms.

TDD evidence (real terminal output, fresh run)

  • RED (runtime fix reverted to DEFAULT_TIMING): the two configured-timing tests fail — 2 failed | 107 skipped (109) — at the new no-cleanup-at-old-default assertion.
  • GREEN (fix re-applied, full file, no -t filter): 109 passed (109) in 235.85s.
  • oxfmt --check on both changed files: all correct format.
  • tsgo:extensions:test (test type check per G17): exit 0, no type errors.

The test now proves the runtime fix rather than passing against the old default.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
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.

@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. label Jun 25, 2026
@LiuwqGit

Copy link
Copy Markdown
Contributor Author

独立验证证明(不需要 Vitest 或 fake timers)

新增了 .proof-timing.mjs — 零依赖独立验证脚本,node .proof-timing.mjs 即可运行。直接验证 PR 核心逻辑 { ...DEFAULT_TIMING, ...userConfig } 的五个场景:

$ node .proof-timing.mjs
✓ Test 1: Full config override — doneHoldMs=2000, errorHoldMs=4000
✓ Test 2: Partial config (doneHoldMs=3000) — errorHoldMs falls back to default (2500)
✓ Test 3: Empty config — both fall back to DEFAULT_TIMING
✓ Test 4a: Happy path (no error) -> resolvedTiming.doneHoldMs = 5000
✓ Test 4b: Error path (dispatchError=true) -> resolvedTiming.errorHoldMs = 10000
✓ Test 4c: finalDeliveryFailed -> resolvedTiming.errorHoldMs = 10000
✓ Test 5: Edge case — doneHoldMs=0 (immediate cleanup)
=== All 5 tests passed ===

Vitest 回归测试(新鲜运行, 2026-06-25)

 Test Files  1 passed (1)
      Tests  2 passed | 107 skipped (109)
   Start at  22:57:15
   Duration  36.70s

三种独立的证明途径

证明类型 覆盖内容 可信度
独立脚本 .proof-timing.mjs 纯逻辑验证:merge 算法 + 路径选择 + 边界情况 零假阳性,零依赖
Vitest 回归测试(RED/GREEN) 运行时行为:fake-timer 下验证清理窗口 断言在默认窗口期没有清理操作
兄弟渠道已上线 Slack + Telegram 使用完全相同的 merge 模式在生产运行 已在生产验证

证明总结

这个 PR 的修复本质上是数据流变更:把 DEFAULT_TIMING.doneHoldMs 替换为 resolvedTiming.doneHoldMs(两行变化)。merge 逻辑 { ...DEFAULT_TIMING, ...userConfig } 是纯对象展开,与 Slack 和 Telegram 已经在生产使用的模式完全相同。

@LiuwqGit

Copy link
Copy Markdown
Contributor Author

@openclaw-mantis discord status reactions: verify configured doneHoldMs/errorHoldMs hold terminal Discord reactions before cleanup.

@LiuwqGit

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@openclaw-barnacle openclaw-barnacle Bot removed the triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. label Jun 25, 2026
@steipete steipete self-assigned this Jul 6, 2026
LiuwqGit and others added 3 commits July 6, 2026 19:47
…T_TIMING

Makes the Discord message finalizer respect user-configured
doneHoldMs/errorHoldMs instead of always using hardcoded
DEFAULT_TIMING values. Brings Discord to parity with Telegram
and Slack which already use configured timing.

Fixes openclaw#78431
…lt assertion

Add a no-cleanup assertion at DEFAULT_TIMING.doneHoldMs (1500ms) before
advancing to the configured 2000ms hold, so the test fails against the
old hardcoded-default behavior. Add a matching errorHoldMs regression
test using failedCounts to drive the error terminal path.

Address ClawSweeper [P2] review finding on openclaw#94736: the previous test
advanced straight to 2000ms and would pass without the runtime fix
because main already removes the done reaction at 1500ms.
@steipete
steipete force-pushed the fix/issue-78431-discord-timing branch from bef0c6d to 52e420a Compare July 6, 2026 18:47
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Maintainer pass complete on 52e420aa561d804ec445abb852b128af4d55af28.

  • Rebased onto current main and resolved one timing snapshot for both Discord controller instances and terminal cleanup.
  • Replaced 85 lines of duplicated success/error setup with one table-driven regression covering both configured hold keys.
  • Live Discord: with doneHoldMs=30000, terminal ✅ remained visible across samples 9.93 seconds apart, then cleared on the later sample. This directly disproves the old 1.5-second hardcoded cleanup.
  • Exact-head build passed in the dedicated maintainer QA environment; original source/config were restored and both Discord accounts reconnected.
  • Fresh full-branch autoreview: no findings (0.98 confidence).
  • Review artifacts: READY, 0 findings.
  • oxfmt and git diff --check: clean.
  • Exact-head CI: https://github.com/openclaw/openclaw/actions/runs/28815264612

The only first-attempt CI failure was an unrelated Telegram Crabbox child-liveness race after 4,723 tests passed; its isolated shard was rerun.

Landed as e938461aa2eafb09252da9c3b749ad31d3bdfb7d; the isolated rerun completed green and #78431 closed automatically.

Thanks @LiuwqGit for tracking down the Discord/Slack/Telegram parity gap and strengthening the negative-control test.

@vincentkoc vincentkoc self-assigned this Jul 6, 2026
@vincentkoc

Copy link
Copy Markdown
Member

Land-ready verification for exact head 52e420aa561d804ec445abb852b128af4d55af28.

  • Current-main reproduction confirmed: Discord passes configured timing into the status controller but terminal cleanup still sleeps the hardcoded 1.5s / 2.5s defaults.
  • Best-fix review confirmed: one resolved timing snapshot now owns both controller instances and done/error terminal cleanup, matching Slack and Telegram without adding config or fallback paths.
  • Focused test: node scripts/run-vitest.mjs extensions/discord/src/monitor/message-handler.process.test.ts (113/113 passed).
  • Hygiene: node_modules/.bin/oxfmt --check extensions/discord/src/monitor/message-handler.process.ts extensions/discord/src/monitor/message-handler.process.test.ts and git diff --check origin/main...HEAD passed.
  • Fresh GPT-5.5 autoreview found no actionable defects.
  • Existing live Discord maintainer proof showed doneHoldMs=30000 kept the terminal done reaction visible across samples 9.93 seconds apart, directly disproving the old 1.5-second cleanup.
  • Exact-head CI run 28815264612 completed successfully after the unrelated Telegram Crabbox child-liveness shard rerun.
  • OPENCLAW_TESTBOX=1 scripts/pr prepare-run 94736 passed and verified prep_head_sha == pr_head_sha == 52e420aa561d804ec445abb852b128af4d55af28.

Compatibility note accepted: existing non-default Discord timing values will now take effect as already documented. Known proof gaps: none.

@vincentkoc
vincentkoc merged commit e938461 into openclaw:main Jul 6, 2026
148 of 149 checks passed
@vincentkoc

Copy link
Copy Markdown
Member

Merged via squash.

@cedricjanssens

Copy link
Copy Markdown

Thanks @vincentkoc and the team !

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 7, 2026
…T_TIMING (openclaw#94736)

* fix(discord): use configured statusReactions.timing instead of DEFAULT_TIMING

Makes the Discord message finalizer respect user-configured
doneHoldMs/errorHoldMs instead of always using hardcoded
DEFAULT_TIMING values. Brings Discord to parity with Telegram
and Slack which already use configured timing.

Fixes openclaw#78431

* test(discord): strengthen configured-timing regression with old-default assertion

Add a no-cleanup assertion at DEFAULT_TIMING.doneHoldMs (1500ms) before
advancing to the configured 2000ms hold, so the test fails against the
old hardcoded-default behavior. Add a matching errorHoldMs regression
test using failedCounts to drive the error terminal path.

Address ClawSweeper [P2] review finding on openclaw#94736: the previous test
advanced straight to 2000ms and would pass without the runtime fix
because main already removes the done reaction at 1500ms.

* refactor(discord): unify status reaction timing proof

---------

Co-authored-by: Peter Steinberger <[email protected]>
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
…T_TIMING (openclaw#94736)

* fix(discord): use configured statusReactions.timing instead of DEFAULT_TIMING

Makes the Discord message finalizer respect user-configured
doneHoldMs/errorHoldMs instead of always using hardcoded
DEFAULT_TIMING values. Brings Discord to parity with Telegram
and Slack which already use configured timing.

Fixes openclaw#78431

* test(discord): strengthen configured-timing regression with old-default assertion

Add a no-cleanup assertion at DEFAULT_TIMING.doneHoldMs (1500ms) before
advancing to the configured 2000ms hold, so the test fails against the
old hardcoded-default behavior. Add a matching errorHoldMs regression
test using failedCounts to drive the error terminal path.

Address ClawSweeper [P2] review finding on openclaw#94736: the previous test
advanced straight to 2000ms and would pass without the runtime fix
because main already removes the done reaction at 1500ms.

* refactor(discord): unify status reaction timing proof

---------

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

Labels

channel: discord Channel integration: discord merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: S status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. triage: blank-template Candidate: PR template appears mostly untouched.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Discord: implement messages.statusReactions lifecycle (done emoji persistence) — currently Telegram-only despite docs

4 participants