Commit Graph

2119 Commits

Author SHA1 Message Date
ethernet
8f6d98e4c3 fix activation of devenv, use /usr/bin/env bash everywhere 2026-09-11 11:17:18 -04:00
ethernet
b3bfc3afe5 Merge remote-tracking branch 'origin/main' into ethie/pm-clean
# Conflicts:
#	apps/desktop/electron/backend-connection-state.test.ts
#	apps/desktop/electron/backend-connection-state.ts
#	apps/desktop/electron/backend-exit.test.ts
#	apps/desktop/electron/main.ts
#	apps/desktop/electron/pool-spawn-coordinator.test.ts
#	apps/desktop/electron/pool-stop.ts
#	apps/desktop/electron/preload.ts
#	apps/desktop/src/app/settings/about-settings.tsx
#	apps/desktop/src/app/updates-overlay.tsx
#	apps/desktop/src/global.d.ts
#	apps/desktop/src/store/notifications.ts
#	apps/desktop/src/store/updates.ts
#	gateway/config_loader.py
#	hermes_cli/banner.py
#	plugins/platforms/dingtalk/adapter.py
#	tests/hermes_cli/test_plugins_cmd.py
#	tests/test_live_system_guard.py
#	tui_gateway/server.py
#	website/docs/user-guide/desktop.md
2026-09-11 09:36:04 -04:00
shannonsands
a6ee31f55a feat(wisdom): add Hermes Collective Wisdom Agent V1 (#94266)
* feat(wisdom): add trusted publish and install foundation

* feat(wisdom): add private contribution loop

* feat(wisdom): add managed consumption workflows

* fix(wisdom): close cross-repository safety gaps

* fix(wisdom): align local package and lifecycle policy

* fix(wisdom): require explicit profile setup

* docs(wisdom): repin reconciled gateway head

* fix(wisdom): fence content downloads and approval receipts

* docs(wisdom): record generation-fenced downloads

* docs(wisdom): record unified delivery PR

* fix(ci): stop passing invalid classifier inputs

* docs(wisdom): remove internal requirements ledger

* feat(wisdom): localize dashboard and desktop copy

* feat(wisdom): complete local contribution and consumption UX

* style(wisdom): satisfy desktop lint

* chore(wisdom): refresh requirements pin

* test(dashboard): allow formatted profile copy

* test(wisdom): stabilize desktop interaction coverage

* fix(wisdom): surface dashboard action failures

* fix(wisdom): add repeatable Portal demo login

* feat(wisdom): add actionable skill notifications

* feat(wisdom): add notification install and update actions

* fix(wisdom): make Telegram skill alerts actionable

* fix(wisdom): always refresh demo Agent login

* feat(wisdom): embed Telegram notification actions

* fix(wisdom): preserve Telegram notifications after actions

* fix(wisdom): keep Telegram notification cards readable

* feat(wisdom): add Telegram candidate approval flow

* feat(wisdom): explain Telegram qualification reasons

* fix(wisdom): reconcile cross-surface candidate actions

* feat(telegram): add Collective Wisdom management command

* chore(wisdom): refresh Gateway contract pin

* chore(wisdom): advance Gateway contract pin

* feat(wisdom): align command UX across clients

* feat(slack): add Collective Wisdom management parity

* feat(wisdom): add security and professionalism reviews

* feat(wisdom): add first-time qualification guidance

* feat(wisdom): simplify qualification sharing choices

* feat(skills): add optional editorial metadata

* feat(wisdom): enrich legacy skill presentation

* fix(wisdom): harden review and update boundaries

* fix(wisdom): emit canonical review timestamps

* fix(wisdom): align with merged gateway and main

* wisdom: add agent-led sharing core (policy, evidence, schemas, templates, delivery, weekly job, share/install flows)

- hermes_wisdom/agent_led/: policy resolution (server > local > defaults),
  7-day evidence builder that excludes bundled/hub/managed skills and
  dismissed/handled/recently-suggested content hashes, strict pydantic
  schemas for agent output with repair-or-reject, fixed copy templates
  (Share / Teammate / Published / Update / Mute), idempotent retried
  delivery ledger with stale-action resolution, weekly review job,
  resumable Share and Install flows.
- prompts/: candidate review, recipient recommendation, share packaging.
- tests/wisdom/test_agent_led.py: 30 tests.

* wisdom: agent-led renderers and button action dispatcher

- render.py: Telegram HTML, Slack blocks, Desktop payload; editorial name
  is the emphasized line, product label stays separate.
- actions.py: resolve opaque wa:<action>:<dedup> targets via the delivery
  ledger; Not now -> dismissal, Mute -> fixed options, Share -> resumable
  packaging flow, Install/Update -> plan command. Never publishes/installs.

* wisdom: CLI verbs, agent_led config default, conversational catalog skill

- hermes wisdom browse/review-week/act/share/dismiss/mute (all --json).
- wisdom.agent_led config block, default enabled.
- SKILL.md rewritten so natural-language catalog questions map to the CLI
  verbs, share/install flows and fixed notification templates.

* wisdom: wire agent-led weekly review into gateway tick and Telegram buttons

- gateway housekeeping tick calls maybe_run_weekly_review with a home
  channel sender when a Telegram adapter is available.
- Telegram: wa: callbacks resolved through the ledger (stale-safe), mute
  duration keyboard, send_wisdom_agent_recommendation rich card + fallback.

* fix(wisdom): integrate local mediation and harden model and setup boundaries

* fix(wisdom): honor authoritative recommendation policy and defer on failure

* fix(wisdom): synchronize opaque suppression and recheck delivery preferences

* feat(wisdom): route weekly selection through the session-owned assessment queue

* fix(wisdom): prepare and submit the reviewed generated share package

* feat(wisdom): separate native Share preparation from publication consent

* feat(wisdom): sync native mute choices through a leased preference outbox

* feat(wisdom): bind native mute controls to durable preference choices

* feat(wisdom): add scoped desktop and dashboard notification settings

* fix(wisdom): revalidate feed recommendations before assessment and delivery

* fix(wisdom): persist validated delivery receipts before completing notices

* feat(wisdom): add private notification claim and receipt client

* Persist Wisdom send reservations and recover delivery acknowledgements

* Route legacy Wisdom controls through current native review

* Add typed private Wisdom operation outcome client

* fix(wisdom): make agent-led advice usable in the local demo

* fix(wisdom): keep requested consent outside proactive limits

* fix(wisdom): distinguish unavailable assessments and preserve digest text

* fix(wisdom): assess ongoing usefulness beyond the current task

* fix(wisdom): restore immediate qualification sharing controls

* fix(wisdom): separate qualification review from installation advice

* fix(wisdom): collapse review checklists and simplify sharing copy

* fix(wisdom): show compact sharing progress and publication receipts

* fix(wisdom): require credential prefixes rather than matching skill names

* fix(wisdom): finish package checks before presenting sharing consent

* fix(wisdom): scan local skills before qualification cards

* fix(wisdom): update moderation results on existing sharing cards

* fix(wisdom): keep sharing review accessible from receipt cards

* fix(wisdom): align mediated review cards and collapsible checks

* fix(wisdom): clarify clean security summary wording

* fix(wisdom): normalize consent plans and add explicit recheck

* fix(wisdom): keep install and update receipts concise

* fix(wisdom): collapse assessments and deduplicate operation cards

* fix(wisdom): restore private Portal review from native cards

* fix(wisdom): sync Portal publication to original consent card

* fix(wisdom): show local skill version on sharing cards

* fix(wisdom): skip agent recommendations for self-published versions

* fix(wisdom): simplify candidate notices and local-edit recovery copy

* feat(wisdom): submit locally reviewed packages with one confirmation

* feat(wisdom): expose safe receipt and outcome sync recovery

* wisdom: onboarding notice says detect and share, names the user's own skill

Copy review from the product owner on the first and returning
qualification notices (fixed delivery mode):
- the feature blurb now says the org enabled detection *and sharing*
- both notices say the detected skill is one the user created
- both close with an exclamation mark

Applied identically to hermes_wisdom.notice, the desktop and web i18n
strings, and the tests that assert the sentences.

* wisdom: one opener, no approval line, ask to share after the skill is shown

Product owner review of the candidate card.

- The Hermes written card now opens with the same sentence as the fixed card
  ("Your organisation has enabled Collective Wisdom, a feature designed to
  automatically detect and share useful skills across all team members.")
  instead of its own blurb, so there is one first time message.
- "Nothing is shared without your approval." removed from Telegram, Slack
  and Desktop. The buttons already make the permission explicit.
- "Would you like to share?" no longer appears before the skill is named.
  It is now the last line, after the skill name, description, why suggested
  and the checks, and reads "Would you like to share it?" (matching the
  agent led template wording).

Tests updated for the new order; proposalNotice removed from all desktop locales.

* wisdom: American spelling, organization

Product owner decision: user facing copy uses American spelling.
Changes "Your organisation" to "Your organization" in the chat notice,
the Hermes written card opener, the desktop and web strings, and the
tests that assert them. Identifiers such as nas_organisation:* and the
German and French locales are untouched.

* wisdom: candidate card copy round 4 (owner review)

Apply the product owner's round 4 copy decisions to the Hermes Collective
Wisdom candidate card on Telegram, Slack, Desktop and the shared views:

1. Hermes-written cards are titled "Hermes Collective Wisdom" instead of
   the bare "Collective Wisdom".
2. The "Reusable skill ready to review" line is gone from the candidate
   card (Telegram rich card and plain fallback, legacy agent-led share
   template).
3. The skill name and description are labelled: "Skill name: <name>" and
   "What it does: <description>" (Telegram, Slack, Desktop).
4. "Why suggested:" is now "Why others might benefit:".
5. A passing professionalism review reads "Safe to share at work ✓ (no
   inappropriate content found)" with no per-check bullets and no "Pass";
   a failed review reads "Needs a look before sharing at work (possible
   inappropriate content)" and lists only the checks that flagged
   something. Pending/unavailable wording is unchanged.
