Skip to content

mattermost: fix /oc_* slash command 503 from duplicate slash-state instance#68089

Closed
allenliang2022 wants to merge 4 commits into
openclaw:mainfrom
allenliang2022:fix/mattermost-slash-command-503
Closed

mattermost: fix /oc_* slash command 503 from duplicate slash-state instance#68089
allenliang2022 wants to merge 4 commits into
openclaw:mainfrom
allenliang2022:fix/mattermost-slash-command-503

Conversation

@allenliang2022

Copy link
Copy Markdown

Summary

  • Problem: Mattermost slash commands (/oc_model, /oc_status, /oc_help, …) always return 503 Service Unavailable with {"response_type":"ephemeral","text":"Slash commands are not yet initialized. Please try again in a moment."}, even after the log confirms mattermost: slash commands activated for account default (8 commands).
  • Why it matters: On macOS/Linux installs, every `/oc_*` slash command in Mattermost is broken, with no path to recovery short of patching the installed npm package. Slack, Discord, etc. are unaffected.
  • What changed: extensions/mattermost/index.ts now imports registerSlashCommandRoute statically from ./slash-route-api.js instead of resolving it through the sync jiti loader loadBundledEntryExportSync. That makes the plugin-registration path and the monitor path share a single ESM instance of slash-state.ts, so the HTTP route closure and activateSlashCommands see the same accountStates map.
  • What did NOT change (scope boundary): No changes to slash-state.ts, monitor-slash.ts, monitor.ts, the HTTP handler, slash command registration flow, or any other extension. Just the single import in extensions/mattermost/index.ts. Slack's extensions/slack/index.ts has a similar-looking dual-path import, but its route handler does not close over module state (the handler uses await import("./handler.runtime.js") inside), so Slack is not affected by the same bug and is explicitly out of scope here.

Change Type (select all)

  • Bug fix

Scope (select all touched areas)

  • Integrations

Linked Issue/PR

  • Closes #
  • Related #
  • This PR fixes a bug or regression

Root Cause

extensions/mattermost/index.ts::registerFull used loadBundledEntryExportSync(import.meta.url, { specifier: "./slash-route-api.js", exportName: "registerSlashCommandRoute" }) to load the route registrar. On macOS/Linux that helper resolves through jiti (see src/plugin-sdk/channel-entry-contract.ts: nodeRequire is only tried inside the Win32 branch, everywhere else falls through to getJiti(modulePath)(modulePath)).

slash-route-api.ts re-exports registerSlashCommandRoute from ./src/mattermost/slash-state.js. Loading it via jiti causes jiti to re-evaluate slash-state.ts inside its own module registry, producing a second live instance of the module. Meanwhile src/mattermost/monitor-slash.ts and src/mattermost/monitor.ts (and therefore the channel runtime loaded via await import("./channel.runtime-*.js")) import ./slash-state.js through native ESM, giving them instance A.

The result: two separate accountStates maps.

  • activateSlashCommands / deactivateSlashCommands mutate the ESM copy → the log line "slash commands activated for account default (N commands)" fires on the ESM instance.
  • registerSlashCommandRoute's routeHandler closure closes over the jiti copy's accountStatesaccountStates.size stays 0 for the lifetime of the process → every callback returns 503 "Slash commands are not yet initialized. Please try again in a moment.".

This matches the guidance in src/plugin-sdk/CLAUDE.md:

Do not mix static and dynamic imports for the same runtime surface when shaping SDK seams.

The fix is the straightforward application of that rule: index.ts should import ./slash-route-api.js statically so slash-state.ts loads through native ESM exactly once, shared with the monitor / channel-runtime path.

Missing detection / guardrail

