Commit Graph

34089 Commits

Author SHA1 Message Date
ethernet
d4e5ecce59 fix(bundle): reject nonstable Store builds before staging 2026-09-11 20:15:44 -04:00
ethernet
32db27d63f fix(desktop): respect package ownership before uninstalling 2026-09-11 20:14:42 -04:00
ethernet
627196d746 fix(release): link incomplete build rows to their workflow run 2026-09-11 20:05:11 -04:00
ethernet
6b1672d375 chore: add explicit types to desktop identity tests 2026-09-11 20:03:22 -04:00
ethernet
2a1cb9c62e docs(release): name commit build pages before dispatch 2026-09-11 20:00:46 -04:00
ethernet
de5615d2b8 fix: publish tagged build diagnostics after release failures 2026-09-11 20:00:42 -04:00
ethernet
c4e2d937f7 fix(desktop): isolate canary and commit package identities
Canary and commit builds must not replace stable or share its desktop
state. Package names alone are insufficient because Electron reads the
product name before main initializes its paths. Pin nonstable userData
before the first lookup, and keep the packaged identity independent of
runtime build variables.

Keep release artifact filenames unchanged. Qualify payload CLI names,
route each nonstable MSIX alias to its own entrypoint, and copy the
immutable desktop provenance into the embedded Python checkout. Only
stable releases can use the official Store identity.

Targeted validation: 75 JavaScript tests passed, 2 platform skips;
15 Python tests passed with file retries disabled. Native Windows SDK
manifest proof is tracked separately. Full app install, signing and macOS
launch validation are not claimed.
2026-09-11 19:59:38 -04:00
ethernet
e697069431 Disable updates for single-commit desktop builds
Use the build stamp to refuse CLI, backend, and desktop updates. Keep release channels fixed for packaged clients and report the client version independently of a remote backend. Check source release channels against their published release identity.
2026-09-11 19:56:08 -04:00
ethernet
617880db21 test(msix): verify ACP aliases target their own launchers 2026-09-11 19:55:24 -04:00
ethernet
efbb69d0a3 test(desktop): verify distinct GUI and CLI manifest targets 2026-09-11 19:53:45 -04:00
ethernet
cfa142f3e0 feat(icons): distinguish desktop build flavors
Canary uses yellow tiles. Commit builds use red tiles and the first seven
characters of HERMES_BUILD_COMMIT. Vector glyphs need no host fonts.
Only desktop targets use these colors. Shared branding remains unchanged.

PM-generated pixels preserve the artwork and native alpha masks. The macOS
content bounds remain (100, 100, 924, 924) on the 1024 canvas. Stable output
matches the pre-change baseline byte for byte.

Validation: 13 focused Python tests and 7 Node tests pass. Stable, canary,
and commit generation each wrote 35 targets and passed structural checks.
The full suite and native installation acceptance were not run.
2026-09-11 19:52:12 -04:00
ethernet
d207b0607d fix: track published source release channels at exact commits 2026-09-11 19:52:07 -04:00
ethernet
66b5cf155d test(desktop): verify flavor manifests with native Windows SDK 2026-09-11 19:50:21 -04:00
ethernet
f1fe687b10 style(desktop): type shared-profile notification state explicitly 2026-09-11 19:48:23 -04:00
ethernet
4092ac4dc9 feat(desktop): warn when another install uses the same profile
Use the spawn ledger rather than a last-writer stamp. Record the canonical
profile home and require an exact live PID/create-time pair for warnings.
Keep the default ledger policy unchanged for process reapers.

Expose the advisory message through the existing status response. The desktop
shows a dismissible warning on its existing refresh cadence. Do not block
startup, redirect HERMES_HOME, or add a timer or lock.

Verified with real subprocess ledger tests and the status API. The targeted
Python run passed 27 tests. The desktop run passed 12 tests, TypeScript
checking, and lint. No full suite or packaged-app test was run.
2026-09-11 19:47:00 -04:00
ethernet
995a4617ac docs(release): describe nonstable package identity and branding 2026-09-11 19:43:54 -04:00
ethernet
8e49e5e517 docs: define side-by-side builds and source release channels 2026-09-11 19:42:28 -04:00
ethernet
528a9414df fix(build): type the python build helper's error handling for checkJs 2026-09-11 18:51:11 -04:00
ethernet
6f1c436419 chore(tests): remove stale PM entrypoint import 2026-09-11 18:30:05 -04:00
ethernet
db9112a1fc fix(dashboard): use current PM provider admission contracts 2026-09-11 18:28:01 -04:00
ethernet
8b56a9306f refactor(pm): own group-only builds and finish dependency hints 2026-09-11 18:25:05 -04:00
ethernet
d08ff92751 fix(build): prepare icon environments through PM 2026-09-11 18:24:54 -04:00
ethernet
69d6dfd077 fix(doctor): honor selected PM runtimes and launcher ownership 2026-09-11 18:20:54 -04:00
ethernet
596f0216a5 fix(skills): route google workspace dependencies through pm 2026-09-11 18:20:23 -04:00
ethernet
6ee8610b67 refactor(pm): finish consumer contracts and enforce private engine imports 2026-09-11 18:18:58 -04:00
ethernet
ea8adb5e22 fix(tests): isolate the platform-default Hermes root
The shared fixture isolates HERMES_HOME, but profile-root resolution also
resolves the native default. This trips the real-home guard even for tests
that use a temporary custom home. Base 75a646e5b3 has the same failures.

