fix(voice-call): resolve completed calls from the persisted store on status misses#99797
Conversation
|
Codex review: needs changes before merge. Reviewed July 5, 2026, 2:51 PM ET / 18:51 UTC. Summary PR surface: Source +25, Tests +202, Docs +1. Total +228 across 9 files. Reproducibility: yes. Source inspection shows current main drops terminal calls from active maps while status paths only check those active maps; I did not run a live carrier call in this read-only review, but the PR discussion includes live Gateway proof. Review metrics: 1 noteworthy metric.
Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Keep the centralized active-first retained-store fallback and focused tests, remove the release-owned changelog edit, and let the linked issue close after this PR merges. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows current main drops terminal calls from active maps while status paths only check those active maps; I did not run a live carrier call in this read-only review, but the PR discussion includes live Gateway proof. Is this the best way to solve the issue? Yes. Centralizing an active-first retained-store lookup at the manager/store boundary is the narrowest maintainable fix for the status miss; the remaining issue is release-process cleanup, not runtime design. Full review comments:
Overall correctness: patch is correct AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 3f380635f59b. Label changesLabel justifications:
Evidence reviewedPR surface: Source +25, Tests +202, Docs +1. Total +228 across 9 files. View PR surface stats
Acceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
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
Review history (9 earlier review cycles; latest 8 shown)
|
9558d31 to
f39060a
Compare
|
Addressed the review feedback:
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
8a648d2 to
5028336
Compare
|
Maintainer fixup and exact-head proof complete at
No known proof gaps for this status-only fix. Transcript retrieval remains a separate product/API concern. |
5028336 to
da691d0
Compare
|
Exact-head follow-up after the main resync:
Land-ready at the exact reviewed head. |
da691d0 to
47c3ba8
Compare
|
Exact-head land-ready recheck for
Known gaps: none for the changed surface. |
3d175b4 to
5c82305
Compare
…status misses
get_status, the legacy status mode, and the voicecall.status gateway method
only consulted the in-memory call manager. Once a call was evicted (finalize,
gateway restart, or max-duration expiry) they reported { found: false } even
though the full record remained on disk. Fall back to the persisted call
history and resolve the NEWEST matching snapshot — history is oldest-first, so
a forward find() returns a stale record (the regression in the prior attempt).
Closes openclaw#96586
Co-Authored-By: Claude Fable 5 <[email protected]>
Avoids the typescript(unbound-method) lint rule that flags referencing a typed method (`runtimeStub.manager.getCallHistory`) as an unbound value. Bracket access matches the existing mock-assertion pattern in this file (e.g. `runtimeStub.manager["sendDtmf"]`). Co-Authored-By: Claude Fable 5 <[email protected]>
The local CLI `voicecall status` gateway-unavailable fallback only consulted
the in-memory manager, so a completed/evicted call still returned
{ found: false } even though the gateway/tool/legacy status paths now fall
back to the persisted store. Align this fourth status reader: consult
getCallByProviderCallId in addition to getCall, and on an active miss resolve
the NEWEST matching persisted snapshot via getCallHistory(100) +
toReversed().find(...) (history is oldest-first), mirroring the gateway/tool
paths. Return shape is unchanged.
Per review on openclaw#96586 (align CLI status before merge).
Co-Authored-By: Claude Fable 5 <[email protected]>
Co-authored-by: 曾文锋0668000834 <[email protected]>
5c82305 to
9db0aab
Compare
|
Exact-head land-ready recheck for
Known gaps: none for the changed surface. |
|
Merged via squash.
|
…status misses (openclaw#99797) * fix(voice-call): resolve completed calls from the persisted store on status misses get_status, the legacy status mode, and the voicecall.status gateway method only consulted the in-memory call manager. Once a call was evicted (finalize, gateway restart, or max-duration expiry) they reported { found: false } even though the full record remained on disk. Fall back to the persisted call history and resolve the NEWEST matching snapshot — history is oldest-first, so a forward find() returns a stale record (the regression in the prior attempt). Closes openclaw#96586 Co-Authored-By: Claude Fable 5 <[email protected]> * test(voice-call): use bracket access for mocked getCallHistory assertion Avoids the typescript(unbound-method) lint rule that flags referencing a typed method (`runtimeStub.manager.getCallHistory`) as an unbound value. Bracket access matches the existing mock-assertion pattern in this file (e.g. `runtimeStub.manager["sendDtmf"]`). Co-Authored-By: Claude Fable 5 <[email protected]> * ci: re-trigger QA Smoke (transient build-OOM, also failing main run 28695162780) * fix(voice-call): resolve persisted calls in the CLI status fallback too The local CLI `voicecall status` gateway-unavailable fallback only consulted the in-memory manager, so a completed/evicted call still returned { found: false } even though the gateway/tool/legacy status paths now fall back to the persisted store. Align this fourth status reader: consult getCallByProviderCallId in addition to getCall, and on an active miss resolve the NEWEST matching persisted snapshot via getCallHistory(100) + toReversed().find(...) (history is oldest-first), mirroring the gateway/tool paths. Return shape is unchanged. Per review on openclaw#96586 (align CLI status before merge). Co-Authored-By: Claude Fable 5 <[email protected]> * refactor(voice-call): centralize persisted status lookup Co-authored-by: 曾文锋0668000834 <[email protected]> --------- Co-authored-by: Claude Fable 5 <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
What Problem This Solves
Fixes an issue where voice-call status lookups reported
{ found: false }for calls that had completed successfully and had a full transcript persisted to disk. Once a call was evicted from the in-memory call manager (after finalize, a gateway restart, or max-duration expiry), the lookups only checked memory and never fell back to the persisted store, so the agent/operator could not retrieve the conversation.Why This Change Was Made
All FOUR status-lookup sites now fall back to the persisted call history when the in-memory manager has no entry, resolving the NEWEST matching snapshot:
voicecall.statusgateway method,voice_calltoolget_statusaction,mode: "status"tool branch, andvoicecall statusgateway-unavailable fallback.History is returned oldest-first, so the lookup uses
toReversed().find(...)— a forwardfind()would return a stale/older snapshot. This mirrors the existingdescribeHistoricalCallhelper. The CLI fallback previously consulted onlygetCall(callId)(narrower than the gateway path), so it now also consultsgetCallByProviderCallId, aligning all four readers.Per review on #96586: the CLI path must agree with the gateway/tool paths, so the CLI fallback is included here rather than split out. Note the existing stalled PR #96624 takes the same direction but selects the oldest snapshot via
events.find(); this change resolves the newest snapshot instead.User Impact
Operators and agents can retrieve the status and transcript of completed voice calls after they leave the in-memory manager (e.g. after a gateway restart or enough time has passed), from the tool, the gateway, or the CLI — instead of a dead-end
{ found: false }.Evidence
extensions/voice-call/index.test.ts: two regression tests — newest snapshot wins over an olderringingrecord;{ found: false }when absent.extensions/voice-call/src/cli.test.ts: two integration tests drive the realvoicecall status --call-id ... --jsoncommand with the gateway unavailable (ECONNREFUSED) and an evicted call — asserting the CLI fallback resolves the newest persisted snapshot (state: completed) and reports{ found: false }when neither active nor persisted. This exercises the actual CLI action end-to-end (only the gateway transport and the in-memory manager are stubbed).pnpm test:extension voice-call:index.test.ts41/41 andcli.test.ts10/10 pass. The full extension suite only has pre-existing WindowsEPERMteardown flakes insrc/manager/events.test.ts(temp-dirfs.rmSync), unrelated to this change.🤖 AI-assisted. Generated with Claude Code.
Closes #96586