6. Telegram button toasts: "Will ask later...", "Preparing more
   details...", "Sharing...".
7. Qualification reasons: "You used this skill consistently across many
   days." and "You've really refined this skill."
8. prompts/wisdom_candidate_review.md asks for a compelling
   editorial_name, a simple one_line_description and a compelling
   why_coworkers_benefit under 300 characters; "Be concise and
   convincing." becomes "Be concise and compelling: the goal is that the
   user wants to share it."

Tests updated for the new strings; review_text() gains direct coverage.

* wisdom: re-apply owner copy after rebase

- Native share cards (advice_view/interaction_view): drop the approval line, ask "Would you like to share it?" as the last line after the checks
- Hermes-written completion card titled "Hermes Collective Wisdom"
- Qualification reasons use the owner wording (consistently across many days / really refined)
- American spelling (organization) in remaining English copy
- Desktop test asserts the current Share button; web test matches the returning notice

* fix(wisdom): pin reconciled Gateway and verify Unicode hash vectors

Pin Gateway 60cd2d6b613ae3cd4a6e65155d1142006d907e78 and byte-identical producer artifacts. Verify every content-order case and package-manifest binding. Validation: 186 focused Python tests, Ruff and contract verifier.

* fix(wisdom): reconcile optional SDK tests and frontend lint

* fix(wisdom): default to agent-written notification summaries

* fix(wisdom): restore deferred install review and browse controls

* feat(wisdom): inspect installed setup with exact package provenance

* feat(wisdom): run native-approved installed setup steps with durable evidence

* fix(wisdom): recover interrupted setup with explicit native consent

* feat(wisdom): hand native installs into guided setup review

* fix(wisdom): continue requested setup with fixed notification copy

* fix(wisdom): preserve setup while waiting for a session model

* fix(wisdom): expose canonical setup review controls on desktop

* fix(wisdom): resume setup after recorded automatic updates

* fix(wisdom): make missing setup prerequisites recheckable

* chore(wisdom): align Agent with verified Gateway contract

* fix(wisdom): stop guessing team slugs in portal links

* fix(wisdom): retire pending advice on account sign-out

* fix(wisdom): cancel advice after terminal account revocation

* fix(wisdom): fence feed responses across account sign-out

* fix(wisdom): checkpoint signed-out feed before reactivation

* fix(wisdom): link proactive advice to scoped notification settings

* fix(wisdom): coalesce queued publication recommendations by version

* fix(wisdom): keep package review navigation local and deferable

* fix(wisdom): reflect installed state in discovery controls

* fix(wisdom): show exact checks before command confirmation

* chore(wisdom): pin bounded analytics privacy contract

* chore(wisdom): pin retired legacy notification contract

* feat(wisdom): review publisher usage with exact sharing copy

* fix(wisdom): align discovery and review check summaries

* fix(wisdom): show expired consent before confirmation

* fix(wisdom): require fresh review for legacy install controls

* fix(wisdom): preserve review expiry across check toggles

* fix(wisdom): retain update policy in native install reviews

* fix(wisdom): surface failed native card edits

* fix(wisdom): persist local command approval reviews

* fix(wisdom): use saved approvals for messaging commands

* test(wisdom): provide scan result in setup handoff fixture

* test(wisdom): exercise Telegram approvals with saved review state

* fix(wisdom): retain suppression policy for offline deferral

* fix(wisdom): reconsider candidates after deferred suppression expires

* fix(wisdom): bind review checks and report verified readiness separately

* fix(wisdom): persist accepted publication intent and recover exact outcomes

* fix(sync): pin UTF-8 tree ordering across writers

* chore(wisdom): pin organisation-scoped Gateway authorization

* fix(wisdom): restrict consent delivery to user-facing sessions

* chore(wisdom): refresh reviewed Gateway contract pin

* fix(wisdom): preserve kept tools in Blank Slate exclusions

* test(auth): reset anonymous fixture with a profile-scoped cache

* fix(wisdom): gate local surfaces and work on current profile entitlement

* fix(wisdom): invalidate quiet tool cache on entitlement changes

* test(wisdom): authorize local consent gateway fixtures

* fix(wisdom): keep entitlement decoding free of native crypto imports

* test(wisdom): provide local entitlement to demo CLI subprocess

* ci: leave upstream workflow unchanged in Wisdom PR

* fix(wisdom): ship package and contracts in Nix wheels

---------

Co-authored-by: hbizi <36184542+hbizi@users.noreply.github.com>
2026-09-11 19:04:06 +10:00
ethernet
c8a9682505 fix(pm): preserve pinned binary inputs in R2
Termux removes old package files, so a pinned URL and hash do not keep
build inputs available. Preserve the exact bytes without changing pins.

Archive every PM HTTP artifact and the Termux runtime inputs by SHA256.
CI reads R2 first. Only a missing object permits an upstream download,
hash verification, immutable upload, and verified readback. Seed the
actual toolchain and payload stores before their consumers run.

Use the public archive as a pinned fallback in PM, bootstrap installers,
and Nix fetchers. Keep network retries bounded and report attempted URLs.
Keep publication credentials in protected CI jobs, not installed clients.

Verification:
- 283 targeted tests passed; five POSIX tests skipped on Windows.
- All 87 preserved Termux packages passed local archive miss/hit checks.
- Native ARM64 ripgrep installed through the mirror and ran successfully.
- Wheel import, workflow lint, Python lint, shell syntax, and pins passed.

Live R2 publication, POSIX tests, and Nix builds remain for native CI.
The real-byte archive checks used loopback HTTP, not the live bucket.
2026-09-10 18:17:08 -04:00
ethernet
6756d11b5f fix(pm): ship full chromium without headless shell
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.
2026-09-10 16:08:03 -04:00
ethernet
d233b6d7a9 feat(release): publish downloads pages to the release bucket
The builds table only ever existed inside a GitHub release body. Emit the
same rows as a tiny standalone page in R2, so a build is readable straight
from the download origin:

  releases/<channel>/index.html     latest stable / canary builds, every
                                    variant, replaced by each tag run
  releases/commit/<sha>/index.html  every expected binary of one commit
                                    build, built or not

scripts/render-builds-table.py keeps ONE row set per mode and renders it
into two sinks (release body markdown, page HTML), so the page can never
list different artifacts than the release. A channel page is a mutable
pointer written from a per-tag job, so it records its release tag and the
writer compares that against scripts/releases/semver.py before replacing:
re-running an older tag cannot regress a newer channel page.

Pages need two registrations to be usable: `.html` maps to
text/html; charset=utf-8 in release-content-types.json (unregistered, R2
serves the object as an octet-stream download) and to no-store in
r2.cache_control_for (the page is a pointer, not an artifact). Page keys
and public URLs come from new r2 layout helpers, shared with
`release.py --build-commit`, which now prints the commit page URL before
dispatching. No workflow change: the existing renderer jobs already carry
the R2 credentials.

Verified: 76 tests over the renderer/release/transport files, including a
loopback R2 PUT proving the page object lands as text/html with no-store.
2026-09-10 11:15:36 -04:00
ethernet
063cf4428a feat(release): build and stage admitted commits without channels
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.
2026-09-10 05:42:18 -04:00
Teknium
8068c09432 fix(desktop): verify the Windows update receipt against the checkout, not cwd
The Windows hand-off script runs from the PRE-update checkout, spawned from
HERMES_HOME by the Desktop. e7eaff68 shipped the post-update verify step
without the cwd pin that landed a day later, so verify_windows_desktop_update(Path.cwd())
looked for apps/desktop/release under ~/.hermes and reported a healthy,
fully updated install as "The updated Desktop executable is missing" (exit 8,
error dialog, app relaunched fine).

Derive the root from the imported hermes_cli package instead; the ps1 no
longer passes a cwd. The cwd pin stays as belt for the other child steps.
2026-09-10 01:25:45 -07:00
ethernet
11c65c4f33 feat(release): dispatch exact-commit builds and bind their stamps
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.
2026-09-10 03:45:03 -04:00
ethernet
e49073ecf3 fix(install): publish source launchers through one writer
Setup searched for console scripts in a checkout-local venv that PM no
longer creates. Publish both commands through the shared writer after
PM setup, using store Python rather than a dependency interpreter.

