Skip to content

fix(gateway): dedupe TTS status provider diagnostics [AI-assisted]#93868

Open
harjothkhara wants to merge 3 commits into
openclaw:mainfrom
harjothkhara:codex/81355-tts-status-provider-diagnostics
Open

fix(gateway): dedupe TTS status provider diagnostics [AI-assisted]#93868
harjothkhara wants to merge 3 commits into
openclaw:mainfrom
harjothkhara:codex/81355-tts-status-provider-diagnostics

Conversation

@harjothkhara

@harjothkhara harjothkhara commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #81355.

This keeps the already-merged applyPluginAutoEnable cache fix intact and addresses the remaining tts.status Gateway hot path. The status handler now yields once before synchronous provider diagnostics, builds the config-aware speech provider inventory once, and reuses that same inventory/configured-state pass for both providerStates and fallback filtering.

Best-fix rationale: this preserves the existing tts.status response shape and config-aware provider inventory contract, avoids changing the synchronous SpeechProviderPlugin.isConfigured SDK contract, and keeps the blast radius to tts.status plus the provider-order helper.

Real behavior proof

Behavior addressed: tts.status no longer performs duplicate provider inventory/configured-state work before responding, and it yields before provider diagnostics so sibling Gateway RPCs can run.

Real environment tested: Local OpenClaw source checkout on this PR branch with an isolated real Gateway process, temp HOME/state/config, normal Gateway WebSocket client, real speech-provider plugin metadata loading enabled, and channel/background sidecars skipped. This was not a mocked handler call.

Exact steps or command run after this patch:

  • node --import tsx --input-type=module -e '<isolated Gateway tts.status proof using test/helpers/openclaw-test-instance.ts and src/gateway/test-helpers.e2e.ts>'
  • The proof config used messages.tts.provider: "openai" with messages.tts.providers.openai.apiKey: "test-openai-key" and messages.tts.providers.microsoft: {}; the Gateway env removed OPENCLAW_SKIP_PROVIDERS, set OPENCLAW_TEST_MINIMAL_GATEWAY=0, and kept channel sidecars skipped through the existing test helper.
  • node scripts/run-vitest.mjs src/gateway/server-methods/tts.test.ts packages/speech-core/src/tts.test.ts src/tts/provider-registry.test.ts src/plugins/contracts/tts.contract.test.ts src/plugins/capability-provider-runtime.test.ts
  • git diff --check
  • gh pr checks 93868 --repo openclaw/openclaw --watch=false

Evidence after fix:

{
  "ok": true,
  "branch": "codex/81355-tts-status-provider-diagnostics",
  "providerIds": ["microsoft", "openai"],
  "secondProviderIds": ["microsoft", "openai"],
  "providerStateCount": 2,
  "configuredProviders": ["microsoft", "openai"],
  "enabled": true,
  "provider": "openai",
  "fallbackProvider": "microsoft",
  "fallbackProviders": ["microsoft"],
  "prefsPathSuffix": ".openclaw/settings/tts.json",
  "firstElapsedMs": 320,
  "secondElapsedMs": 1,
  "totalElapsedMs": 6527,
  "siblingTurnBeforeCompletion": true,
  "stableProviderStates": true
}

Focused Vitest proof also passed 5 shards. The active-registry probe returned ok: true, elapsedMs: 3, immediateAtRespond: true, and providerStates: ["openai", "acme-speech"]. Current PR checks are green, including Critical Quality (gateway-runtime-boundary), check-lint, check-additional-boundaries-a, Real behavior proof, and the Node/core CI shards selected for this diff.

Observed result after fix: In a running Gateway, tts.status responds successfully over the normal WebSocket RPC path, reports real provider diagnostics for configured speech providers, preserves the public status shape and configured provider, returns the expected fallback list, and keeps provider diagnostics stable across repeated calls. The local sibling event-loop turn completed before the status call finished, matching the intended pre-diagnostics yield.

What was not tested: No live Control UI browser/dashboard session and no external TTS synthesis request were exercised. The real Gateway proof used fake local provider config only to satisfy configured-state diagnostics and did not call external provider APIs.

Tests and validation

  • node --import tsx --input-type=module -e '<isolated Gateway tts.status proof using test/helpers/openclaw-test-instance.ts and src/gateway/test-helpers.e2e.ts>'
  • node scripts/run-vitest.mjs src/gateway/server-methods/tts.test.ts packages/speech-core/src/tts.test.ts src/tts/provider-registry.test.ts src/plugins/contracts/tts.contract.test.ts src/plugins/capability-provider-runtime.test.ts
  • git diff --check
  • gh pr checks 93868 --repo openclaw/openclaw --watch=false
  • Local structured autoreview: clean after addressing accepted findings

Risk checklist

  • Preserves public tts.status payload shape
  • Preserves config-aware provider inventory behavior
  • Does not change plugin SDK isConfigured sync contract
  • Does not touch the already-shipped applyPluginAutoEnable cache path
  • No config, migration, dependency, lockfile, or docs surface changed

Current review state

Stage 2 blind review completed:

  • Reviewer A: no blocking runtime/correctness findings
  • Reviewer B: raised a provider-inventory contract risk; fixed by preserving listSpeechProviders(cfg) as the status inventory source

Autoreview completed cleanly after two accepted findings were fixed:

  • typed the Gateway test provider mock to avoid never[]
  • normalized inventory-backed provider alias matching

AI-assisted: this PR was implemented with Codex assistance; the human author should review and own the final diff before marking ready.

@openclaw-barnacle openclaw-barnacle Bot added triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI. gateway Gateway runtime size: M labels Jun 17, 2026
@harjothkhara
harjothkhara marked this pull request as ready for review June 17, 2026 02:34
@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
@clawsweeper

clawsweeper Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 16, 2026, 7:55 PM ET / 23:55 UTC.

Summary
The PR makes tts.status yield before synchronous provider diagnostics, reuses one config-aware provider inventory and configured-state pass, and extends speech-core ordering and configuration helpers to accept prepared providers.

PR surface: Source +47, Tests +151. Total +198 across 4 files.

Reproducibility: yes. at source level: the linked issue provides a concrete cold-start Gateway fanout procedure and the synchronous provider diagnostics explain the reported event-loop occupancy. The PR also supplies an after-fix real Gateway run, although this review did not independently execute the untrusted branch.

Review metrics: 1 noteworthy metric.

  • Configured-state evaluation: 2 consumer passes reduced to 1 cached pass. This is the central hot-path improvement and must remain intact through conflict resolution.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #81355
Summary: This PR is the candidate fix for the remaining TTS-status cause in the canonical cold-start fanout issue; the independent plugin auto-enable cause was already merged separately.

Members:

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

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

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

Rank-up moves:

  • Rebase onto current main and rerun the focused speech-core/Gateway tests plus the isolated Gateway proof on the resolved head.

Risk before merge

  • [P1] The current head has a merge conflict with current main and must be rebased before its exact merged behavior can be reviewed.
  • [P2] Conflict resolution across the shared speech-core helper must preserve config-aware provider inventory, alias ordering, and each provider's canonical diagnostic timeout.

Maintainer options:

  1. Rebase without semantic drift (recommended)
    Resolve the current-main conflicts while retaining the prepared-inventory ordering and canonical timeout behavior, then rerun exact-head validation.
  2. Pause if the helper changed upstream
    If current main has established a different provider-order or diagnostic contract, pause this PR and adapt the fix to that canonical path before landing.

Next step before merge

  • The contributor should rebase and resolve the current-main conflict; maintainers can review the resulting exact head once tests and real Gateway proof are refreshed.

Security
Cleared: The patch changes internal TypeScript runtime and tests without adding dependency, workflow, secret, permission, download, package-resolution, or supply-chain surface.

Review details

Best possible solution:

Rebase onto current main while preserving the one-pass inventory, alias behavior, canonical provider timeouts, and unchanged tts.status payload, then rerun the focused tests and isolated Gateway proof on the resolved head.

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