Isolate the native default in the shared fixture. Capture its parent before
test fixtures run so explicit home overrides keep their own layout. Leave
HOME, Path.home(), production resolver behavior, and the I/O guard intact.

On the original base, this fixture fixes all 24 PM authority failures and
92 update failures/setup errors. The same four unrelated /proc DB-holder
probe failures remain on both base and current code. Current targeted
profile, path, PM, and guard checks pass: 214 passed, 4 skipped.
2026-09-11 18:15:30 -04:00
ethernet
c91d2be042 fix(pm): gate build work and reuse wheelhouse install policy
Ready tools do not authorize dependency operations when lazy installs are
disabled. Apply the shared guard before build, export, or online lock checks.
Keep offline lock checks passive. Cache pruning only reads the pinned
toolchain and cannot acquire missing tools.

Use one requirements-file installer for requirement builds and runtime
wheelhouse staging. Both enforce the same index and binary-only policy.

Verified 36 targeted tests, including missing-toolchain pruning, disabled
lazy operations with ready tools, and real offline runtime staging.
2026-09-11 18:15:14 -04:00
ethernet
884a0241ca Drop retired Python environment references from bootstrap documentation 2026-09-11 18:15:13 -04:00
ethernet
a154b89b9f Route build and CI Python preparation through PM operations 2026-09-11 18:14:43 -04:00
ethernet
cdd76e03ec fix(pm): enforce install policy for explicit Python builds 2026-09-11 18:13:56 -04:00
ethernet
fc4086c4c5 fix(cli): route dependency hints through pm
Replace direct Hermes-environment pip advice with PM repair, existing
setup commands, or explicit extra sync. Keep Termux package guidance.
Plugin discovery reports missing dependencies without installing them.

Targeted Nix runner, HERMES_TEST_FILE_RETRIES=0:
- Seven focused files: 153 passed.
- Voice CLI integration: 31 passed on the follow-up run.
- Dashboard follow-up: 33 passed before one failure with --maxfail=1.
  test_post_memory_provider_setup_routes_pip_through_pm receives failed
  instead of restart_required from the memory setup endpoint.

Doctor launcher and runtime-detection gaps are reported separately.
No doctor checks are disabled. The full suite was not run.
2026-09-11 18:13:53 -04:00
ethernet
f697856f10 docs(pm): clarify worker probes and manager bootstrap 2026-09-11 18:13:22 -04:00
ethernet
ed568bd947 fix(runtime): route dependency hints through pm 2026-09-11 18:13:06 -04:00
ethernet
547b5de29d docs(pm): route dependency setup through public operations
Direct package installs bypass PM's dependency selection and do not survive
new generations. Document explicit runtime extras, recorded repair, fresh
build outputs, and lock generation through PM instead.

Keep the prepared-interpreter prerequisite and explicit removal requirement
for disposable test environments. Preserve Nix and external-project package
manager ownership. Correct platform and Python-marker claims where the
manifest contradicts the installation hints.

Checked the public CLI help, literal PM calls against public signatures and
extra declarations, fenced blocks, and whitespace. No dependency build or
site build ran. The docs toolchain is not installed in this checkout.
2026-09-11 18:12:49 -04:00
ethernet
9aac9f9fe8 refactor(cli): delegate Python setup and sync to PM 2026-09-11 18:12:12 -04:00
ethernet
c7b1f238b5 fix(pm): keep bootstrap and readiness checks behind safe operations 2026-09-11 18:11:59 -04:00
ethernet
8417678ae2 feat(pm): add semantic build and cache operations
Build callers need lock validation without mutation and frozen exports that
retain markers and Git pins. Route these operations through the private
engine instead of giving callers uv commands.

Requirement builds claim fresh destinations, validate installed packages,
and remove failed candidates. Wheelhouse builds reject indexes and source
builds. Cache pruning keeps downloaded wheels except in CI mode.

