Skip to content

fix(reply): prevent hung pre-delivery hooks from blocking lanes#104256

Merged
steipete merged 16 commits into
openclaw:mainfrom
NianJiuZst:codex/fix-before-deliver-deadlock
Jul 11, 2026
Merged

fix(reply): prevent hung pre-delivery hooks from blocking lanes#104256
steipete merged 16 commits into
openclaw:mainfrom
NianJiuZst:codex/fix-before-deliver-deadlock

Conversation

@NianJiuZst

@NianJiuZst NianJiuZst commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Closes #103684.

What Problem This Solves

Fixes an issue where a final channel reply could remain undelivered and keep the serialized reply lane busy forever when a pre-delivery callback never settled. Affected users could see reactions but no answer, while later messages accumulated behind the stuck lane.

The original report was captured on WhatsApp 2026.6.11. The exact callback was not isolated, so this change covers every remaining production pre-delivery owner without changing the foreground freshness contract.

Why This Change Was Made

The dispatcher keeps one flattened internal stage list. Constructor, channel-custom, and post-construction stages each receive their own 15-second settlement deadline; appended stages cannot escape the policy, and two individually valid slow stages do not share an aggregate deadline. The foreground freshness fence remains lifecycle-owned and unbounded because timing it out could release a stale older reply.

message_sending and reply_payload_sending use the hook runner's existing 15-second per-handler default and fail-open behavior. Explicit plugin/operator hook timeout overrides remain authoritative.

The shipped openclaw/plugin-sdk/reply-runtime dispatcher contract now also lets channel-plugin owners declare a positive finite budget for their own callback: beforeDeliverOptions: { timeoutMs } at construction, or dispatcher.appendBeforeDeliver(handler, { timeoutMs }) for appended work. The default remains 15 seconds, while an explicit budget is still per stage. This adds no config key, environment variable, protocol field, or general SDK configuration surface.

A timeout is recorded as failed-before-deliver, not as an intentional cancellation. Per-payload completion preserves pendingFinalDelivery only when every relevant final failed before transport started; delivery, explicit suppression, or an error after transport began retains the existing no-blind-retry behavior. The public send*(): boolean contracts are unchanged.

The one bundled Mattermost button-click caller that skipped dispatcher settlement now uses the existing shared lifecycle owner; all other bundled/core callers were already settled. There is no persistent data-model or migration change: the documentation update describes the public callback contract only.

User Impact

A hung pre-delivery callback releases the owning lane after a bounded wait, so subsequent replies can continue. Plugin hook timeouts continue with the latest safe payload. Channel plugins with legitimate slower beforeDeliver work can declare a larger per-callback deadline instead of being forced into the new 15-second default. A final that definitely failed before send keeps its durable pending state instead of being silently marked delivered.

Evidence

Deterministic repository regressions cover:

  • constructor and appended hooks that never settle, including recovery of the same dispatcher and a WhatsApp-shaped buffered lane;
  • a constructor or appended callback completing after 15 seconds under its explicit 20-second budget, including the foreground freshness-fence path;
  • two 10-second internal stages succeeding under separate 15-second budgets;
  • registration-specific plugin hook timeouts longer than the default;
  • successful, cancelled, pre-send failed, after-send failed, and mixed multi-final pending-state transitions;
  • enqueue-then-append timing compatibility and the public Plugin SDK type contract.

