From f5b4371f4a335a440e7bb08471ed6b1f6da74fea Mon Sep 17 00:00:00 2001 From: baketnk Date: Fri, 25 Sep 2026 11:07:43 -0400 Subject: [PATCH] Release v0.1.202609251506 Pin the installer to this release; README documents the curl | sh install. Co-Authored-By: Claude Opus 5.5 --- README.md | 13 +++++++------ TODO.md | 6 ++++-- docs/install-design.md | 6 ++++-- install.sh | 2 +- scripts/install_payload.py | 2 +- tests/test_installer.py | 4 +++- 6 files changed, 20 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 94c7da0..6a24852 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Voice typing on Steam Frame, with recognition on the headset rather than a desktop or cloud server. Hold a controller button to record, review the transcript, then deliberately type it into the focused app. -Standalone OpenVR overlay; no Steam store AppID or sudo. First v0.1 release is in progress. +Standalone OpenVR overlay; no Steam store AppID or sudo. First release: v0.1.202609251506. ## Requirements @@ -10,16 +10,17 @@ Standalone OpenVR overlay; no Steam store AppID or sudo. First v0.1 release is i - For voice recognition, a **CPU Python runtime** (moondream 2.4.0 / Kestrel 0.8.0, CPU Torch 2.8.0) and the pinned local Parakeet Redux model. Neither is bundled; each has its own explicit install step: `sh install.sh --install-model --backend redux --yes` and `sh install.sh --install-runtime --yes` (needs Python 3.10–3.13 with venv; about 200 MB download). Use `--print-plan` first to see exactly what each fetches. There is no fallback ASR service. - A local source build needs CMake 3.20+, C++20 and explicit native libraries/SDK; the default hardware-free build needs only CMake and C++20. See [build requirements](docs/build.md). -## Install (local artifacts only) +## Install -**No public release is published.** To install a locally vetted, checksummed ARM64 native-only archive without a compiler: +On the Frame, open a terminal (desktop mode's Konsole, or SSH) and run: ```sh -sh install.sh --mode binary --archive /path/to/frameyap-VERSION-linux-aarch64.tar.gz \ - --sha256 ARCHIVE_SHA256 --version VERSION +curl -fsSL https://github.com/baketnk/frame-yap/releases/latest/download/install.sh | sh ``` -`VERSION` is numeric `0.1.YYYYMMDDHHMM` for this release line; a future release tag will be `vVERSION`. The installer has an explicit local source-build path with toolchain/dependency inputs, and a read-only `--print-plan`/machine-readable `--json` mode; the producer stage→archive path still needs a clean-account artifact test and release audit. See [packaging](docs/packaging.md). Installation is user-local with rollback, no automatic launch or registration, and no Steam store AppID. Before voice typing, independently supply a licensed Python CPU environment and pinned weights, and configure their absolute paths in `~/.config/frameyap/paths.conf` (or the XDG config equivalent). Model download is opt-in and separate: `sh install.sh --install-model --backend redux --print-plan --json` inspects pinned metadata, while `--yes` explicitly authorizes installation from the *installed* manifest; `--expected-manifest-sha256 HASH` additionally binds consent to its exact bytes. The locally implemented Settings → Models chooser offers selection/restart and a two-click Install/Confirm Install with source, size, license, attribution and manifest SHA-256; it has not been validated as an installed/headset flow. No chooser action installs the Python runtime. Do not mistake a native-only install for working ASR. The pinned GitHub download route must not be advertised as functional until a vetted release exists. +You can download and read `install.sh` first; it is one self-contained file. The installer pins its own release (currently `v0.1.202609251506`) and verifies the archive's SHA-256. It asks three y/n questions: install FrameYap, download the Parakeet Redux speech model (about 180 MB, CC-BY-4.0), and pip-install the CPU Python runtime (moondream/Kestrel with CPU Torch; about 200 MB download, roughly 1–1.5 GB on disk). Everything goes under your home directory: no sudo, compiler or Steam store AppID. Afterwards, launch **FrameYap** from the desktop application menu. + +The release archive contains FrameYap, SDL3 and the OpenVR client library only; Kestrel, Torch, moondream and the model weights are fetched on your machine from PyPI and Hugging Face. For automation, the same steps are `sh install.sh --yes`, `sh install.sh --install-model --backend redux --yes` and `sh install.sh --install-runtime --yes`; add `--print-plan --json` to preview any step. Maintainers build release archives on Linux ARM64 with `sh scripts/build-release.sh WORKDIR VERSION`. See [packaging](docs/packaging.md) and [install design](docs/install-design.md). ## Controls (default Frame binding) diff --git a/TODO.md b/TODO.md index efed8cd..6aae25a 100644 --- a/TODO.md +++ b/TODO.md @@ -130,8 +130,10 @@ fresh clean install on Frame (install → `--install-model` → `--install-runti `--print-plan` and `--json` support offline plans and structured outcomes; explicit model installs use installed pinned manifests. Tested with local fixtures only, not a released archive or an installed Frame UI handoff. -- [ ] **D3. Publish a prebuilt ARM64 archive.** (M) **Deferred.** v0.1 is - source-only. Revisit after source-build acceptance. +- [x] **D3. Publish a prebuilt ARM64 archive.** (M) `scripts/build-release.sh` + builds SDL3/OpenVR-pinned archives on Linux ARM64; v0.1.202609251506 is built + on the Frame and published with its checksum and `install.sh`. The archive has + no Kestrel/Torch/moondream/model; those are user-side downloads. - [x] **D4. Installer fetches the Python runtime with pip.** (M) Implemented 2026-09-25 as explicit `install.sh --install-runtime --yes`: user-local venv, CPU `torch==2.8.0` from PyTorch's CPU index, `moondream==2.4.0` from PyPI, diff --git a/docs/install-design.md b/docs/install-design.md index 5f392e5..b85e185 100644 --- a/docs/install-design.md +++ b/docs/install-design.md @@ -1,8 +1,10 @@ # Installation goal and current boundary Goal: a one-command, pinned GitHub release install for Steam Frame without a Steam -store AppID, sudo or end-user compiler. **No public archive or verified clean -install is published. Do not advertise a `curl | sh` command as functional.** +store AppID, sudo or end-user compiler. Release v0.1.202609251506 publishes an +ARM64 archive, its `.sha256` and `install.sh` on GitHub, built on a Frame with +`scripts/build-release.sh`; `curl …/releases/latest/download/install.sh | sh` +runs the attended flow. A clean-install check on Frame is the remaining gate. The local installer has binary-archive and explicitly provisioned source-build modes, machine-readable plans/results and an attended TTY path. The native-only artifact does not include an ASR runtime; a separate explicit diff --git a/install.sh b/install.sh index c59cd1d..47d991f 100755 --- a/install.sh +++ b/install.sh @@ -45,7 +45,7 @@ import urllib.request KEY = "local.frameyap.overlay" # The pinned release this installer belongs to (set in the release commit that # is tagged vRELEASE_VERSION); empty in a development tree. -RELEASE_VERSION = "" +RELEASE_VERSION = "0.1.202609251506" MARKER = "# FrameYap managed launcher v1\n" ARCHIVE_LIMIT = 12 * 1024**3 MEMBER_LIMIT = 50000 diff --git a/scripts/install_payload.py b/scripts/install_payload.py index 53eca22..335b88d 100644 --- a/scripts/install_payload.py +++ b/scripts/install_payload.py @@ -25,7 +25,7 @@ import urllib.request KEY = "local.frameyap.overlay" # The pinned release this installer belongs to (set in the release commit that # is tagged vRELEASE_VERSION); empty in a development tree. -RELEASE_VERSION = "" +RELEASE_VERSION = "0.1.202609251506" MARKER = "# FrameYap managed launcher v1\n" ARCHIVE_LIMIT = 12 * 1024**3 MEMBER_LIMIT = 50000 diff --git a/tests/test_installer.py b/tests/test_installer.py index 2bf4b65..458bb85 100644 --- a/tests/test_installer.py +++ b/tests/test_installer.py @@ -762,8 +762,10 @@ class InstallTests(unittest.TestCase): output.extend(os.read(master, 8192)) except OSError: break - self.assertEqual(child.wait(timeout=8), 2) + # Dev tree: usage error. Release: defaults to its pin, then needs --yes. + self.assertEqual(child.wait(timeout=8), 1 if installer.RELEASE_VERSION else 2) self.assertNotIn(b"Mode [binary/source]:", output) + self.assertNotIn(b"[y/n]:", output) self.assertFalse((self.data / "frameyap").exists()) finally: if child.poll() is None: