Skip to content

fix: import completed call logs#261

Merged
steipete merged 2 commits into
openclaw:mainfrom
dovocoder:fix-256
May 22, 2026
Merged

fix: import completed call logs#261
steipete merged 2 commits into
openclaw:mainfrom
dovocoder:fix-256

Conversation

@dovocoder
Copy link
Copy Markdown
Contributor

@dovocoder dovocoder commented May 22, 2026

Summary

Fixes #256 by importing completed WhatsApp call logs from the app-state/history paths that actually carry them, instead of relying only on live call signaling events.

What changed

  • Replay the regular app-state collection during sync so existing call-log records are emitted and stored idempotently.
  • Store HistorySync.callLogRecords when WhatsApp includes call logs in history sync payloads.
  • Decode app-state call records correctly:
    • startTime can be seconds, milliseconds, or microseconds
    • self identity prefers the linked-device LID for app-state call records
    • one-to-one records resolve to the peer chat, not the account’s own JID
  • Make call-event upserts correct previously imported rows for the same call ID, including timestamp/chat fixes.

Root cause

calls list mostly showed live offer events because completed call logs arrive as call-log records in WhatsApp app-state/history data. The regular app-state collection was not being replayed, so if WhatsApp had already advanced that collection before wacli knew how to store call logs, later delta syncs could not recover those records. The call-log parser also assumed millisecond timestamps and PN self identity, which made replayed records land under 1970/self-chat in local testing.

Local verification

Full local gate passed:

pnpm format:check && pnpm lint && pnpm test && pnpm build && git diff --check

Redacted live proof from a local store:

Before the fix, after sync:

{"success":true,"data":{"calls":null},"error":null}

After the fix, sync --once imported the same-day completed call as a structured call-log row:

{
  "chat_jid": "<peer>@s.whatsapp.net",
  "chat_name": "<redacted>",
  "sender_jid": "<self>@s.whatsapp.net",
  "sender_name": "<redacted>",
  "call_id": "0002...1BC",
  "event_type": "call_log",
  "direction": "outbound",
  "media": "audio",
  "outcome": "connected",
  "call_type": "regular",
  "duration_secs": 9,
  "timestamp": "2026-05-22T07:44:30Z",
  "participants": [
    {"jid": "<peer>@s.whatsapp.net", "outcome": "connected"}
  ]
}

This proves the missing completed-call case from #256: the imported row is no longer just an offer; it has the peer chat, real timestamp, duration, direction, media, and connected outcome.

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 22, 2026

Codex review: needs maintainer review before merge.

Latest ClawSweeper review: 2026-05-22 12:28 UTC / May 22, 2026, 8:28 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 branch imports completed WhatsApp call logs from history sync and regular app-state replay, updates call parsing/upsert identity handling, adds regression tests, and records a changelog entry.

Reproducibility: yes. Source inspection shows current main does not fetch the regular app-state collection or store HistorySync.CallLogRecords, and the PR body provides redacted live before/after output for the completed-call case.

PR rating
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Summary: The proof and regression tests are strong, and the remaining concern is a maintainer-owned default sync availability tradeoff rather than a discrete patch bug.

Rank-up moves:

  • Have a maintainer explicitly accept the default full regular app-state replay behavior or choose an explicit calls-history recovery path.
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 (live_output): The PR body includes redacted copied live output showing after-fix sync --once importing a completed call as a structured call_log row.

Risk before merge

  • Default sync --once now performs a full regular app-state fetch in addition to existing app-state delta fetches, which could increase runtime or delay idle exit for cron-style collectors on larger stores.
  • The live proof is useful but covers one redacted local store, so maintainers still need to decide whether the default replay cost is acceptable for all users.

Maintainer options:

  1. Accept default regular replay
    Maintainers can merge this as the default if completed-call recovery is worth the possible sync latency and idle-exit impact.
  2. Gate replay behind explicit recovery
    Keep ordinary sync behavior unchanged and expose full regular replay through a dedicated calls-history recovery flow if the default cost is too risky.
  3. Pause for broader live proof
    Ask for proof on a larger or slower store if maintainers need more confidence in sync duration before changing the default.

Next step before merge
No automated repair remains; the remaining action is maintainer judgment on the default full regular app-state fetch risk.

Security
Cleared: No concrete security or supply-chain regression was found in the diff.

Review details

Best possible solution:

Land the call-log import after maintainers explicitly accept the default regular replay cost or choose a narrower calls-history recovery path.

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

Yes. Source inspection shows current main does not fetch the regular app-state collection or store HistorySync.CallLogRecords, and the PR body provides redacted live before/after output for the completed-call case.

Is this the best way to solve the issue?

Mostly yes. App-state and history call-log records are the right source for completed-call metadata; the remaining solution-fit question is whether full regular replay belongs in default sync or behind an explicit recovery path.