Native and shell launchers load the selected dependency generation at
boot, retain the custom-home default, and ignore foreign Python paths.
Both installer stages reuse their bootstrap interpreter for publication.
PowerShell passes the resolved home to child processes.

Verified: 57 focused tests passed with one POSIX host skip. Real Windows
launchers, generated shell scripts, and both stage callers ran against
temporary trees. No full cold dependency install or native POSIX install
was run. The user-PATH edge is stubbed in the PowerShell test.
2026-09-10 01:58:34 -04:00
ethernet
5eec230f48 fix(bundle): record tool digests after signing transforms
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.
2026-09-09 23:35:59 -04:00
ethernet
f2db4349e8 fix(pm): inventory features in the staged interpreter
The builder's imported modules could mark an empty dependency tree as
installed. Probe every anchor in one isolated target process. Require
all anchors for a multi-module extra, and process only the selected
tree's .pth files so editable packages retain their launch behavior.

The native builder passes its staged Python explicitly and stops before
manifest publication when the inventory fails. Correct the Hindsight
and Teams anchors using the namespaces in their locked wheels.

Verified: 31 tests passed, 3 host skips. A real target child records its
identity, and a caller mutation back to the builder Python fails the
regression. Both downloaded SDK wheels match uv.lock and pass inventory
and availability checks. Ruff and added-comment checks passed.

No full native package or signing run is claimed.
2026-09-09 21:47:54 -04:00
ethernet
1c4093fdc9 feat(release): stage commit builds with verified receipts
Commit builds use their own immutable namespace and the shared signed
transport. Publish each receipt after its files, and fetch shared files
once only when their receipt records agree.

Summary links retain the full object key. A completed row requires its
own validated receipt and listed object. Missing, corrupt and ambiguous
results remain distinct. Include both universal Windows bundles.

Verified: 85 tests passed across transfer, rendering, candidate and
promotion paths. The subprocess test fetches the rendered download URL
from loopback HTTP. Ruff and added-comment checks passed.

No live R2 writes, workflow dispatch or native package build ran.
The commit-build CLI and workflow changes remain separate drafts.
2026-09-09 21:29:34 -04:00
ethernet
3786bf1478 fix(release): create the revision anchor when absent
The version writer only replaced an existing assignment. Modules
without the field therefore lost the Git-count anchor used for
package distance reporting.

Append the missing assignment and retain updates to an existing one.
A real temporary repository verifies that the emitted count equals
the resulting release commit, with other version files still aligned.
The revision and canary gates passed 20 tests. No Nix build or real
release operation was run.
2026-09-09 21:03:17 -04:00
ethernet
3991d4e8e6 fix(install): report every stage outcome once
Explicit failures exited before the dispatcher could emit its result.
Unchecked writes could instead reach the success log. Run each stage
in an errexit subshell and emit one EXIT result with the actual status.
Escape JSON text before reporting paths or diagnostic messages.

Accept the desktop's home argument, derive the default install path
from it, and export it to child processes. Explicit install paths win.

Verified actual Bash stage calls over disposable repositories and
failed writes, plus the real CLI's argument and platform boundaries.
No complete POSIX installation or native package acceptance is claimed.
2026-09-09 19:49:45 -04:00
ethernet
4188301624 fix(build): propagate icon and queued-open failures
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.
2026-09-09 18:38:26 -04:00
ethernet
e4cc7f09d9 merge: integrate upstream catalog with PM publication
Keep upstream's reviewed catalog as the only plugin name index.
Catalog pins and custom update sources share staged PM validation.
Publish code and dependencies with recovery after process death.
Reject a concurrent enablement change before publishing disabled code.

Use the manifest loader's supported version in the installer. Keep
probe cooldowns for timeouts, not TLS failures that a CA change fixes.
Preserve the backup, uninstall, browser and memory-provider repairs.

Verified with the canonical runner on native Windows ARM64, real Git
repositories, local TLS endpoints and UV dependency generations.
Desktop catalog tests and both TypeScript checks pass. The full suite
and native release builds were not run. No remote push.
2026-09-09 16:49:27 -04:00
ethernet
1c8fae6180 fix(pm): preserve runtime and user state across failure paths
Keep downloads bound to their remote representation and publish through
atomic destination-local staging. Serialize shared partial ownership.

Keep explicit CA trust scoped to provider probes. Preserve checkpoint
history and edited files, validate all profile inputs before dependency
publication, and separate data removal from installed runtime ownership.

Exclude machine-specific PM state from portable transfers. Keep plugin
files and nested skill tools intact. Preserve native test isolation.

