ios-qa daemon: boot-token never written (silent try? on NSTemporaryDirectory) — tunnel dies after 1-2 requests; bootstrap.ts claims os_log scrape but does file-copy
- Dominant language
- TypeScript
- Stars
- 133k
- Forks
- 19.9k
- Avg merge
- 18h 46m
- Merged PRs (30d)
- 26
Description
**gstack version:** v1.55.0.0
**Skill:** `/ios-qa` (Mac daemon / vision-loop)
**Discovered:** 2026-06-01, `/ios-qa` session on Dugout Sports (real device, iPhone 16 Pro).
**Related:** companion template-bug report (the five build/SPI fixes) — separate issue.
### Symptom
The daemon's tunnel authenticates for at most one or two requests right after spawn, then dies for the rest of the session. Burst-firing taps works only within a ~10s window immediately after a fresh daemon spawn; after that the tunnel proxies nothing.
### Root cause
`bootstrap.ts` documents that it scrapes `os_log` to recover the boot token, but it actually does a `devicectl appDataContainer` file-copy of `tmp/gstack-ios-qa.token`. On Dugout, `StateServer.start()`'s
```swift
try? bootToken.write(toFile: ...) // NSTemporaryDirectory()-based path
```
silently fails — a direct `devicectl` probe of the app sandbox shows the file is genuinely absent. Because the write is a `try?`, the failure is swallowed, the token file never exists, and the daemon never gets a valid token. The one or two requests that do go through immediately post-spawn appear to use a stale/cached rotated token, which then expires.
### Possible fixes (any one would help; first matches the docs)
1. **Actually implement the os_log scraping** that `bootstrap.ts` already claims to do, instead of relying on the file copy.
2. **Write the token under `NSHomeDirectory()/Documents`** instead of `NSTemporaryDirectory()` — the Documents container is reliably readable via `devicectl appDataContainer`.
3. **Escalate the silent `try?`** in `StateServer.start()` to a `logger.error` (or `do/catch` that logs) so the write failure is visible rather than swallowed.
### Workaround we used
Kill daemon → `terminate`-and-relaunch the app → spawn daemon → burst-fire ≤3 taps within ~10s. Repeat per burst. Not sustainable for a full QA loop.
Lower priority than the template build/SPI fixes, but it's the reason the vision loop couldn't complete a multi-step flow (we got dashboard → More → Profile but the tunnel dropped before the Sign-in-with-Apple flow).
Contributor guide
Assessment
This issue has not been assessed yet.