Completed with the exact pushed content (625b270e6fff00a0958a9f402791352e93dda6be):

  • node scripts/run-vitest.mjs src/auto-reply/reply/reply-flow.test.ts src/auto-reply/reply/dispatch-from-config.reply-dispatch.test.ts src/auto-reply/dispatch.freshness.test.ts src/plugins/wired-hooks-message.test.ts src/plugins/wired-hooks-reply-payload-sending.test.ts src/plugins/contracts/plugin-sdk-subpaths.test.ts — passed: 6 files / 82 tests across 3 Vitest shards.
  • node scripts/build-all.mjs — passed.
  • node scripts/package-openclaw-for-docker.mjs --allow-unreleased-changelog --skip-build --output-dir <temp> --output-name openclaw-current.tgz — passed the package inventory and tarball import-graph checks.
  • Fresh temporary npm project installed that tarball; openclaw/plugin-sdk/reply-runtime resolved to the installed package's dist/plugin-sdk/reply-runtime.js.
  • Installed-runtime lane recovery through that public SDK entrypoint: after 15,007 ms, the unresolved first final failed with beforeDeliver timed out after 15000ms; the same dispatcher delivered follow-up-final, with failed counts { tool: 0, block: 0, final: 1 }.
  • Installed-runtime declared-budget proof: constructor and appended callbacks each waited 15,250 ms under explicit 20-second budgets; after 30,509 ms the installed dispatcher delivered budget-final:constructor:appended with no errors and final failed count 0.
  • node --max-old-space-size=8192 --import tsx scripts/generate-plugin-sdk-api-baseline.ts --check — passed after refreshing the committed SDK baseline hash.
  • OPENCLAW_OXLINT_SKIP_PREPARE=1 node scripts/run-oxlint.mjs <touched TypeScript files> and git diff --check — passed.
  • .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main --stream-engine-output — no accepted/actionable findings reported.

Runtime proof boundary:

  • This is an installed-package public-SDK lane-recovery proof, not a live WhatsApp delivery. No WhatsApp credentials were available.
  • Sanitized direct AWS Crabbox was attempted from a clean trusted main checkout, with public networking and no hydration. It could not acquire broker credentials because this environment has no EC2 IMDS role; no credentialed Testbox or live-channel run was used.
  • Exact-head GitHub Actions are in progress for this update.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: mattermost Channel integration: mattermost size: L labels Jul 11, 2026
@NianJiuZst
NianJiuZst marked this pull request as ready for review July 11, 2026 07:00
@NianJiuZst
NianJiuZst force-pushed the codex/fix-before-deliver-deadlock branch from 37f4152 to f7c8567 Compare July 11, 2026 07:13
@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. P0 Emergency: data loss, security bypass, crash loop, or unusable core runtime. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jul 11, 2026
@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 11, 2026, 6:28 PM ET / 22:28 UTC.

Summary
Adds owner-overridable per-stage pre-delivery deadlines, outcome-based pending-final reconciliation, shared Mattermost dispatcher settlement, Plugin SDK typing, documentation, and regression coverage.

PR surface: Source +508, Tests +915, Docs +13, Generated 0, Other -1. Total +1435 across 24 files.

Reproducibility: yes. at source level: an unresolved pre-delivery callback retains the serialized send chain and prevents waitForIdle() from settling. A live WhatsApp reproduction was not performed because credentials were unavailable.

Review metrics: 1 noteworthy metric.

  • Public API surface: 1 type added, 1 method signature extended. The owner-declared timeout becomes a shipped Plugin SDK compatibility contract for channel plugins.

Stored data model
Persistent data-model change detected: serialized state: CHANGELOG.md, serialized state: docs/plugins/hooks.md. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #103684
Summary: This PR is the active comprehensive fix candidate for the instrumented reply-lane deadlock; the earlier narrow timeout attempt closed unmerged.

Members:

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

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] Unannotated channel-owned callbacks that previously had no dispatcher deadline now time out after 15 seconds; legitimately slower existing callbacks must declare a larger per-stage budget.
  • [P1] The change controls durable pending-final session state and final-message delivery, so future edits must preserve the distinction between failure before transport and failure after transport starts.

Maintainer options:

  1. Merge after exact-head checks (recommended)
    Land the reviewed implementation once the remaining required check succeeds because focused coverage and maintainer integration address the identified compatibility and state risks.
  2. Pause for credentialed channel proof
    Delay merge only if maintainers require a live WhatsApp reproduction beyond the installed-package lane proof, Testbox validation, and focused lifecycle tests.

Next step before merge

  • [P2] No repair is needed; the remaining action is normal merge gating on the exact current head.

Security
Cleared: The diff adds no dependency, workflow, secret, permission, downloaded-code, or package-resolution change, and no concrete security regression was found.

Review details

Best possible solution:

Merge this single owner-aware timeout and intent-safe reconciliation path after the final required exact-head check succeeds, retaining the documented per-stage override for legitimately slow callbacks.

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

Yes at source level: an unresolved pre-delivery callback retains the serialized send chain and prevents waitForIdle() from settling. A live WhatsApp reproduction was not performed because credentials were unavailable.

Is this the best way to solve the issue?

Yes. Per-stage owner-overridable deadlines preserve legitimate slow work better than an aggregate timeout, while delivery-outcome and intent-identity reconciliation avoids cancellation and blind pending-state clearing.

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): Installed-package terminal output demonstrates public-SDK lane recovery and declared timeout budgets, supplemented by focused tests, Testbox validation, and exact-head CI; no live WhatsApp smoke was available.
  • remove rating: 🦐 gold shrimp: Current PR rating is rating: 🦞 diamond lobster, so this older rating label is no longer current.
  • remove status: ⏳ waiting on author: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P0: The linked defect can suppress final replies and indefinitely block subsequent lane work until technical recovery.
  • merge-risk: 🚨 compatibility: Unannotated channel callback stages gain a 15-second default deadline, while slower existing plugins must explicitly request a larger budget.
  • merge-risk: 🚨 message-delivery: The new timeout and fail-open behavior directly controls whether final payloads are modified, cancelled, failed, or delivered.
  • merge-risk: 🚨 session-state: The patch changes when durable pending-final intent is retained, narrowed, or cleared after delivery settlement.
  • 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 (terminal): Installed-package terminal output demonstrates public-SDK lane recovery and declared timeout budgets, supplemented by focused tests, Testbox validation, and exact-head CI; no live WhatsApp smoke was available.
  • proof: sufficient: Contributor real behavior proof is sufficient. Installed-package terminal output demonstrates public-SDK lane recovery and declared timeout budgets, supplemented by focused tests, Testbox validation, and exact-head CI; no live WhatsApp smoke was available.
Evidence reviewed

PR surface:

Source +508, Tests +915, Docs +13, Generated 0, Other -1. Total +1435 across 24 files.

View PR surface stats
Area Files Added Removed Net
Source 12 618 110 +508
Tests 7 933 18 +915
Docs 2 13 0 +13
Config 0 0 0 0
Generated 1 2 2 0
Other 2 1 2 -1
Total 24 1567 132 +1435

What I checked:

  • Per-stage timeout implementation: The dispatcher retains a separate deadline for each real callback, supports owner-declared budgets, and avoids wrapping lifecycle-owned hooks in an aggregate deadline. (src/auto-reply/reply/reply-dispatcher.ts:93, fa43be8d8553)
  • Delivery outcome tracking: Each queued payload records whether it was delivered, intentionally cancelled, failed before transport, or failed after transport began, while preserving the existing boolean send methods. (src/auto-reply/reply/reply-dispatcher.ts:412, fa43be8d8553)
  • Generation-safe session reconciliation: Settlement rereads the authoritative session entry, rejects stale intent identities, retains only finals that failed before transport, and clears pending state after delivery, cancellation, or a failure after transport started. (src/auto-reply/reply/dispatch-from-config.ts:1206, fa43be8d8553)
  • Mattermost lifecycle ownership: The bundled Mattermost interaction path now uses the shared dispatcher lifecycle helper so settlement and idle cleanup run even when dispatch throws. (extensions/mattermost/src/mattermost/monitor.ts:859, fa43be8d8553)
  • Regression coverage: Focused tests cover hung constructor and appended callbacks, explicit longer budgets, per-stage timing, stale intent protection, mixed finals, cancellation, pre-send failure, and transport-start failure. (src/auto-reply/reply/dispatch-from-config.reply-dispatch.test.ts:210, fa43be8d8553)
  • Current-main comparison: The only current-main commit after the PR base changes browser surfaces, so it does not supersede or conflict with the reply, session, hook, SDK, or Mattermost implementation. (8a4463eef1b9)