Yes at source level: the linked issue provides a concrete cold-start Gateway fanout procedure and the synchronous provider diagnostics explain the reported event-loop occupancy. The PR also supplies an after-fix real Gateway run, although this review did not independently execute the untrusted branch.

Is this the best way to solve the issue?

Yes: reusing one config-aware provider inventory inside tts.status avoids duplicate work at the correct owner boundary without changing the synchronous plugin contract or response shape. The implementation still needs a clean current-main rebase before merge.

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add merge-risk: 🚨 compatibility: The PR changes shared provider ordering and timeout-aware diagnostics, so conflict resolution could alter existing provider selection or status behavior.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body contains after-fix output from an isolated real Gateway process over the normal WebSocket RPC path, demonstrating stable provider diagnostics, expected fallback behavior, and sibling event-loop progress.
  • remove rating: 🦐 gold shrimp: Current PR rating is rating: 🐚 platinum hermit, 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:

  • P2: This is a bounded Gateway responsiveness fix with limited TTS scope and no evidence of an outage or data loss.
  • merge-risk: 🚨 compatibility: The PR changes shared provider ordering and timeout-aware diagnostics, so conflict resolution could alter existing provider selection or status behavior.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body contains after-fix output from an isolated real Gateway process over the normal WebSocket RPC path, demonstrating stable provider diagnostics, expected fallback behavior, and sibling event-loop progress.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body contains after-fix output from an isolated real Gateway process over the normal WebSocket RPC path, demonstrating stable provider diagnostics, expected fallback behavior, and sibling event-loop progress.
Evidence reviewed

PR surface:

Source +47, Tests +151. Total +198 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 2 66 19 +47
Tests 2 161 10 +151
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 4 227 29 +198

What I checked:

  • Prior blocker resolved: The current head delegates prepared-provider configuration checks through the canonical helper and adds coverage proving defaultTimeoutMs is preserved, addressing the previous review finding. (packages/speech-core/src/tts.test.ts:484, 75b7f09298d9)
  • Single diagnostics pass: The Gateway handler builds one speech-provider inventory, caches each provider's configured state, and reuses both for provider states and fallback filtering. (src/gateway/server-methods/tts.ts:53, 75b7f09298d9)
  • Shared ordering contract: The speech-core helper accepts an optional prepared inventory while retaining config-aware alias normalization and deterministic auto-selection ordering. (packages/speech-core/src/tts.ts:1029, 75b7f09298d9)
  • Real Gateway proof: The PR body reports an isolated real Gateway WebSocket run with stable provider states, the expected primary and fallback providers, and a sibling event-loop turn completing before tts.status. (75b7f09298d9)
  • Current merge state: The hydrated GitHub state reports mergeable: false and mergeableState: dirty against an advanced current main, so the reviewed patch cannot presently land unchanged. (b1eaf536728a)
  • Feature provenance: Gateway TTS and speech-provider architecture history repeatedly traces through the core move, provider registration, fast-path work, and plugin-owned configuration refactor. (src/gateway/server-methods/tts.ts:1, d9a467f)

