Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions PRODUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ Default register when a command does not name a surface: **product**. The viewer

## Users

Short note: viewer polling and WDA heavy-tail

The viewer's periodic /api/phone poll can trigger a WDA "heavy-tail" wedge on some devices (TikTok For You feed). By default the viewer no longer polls /api/phone periodically; enable it with VIEWER_PHONE_POLL_SECONDS in .env (seconds, 0 = disabled). See docs/VIEWER_PHONE_POLL.md for guidance and log-collection steps.

## Users

**The operator** is a solo developer running SideTap against their own real iPhone, on their own Windows PC, with no Mac and no paid Apple developer account. They are not moving through a sales funnel and they are not an IT admin managing a device fleet. They are one person who just told an LLM agent to do something on their phone (read a text, open an app, send a reply) and now has to watch it happen.

- **On the viewer**, the operator is mid-session with divided attention: half watching a live phone screen, half doing something else, until the moment the agent does something wrong. At that moment their entire job becomes hitting STOP before the next action lands. Supervision with a fast exit is the primary task every time this screen is open, not configuration or exploration.
Expand Down
20 changes: 20 additions & 0 deletions docs/VIEWER_PHONE_POLL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Viewer /api/phone polling

Problem

Some apps (notably TikTok's For You feed) can cause WDA to enter a "heavy-tail" state: calls that resolve the active application (e.g. /wda/activeAppInfo) may hang indefinitely and queue every other request. The viewer previously polled /api/phone every 10s; that poll itself can trigger a wedge.

Mitigation

- The viewer no longer polls /api/phone by default. Use VIEWER_PHONE_POLL_SECONDS in .env to re-enable periodic polling when you need it (example: VIEWER_PHONE_POLL_SECONDS=10).
- Recommended default: 0 (disabled). The viewer still fetches /api/phone once on page load.

How to test

1. Set VIEWER_PHONE_POLL_SECONDS=0 in .env or leave unset; restart the viewer.
2. Reproduce the TikTok wedge (follow repro script). With the poll disabled, leaving the viewer open should not trigger a wedge by itself.
3. To re-enable polling for comparison, set VIEWER_PHONE_POLL_SECONDS=10, restart the viewer, and observe whether the viewer-originated polls correlate with hangs.

Notes

This is a short-term mitigation. The real upstream fix is to bound WDA's active-application/snapshot calls (see appium/WebDriverAgent#1210). The viewer change reduces accidental triggers while that upstream work proceeds.
61 changes: 61 additions & 0 deletions scripts/collect_wedge_logs.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<#
collect_wedge_logs.ps1

Usage (run from repo root):
./scripts/collect_wedge_logs.ps1 -OutDir .\logs -ReproScript .\reproduce-tiktok-wedge.ps1

What it does:
- Starts `ios syslog` and writes to a timestamped file in OutDir
- Runs the provided repro script (synchronous)
- Stops the syslog capture and prints the saved file path

Notes:
- ios syslog produces ~27 KB/s. A 2 minute capture is a few MB.
- Inspect the saved file before sharing; device names and bundle ids appear in the log.
- This script requires `ios` (go-ios) on PATH.
#>
param(
[string]$OutDir = "./logs",
[string]$ReproScript = "./reproduce-tiktok-wedge.ps1",
[int]$SyslogTimeoutSeconds = 240
)

if (-not (Get-Command ios -ErrorAction SilentlyContinue)) {
Write-Error "`n`n" + "ios not found on PATH. Install go-ios and ensure `ios` is available before running this script."; exit 2
}

New-Item -ItemType Directory -Path $OutDir -Force | Out-Null
$ts = (Get-Date).ToString('yyyyMMdd-HHmmss')
$logPath = Join-Path (Resolve-Path $OutDir) ("wedge-syslog-$ts.log")

Write-Host "Starting ios syslog -> $logPath"
# Start syslog and redirect stdout to file. -NoNewWindow so output goes to file.
$proc = Start-Process -FilePath ios -ArgumentList 'syslog' -RedirectStandardOutput $logPath -NoNewWindow -PassThru
Start-Sleep -Seconds 1

if (-not $proc -or $proc.HasExited) {
Write-Error "Failed to start ios syslog."
exit 3
}

try {
if (-not (Test-Path $ReproScript)) {
Write-Warning "Repro script $ReproScript not found. Run it manually while this syslog runs."
Write-Host "Press Ctrl+C to stop syslog when done."
Wait-Process -Id $proc.Id
} else {
Write-Host "Running repro script: $ReproScript"
& powershell -ExecutionPolicy Bypass -File $ReproScript
Write-Host "Repro script finished. Waiting up to $SyslogTimeoutSeconds s for post-recovery logs..."
Start-Sleep -Seconds ([math]::Min(30, $SyslogTimeoutSeconds))
# Give a small grace window after recovery to capture tail lines
}
} finally {
if (-not $proc.HasExited) {
Write-Host "Stopping ios syslog (pid $($proc.Id))"
Stop-Process -Id $proc.Id -ErrorAction SilentlyContinue
}
}

Write-Host "Saved syslog to: $logPath"
Write-Host "Tip: review $logPath and redact device identifiers or serials before sharing publicly."