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.
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.
Commit builds now show 'Hermes Agent <sha7>' (e.g. Hermes Agent abc1234)
and canary builds 'Hermes Canary' / 'Hermes Light Canary' / 'Hermes Agent
Canary' as the OS-visible product name, so side-by-side installs and
per-commit artifacts are readable at a glance.
Display-only by design: appId, appNamePascal, and msixAppIdWithOrg are
unchanged, so a canary MSIX still updates in place over stable and
userData / single-instance sharing with the stable install is unaffected.
bundle-electron-main.mjs derives the commit from the install stamp
(source='commit-build') so the baked runtime identity matches the
packaging identity.
Build TUI, web, desktop UI and runnable agent products from explicit
prepared inputs. Keep dependency preparation separate from distribution
packaging, with PM and native builds sharing uv environment construction.
Docker copies compiled frontend products instead of build dependencies.
Nix retains uv2nix environments and consumes shared assembly through store
references. Native desktop and Termux use the same launcher and frontend
contracts. Preserve the independent PM runtime and source imports from
arbitrary working directories.
Keep failed frontend builds from replacing the previous product, reject
source/output overlap, and bound dependency-process output draining.
Include hermes_wisdom in the Nix wheel: real CLI smoke tests exposed its
missing package declaration on the base revision too.
Verified focused Python and JavaScript suites, Docker build/runtime checks,
Nix desktop and CLI/ACP checks, standalone TUI and packaged Electron PTY,
and real full-Chromium interaction. Native signed installers, Android device
installation and the full repository suite remain CI verification.
Full Chromium serves both headed and headless sessions. The separate
shell duplicates the browser payload and is not needed for either mode.
Remove the shell from PM and Docker. Select the managed Chromium
executable for agent-browser and the full Chromium channel for direct
Playwright callers. Route setup through PM and remove retired packages
from cached bundle stores without changing the user's tool store.
Update signing, architecture checks, launch probes and install guidance.
Leave llama packages and Docker archive cleanup unchanged.
Verification:
- Real agent-browser navigation, clicks, DOM reads and screenshots pass
in headed and headless modes with the same Chromium executable.
- The direct Playwright doctor probe passes.
- Focused Python and desktop packaging tests pass, as do six Docker
checks and both real-browser task-scroll tests.
- The built linux/amd64 image is 1.393 GB compressed, 223.6 MB smaller.
- The broader PM suite and two unrelated setup tests still fail.
Those failures reproduce on unchanged HEAD.
- Five updated eval scripts parse; their full scenarios were not run.
Use a verified writable copy of pinned Python for uv builds. Keep the
signed launchers and bundled Python as the MSIX runtime so plugin
rebuilds do not remove package access.
Identify Microsoft Store builds from the artifact stamp. Use StoreContext
for update checks, downloads, and installation requests inside Hermes.
Keep relaunch and recovery ownership across the update. Do not report
unknown checks or no-op requests as successful installations.
Open the build commit link in the system browser.
Verification: 168 Python tests, 107 Electron tests, and 121 renderer tests
passed. Typechecks, lint, lock validation, and desktop builds passed.
A real packaged process completed plugin admission, import, and repair.
Store-acquired download, installation, and relaunch remain unverified.
This host has only the sideloaded MSIX. Its real Store API call returned
an error, which the app reports as unknown. macOS updates are unchanged.
Keep commit admission on the trusted workflow checkout and reject mixed
release inputs before loading repository code. Stage every built product
under its commit with receipt-bound summary links, never channel writes.
Build both Windows universal bundles through the existing SDK scripts.
Keep Store calendar versions separate from sideload app versions so zero-
major app versions remain packageable. Reject invalid arguments before
modifying bundles. Bind desktop and Termux versions to the source commit,
and record Termux cache provenance without labeling commits as tags.
Verification: 77 Python tests and 36 JS tests passed. Real makeappx packed
and unpacked disposable per-arch and universal packages. Seven official
workflow-expression checks, actionlint, syntax, lint and prose passed.
No signing, installed-app update, Android build, or remote dispatch ran.
Resolve pushed revisions before dispatching the default-branch workflow.
Reject release-mode flags and untrusted admission contexts. A dry run
never dispatches or creates a tag. Preserve Git's effective push URL
when choosing the GitHub repository.
Commit-build stamps check the actual checkout, including an explicit
Python --commit argument. The workflow SHA cannot replace build identity.
Direct Git argv also avoids the Windows command-shell PATH limit.
Real temporary Git CLI and stamp tests pass: 60 Python tests and 22 JS
tests, with no failures. GitHub authorization and dispatch are intercepted
at their process boundary. Workflow guards and native assembly remain
separate work. No live dispatch, signature, or package acceptance claimed.
Staging digests became stale after PE repair or payload signing.
Refresh all tool facts atomically while preserving their identity.
Windows refreshes after the batch signer. The macOS wrapper delegates
to the installed signer and refreshes after children, before the outer
app signature. Entitlements and file selection remain intact.
The real builder dispatcher caught the rejected factory shape. Tests
execute the installed signing walk with only codesign intercepted,
then compare the recorded bytes at the outer signing boundary.
Corrupt facts abort that boundary. Enabling batching fails the tests.
Verification: 80 Python tests passed with 3 host skips. 36 JavaScript
tests passed with 1 host skip. Lint, config typecheck and schema pass.
No real Apple/Azure signature, native package install or release run.
Icon generation reported errors but returned success. Aggregate target
write and verification failures into exit 1, while processing later
targets. Keep rendering dependencies in the isolated build group.
A synchronous open error consumed a slot. Returning that slot alone
still let a deferred throw suppress an earlier callback and stall the
queue. Schedule queue draining outside completed callbacks and retain
the original exception.
Verified real clean-source generation and structural checks for all
35 targets, plus a real write failure through the Node/uv runner.
Native Windows child tests cover immediate and deferred open errors.
POSIX descriptor-limit cases are explicit skips here, not passes.
No signed package or native macOS acceptance is claimed.
DMG failures lose their useful state when dmgbuild performs forced
cleanup. Capture open handles immediately after a failed native detach,
before the supplier retries or cleans up the staging image.
Use the resolved dmgbuild toolset and its paired Python interpreter.
Report scoped lsof results, including process IDs, descriptors and paths.
Keep detach results, arguments, signing and retry policy unchanged.
Verification: three JS tests and two portable Python tests pass.
The macOS held-file test is added but skipped on this Windows host.
Real builder download/interception and Node-to-Python wiring pass.
ESLint, Ruff, syntax and new-file formatting checks pass.
Merge upstream b1f003e186 while preserving PM runtime ownership and
Python 3.14 worker startup, Windows signing, and macOS wait recovery.
Keep retired runtime modules deleted. Port upstream updater preflight
checks into the checkout strategy and preserve live build logging.
Carry checkpoint filename handling and process recovery into the current
module layout. Regenerate locks and adapt incoming platform test markers.
Focused Python and JavaScript tests, desktop and root-test typechecks,
conflict-path lint checks, lock validation, and retired-import checks pass.
The full test suite and packaged release builds were not run.
An Apple status request can time out while notarization continues. Keep submit --wait as the normal path. Resume the same submission with notarytool wait only after the observed HTTP timeout.
Bound retries by one shared deadline and increase the existing macOS job and build-step limits. Unknown submission IDs and permanent failures still fail the build.
Focused notarization and macOS packaging tests pass, with lint, syntax, and workflow checks. Live Apple notarization remains unverified.
The afterPack payload signer runs before the Azure manager downloads its dlib. An empty cache therefore stopped the Windows build before signing.
Use the shared tool provisioner with the actual packager config. Keep the SDK, ATS dlib, and .NET runtime paired and remove the cache walkers.
Verified the cold-cache regression, native SDK execution, signature-cache contracts, and focused signing tests. ESLint passes. Full signed x64 release verification remains pending.
The envelope signer selected a cached .NET ZIP as DOTNET_ROOT. Its local
cache walker included archive and state files beside the extracted runtime.
The payload signer already filters these entries correctly.
Reuse the payload signer's runtime and dlib resolvers. Remove both duplicate
cache walkers and cover archive/state siblings in the shared resolver tests.
The actual bundle script failed before this change and passed afterward
with the same published packages and real Azure signing. The 4.9 GB bundle
passed native signature verification. All 34 focused tests pass. Remote
publication still needs a release run containing this fix.
PowerShell selects the Microsoft catalog signature for some payload DLLs.
That hides the valid Nous signature and rejects the signed payload cache.
For catalog matches, verify the primary embedded signature with signtool.
Require a trusted timestamp and the expected embedded publisher. Keep the
existing content binding and reject catalog-only trust.
The native regression rejects corrupt certificates and missing timestamps.
All 36 focused tests pass. Real Azure signing and duplicate restoration
pass with signer calls forbidden on the warm cache path. Full release
acceptance remains pending.
The osx-sign dependency accepts protobuf-like file lengths beyond its
512-byte sample and keeps allocating after EOF. That crashes the native
macOS signing walk before codesign can finish.
Pin the scanner used by osx-sign to the fixed version already in the
build closure. Keep signature checks enabled. A real signing-walk test
reproduces the allocation failure before the override and passes after it.
Finish bootstrap uv before PM replaces its store entry. Keep failure
receipts stdlib-only and align the cryptography requirement and override
with the locked version.
Let bundle builders declare launch paths and update ownership. Remove
payload discovery, Store probing, and the unused develop command.
Derive Nix Python from the PM lock and share its provenance stamp.
Document setup, activation, optional dependencies, and distribution
ownership. Targeted Windows tests, relocated runtime launches, Electron
bundling, and bilingual docs builds pass. Native Nix and signed-package
acceptance remain CI gates.
The Windows package version ignored an explicit stable tag.
Use the tag for sideload version derivation and reject candidate metadata
that does not match. Keep the separate Store version policy unchanged.
Restrict baseline manifests to the configured release origin and reject
cross-origin manifest responses. Cover the checks with real loopback HTTPS
and extend the version and empty-gate regression tests.
Document retries that reuse the original artifacts. Remove an unreachable
manifest check and an unused test import.
Targeted Python and JavaScript tests, Ruff, ESLint and the shared MSIX
module typecheck passed. Full signed native release acceptance was not run.
The Windows release signed 1,106 payload binaries for each of the bundled
and Store variants. Both passes repeated remote signing and timestamping.
Cache signed payload bytes by exact input SHA256 and signing policy.
Paths and release versions do not affect entry identity. Verify content
binding, publisher and timestamp before restoring a hit. Sign duplicate
inputs once and publish cache entries only after successful verification.
Keep product EXEs and package envelopes on the fresh signing path.
Persist the cache across release runs and test its native verification
in the Windows release lane. Targeted signing tests: 35 passed.
Real Azure signing of three mixed binaries took 9.6s cold and 1.8s warm.
Warm probes restored identical signed bytes with no signtool calls.
Full release performance and cache transfer overhead remain unverified.
Both Darwin release jobs failed with stapler error 65 and a missing
CloudKit record. The hook discarded the submission result, so the logs
could not distinguish rejection from delayed ticket delivery.
Require Accepted status and retrieve Apple's diagnostic log on failure.
Retry only the missing-ticket signature after acceptance. Share the path
between API-key and keychain-profile builds without resubmitting.
Targeted notarization and macOS packaging tests, lint and syntax checks
passed. Apple acceptance still requires a native signed build.
Preserve the PM runtime-repair module boundary. Port the incoming stderr-streaming fix without restoring the deleted managed_uv downloader. Targeted runtime/progress tests and root JS checks passed; desktop typechecks passed.
Route packaged macOS bundles and Light through the updater strategy.
Use electron-updater 6.8.9 and wait for native signature acceptance before
backend teardown. Keep checkout and Store ownership separate.
Share Darwin feed paths between packaging, runtime and publication.
Validate both native feeds, verify streamed artifact hashes, prevent
same-tag artifact replacement, and conditionally update the channel
pointer. Protect live feed references during canary retention.
Use one notarization owner. Require publishing credentials and validate
the stapled app. Keep Windows, Linux and Termux jobs unchanged.
Verified with updater/feed unit and transport tests, release-helper tests,
desktop typechecks, the desktop JS build, and workflow lint. No E2E,
native macOS install, release dispatch or public publication was run.
Microsoft disables ms-appinstaller by default. Download a bounded local descriptor before teardown and open its file association. Read the registered source URI from Windows when no feed override is configured. Remove the invalid default URL and share checker parsing.
Verified real loopback download, size/error boundaries, apply ordering, 35 Electron tests, Electron typecheck, and 8 Python projection tests. Packaged update acceptance remains separate.
Merge upstream 5e645791ac.
Retain the PM feature-flag owner and add upstream connection options.
Use the deny-only window-open policy while trusted external links keep
the existing IPC path. Keep both session-import and external-link copy.
Preserve captured timeout output when adding terminal yield handoff.
Quickstart tests patch the explicit upstream model-assignment owner.
Migrate incoming legacy OS markers to the branch's platforms gate.
Desktop renderer and Electron typechecks passed. Targeted Electron tests
passed (42 tests), Python conflict checks passed (26 tests, 3 skips),
and the plugin-compat import checker passed. CI owns the broad merge gate.
Dependency publication now recovers interrupted config/facts changes before
activation and leases live generations during collection. Receipts retain
update correlation and failed steps across nested command boundaries.
Doctor and desktop surfaces report those failures through shared owners.
Move checkout updates out of the desktop facade. Stage a detached Windows
relaunch waiter before shutdown, with bounded handshake and process-birth
checks. Keep packaged lifecycle tests isolated from the installed app.
Native verification exposed two production races: cron maintenance imported
the interactive CLI and rewrote TERMINAL_CWD, and install-ID reads collided
with first publication. Use the existing owners and locks. Plugin checks
now run at startup and each due-gated housekeeping tick, not after 60 ticks.
Share updater-test mutation boundaries and remove collection-root fixtures.
Separate cold MCP startup from command latency and give the real HTTP drip
test enough time to reach body handling.
Root npm check passed, including packaging. The fixed-tree Windows Python
run reported 44557 passed, one failed, and 1404 skipped, plus one retry-only
HTTP test. Those final failures now pass in a 35-test bounded batch. A real
isolated gateway wrote startup and periodic plugin-check receipts.
Full final-tree CI, bundled Sandbox deployment, and actual App Installer
relaunch remain unverified. docs/pm-audit-status.md records these limits.
A delayed browser could miss the 900ms terminal event and spin forever after the updater exited. Retain terminal delivery until the page acknowledges it, bound unavailable-client teardown and failed requests, and preserve a truthful final display.
Fixes#103747. Builds on OutThisLife and Teknium detached handoff work in #83634 and the #75895 quiet-window design. Continues Axl Ibiza Windows update investigation (#60233, #94107, #100763), including source/review contributions carried by merged #93353 and #85170. Existing #102373, #103140, #95719, #97299 and #103632 retain their separate scopes.
Prepare dependency generations before selecting them. Keep shipped tool
bytes separate from writable additions, and store facts beside their entries.
Validate proposed plugin sets before config publication. Restore the previous
config if the facts write fails.
Consolidate duplicate updater, backup, setup, and voice helpers. Repair
launcher selection, dependency consumers, download ownership, update feeds,
and native Windows process and file handling.
Verification: 206 changed/prior-failing Python files reported 4630 passed,
one failed, and 330 skipped. Fix the remaining Hindsight fixture boundary.
The final targeted rerun reported 234 passed and two skipped. The store
review regression batch reported 83 passed and one skipped. Desktop
TypeScript checks, 56 selected Electron tests, 24 release tests, and the
removed-import/compatibility guards passed.
This is an integration checkpoint, not full audit acceptance. The complete
Python suite has not run on this fixed tree. Crash-atomic plugin publication,
generation cleanup, receipt correlation, and packaged lifecycle acceptance
remain open in docs/pm-audit-status.md.
Task 2 of the gateway-as-MSIX-service plan (settled: user-context,
1903 floor, config-only demand-start):
- before-build.mjs serviceExtensions(): the desktop6:Service fragment
— Executable = the payload launcher hermes.exe (the same distlib
PE serving the AppExecutionAliases; gateway run --service is the
SCM frontend — NO shim binary), Name=HermesGateway,
StartupType=demand (config-only posture: arrives stopped;
`hermes gateway service on` flips to automatic-at-logon),
StartAccount omitted (desktop6 default = installing user's context;
localSystem explicitly rejected). light + store variants render
service-less (store policy is the plan's open risk item). Rides
the existing generated build/msix-extensions.xml via
customExtensionsPath — same mechanism as the aliases + copilot-key
fragments.
- gen-msix-manifest.mjs: minVersion 10.0.17763 → 10.0.18362 (Win10
1903, the desktop6:Service requirement; settled support-matrix
bump — 1809 is a 2018 OS; rides the release notes).
- Verified: the REAL rendered manifest carries the service block
(gen-msix-manifest bundled x64 → desktop6:Service
Name=HermesGateway Executable=...hermes.exe); the staged fragment
regenerates with it (caught + fixed a serviceFragment→
serviceExtensions name bug live via the real beforeBuild import).
A flat-dir makeappx probe fails identically WITH and WITHOUT the
fragment (the probe harness lacks signing identity) — the honest
full validation is the win32 CI lane's real signed pack.
- tests: 4 serviceExtensions contract tests (category/name/exe/
demand-start/one-block/xmlns-root/light-store-empty/name-prop)
in cli-launchers.test.mjs — 15/15 pass; full scripts/ suite: my
files green (1 pre-existing darwin-staging failure is the sibling
agent's uncommitted territory).
The pm bundle deliberately ships uv-cache/ (warm venv rebuilds) and the
arch audit already exempts it — but batchSignAppTree enumerated and
signed every .exe/.dll under it. That wastes hundreds of Azure sign
round-trips on inert sdist/archive artifacts and FAILS when the cache
holds files that were removed between pm bundle staging and the afterPack
walk ("SignTool Error: File not found" — reproduced on a local win32-arm64
build).
Skip agent-payload/uv-cache/ in the batchSignAppTree enumeration (same
exemption class as the audit), pinned by a test asserting a uv-cache exe
is excluded while the rest of the tree is still signed.
Verified: 90 batch-sign tests pass.
A local win32-arm64 build exposed it: audit-bundle-arch fails because
the payload deliberately ships uv-cache/ (pm bundle copies it for warm
rebuilds of the mutable venv) and that cache holds sdists/archives uv
built for ANY arch — x64/ia32 PEs on an arm64 payload. They are inert
cache bytes, never loaded at runtime, the same class as the fetch-*
prune, but the audit treated them as wrong-arch binaries.
Exempt agent-payload/uv-cache/ with a comment tying it to the pm bundle
behavior, and pin it with a test (exempt inside the cache, still audited
outside).
Verified: local arm64 build + audit green (2019 native binaries, all
arm64, 615 exempt stubs); 160 audit tests pass.
One conflict: upstream 6e7c7c7da9 replaced bot-mode-closed-chat-stays-closed.spec.ts with bot-mode-row-click-mirrors-registry.spec.ts while our side had rewired its mock-server import. Kept upstream's replacement and rewired the three new specs importing ./mock-server to the consolidated tests-js copy (symbols verified present).