- publish-release.sh: the fallback takes only an untagged-... draft titled
exactly "Frame Control X.Y.Z" (optionally ": subtitle"); a pre-release's
draft ("9.8.7-rc.1") or one bound to another tag is refused.
- updater.js: ignore the page in update.json/the API entirely and always
link to releases/tag/v<version> built from the validated version, so a
path like tag/..\..\other/repo can't reach shell.openExternal.
- Tests for both, including backslash and %2e%2e traversal.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
publish-release.sh took update.json's "page" from the draft's url, which is
releases/tag/untagged-... and dies on publishing; 0.4.0's manifest shipped
that dead link. It also looked the draft up with `gh release view <tag>`,
which reports "release not found" while a draft's tag_name still reads
untagged-... (and uses rate-limited GraphQL).
- publish-release.sh: REST only. Checks the tag exists, finds the release by
tag_name or else the one untagged draft titled "Frame Control X.Y.Z",
keeps the 8-installer digest check, replaces update.json via the uploads
API, then PATCHes tag_name/draft/prerelease/make_latest. Adds --dry-run.
- updater.js: trust only this repo's releases/tag/<tag> pages (never
untagged-...); otherwise link to releases/tag/v<version>.
- release.yml: one draft job before the matrix (no racing creates), with
--verify-tag and tag_name set explicitly.
- Tests: tests/test_publish_release.py with a stand-in gh (tests/fakegh/gh),
and an updater test for the page.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Anonymous PostHog analytics (ui/frame_telemetry.py): usage on by default
after a first-run notice; compatibility results and error details opt-in,
offered together by the notice's "Share more to help fix problems" button.
Random id, no person profiles or GeoIP, scrubbed text, an offline outbox,
and "Show what's been sent" in the new Privacy panel. Inert without a
project key, from a source checkout, or with DO_NOT_TRACK=1.
- APK installs now record install_failed when the APK itself won't install,
and offer a 20-second test after installing. Opted-in reports reach the
shared database through PostHog and `frame_compat_db.py sync`.
- The desktop app updates itself from published releases (app/updater.js):
update.json from releases/latest/download, SHA-256 checked, no downgrades;
macOS bundle swap, Windows NSIS, Linux AppImage, otherwise the release page.
scripts/publish-release.sh publishes a tested draft with its manifest.
- Report a problem (header button, Privacy panel, Help menu) files a GitHub
issue through the website's feedback API, with a previewed, scrubbed
diagnostics snapshot; activity and logs only when asked for.
Reviewed by GPT-6 Astra (xhigh, read-only) three times; all findings fixed.
Docs: docs/privacy.md, docs/releasing.md.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>