Likely related people:

  • steipete: The area history is dominated by this contributor, who also integrated the branch's retry-identity, canonical-accessor, SDK baseline, and lifecycle fixes and posted the land-ready proof. (role: feature owner and recent integrator; confidence: high; commits: fa664fa2a5a1, 16dc2ae503e9, 48161b1c6182; files: src/auto-reply/reply/reply-dispatcher.ts, src/auto-reply/reply/dispatch-from-config.ts, extensions/mattermost/src/mattermost/monitor.ts)
  • Josh Lehman: The SQLite session and transcript refactor established the canonical persisted-session access path now used by settlement reconciliation. (role: recent session-storage refactor author; confidence: medium; commits: 0a8e3604ba24; files: src/auto-reply/reply/dispatch-from-config.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.
Review history (9 earlier review cycles; latest 8 shown)
  • reviewed 2026-07-11T10:41:51.057Z sha 625b270 :: needs changes before merge. :: [P2] Refresh the public SDK surface budget for this export
  • reviewed 2026-07-11T11:27:25.303Z sha 59e7daf :: needs changes before merge. :: [P2] Refresh the public SDK surface budget for this export
  • reviewed 2026-07-11T11:33:06.443Z sha 59e7daf :: needs changes before merge. :: [P2] Refresh the public SDK export budget
  • reviewed 2026-07-11T11:50:43.610Z sha d0cc47d :: needs maintainer review before merge. :: none
  • reviewed 2026-07-11T14:07:31.801Z sha d0cc47d :: needs maintainer review before merge. :: none
  • reviewed 2026-07-11T21:30:18.660Z sha 0dcfd5f :: needs changes before merge. :: [P2] Use the canonical session accessor for settlement state | [P2] Pin the SDK budget to the generated export count
  • reviewed 2026-07-11T21:41:51.293Z sha 0dcfd5f :: needs changes before merge. :: [P2] Use the canonical session accessor for settlement state | [P2] Pin the SDK budget to the generated export count
  • reviewed 2026-07-11T22:00:35.988Z sha 888124a :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. 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: 🧂 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. labels Jul 11, 2026
@NianJiuZst
NianJiuZst force-pushed the codex/fix-before-deliver-deadlock branch from 625b270 to 59e7daf Compare July 11, 2026 11:19
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Jul 11, 2026
@NianJiuZst
NianJiuZst force-pushed the codex/fix-before-deliver-deadlock branch from 59e7daf to d0cc47d Compare July 11, 2026 11:41
@openclaw-barnacle openclaw-barnacle Bot added the scripts Repository scripts label Jul 11, 2026
@clawsweeper clawsweeper Bot added 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. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jul 11, 2026
@steipete steipete self-assigned this Jul 11, 2026
@steipete
steipete force-pushed the codex/fix-before-deliver-deadlock branch from d0cc47d to 0dcfd5f Compare July 11, 2026 21:22
@clawsweeper clawsweeper Bot added the merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. label Jul 11, 2026
@steipete
steipete force-pushed the codex/fix-before-deliver-deadlock branch from 0dcfd5f to 888124a Compare July 11, 2026 21:49
@steipete

steipete commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Maintainer land-ready pass complete at fa43be8d8553697da923130856435870655d58c3.

What changed during review:

  • accepted the 15-second default for unannotated pre-delivery stages;
  • preserved per-stage owner budgets instead of applying an aggregate chain timeout;
  • made pending-final reconciliation generation-safe and narrowed mixed-final retry text;
  • moved the new settlement reads/writes to the canonical session accessor and ratcheted its debt baseline;
  • refreshed the exact Plugin SDK public-surface budget after the rebase.

Proof:

  • sanitized AWS original-head focused suite: 82 passed;
  • Blacksmith Testbox prepared-tree touched suite: 189 passed, plus a final 19-test harness rerun;
  • Blacksmith changed-surface proof: formatting, all four production/test typecheck lanes, core/extensions lint, storage guards, and import-cycle checks passed; the only local broad-gate failure was a byte-identical current-main Docker E2E source-import guard outside this PR;
  • exact-head GitHub Actions: run 29170296958 passed after one unrelated timing-only tooling-shard rerun;
  • fresh full-branch autoreview completed with no accepted/actionable finding.

Proof gap: no credentialed live WhatsApp smoke. The defect and fix sit in the channel-agnostic serialized reply-lane owner, and the focused lifecycle tests exercise the hung-callback, timeout, queue-release, retry, stale-intent, and transport-start branches directly.

Ready to merge. Thanks @NianJiuZst for the original fix and tests.

@steipete
steipete force-pushed the codex/fix-before-deliver-deadlock branch from 888124a to fa43be8 Compare July 11, 2026 22:19
@clawsweeper clawsweeper Bot added 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. and removed 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 Jul 11, 2026
@steipete
steipete force-pushed the codex/fix-before-deliver-deadlock branch from fa43be8 to ba2ea9d Compare July 11, 2026 22:40
@steipete
steipete merged commit da6a24d into openclaw:main Jul 11, 2026
105 checks passed
@steipete

Copy link
Copy Markdown
Contributor

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 12, 2026
…claw#104256)

* fix(reply): bound pre-delivery hook settlement

* test(plugins): preserve hook timeout fixtures

* fix(reply): preserve declared pre-delivery budgets

* chore(reply): finalize pre-delivery recovery

* fix(reply): preserve per-final recovery semantics

* fix(reply): guard pending-final settlement identity

* test(reply): align pending-final store fixture

* fix(reply): bind settlement to originating intent

* test(reply): satisfy timeout fixture lint

* chore(plugin-sdk): refresh rebased baseline

* fix(reply): preserve normalized retry ownership

* fix(reply): narrow pending retry metadata

* fix: align reply dispatch state access

* chore(plugin-sdk): refresh rebased surface baseline

* test(reply): align rebased accessor assertion

* chore(plugin-sdk): regenerate drifted API baseline

---------

Co-authored-by: NianJiuZst <[email protected]>
Co-authored-by: Peter Steinberger <[email protected]>
ceckert added a commit to ceckert/openclaw that referenced this pull request Jul 14, 2026
…hreadDirectMessages

The 7.2 cherry-pick resolved extensions/mattermost/src/mattermost/monitor.ts by
taking our side wholesale, silently reverting six upstream commits landed between
7.1 and 7.2. Adopt them instead of clobbering:

  f77c2aa  truncate the inbound preview on a code-point boundary (openclaw#101630)
  b7ab62c  preserve text-block boundaries in the draft preview (openclaw#87449)
  da6a24d  prevent hung pre-delivery hooks from blocking lanes (openclaw#104256)
  218dcd8  noUncheckedIndexedAccess in the extensions lane (openclaw#105132)
  9cdf166  trim the monitor gating facade (openclaw#106021)

70a7e6e (opt-in DM threading by chat type) was already in the impl; three 7.1-era
assertions in monitor.test.ts that upstream had superseded move to upstream's
semantics (the implementations are byte-identical to upstream).

b7ab62c's 173-line monitor hunk (block-preview boundary machinery) was hand-ported
onto our activity/warm-fallback interleaving; the block-preview code is now
byte-identical to pristine 7.2.

threadDirectMessages kept as a thin compat feeding upstream's replyToModeByChatType,
because Dockerfile.base's shared config probe still writes it and the probe spans
matrix bases older than 2026.7.2. Retire both together later.

Mattermost suite 630/632. The 2 remaining timeouts are localized to
deliverMattermostReplyWithDraftPreview: with a mocked-rejecting updateMattermostPost,
our patched buildFinalEdit attempts the in-place edit (pristine skips it), the edit
rejects, and the deliverNormally fallback awaits the unmocked deliverMattermostReplyPayload
which never resolves under the test's bare sendMessageMattermost stub. Behavioral
divergence in our activity/warm-fallback finalize path, not the upstream port. TODO.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: mattermost Channel integration: mattermost docs Improvements or additions to documentation merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P0 Emergency: data loss, security bypass, crash loop, or unusable core runtime. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. scripts Repository scripts size: XL 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.

Final reply is never delivered: dispatcher.waitForIdle() blocks forever on a beforeDeliver hook, and the lane stays blocked

2 participants