Focused native Windows receipts cover the individual repairs and their
integration. This commit does not claim a full-suite or release build.
2026-09-09 15:17:08 -04:00
Teknium
e74c4a00ca Merge pull request #69446 from NousResearch/feat/plugin-catalog
feat: plugin catalog — curated SHA-pinned plugin index (CLI, admission CI, docs, dashboard)
2026-09-09 09:22:21 -07:00
Teknium
e8bac35a40 refactor(whatsapp): bridge.js reuses the helpers' getMessageContent
bridge.js carried its own copy of getMessageContent with the single-layer
envelope list, alongside an unused getContextInfo. With envelope peeling now
living in bridge_helpers.js, the copy would drift (a nested envelope around
a pollUpdateMessage is peeled by the helpers but not by the copy), so import
the shared one instead of keeping a second unwrapping list.
2026-09-09 09:21:12 -07:00
Konstantin Khlopkov
7ecd4d14a5 fix(whatsapp): peel nested envelopes and restore immediate payload return
A quoted message can carry its own envelope stack (ephemeral
wrapping viewOnce wrapping the payload), and a reply itself can be
enveloped: both layers now unwrap iteratively (bounded) before quote
extraction. Peeled top-level envelopes return their inner message
immediately, as before — the template/buttons/list branches only
apply to unenveloped messages.
2026-09-09 09:21:12 -07:00
Konstantin Khlopkov
5de769956f fix(whatsapp): unwrap quoted-message envelopes before extracting quote text 2026-09-09 09:21:12 -07:00
Teknium
d47adec28f Merge origin/main into feat/plugin-catalog
Python plugin CLI/loader/web/tui files taken from main wholesale; the
catalog layer is re-ported onto main's decomposed shapes in the
following commits. plugin_index.py removed (catalog is the sole
discovery system).
2026-09-09 04:15:27 -07:00
Teknium
bf53ff00a7 fix(config): one bounded backups/config/ dir replaces four config.yaml.bak schemes
Four writers each dropped their own uniquely-named copy of config.yaml next to
the real file and none of them ever deleted anything: hermes setup
(config.yaml.bak.YYYYMMDD_HHMMSS, one per run even with no change), the
corrupt-YAML snapshot (config.yaml.corrupt.<ts>.bak), hermes migrate xai
(config.yaml.bak-pre-migrate-xai-<ts>) and the Docker boot migration
(config.yaml.bak-<ts>, .env.bak-<ts>). A home dir accumulated a dozen variants
with no way to tell which mattered.

hermes_cli/config_backups.py::backup_config is now the single writer:
backups/config/config.yaml.<reason>.<YYYYMMDD-HHMMSS>, skipped when the newest
copy for that reason is byte-identical, rotated to the newest five per reason.
backups/ is already excluded from full backups so nothing nests. Legacy
siblings written by the old schemes are moved into the dir on first use;
hand-named copies (config.yaml.bak-my-note) are left alone.

Live: three `hermes setup --non-interactive` runs against an unchanged config
went from three .bak files in HERMES_HOME to one pre-setup copy under
backups/config/; repeated loads of broken YAML produce one corrupt copy
instead of one per process (deduped by content).
2026-09-09 02:36:00 -07:00
ethernet
3f43d634d2 fix(termux): replace the retired libffi runtime archive
Termux removed libffi 3.5.2 from its rolling package pool. The pinned URL
returns 404 and stops runtime-library staging. Pin the available 3.8.0
archive with its downloaded SHA-256, which matches the package index.

Name the package, version and URL when a download fails. Flush staging
progress so piped build logs preserve the failure order. Update the
bionic Python tests to follow the current supplier and binary layout.

Verified all 83 library/license archives and 265 staged shared libraries.
The complete staging step and its verified cache hit both returned 0.
The pinned Python ctypes extension finds its required libffi symbols.
Focused tests: 19 passed, 2 skipped. Bionic execution remains a CI gate.
2026-09-09 00:01:51 -04:00
ethernet
8b7eae99ef fix(pm): own interpreter selection and dependency recovery
Pin uv and uvx to the PM interpreter instead of ambient Python discovery.
A matching dependency stamp cannot prove that installed files still exist.
Repair now rebuilds the recorded workspace and lock in a fresh generation,
checks startup imports, and publishes the selection only after success.

Run startup recovery before dependency activation. Keep manual PM repair
reachable when the selected environment is damaged. Preserve plugin
selection, retry ownership, and the previous generation on failure.
Remove the separate pip, ensurepip, per-extra, and install-time quarantine
ladders. Keep orphan launcher restoration.