Label justifications:

  • P2: This is a normal-priority call-log correctness fix with focused scope and a linked user report, but it is not an emergency runtime failure.
  • merge-risk: 🚨 availability: The diff adds a full regular app-state fetch to default sync, which could lengthen sync --once or affect idle-exit behavior.
  • rating: 🐚 platinum hermit: Current PR rating is 🐚 platinum hermit because proof is 🦞 diamond lobster, patch quality is 🐚 platinum hermit, and The proof and regression tests are strong, and the remaining concern is a maintainer-owned default sync availability tradeoff rather than a discrete patch bug.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body includes redacted copied live output showing after-fix sync --once importing a completed call as a structured call_log row.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes redacted copied live output showing after-fix sync --once importing a completed call as a structured call_log row.

What I checked:

  • Current main app-state fetch scope: Current main only fetches regular_high and regular_low app-state deltas after connect, so the central regular collection path used by the PR is not present on main. (internal/app/sync.go:180, 20e114aa9df2)
  • Current main history sync path: Current main handles history conversations and messages but does not iterate HistorySync.CallLogRecords, which matches the linked report's completed-call gap. (internal/app/sync_events.go:284, 20e114aa9df2)
  • PR adds regular app-state replay: The PR changes sync to fetch regular_high, regular_low, and regular, using fullSync=true for regular; this is the useful fix and the availability tradeoff. (internal/app/sync.go:181, a407a2bc621c)
  • PR stores history call-log records: The PR calls storeHistoryCallLogRecords from history sync and parses each CallLogRecord with linked LID and PN identities before storing it as a call event. (internal/app/sync_events.go:311, a407a2bc621c)
  • PR hardens call-log parsing: The PR adds exported ParseCallLogRecord, recognizes seconds/milliseconds/microseconds timestamps, ignores self group JIDs for one-to-one calls, and compares both PN and LID identities. (internal/wa/calls.go:141, a407a2bc621c)
  • Regression coverage: The PR adds tests for history call-log records, regular app-state call-log replay, PN identity for live call offers, timestamp units, self identity handling, and duplicate call IDs across chats. (internal/app/sync_test.go:344, a407a2bc621c)

Likely related people:

  • Peter Steinberger: Blame and git log -S tie the current call parsing, call_events storage, and sync app-state surface to the v0.10.0 release commit, and the PR timeline shows a later hardening fixup on the same call-log import path. (role: introduced behavior and recent fixup author; confidence: high; commits: eb3bd3c44844, a407a2bc621c; files: internal/wa/calls.go, internal/store/calls.go, internal/app/sync.go)
  • Dovocoder: Current main includes recent sync-events work in commit 20e114a, and the first PR commit implements the completed call-log import path under review. (role: recent adjacent contributor; confidence: medium; commits: 20e114aa9df2, dc545b6a7cf8; files: internal/app/sync_events.go, internal/app/sync.go, internal/wa/calls.go)

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

@dovocoder dovocoder marked this pull request as ready for review May 22, 2026 10:52
@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 priority bug or improvement with limited blast radius. merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. labels May 22, 2026
@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 22, 2026

ClawSweeper PR egg

✨ Hatched: ✨ glimmer Sunspot Lint Imp

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.

Rarity: ✨ glimmer.
Trait: sparkles near resolved comments.
Image traits: location review cove; accessory release bell; palette rose quartz and slate; mood sparkly; pose stepping out of a freshly hatched shell; shell smooth pearl shell; lighting gentle morning glow; background small green status lights.
Share on X: post this hatch
Copy: My PR egg hatched a ✨ glimmer Sunspot Lint Imp in ClawSweeper.

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.

@dovocoder dovocoder changed the title fix: import historical call events fix: import completed call logs May 22, 2026
@dovocoder
Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 22, 2026

🦞🧹
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 proof: sufficient Contributor real behavior proof is sufficient. 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. 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 May 22, 2026
@dovocoder
Copy link
Copy Markdown
Contributor Author

Addressed the ClawSweeper finding.

What changed in the updated single commit:

  • live call signaling events now use the PN LinkedJID identity for ParseLiveCallEvent direction checks
  • app-state/history call-log records still use the LID-first identity path for CallLogRecord parsing
  • added regression coverage for an outbound live call offer when LinkedLID is present, so it remains direction: outbound

Acceptance checks passed:

go test ./internal/app ./internal/wa ./internal/store
pnpm format:check
git diff --check

@clawsweeper re-review

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 22, 2026

🦞🧹
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: 🐚 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. and removed 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. labels May 22, 2026
@steipete
Copy link
Copy Markdown
Collaborator

Pushed a maintainer fixup in a407a2b.

What changed:

  • scoped call-event correction updates to one existing row in the same chat, avoiding cross-chat movement for duplicate call IDs
  • passed both linked LID and linked PN identities into app-state/history call-log parsing
  • added regressions for duplicate call IDs across chats and PN/LID self matching

Local proof:

  • go test ./internal/app ./internal/wa ./internal/store
  • pnpm format:check && pnpm lint && pnpm test && pnpm build && git diff --check
  • autoreview local patch clean: no accepted/actionable findings

@clawsweeper re-review

@clawsweeper
Copy link
Copy Markdown

clawsweeper Bot commented May 22, 2026

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

@steipete steipete merged commit 12c8d8a into openclaw:main May 22, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

call_events only captures 'offer' — no duration/outcome from sync --once

2 participants