Safety commit so the 94 uncommitted files in the working tree (in-flight Account/Mac/Tip work plus the feature-preview recording tooling) survive the move onto cursor/cloud-agent-1787824905651-vxuwc. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
82 lines
3.6 KiB
Markdown
82 lines
3.6 KiB
Markdown
# Keyboard memory budget — acceptance (OSGDiag)
|
||
|
||
Phase 0 / 2 memory work is validated on a **physical iPhone** with Console
|
||
filtering for `OSGDiag`. Unit tests and `xcodebuild` cover compile-time
|
||
wiring; jetsam behavior is device-only.
|
||
|
||
## Hybrid Flow (product default)
|
||
|
||
- Foreground host is **light by default**: orphan Live Activity cleanup only —
|
||
**no** auto `startSession` / continuous capture on appear.
|
||
- Capture starts only on explicit Start / `osgkeyboard://startflow` / mic press.
|
||
- Idle background capture is stopped so a parked host does not jetsam the keyboard.
|
||
- **Do not** stack CLM + Rime + ASR in the same second after onboarding.
|
||
- ASR warmup runs on **first mic press** (`beginUtterance`), gated by
|
||
`HostMemoryBudget` (~260 MB RSS). `hostHeavy` is set only while heavy work
|
||
actually runs, then cleared. A sticky `hostHeavy` (host died mid-work)
|
||
expires after `hostHeavyMaxAge` (~120 s) and is cleared on
|
||
`clearFlowState` / host-launch reconciliation so typing 中文/EN is not
|
||
permanently blocked.
|
||
|
||
## Console checklist
|
||
|
||
Filter Console by process separately: host `OSGKeyboard` vs extension
|
||
`com.osgkeyboard.ios.keyboard`. Host-only filter will never show `KVC.*`.
|
||
|
||
| Scenario | Expect |
|
||
|----------|--------|
|
||
| **Force-quit host**, open Notes, switch to OSG | First `dyld.constructor`, then `KVC.init` → `viewDidLoad` → `viewDidAppear` |
|
||
| Host foreground right after launch | `skip capture` + `postOnboardingWarmup scheduled … delay=45s` (no immediate Rime/CLM) |
|
||
| ~45 s later, host still active | Serial `rime.installIfNeeded` then `clm.prepare` |
|
||
| First mic press | `scheduleASRWarmup`; `hostHeavy` only while work runs |
|
||
| Switch to typing | Single `rime.prepare` / `englishPrepare` |
|
||
|
||
If neither `dyld.constructor` nor `KVC.init` appears after force-quitting the host,
|
||
the extension is dying in dyld (Shared≈9.4 MB + librime) — next lever is splitting
|
||
Rime out of Shared.
|
||
|
||
## RSS comparison (optional)
|
||
|
||
Record `OSGDiag` `rss=` tags for:
|
||
|
||
1. Cold voice surface only
|
||
2. Cold typing after prepare
|
||
3. Host foreground + extension
|
||
|
||
Target: typing peak below the old “voice + eager Librime construct” baseline.
|
||
|
||
## Extension physical-footprint budget
|
||
|
||
`phys_footprint` is the primary extension metric because device jetsam follows
|
||
it more closely than RSS. `KeyboardExtensionMemoryTelemetry` records structured
|
||
`[OSGDiag/memory] extMemory` lines at lifecycle and heavy-resource milestones,
|
||
plus 50 ms samples during the first four seconds:
|
||
|
||
- **Normal:** below 36 MiB
|
||
- **Warning:** 36–40 MiB
|
||
- **High:** 40–48 MiB; 40 MiB is the internal safe peak
|
||
- **Critical:** 48 MiB or above
|
||
|
||
The approximate 60 MiB device boundary is not a public Apple contract. The
|
||
40 MiB target deliberately reserves room for transient SwiftUI, Rime, and
|
||
system-framework pages. Telemetry is observation-only: crossing a band logs
|
||
`crossed=1` but does not change the selected surface or unload resources.
|
||
|
||
Each record includes the current and peak footprint, delta from process start,
|
||
elapsed startup time, surface/language, Full Access, clipboard state, and
|
||
operation-specific context. Filter Console by `OSGDiag/memory` and compare:
|
||
|
||
1. `KVC.viewDidLoad.afterInstallServices`
|
||
2. `KVC.viewDidLoad.afterInstallSwiftUI`
|
||
3. `typing.englishPrepare.done`
|
||
4. `typing.rimePrepare.done`
|
||
5. `clipboard.reload.done`
|
||
6. `KVC.viewDidAppear.done`
|
||
|
||
## Structural split
|
||
|
||
- Extension links **OSGKeyboardShared** only (no Charts / StoreKit / Speech / HostSupport).
|
||
- Host embeds **OSGKeyboardHostSupport** (ASR, CLM, CloudASR, charts UI).
|
||
- Heavy assets (`osg_pinyin.dict.yaml`, CLM bin, licenses, local-asr catalog)
|
||
ship in the **host app** bundle; extension reads Rime from App Group after deploy.
|