Verification: 717 targeted tests passed on native Windows ARM64, with
56 skipped. Ruff, diff checks, and the source-scoped compat check passed.
A disposable real Hermes install recovered deleted YAML and dotenv files,
then printed CLI help with exit 0. Its lock and stamp stayed unchanged.
The full suite and a release build were not run for this change.
2026-09-08 23:39:55 -04:00
ethernet
f6db54ddf2 fix(release): report handles on failed dmg detach
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.
2026-09-08 22:53:41 -04:00
ethernet
5874b11ec6 fix(release): move artifact handoffs to r2
Release jobs duplicate package transfers through GitHub artifacts and R2.
Use immutable R2 tag archives for build and stable candidate handoffs.
Keep stable feeds behind the existing acceptance and publication gates.

Publish tag and commit receipts after all files upload. Verify file sizes
and SHA256 digests during streamed downloads. Refresh request signatures
on retries. Remove candidate TAR copies and duplicate package uploads.
Select the previous Termux package by its published release tag.

Enable the existing uv built-wheel cache for Windows and macOS builds.

Verification: 76 focused tests pass through scripts/run_tests.sh.
Ruff, actionlint and scoped diff checks pass. No live release was run.
2026-09-08 21:56:39 -04:00
Teknium
c32e0acb0e test(desktop): exercise production cwd setup in Windows self-test 2026-09-08 17:13:48 -07:00
fangliquanflq
610b6731d4 fix(desktop): pin Windows update handoff cwd 2026-09-08 17:13:48 -07:00
ethernet
7d2b3b767d merge: integrate upstream/main into ethie/pm-clean
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.
2026-09-08 19:17:39 -04:00
ethernet
d36562ac9f fix(release): provision Windows bundle tools on cache misses 2026-09-08 14:32:30 -04:00
ethernet
54373e4363 better builds table 2026-09-08 13:52:25 -04:00
ethernet
ecefb138e5 fix: release.py still generates fmt with no_changelog 2026-09-08 13:25:23 -04:00
ethernet
7df50e8ab9 test(ci): exercise locked toolchain build consumers 2026-09-08 13:02:14 -04:00
ethernet
b676997d2d ci: provision locked Python and Node toolchains through PM 2026-09-08 12:45:15 -04:00
ethernet
c8aa5608c2 Merge pull request #101420 from ethernet8023/ethie/desktop-update-tests
test(install): cross-OS install/update E2E matrix (windows, macos, linux)
2026-09-08 10:30:44 -04:00
ethernet
67e5572ed1 fix(signing): share the verified runtime resolver for MSIX bundles
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.
2026-09-08 04:20:20 -04:00
ethernet
d6999fa8b8 fix(bundle): omit compressed build wheels from the payload cache
Apple rejects unsigned native code inside cached wheel ZIPs. The macOS
signer can reach the extracted copies, but not the copies inside ZIPs.

Keep the extracted cache and omit compressed wheels from its sdist bucket.
The build machine retains its original cache. uv installs from the extracted
entries, so offline environment rebuilds do not need the compressed copies.

The native regression builds a real source package with uv. Its offline
install succeeds after the server stops and the source files are deleted.
Focused tests report 11 passed and 3 platform skips. A real pilk native
extension also installs and imports from the pruned cache. Apple acceptance
remains pending on the next release run.
2026-09-08 01:47:57 -04:00
ethernet
712734436e fix(pm): make bootstrap and bundle ownership explicit
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.
2026-09-08 00:24:51 -04:00
ethernet
6590ecdc2d fix(termux): pin upstream psutil Android support
Pin Android psutil to upstream commit
380bd2b59c67b0e1b04bbf3a90b11744f4f96644. It contains the unreleased
platform recognition and disk_partitions fixes. Other platforms keep 7.2.2.
Remove the local psutil source patch.

Retain the Git source through requirement normalization and wheel builds.
Use its locked version for offline installation. Provision Git in the
builder and host parsing dependencies through an isolated uv environment.
Wire the source-pin regression tests into Termux verification.

Targeted tests, lock checks, Ruff and shell/workflow checks passed. A real
wheel from the pinned source built and ran on Windows ARM64. Cold-cache
host normalization also passed without packaging installed on the host.
Full bionic compilation remains unverified.
2026-09-07 18:17:06 -04:00
ethernet
7bb62782cc merge: integrate ethie/py314 into ethie/pm-clean
Bring in the Python 3.14 runtime pins and wake-engine changes while
preserving the staged stable-release gate and review fixes.