Likely related people:

  • steipete: History repeatedly connects this person to the Gateway TTS path and speech-provider architecture, including the core move, provider registration, fast-path work, and plugin-owned configuration refactor. (role: feature owner and recent area contributor; confidence: high; commits: d9a467f, fc0e303, 662031a; files: src/gateway/server-methods/tts.ts, packages/speech-core/src/tts.ts)
  • Glucksberg: The history for the TTS core move credits this person with the original feature contribution, making them relevant to the established behavior contract. (role: original feature contributor; confidence: medium; commits: d9a467f; files: src/gateway/server-methods/tts.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 (6 earlier review cycles)
  • reviewed 2026-06-21T05:18:20.436Z sha b249647 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-01T07:02:57.595Z sha b249647 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-12T21:53:41.529Z sha f10f552 :: needs changes before merge. :: [P1] Preserve the canonical provider timeout in the shared check
  • reviewed 2026-07-12T22:01:32.011Z sha f10f552 :: needs changes before merge. :: [P1] Preserve the canonical provider timeout in the shared check
  • reviewed 2026-07-16T21:27:41.020Z sha 75b7f09 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-16T22:11:04.136Z sha 75b7f09 :: needs changes before merge. :: [P2] Yield before the synchronous status setup

@harjothkhara
harjothkhara force-pushed the codex/81355-tts-status-provider-diagnostics branch from c39c811 to b249647 Compare June 20, 2026 06:03
@xuwei-xy

Copy link
Copy Markdown

I think the fix would involve adjusting ui. Would that work for your use case?

@harjothkhara

Copy link
Copy Markdown
Contributor Author

Fixed both CI failures: check-lint (no-promise-executor-return) and check-additional-boundaries-a (stale-base; clean after rebasing onto main).

On the proof gate: this is a no-output perf change — it dedupes the tts.status provider scan (twice → once) and yields once before diagnostics, so the response is byte-identical. The dedup + yield run against the real handler in tts.test.ts (only the provider list is stubbed). The gate is non-blocking, so proof: override or merge-as-is works — happy to add a Crabbox tts.status capture if you'd prefer.

@clawsweeper clawsweeper Bot added status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 20, 2026
@harjothkhara

Copy link
Copy Markdown
Contributor Author

Added the missing real Gateway proof to the PR body.

Proof summary: I started an isolated source Gateway on this PR branch, removed OPENCLAW_SKIP_PROVIDERS, disabled the minimal test Gateway path, connected with the normal Gateway WebSocket client, and called tts.status twice. The live response exposed providerStates for microsoft and openai, preserved provider: "openai", returned fallbackProviders: ["microsoft"], stayed stable across the second call, and recorded siblingTurnBeforeCompletion: true.

No code changes in this refresh. gh pr checks 93868 --repo openclaw/openclaw --watch=false is green on the current PR head.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 21, 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.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. labels Jun 21, 2026
@clawsweeper clawsweeper Bot added the merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. label Jul 6, 2026
@harjothkhara
harjothkhara force-pushed the codex/81355-tts-status-provider-diagnostics branch from b249647 to f10f552 Compare July 12, 2026 21:47
@clawsweeper clawsweeper Bot added 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: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. merge-risk: 🚨 other 🚨 Merging this PR has meaningful risk outside the owned taxonomy. labels Jul 12, 2026
@harjothkhara
harjothkhara force-pushed the codex/81355-tts-status-provider-diagnostics branch from f10f552 to 571e1bc Compare July 16, 2026 21:15
@harjothkhara
harjothkhara force-pushed the codex/81355-tts-status-provider-diagnostics branch from 571e1bc to 95f3db5 Compare July 16, 2026 21:17
@harjothkhara

harjothkhara commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the current-head timeout-semantics blocker and rebased onto current main.

  • exact head: 75b7f09298d968b4e2839d5dbc2ea282934bae0f
  • tts.status still prepares one provider inventory/configured-state pass, but now delegates each prepared provider check to the canonical speech-core timeout resolver
  • added regression coverage proving a prepared provider keeps its defaultTimeoutMs
  • focused proof: node scripts/run-vitest.mjs src/gateway/server-methods/tts.test.ts packages/speech-core/src/tts.test.ts -- --reporter=dot (2 shards, 52 tests passed)
  • targeted oxfmt, oxlint, git diff --check, and full branch autoreview are clean
  • fixed the exact-head check-test-types failure by asserting the indexed Gateway handler before invocation; the focused Gateway shard and a fresh autoreview pass clean
  • private grogu+mario cross-review was attempted but blocked by the workspace data-export policy; no bypass was used

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 16, 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.

@harjothkhara

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 16, 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.

Re-review progress:

@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. 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. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. 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. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. 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. labels Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: M status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. triage: mock-only-proof Candidate: PR proof only shows tests, mocks, snapshots, lint, typecheck, or CI.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: First-load RPC fanout: tts.status monopolizes event loop ~1.5s and applyPluginAutoEnable recomputes 8× per fanout

2 participants