garrytan / garrytan/gstack

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

Open
#1,837 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.