The merge has no conflicts. Targeted tests on the existing Python 3.11
dev environment passed: 130 passed, 8 skipped. The lock check passed
with Python 3.14.7. Workflow lint and shell syntax checks also passed.
Full Python 3.14 runtime and native release acceptance remain for CI.
2026-09-07 15:12:55 -04:00
ethernet
8c2e88aa4d fix(release): bind stable package versions and manifest origins
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.
2026-09-07 14:59:29 -04:00
ethernet
b0ab0162b0 feat(release): gate stable promotion through the full release pipeline
Run the entire CI workflow before Docker build and tests. Require Nix,
native payload smoke tests, install/update E2E and signed-package upgrade
acceptance before publishing. Keep Desktop Playwright E2E deferred.

Archive tested Docker images and signed bundle candidates with provenance
and hashes. Publishers consume those exact artifacts without rebuilding.
Advance stable channels only after all required publications succeed.
Keep canaries on their separate path and reject direct stable-builder
publication that bypasses the gate.

Move shared release transport, manifests and gates to Python. Keep native
Electron adapters in JS and share feed/MIME facts as JSON. Replace the
R2/feed JS implementation and move its protocol tests to Python.

Verified targeted Python and JS tests, real loopback transport and CLI
execution, temporary Git admission, workflow graph lint, and typechecks.
No live stable release was run. Native signing, package upgrades and real
registry/Store promotion still need their release-run receipts. Separate
services cannot promote atomically. A promotion failure keeps the run red.
2026-09-07 14:40:10 -04:00
ethernet
cd0f97f833 feat(python): pin bundled runtime to 3.14 everywhere (pm, termux lane, CI, installers)
pm python node: 3.14.7+20260901 (freshest python-build-standalone 3.14
build) for the 6 desktop targets; the bionic row moves from the third-party
TUR python3.11 deb to the official termux-main python_3.14.6-1 deb (which
lags PBS by one patch — pinned manually, documented). All 7 digests fetched
from the live sources (PBS release API + termux-main Packages index).
pm/packages.py: main_bin_rel python3.14, deb_package python, bionic fetch
constant, latest_versions guards bionic (no PBS build exists).

termux lane: PYTHON_ABI cp311->cp314, python3.11->python3.14 paths,
libpython3.11.so->3.14, TARGET_ENV 3.11.15->3.14.6 AND sys_platform
linux->android (CPython 3.13+ reports 'android', docs-verified) — linux-
gated markers no longer admit the termux target. runtime_libs.json needs no
change: every python 3.14.6-1 Depends is already staged.

CI: python-version/--python 3.11->3.14 across all 11 workflows incl. the
uv lockfile-check lane. Installers derive the minor from the lock already;
fallbacks bumped. Sandbox images nikolaik/python-nodejs:python3.11-nodejs20
-> python3.14-nodejs22 (tag exists). runtime_repair fall-forward cap now
tracks the <3.15 requires-python window. Docs/README python version claims
updated.
2026-09-07 14:19:18 -04:00
Teknium
a662f9d513 fix(desktop-update): discard failed profile allocation output 2026-09-07 06:09:56 -07:00
Teknium
ca812ba3b5 fix(desktop-update): atomically claim the temporary browser profile
Use mktemp -d before launching the optional UI; skip UI if allocation fails. Native Chrome collision and allocation-failure probes preserve preexisting directories.
2026-09-07 06:09:56 -07:00
Teknium
1bd7364d8e fix(desktop-update): clean only the captured shim profile
Track the path actually launched, preserving the no-UI case and unrelated profiles. Adapted the ownership approach from #104362.

Co-authored-by: liuhao1024 <sunsky.lau@gmail.com>
2026-09-07 06:09:56 -07:00
Rohith Pariki
97f74b8361 fix(desktop-update): clean up throwaway browser profile directory
Deletes the temporary --user-data-dir used by the update UI shim when the browser process is shut down, preventing ~100MB leaks per update. Fixes issue #104350.
2026-09-07 06:09:56 -07:00
yoniebans
15860dfe9f Merge ethie's suite hardening; her input preparation supersedes the dispatchEvent fallback
Both sides fixed the swallowed-click class on the onboarding picker.
Hers is the root cause: persistent 100% zoom through the app's own
setting, verified from both the renderer IPC and the BrowserWindow, and
re-applied before the dismiss loop — scale drift is what moved real
click points onto the wrapping container. The dispatchEvent fallback is
dropped: it bypassed hit-testing, so a leg could pass where a real
user's click would fail.

Comment-only conflicts in managed_uv.py and main_install_repair.py
resolved by keeping the fuller mechanism text (import-order reach and
the legacy hand-off scope).
2026-09-07 14:58:54 +02:00