6.7 KiB
GCall Call Review Template
Use this file as the repeatable checklist and logging format for new group-call diagnostics exports.
Related docs:
Primary runtime fields:
audioSurfaceRuntimeDiagnostics.receiveEngine.livePolicyProfilesBySourceaudioSurfaceRuntimeDiagnostics.receiveEngine.livePolicyStateBySourceaudioSurfaceRuntimeDiagnostics.receiveEngine.profileTransitionsrecentWindowTrendsrecentWindowSummaryliveMetricsSnapshotaudioSurfaceRuntimeDiagnostics.receiveEngine.playouts
Purpose
Use this template to answer the same questions for every new call:
- What profile was each side in?
- Did that profile match the actual user symptom?
- Was the call bad because of:
- state/key/authority correctness
- startup playout readiness
- or receive-policy quality
- What single profile or subsystem should be tuned next?
This is meant to stop ad hoc analysis and make profile tuning cumulative.
Review Workflow
For each new call:
- Confirm both exports belong to the same room.
- Record user-reported symptom first.
- Record what each side’s dominant profile was.
- Check whether classification matched the symptom.
- Decide whether the next fix belongs to:
- a specific receive profile
- startup playout path
- failover/key/state correctness
- or baseline policy
- Only propose a new profile if the call does not fit existing ones cleanly.
Quick Triage
Use this before deeper tuning:
packetsDroppedPendingDecrypt > 0- likely decrypt/key path issue
packetsDroppedDecodeFailure > 0- likely decode/key/session mismatch
transportTriadSnapshot.*HighWater > 0- possible queue/backpressure issue
jitterBufferedFrames > 0andjitterHasReadyFrame: falsewith no real playout- likely startup/playout-ready issue
- no correctness/path errors, but bad profile activation
- likely receive-policy tuning issue
Per-Call Summary Template
Copy this section for each new call:
## Call: <date / short label>
Room:
- `<room id>`
Files:
- Side A: `<path>`
- Side B: `<path>`
User symptom:
- `<plain description>`
High-level verdict:
- `<good / mixed / bad / catastrophic>`
- `<one sentence summary>`
Not the problem:
- `<decrypt / decode / queue / failover / startup / etc.>`
Primary next target:
- `<profile or subsystem>`
Side-By-Side Table Template
| Side | Role | Dominant Profile | User-Bad? | avgPcmBufferedMs | missingFrames | concealmentTicks | UnderTarget | Rate<0.97 | Adaptive Mode | Notes |
| --- | --- | --- | --- | ---: | ---: | ---: | ---: | ---: | --- | --- |
| A | `<root/standby/participant>` | `<profile>` | `<yes/no>` | `<n>` | `<n>` | `<n>` | `<n>` | `<n>` | `<mode>` | `<short note>` |
| B | `<root/standby/participant>` | `<profile>` | `<yes/no>` | `<n>` | `<n>` | `<n>` | `<n>` | `<n>` | `<mode>` | `<short note>` |
Classification Check
For each side:
### Side A
Expected profile from symptom:
- `<profile>`
Actual exported profile:
- `<profile>`
Did classification match?
- `<yes/no/partly>`
If no:
- `<what looked wrong>`
- `<whether to retune selector or create a new profile>`
Trend Check
Use recentWindowTrends to decide whether the call was:
- flat-bad the whole sampled window
- gradually degrading
- hit by a discrete event
- oscillating between modes
Prefer the windowed delta fields when judging whether the call is still bad now:
missingFramesDeltaconcealmentTicksDeltapacketsDroppedPendingDecryptDeltapacketsDroppedDecodeFailureDeltaoutboundNoTargetSkipsDelta
Use recentWindowSummary for a quick whole-export-window read, then inspect the raw
trend rows when a side improved or degraded during the call.
Use profileTransitions and livePolicyStateBySource to answer:
- when a profile changed
- what metrics caused the transition
- whether a profile is stuck because hold timers or clear conditions remain active
- what target/floor/extra-hold values were actually applied
Template:
## Trend Read
Side A:
- `<flat-bad / gradual / discrete / oscillating>`
- Reasons seen:
- `<entered-recovery>`
- `<concealment-spike>`
- `<missing-frames-spike>`
- `<none>`
Side B:
- `<flat-bad / gradual / discrete / oscillating>`
- Reasons seen:
- `<...>`
Decision Rules
Use these rules to pick the next change:
- If classification was correct and the profile stayed active too long:
- tune that profile’s hold and clear conditions first
- If classification was correct but the immediate quality was still bad:
- tune that profile’s target boost and floor
- If classification was wrong:
- tune selector entry logic before touching target sizes
- If multiple unrelated profiles failed in the same batch of calls:
- inspect baseline policy and recovery hysteresis
- If state/key/failover/startup is implicated:
- do not tune receive profiles first
New Profile Gate
Only add a new profile if all are true:
- the failure shape recurs
- it does not fit an existing profile cleanly
- forcing it into an existing profile would likely worsen other calls
- the symptom can be described as a stable class, not a one-off export quirk
Record the proposal like this:
## New Profile Proposal
Name:
- `<candidate profile name>`
Why existing profiles were insufficient:
- `<reason>`
Recurring evidence:
- `<call ids or export labels>`
Distinct signals:
- `<metrics / trends / user symptom>`
Risk if folded into an existing profile:
- `<what would likely regress>`
Batch Scoreboard Template
Use this when reviewing multiple calls on one build:
| Call | Side | Dominant Profile | User-Bad? | Classification Correct? | Main Issue Class | Next Action |
| --- | --- | --- | --- | --- | --- | --- |
| `<call id>` | A | `<profile>` | `<yes/no>` | `<yes/no/partly>` | `<receive/startup/key/etc.>` | `<tune X / no change>` |
| `<call id>` | B | `<profile>` | `<yes/no>` | `<yes/no/partly>` | `<receive/startup/key/etc.>` | `<tune X / no change>` |
Success Criteria
Treat a build as materially improved when a batch of ordinary calls shows:
- most sides spend most time in
clean-low-latency - bad profiles are brief, not dominant for the whole call
recentWindowTrendsare mostly quietmissingFramesandconcealmentTicksare modest- no repeated startup/failover/key regressions
- user reports align with the profile diagnostics
Notes
- Prefer profile-specific changes over global baseline changes.
- Prefer changing one profile at a time unless several failure classes regress together.
- Keep short labels for calls consistent so future comparisons are easy.