There is a good unit test for the token-routing logic in extensions/mattermost/src/mattermost/slash-state.test.ts, but it only exercises one import of slash-state, so it cannot detect the dual-instance bug. I am happy to add a regression test that specifically simulates loading slash-route-api.js through jiti alongside the native ESM import and asserts that activation flows through to the route handler — happy to do it in this PR if maintainers prefer. I did not include it in the initial patch because simulating the jiti boundary in Vitest is a bit more involved than the fix itself, and I wanted the minimal-risk diff to land first.

Contributing context

The same loadBundledEntryExportSync pattern is used in extensions/feishu/index.ts, extensions/nostr/index.ts, extensions/qqbot/index.ts, extensions/slack/index.ts, extensions/zalouser/index.ts. Slack is safe because its handler does await import("./handler.runtime.js") inside the request closure instead of closing over module state. I did not audit the others in depth; if similar closures-over-module-state exist there, they would have the same failure mode and warrant a follow-up. Flagging for visibility, not proposing to change them in this PR.

Regression Test Plan

  • Coverage level that should have caught this:
    • Seam / integration test
  • Target test or file: extensions/mattermost/src/mattermost/slash-state.dual-load.test.ts (new) — would load slash-route-api.ts through a jiti instance and slash-state.ts through native ESM in the same test, activate commands on the ESM side, then drive an HTTP request against the jiti-registered route and assert that it does not return 503.
  • Scenario to lock in: "route handler registered via loadBundledEntryExportSync observes activations performed via the monitor's static import of slash-state.js."
  • Why this is the smallest reliable guardrail: The bug is entirely a module-identity bug; pure-unit tests that import slash-state.ts once do not reproduce it. A boundary test that crosses the same jiti / ESM seam is the minimum.
  • Existing test that already covers this: None — slash-state.test.ts is single-import only.
  • If no new test is added, why not: I did not want to block the fix on writing the jiti-boundary harness; happy to add it as a follow-up or in this PR if a reviewer prefers.

User-visible / Behavior Changes

  • Mattermost /oc_status, /oc_model, /oc_models, /oc_new, /oc_help, /oc_think, /oc_reasoning, /oc_verbose (and any user-defined slash commands registered through the same path) start working again instead of responding 503 Service Unavailable / "Slash commands are not yet initialized.".
  • No config changes. No new permissions. The HTTP route path, callback URL behavior, 401/409/413 responses, and multi-account dispatch logic are all unchanged.

Diagram

Before (broken):

  registerFull(api)
    └─ loadBundledEntryExportSync(...) ──(jiti)──► slash-state.ts   (instance B)
                                                     └─ accountStates_B  ◄── routeHandler closure
                                                                                 (size always 0 → 503)

  channel.runtime.ts ──(native ESM import)──► slash-state.ts   (instance A)
                                                 └─ accountStates_A  ◄── activateSlashCommands writes here


After (fixed):

  registerFull(api)
    └─ import { registerSlashCommandRoute } from "./slash-route-api.js"
                                    │
                                    ▼
                              slash-state.ts   (single ESM instance)
                                    └─ accountStates  ◄── routeHandler AND activateSlashCommands

Security Impact

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No — slash-command dispatch semantics, token validation, and multi-account routing are unchanged. The fix only restores the previously-intended flow.
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: macOS 15.3.x (Darwin 25.3.0, arm64)
  • Runtime/container: Node 22.22.0, openclaw installed via npm i -g openclaw@2026.4.15, gateway started as the launchd ai.openclaw.gateway LaunchAgent.
  • Integration/channel: Mattermost 11.5.1 (team edition) behind Caddy, multiple channels.mattermost.accounts.* entries (default / forge / kline / probe / quill / scout) but only the default account has team-admin permission to register commands, so accountStates.size === 1 — the most common production shape.