Verified with real local wheels, a local Git source, and loopback downloads:
30 targeted tests passed across test_build_operations.py and
test_environment_build.py. No full-suite claim while the base migration is
in progress.
2026-09-11 18:11:13 -04:00
ethernet
97252910f3 fix(pm): declare locked setup extras and unsupported engines
Setup needs declared extras instead of unbounded package installs. Pin ddgs,
langfuse and Piper without changing any existing resolved package versions.
Use upload-time cutoffs for the reviewed pins.

NeuTTS excludes Python 3.14. KittenTTS requires misaki, which excludes Python
3.13 and newer. Keep matching dependency markers and PM gates so bundles omit
these engines and explicit requests fail instead of reporting empty success.
Piper also excludes Intel macOS and Windows ARM64 because its native closure
lacks wheels there.

Verify the parent sync gate against the native Python version, including an
installed-anchor override. The test fails without that gate. Check declaration
and runtime gate agreement across bundle targets. Isolate an existing test's
home lookup, whose failure also reproduces on the base commit.

Verification: public PM lock/check and fresh 85-package environment passed in
an isolated manager runtime. DDGS, Langfuse and Piper imports passed on Linux.
No full suite or cross-host execution was performed.
2026-09-11 18:09:08 -04:00
ethernet
8bf20a3bc8 test(pm): align engine fixtures with public builds
Isolate profile discovery and supply explicit engine inputs for output diagnostics. Keep destination safety checks independent of invalid-source error ordering, and verify sealed pruning with real offline wheels.

The requested canonical group passes: 98 passed, 0 failed, 4 Windows-only skips across 15 files. The full suite was not run.
2026-09-11 18:06:20 -04:00
ethernet
80273b4507 refactor(pm): route Python tool installs through PM
Use PM-selected interpreters and tool entrypoints for Browser Use, Hindsight and Python language servers. Sync the declared Google Chat extras instead of changing the active environment with pip.

Verified the affected 11-file Nix test subset: 359 passed, 7 skipped. The full suite and real third-party package installation were not run.
2026-09-11 18:05:43 -04:00
ethernet
cc48185220 refactor(pm): expose Python operations instead of uv binaries 2026-09-11 18:05:28 -04:00
ethernet
01821b8e14 refactor(pm): consolidate private Python environment engine 2026-09-11 18:00:04 -04:00
ethernet
c184f04838 Use prepared Python for bootstrap and desktop build helpers 2026-09-11 17:59:55 -04:00
ethernet
75a646e5b3 fix(icons): render icns on Apple's 824-on-1024 mac grid
Testers reported the macOS app icon reads oversized next to other apps:
the full-bleed 1024 squircle master put the shape ~149px past Apple's
icon grid on every side. macOS icns targets now render from an in-memory
mac master built on new squircle-mac-{light,dark} backgrounds — the same
white/#0d1117 squircle at 824x824 (r=185.4) centered in 1024 with 100px
margins, with the girl box scaled by 824/1024 to keep her relative size
inside the shape. All non-mac targets keep the full-bleed squircle.
2026-09-11 17:22:11 -04:00
ethernet
26c39cbb27 fix(logging): fall back from concurrent-log-handler when portalocker is dead
A Windows bundle whose venv never processed pywin32.pth (see the launcher
fix) fails 'import pywintypes' with ModuleNotFoundError; portalocker 3.x
has no msvcrt fallback, so CLH retries lock() 20x and raises 'Cannot
acquire lock after 20 attempts' — which handleError suppressed entirely.
Result: zero file logging, silently, on every affected install.