Steps

  1. Gateway boots; logs show:
    [plugins] mattermost: registered slash command callback at /api/channels/mattermost/command
    [mattermost] slash commands activated for account default (8 commands)
    [mattermost] slash commands registered (8 commands across 1 teams, callback=http://<lan>:18789/api/channels/mattermost/command)
    
  2. Trigger /oc_model from the Mattermost UI. Server also reproducible via:
    curl -sS -o /dev/null -w "HTTP %{http_code}\n" -X POST \
      http://127.0.0.1:18789/api/channels/mattermost/command \
      -d 'token=<real-token>&command=/oc_model'
    

Expected

  • For a single-account setup, the size === 1 branch should dispatch straight to state.handler, which validates the token internally and returns the normal slash-command response (200 with the ephemeral reply, or a 401 only for a genuinely wrong token).

Actual (before the fix)

  • HTTP 503 with body {"response_type":"ephemeral","text":"Slash commands are not yet initialized. Please try again in a moment."}, even though the activation log fired seconds earlier. The Mattermost UI surfaces this as 触发器 "oc_model" 返回了响应状态 503 Service Unavailable. / "Trigger "oc_model" returned response status 503 Service Unavailable."

Evidence

Failing-before / passing-after against a locally patched installed dist (equivalent rewrite of this TS change onto the bundled output, /opt/homebrew/lib/node_modules/openclaw/dist/extensions/mattermost/index.js):

Before (immediately after launchctl kickstart -k gui/$UID/ai.openclaw.gateway, well past activation):

$ curl -sS -o /dev/null -w "HTTP %{http_code}\n" -X POST \
    http://127.0.0.1:18789/api/channels/mattermost/command \
    -d 'token=foo&command=/oc_model'
HTTP 503
$ curl -sS -X POST http://127.0.0.1:18789/api/channels/mattermost/command \
    -d 'token=foo&command=/oc_model'
{"response_type":"ephemeral","text":"Slash commands are not yet initialized. Please try again in a moment."}

After applying the equivalent patch and restarting the gateway:

$ curl -sS -o /dev/null -w "HTTP %{http_code}\n" -X POST \
    http://127.0.0.1:18789/api/channels/mattermost/command \
    -d 'token=foo&command=/oc_model'
HTTP 400
$ curl -sS -X POST http://127.0.0.1:18789/api/channels/mattermost/command \
    -d 'token=foo&command=/oc_model'
{"response_type":"ephemeral","text":"Invalid slash command payload."}
$ curl -sS -o /dev/null -w "HTTP %{http_code}\n" -X POST \
    http://127.0.0.1:18789/api/channels/mattermost/command \
    --data-urlencode 'token=not-a-real-token' \
    --data-urlencode 'command=/oc_model' \
    --data-urlencode 'team_id=498ogwtouigf8xfbuks451e8aa' \
    --data-urlencode 'channel_id=c' --data-urlencode 'user_id=u' \
    --data-urlencode 'user_name=n' --data-urlencode 'text=' \
    --data-urlencode 'trigger_id=t'
HTTP 401

Interpretation: the 503 "not yet initialized" path is now unreachable — incoming requests flow into the real handler, which correctly rejects malformed payloads (400) and bad tokens (401). A real Mattermost-signed request with the registered token returns the normal slash-command response.

Relevant gateway log lines from the fixed run (unchanged shape, included for completeness):

[plugins] mattermost: registered slash command callback at /api/channels/mattermost/command
[mattermost] [default] starting channel
[mattermost] connected as @nova
[mattermost] command /oc_model already registered (id=fffuot5kpjgafkmx7rc5fk9xjc)
[mattermost] slash commands activated for account default (8 commands)
[mattermost] slash commands registered (8 commands across 1 teams, callback=http://<lan>:18789/api/channels/mattermost/command)

Human Verification

  • Verified scenarios:
    • Single-account (accountStates.size === 1) dispatch path, which was the production failure.
    • End-to-end via the running ai.openclaw.gateway LaunchAgent and real Mattermost (/oc_model from the Mattermost UI).
    • 400 / 401 paths reached correctly with synthetic curl payloads.
  • Edge cases checked:
    • Restart via launchctl kickstart -k between before/after so the Node process and jiti registry are both replaced.
    • Confirmed that the fix does not regress the registered-HTTP-route path set for known callbackPath / callbackUrl overrides (route registration log is unchanged).
  • What I did NOT verify:
    • Multi-account (accountStates.size > 1) token-routing path — code path is untouched, but I did not have a second team-admin account to activate commands on. The unit tests in slash-state.test.ts cover that branch.
    • pnpm check / pnpm build / pnpm test — I did not run these locally before opening the PR (this is my first contribution to the repo and I wanted to avoid a large-deps install cycle before you tell me which gates you want covered). Please run CI; happy to iterate on any failures or add the jiti-boundary regression test if that is what you would like to see.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

  • Risk: slash-route-api.ts and transitively ./src/mattermost/slash-state.ts now load eagerly as part of the plugin entry, instead of only when registerFull fires through jiti. slash-state.ts is a small module (≈300 LOC, top-level state is just one Map), but this does add it to the mattermost plugin's cold-start import cost.
    • Mitigation: the module has no expensive side effects at import time (just a new Map() and function definitions), matches how monitor.ts already imports it on the hot monitor path, and aligns with the SDK guidance that says the eager/light contract belongs next to the plugin entry and only the heavy runtime should live behind a lazy *.runtime.ts boundary. I am happy to instead introduce a dedicated slash-route.runtime.ts and keep registerSlashCommandRoute lazy-but-single-instance if maintainers prefer that shape.
  • Risk: Other bundled channels use the same loadBundledEntryExportSync pattern and may have similar dual-instance bugs depending on whether their route registrars close over module state.
    • Mitigation: Out of scope for this PR — Slack is demonstrably fine. Happy to open a follow-up audit if useful.

@openclaw-barnacle openclaw-barnacle Bot added channel: mattermost Channel integration: mattermost size: XS labels Apr 17, 2026
@greptile-apps

greptile-apps Bot commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a real, user-impacting bug where all Mattermost /oc_* slash commands returned 503 "Slash commands are not yet initialized" despite the activation log firing correctly. The root cause was that loadBundledEntryExportSync used jiti on macOS/Linux, producing a second instance of slash-state.ts whose accountStates map was never populated; the HTTP route handler closed over the jiti copy while activateSlashCommands wrote into the native-ESM copy. Replacing the sync jiti load with a static ESM import is the correct, minimal fix.

Confidence Score: 5/5

Safe to merge — the change is a single correct bug fix with no logic, security, or data-integrity regressions.

The only finding is P2: the static import widens the mattermost channel entry's eager import graph by pulling in slash-http.ts and its operational deps. This is a cold-start tradeoff the PR author explicitly acknowledges with a proposed *.runtime.ts alternative. There are no correctness, security, or data-integrity issues.

No files require special attention beyond the P2 import-topology note on extensions/mattermost/index.ts.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/mattermost/index.ts
Line: 11

Comment:
**Eager import pulls heavy operational modules into the channel entry**

The static import of `./slash-route-api.js` is the right fix for module-identity correctness, but it widens the mattermost channel entry's cold-start import graph. `slash-route-api.ts` re-exports from `slash-state.ts`, which has top-level value imports of `createSlashCommandHttpHandler` from `slash-http.ts` — and `slash-http.ts` brings in `model-picker.js`, `reply-delivery.js`, `client.js`, `monitor-auth.js`, `openclaw/plugin-sdk/ssrf-runtime`, and `openclaw/plugin-sdk/browser-security-runtime`. Previously none of these loaded until the channel runtime was started; now they load even on the lightweight `cli-metadata` registration path.

Per the SDK guidance ("keep public SDK entrypoints cheap at module load; if a helper is only needed on async paths, prefer a narrow `*.runtime` subpath"), the preferred shape would be a thin `slash-route.runtime.ts` that static-imports only `./slash-state.js` (preserving single-instance identity) while keeping `slash-http.ts` and its deps behind the lazy boundary. The PR description already proposes this alternative, so flagging it for maintainer judgment rather than as a blocker.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "mattermost: fix /oc_* slash command 503 ..." | Re-trigger Greptile

Comment thread extensions/mattermost/index.ts Outdated
// route would keep returning 503 "Slash commands are not yet initialized" even
// after activation succeeds. See SDK guidance: do not mix static and dynamic
// imports for the same runtime surface.
import { registerSlashCommandRoute } from "./slash-route-api.js";

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.

P2 Eager import pulls heavy operational modules into the channel entry

The static import of ./slash-route-api.js is the right fix for module-identity correctness, but it widens the mattermost channel entry's cold-start import graph. slash-route-api.ts re-exports from slash-state.ts, which has top-level value imports of createSlashCommandHttpHandler from slash-http.ts — and slash-http.ts brings in model-picker.js, reply-delivery.js, client.js, monitor-auth.js, openclaw/plugin-sdk/ssrf-runtime, and openclaw/plugin-sdk/browser-security-runtime. Previously none of these loaded until the channel runtime was started; now they load even on the lightweight cli-metadata registration path.

Per the SDK guidance ("keep public SDK entrypoints cheap at module load; if a helper is only needed on async paths, prefer a narrow *.runtime subpath"), the preferred shape would be a thin slash-route.runtime.ts that static-imports only ./slash-state.js (preserving single-instance identity) while keeping slash-http.ts and its deps behind the lazy boundary. The PR description already proposes this alternative, so flagging it for maintainer judgment rather than as a blocker.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/mattermost/index.ts
Line: 11

Comment:
**Eager import pulls heavy operational modules into the channel entry**

The static import of `./slash-route-api.js` is the right fix for module-identity correctness, but it widens the mattermost channel entry's cold-start import graph. `slash-route-api.ts` re-exports from `slash-state.ts`, which has top-level value imports of `createSlashCommandHttpHandler` from `slash-http.ts` — and `slash-http.ts` brings in `model-picker.js`, `reply-delivery.js`, `client.js`, `monitor-auth.js`, `openclaw/plugin-sdk/ssrf-runtime`, and `openclaw/plugin-sdk/browser-security-runtime`. Previously none of these loaded until the channel runtime was started; now they load even on the lightweight `cli-metadata` registration path.

Per the SDK guidance ("keep public SDK entrypoints cheap at module load; if a helper is only needed on async paths, prefer a narrow `*.runtime` subpath"), the preferred shape would be a thin `slash-route.runtime.ts` that static-imports only `./slash-state.js` (preserving single-instance identity) while keeping `slash-http.ts` and its deps behind the lazy boundary. The PR description already proposes this alternative, so flagging it for maintainer judgment rather than as a blocker.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@clawsweeper

clawsweeper Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge.

Latest ClawSweeper review: 2026-05-23 04:39 UTC / May 23, 2026, 12:39 AM ET.

Workflow note: Future ClawSweeper reviews update this same comment in place.

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.

Summary
The PR moves Mattermost slash route dispatch into a separate route module, stores slash account state in a Symbol.for-backed shared map, adds a dual-loader regression test, and updates the changelog.

Reproducibility: yes. by source inspection and contributor proof. Current main still loads the route registrar through the bundled-entry loader while activation imports the same state through native ESM, matching the live 503 reports and the PR's before/after terminal evidence.

PR rating
Overall: 🦐 gold shrimp
Proof: 🦞 diamond lobster
Patch quality: 🦐 gold shrimp
Summary: Useful, well-targeted fix with strong real behavior proof, but a current-main fixture mismatch and stale merge state block readiness.

Rank-up moves:

  • Add streamingMode: "partial" to the new dual-load test account fixture.
  • Refresh the branch against current main and resolve the stale changelog/merge state.
  • Run the focused Mattermost slash-state tests plus changed checks after the refresh.
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.

Real behavior proof
Sufficient (terminal): The PR body provides after-fix terminal and live Mattermost proof showing the 503 path replaced by normal handler responses.

Risk before merge

  • The branch is stale and currently mergeable_state dirty, so maintainers need a refresh or replacement branch before merge.
  • The new dual-load test omits the now-required Mattermost account streamingMode field and will fail type/check gates on current main until repaired.
  • I did not run tests because this review was read-only; the focused Mattermost tests and changed checks still need to run after the refresh.

Maintainer options:

  1. Decide the mitigation before merge
    Land this PR or an equivalent Mattermost plugin fix after refreshing it for current main, repairing the dual-load fixture, and rerunning focused slash-state plus changed-check proof.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge
A narrow repair can make the PR current-main compatible by adding the required fixture field and refreshing the stale merge state without a product decision.

Security
Cleared: The diff moves existing Mattermost slash-route/state logic and does not add dependencies, permissions, secret handling, or a new command execution surface.

Review findings

  • [P2] Add streamingMode to the dual-load account fixture — extensions/mattermost/src/mattermost/slash-state.dual-load.test.ts:10-15
Review details

Best possible solution:

Land this PR or an equivalent Mattermost plugin fix after refreshing it for current main, repairing the dual-load fixture, and rerunning focused slash-state plus changed-check proof.

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

Yes, by source inspection and contributor proof. Current main still loads the route registrar through the bundled-entry loader while activation imports the same state through native ESM, matching the live 503 reports and the PR's before/after terminal evidence.

Is this the best way to solve the issue?

Mostly yes. The shared-state split keeps the route loader lazy while making both loader paths observe one account state map, but the PR must be refreshed for current main before it is merge-ready.

Label justifications:

  • P1: This PR targets a confirmed regression that leaves Mattermost native slash commands returning 503 for real users.
  • rating: 🦐 gold shrimp: Current PR rating is 🦐 gold shrimp because proof is 🦞 diamond lobster, patch quality is 🦐 gold shrimp, and Useful, well-targeted fix with strong real behavior proof, but a current-main fixture mismatch and stale merge state block readiness.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): The PR body provides after-fix terminal and live Mattermost proof showing the 503 path replaced by normal handler responses.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body provides after-fix terminal and live Mattermost proof showing the 503 path replaced by normal handler responses.

Full review comments:

  • [P2] Add streamingMode to the dual-load account fixture — extensions/mattermost/src/mattermost/slash-state.dual-load.test.ts:10-15
    On current main, ResolvedMattermostAccount has a required streamingMode field, and the existing slash-state fixtures set it. This new fixture omits the field, so type/check gates will fail after rebase or merge; add streamingMode: "partial" or the intended mode to the returned object.
    Confidence: 0.88

Overall correctness: patch is incorrect
Overall confidence: 0.84

Acceptance criteria:

  • node scripts/run-vitest.mjs extensions/mattermost/src/mattermost/slash-state.dual-load.test.ts extensions/mattermost/src/mattermost/slash-state.test.ts
  • node scripts/crabbox-wrapper.mjs run --shell -- "pnpm check:changed"

What I checked:

Likely related people:

  • mukhtharcm: Authored the merged native Mattermost slash-command support that introduced the current slash-state and registerFull surfaces, and is assigned on the current PR. (role: feature owner; confidence: high; commits: b1b41eb44323; files: extensions/mattermost/index.ts, extensions/mattermost/src/mattermost/slash-state.ts)
  • eleqtrizit: Authored the merged slash callback validation refresh that recently changed slash-state tests and adjacent slash-http behavior. (role: recent area contributor; confidence: medium; commits: 9c0975c1c20e; files: extensions/mattermost/src/mattermost/slash-state.ts, extensions/mattermost/src/mattermost/slash-http.ts, extensions/mattermost/src/mattermost/slash-state.test.ts)
  • obviyus: Recent Mattermost bundled-entry routing work touched the plugin entry path involved in this loader split. (role: adjacent loader-path contributor; confidence: medium; commits: 17573d097b2f; files: extensions/mattermost/index.ts)

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

@ForceConstant

Copy link
Copy Markdown

Any updates on this?

@mukhtharcm mukhtharcm force-pushed the fix/mattermost-slash-command-503 branch from 4bd7742 to 2d6d560 Compare May 2, 2026 18:26
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 12, 2026
@openclaw-barnacle openclaw-barnacle Bot added triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. and removed proof: sufficient ClawSweeper judged the real behavior proof convincing. labels May 12, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 12, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 12, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 12, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 12, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 12, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 12, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 12, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 12, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 12, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 14, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 14, 2026
@openclaw-barnacle

Copy link
Copy Markdown

This assigned pull request has been automatically marked as stale after being open for 27 days.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label May 15, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 16, 2026
@openclaw-barnacle openclaw-barnacle Bot removed stale Marked as stale due to inactivity proof: sufficient ClawSweeper judged the real behavior proof convincing. labels May 17, 2026
@openclaw-barnacle

Copy link
Copy Markdown

This assigned pull request has been automatically marked as stale after being open for 27 days.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label May 17, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. P1 High-priority user-facing bug, regression, or broken workflow. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels May 19, 2026
@clawsweeper

clawsweeper Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

🔥 Warming up: real-behavior proof passed; findings, security review, or rank-up moves are still in progress.

Hatch command

Comment @clawsweeper hatch when this PR is hatchable.

Hatchability rules:

  • Merged PRs are hatchable.
  • Open PRs are hatchable when they are status: 👀 ready for maintainer look, status: 🚀 automerge armed, or labeled clawsweeper:automerge.
  • Closed unmerged PRs are hatchable only when one of those hatchable labels is still present in the durable record.
What is this egg doing here?
  • Eggs appear after the PR passes real-behavior proof. It is here for vibes, not verdicts: it does not change labels, ratings, merge decisions, or automation.
  • The shell reacts to review momentum: open follow-up work warms it up, re-review makes it wobble, and a clean final review lets it hatch.
  • Hatchability usually comes from sufficient real-behavior proof, no blocking P0/P1/P2 findings, no security attention needed, and clean correctness. A merged PR is already final, so merge makes the egg hatchable independently.
  • The hatch is seeded from this repository and PR number, so the same PR keeps the same creature; the reviewed head SHA can only change safe visual details.
  • Rarity is just collectible sparkle: 🥚 common, 🌱 uncommon, 💎 rare, ✨ glimmer, and 🌈 legendary.

@openclaw-barnacle openclaw-barnacle Bot removed the stale Marked as stale due to inactivity label May 20, 2026
@openclaw-barnacle

Copy link
Copy Markdown

This assigned pull request has been automatically marked as stale after being open for 27 days.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label May 20, 2026
@giodl73-repo giodl73-repo removed the triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. label May 21, 2026
@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. label May 21, 2026
@clawsweeper clawsweeper Bot added rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. and removed 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. labels May 21, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the stale Marked as stale due to inactivity label May 22, 2026
@openclaw-barnacle

Copy link
Copy Markdown

This assigned pull request has been automatically marked as stale after being open for 27 days.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added the stale Marked as stale due to inactivity label May 22, 2026
@openclaw-barnacle

Copy link
Copy Markdown

This assigned pull request has been automatically marked as stale after being open for 27 days.
Please add updates or it will be closed.

@barnacle-openclaw

Copy link
Copy Markdown

Closing due to inactivity.
If you believe this PR should be revived, post in #clawtributors on Discord to talk to a maintainer.
That channel is the escape hatch for high-quality PRs that get auto-closed.

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

Labels

channel: mattermost Channel integration: mattermost P1 High-priority user-facing bug, regression, or broken workflow. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. size: L stale Marked as stale due to inactivity 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.

4 participants