* probe portalocker once at import (scratch lock/unlock) and fall back to
  stdlib RotatingFileHandler when it fails; the fallback disables rollover
  (multi-process appends make Windows renames fail with WinError 32, the
  #44873 trap CLH exists to avoid) and setup_logging() warns once
* the suppressed CLH lock timeout now warns once through the logging
  system instead of vanishing
2026-09-11 16:45:38 -04:00
ethernet
f67a3b59db fix(bundle): process the venv's .pth files in payload launchers
The minted launchers wired venv site-packages onto sys.path with a raw
insert (win32 wrapper) / PYTHONPATH (posix), neither of which runs .pth
files. pywin32.pth is load-bearing on Windows: it puts win32\lib on
sys.path, which is what makes 'import pywintypes' resolve — without it
portalocker's Win32Locker dies and concurrent-log-handler silently drops
every file-log record on Windows bundles.

* launcher_wrapper.py: site.addsitedir() for the site entry (repo first,
  site directly after, .pth dirs last)
* launchers.py posix: same via HERMES_SITE env in the -c bootstrap
* pm/environment.py: prune_site_pth() drops _virtualenv.pth and the
  __editable__ pointer (build-machine path) that must never run in a
  sealed payload
* python_env.py: run the prune after every environment build
2026-09-11 16:45:28 -04:00
ethernet
ad231c164b fix(setup): parse lock and mirror json by structure, not indentation
Two pre-Python readers anchored their awk patterns on the exact leading
whitespace of the machine-written json they parse:

- setup-hermes.sh read artifact-mirror.json with /^  "origin"/ (exact
  two spaces), so any other one-member-per-line layout lost the mirror
  fallback silently: the mirror url resolved empty and fetch_pinned
  reported only the primary url it failed on.
- scripts/install.sh read packages.python.version from pm/lock.json
  with exact 4-space and 6-space anchors; on any other layout the pin
  resolved empty and the install fell back to the hardcoded "3.14".

setup-hermes.sh's own pin() already established the contract for the
same file ("follow object names and braces, not indentation"); both
sites now follow it. The mirror read is a flat key match; the python
pin uses the same brace-tracking reader as pin().

No other site in the tree has the pattern: setup-hermes.ps1 uses
ConvertFrom-Json, nix uses builtins.fromJSON, python readers use
json.loads, and remaining awk users parse command output, not config.

Tests:

- tests/pm/test_setup_lock_format.py now parametrizes the mirror json
  indent (it was fixed at 2, leaving the mirror read unguarded) and
  adds a mirror-fallback E2E: the primary url is a dead port (curl
  exit 7, retriable), so the staged uv must come from the mirror,
  with the mirror json written at 9-space indent. Red on the old
  regex (mirror url resolves empty, exit 1), green with the fix.
- tests/test_install_sh_python_pin_indent.py (new) sources
  install.sh --manifest and proves bootstrap_python resolves the
  pinned version through a fake uv that records its calls, across
  2/4/0/tab/blank-line lock layouts.

Verified via scripts/run_tests.sh: 16 passed, 0 failed on the fix; the
new mirror-fallback test fails against the old parsers (verified by
stashing the two script changes and re-running). Sibling install/setup
tests (test_install_sh_node_deps_workspaces, test_install_stage_frames,
test_install_sh_desktop_stage, pm/test_activate_scripts) all green.
2026-09-11 16:33:02 -04:00
ethernet
6d344be588 fix(wake): upgrade sherpa for native Windows ARM64
Sherpa 1.13.8 supplies native Windows ARM64 Python and core wheels.
Remove its platform exclusion so auto selects the keyless engine there.

Declare pypinyin for both wake install paths. The tokenizer imports it
unconditionally, including for English phrases. Include sentencepiece
in the lazy engine extra too. Keep the matching core in the lockfile
and admit the reviewed release with bounded package cutoffs.

Verified native ARM64 Python 3.14 with the unchanged Hermes engine:
three phrases detected twice each, with no triggers in 180 seconds of
silence. Engine construction failed without pypinyin and passed with it.
The tested wheels match the lockfile hashes. Focused tests: 78 passed,
2 skipped. uv lock --check passed. No MSIX rebuild or microphone test.

The dependency audit reports the same existing httpx2/httpcore2
advisories as the parent commit. No unrelated packages changed.
2026-09-11 16:30:47 -04:00
ethernet
410ac37a0b fix(wake): select a supported engine by default
The fixed openWakeWord default selects an unavailable engine on native
Windows ARM64 and Intel macOS. Use auto and the existing PM platform gates
to prefer openWakeWord, then sherpa, then Porcupine.

Keep explicit provider choices unchanged. Porcupine still requires its
access key, and wake detection remains disabled until the user enables it.
Expose auto in the config UI and document the backend-platform selection.

Verified config loading, platform selection, explicit-provider preservation,
key requirements, and the config schema. No microphone detection was run.
2026-09-11 15:59:08 -04:00
ethernet
86efc1f945 fix(release): allow explicit environment clears in commit bundles
An inherited HERMES_HOME can defeat a test bundle's data-directory suffix.
Older Windows installers also persisted that variable in the user registry.
This gives the app fresh UI state while its backend reads existing sessions.

Add --bundle-unset NAME, encoded as null in the existing bundle environment
object. Apply each clear as an explicit empty value before module startup.
Do not restore an explicitly empty HERMES_HOME from the Windows registry.
Ordinary defaults still preserve runtime overrides.

Verified the release parser, builder handoff, compiled startup ordering,
registry opt-out, and child environment with focused regression tests.
A native Windows probe passed with an inherited home. No MSIX was rebuilt.
2026-09-11 15:59:08 -04:00