Skip to content

sync(upstream): merge 74ad422d50 batch - #264

Merged
batumilove merged 1869 commits into
batumi/livefrom
sync/upstream-74ad422d50
Aug 25, 2026
Merged

batumilove merged 1869 commits into
batumi/livefrom
sync/upstream-74ad422d50

Conversation

@batumilove

Copy link
Copy Markdown
Owner

Upstream sync batch (merge-commit landing, #237 pattern)

Merges upstream/main through 74ad422 into batumi/live via a true merge commit so upstream ancestry is recorded (keeps check_fork_delta on the direct path).

Method

  • 174 raw conflicts → recorded ancestry at last integrated base e88d8831d2 (sync(upstream): merge e88d8831d2 batch #245) via -s ours → 18 conflicts, all resolved semantically (relay bridge-loop reuse + contextvars scopes, sync-bridge helpers over upstream session-close lifecycle, systemd restart shortcut kept, watchdog hard-deadline + upstream probes, upstream terminal-job guard over locked cron ledger, background-review test updated for run-token prepare lock).
  • Governance: upstream-base → 74ad422d50; provenance source_head/squash_commit = this branch head line (19aecf2d36/1a2703642d).
  • Local scripts/check_fork_delta.py --fetch-provenance-source: PASS.

Acceptance

Merge with 'Create a merge commit' (not squash) to preserve ancestry.

justcarlosm and others added 30 commits August 23, 2026 18:25
…dirs

Profile-spawned workers (kanban bots, cron jobs) can inherit a PATH of
only version-manager dirs — observed in the wild as one nvm node dir
repeated 7x. The uv-installed browser-use binary is a POSIX sh
trampoline that resolves dirname/realpath through PATH, so it died
with 'realpath: not found … exec: /python: not found' (exit 127)
before its own Python ever started.

_base_subprocess_env now floors the child PATH via browser_tool's
_merge_browser_path (the agent-browser backend already guards the same
hazard), degrading to appending FHS bin dirs if that import is ever
unavailable. Windows is a no-op (.cmd shims don't trampoline).

Verified: unit tests + real uvx browser-use --version under a
nvm-only-PATH worker env, rc 127 -> rc 0.
npm install inside install_node_deps() builds native addons (e.g. node-pty) via node-gyp, which needs a C/C++ compiler. That was never checked, so a missing g++ only surfaced as a generic "npm install failed or timed out" deep inside npm's own output — and because install_node_deps failing short-circuits the rest of main() via `|| return`, users end up with no `hermes` command and no clue why.
Reapply the Playwright dependency update from
NousResearch#77773 and regenerate package-lock.json
against current main.

This fixes the Chromium installation hang under Node 26.

Fixes NousResearch#76312
Supersedes NousResearch#77773
Salvage follow-up for NousResearch#88993: the preflight was defined but never
called from the prerequisites stage or the full-install path, so the
Fedora node-gyp failure (NousResearch#93063) would still occur. Wire it in after
check_node in both sequences.
tests/stress/ was dead weight: its own conftest set
collect_ignore_glob = ["*.py"], so pytest has never collected a single
file from it, the advertised --run-stress flag was a permanent no-op,
and no CI workflow ever invoked the scripts (NousResearch#93135). Rather than wire
a nightly lane for scripts that were never verified end-to-end, remove
the suite. Kanban concurrency behavior remains covered by the regular
tests under tests/hermes_cli/ and tests/gateway/.

Closes NousResearch#93135.
…havior tests

The salvaged hardening tests matched main.ts source text to assert that
fetchConnectionStatus reaches for a bearer and that Apply preflights before
persisting. A rename breaks them while a real auth regression that keeps the
substrings passes.

Make the preflight a first-class option on applyConnectionConfigAtomically so
its ordering is observable, and assert it through the seam: preflight runs
before either write, and a rejected preflight leaves both stores and the
activation untouched.
…nce (NousResearch#93197)

The showAllProfiles browse-mode flag is persisted to localStorage, but
every restart it was force-collapsed anyway: initializeConnectionsRegistry
restores the last-used source via selectConnection, and selectConnection's
post-activation path unconditionally ran $showAllProfiles.set(false).

That collapse is correct for a user click on the connection picker (a
concrete-source action), but the silent boot restore is not a user action.
Gate both reset sites on pendingTarget === null && activeConnectionId ===
null (the fresh-boot state) so the persisted preference survives restart,
while any user-initiated switch still collapses browse mode.

Regression tests cover both directions: boot restore preserves true, a
user switch collapses it.

Fixes NousResearch#93197
…ocal

migrateV1ToRegistry runs exactly once, only when connections.json is absent.
A user who was local at that moment and pointed Settings -> Gateway at a
remote afterwards gets a live remote the registry cannot name: the descriptor
resolves to no connectionId, primary still says 'local', and the boot-time
launch pick force-switches the window onto a fresh local backend seconds after
the sessions list paints. That backend has no provider, so onboarding pops.

Reconcile on read: when the v1 global route names a remote with no matching
registry entry, register it and adopt it as primary/last-used, then persist so
the repair happens once. Narrow on purpose — an already-registered route is
left alone even when primary names something else, because that is the user's
pick in the Connections panel, not drift.

Replaces the hand-edit-connections.json workaround users have been trading.
Reconciliation repairs the drift at its source, but it can still fail to
persist (read-only or full userData), which leaves a window live on a source
the registry cannot name. $activeConnectionId is null there, the preferred-id
guard misses, and the restore re-homes a working connection.

Return early when a connection is live but unnameable. The registry has no
claim on a source it does not know about.
The toggle was gated on having 2+ registered sources, which hid it in exactly
the local-only state the drift produces — the state where a user most needs to
change what launch restores.
Gemini 3 resolves JSON-Schema $ref/$defs pointers inside a
functionResponse.response payload and rejects unknown references with
HTTP 400 INVALID_ARGUMENT ('referenced name #/$defs/...' does not match
a display_name; see vercel/ai#14369).

tool_describe (and any tool whose result is itself a JSON Schema) returns
schema text that previously went back as a structured response, tripping
Gemini's pointer resolution. Detect such results with a $ref-pointer scan
and wrap them as opaque text instead.

Adds regression tests for the wrap path and the unchanged structured path.
…-positive tolerance

Address review feedback:
- Add tests for deeply-nested $ref (recursion), top-level JSON array
  (already wrapped, no 400 path), and $ref without '#/' prefix (stays
  structured).
- Document the deliberate structural (false-positive-tolerant) detection and
  its O(n) cost in the helper docstring.
…g the breaker

Fixes NousResearch#93022. A short session (protection window >= transcript) hits the
"insufficient messages" / "no compressible window" branches twice and
permanently trips the anti-thrash breaker, even though nothing was
eligible to compress - compression was never attempted, so there is
nothing "ineffective" to score. The session then rides past the
threshold with no compaction possible (recovery probes only soften,
not fix, the misclassification).

Distinguish "nothing eligible right now" from "attempted and
underperformed":

- New transient _structural_no_op_backoff_until (in-memory, 300s)
  armed by _record_structural_no_op() at the three structural no-op
  sites: insufficient_messages, no_compressible_window,
  empty_post_handoff_window. No strikes accumulate; auto-compaction
  resumes on its own once the backoff lapses or the transcript outgrows
  the protection window.
- The backoff gates should_compress via
  _automatic_compression_blocked_locally and surfaces in
  _compression_block_reason as "structural_backoff:<seconds>".
- NousResearch#40803's frozen-CLI guarantee is preserved: a transcript that can
  never shrink retries at most once per backoff window instead of
  every turn.
- force=True (/compress) clears an active backoff before attempting;
  record_completed_compaction() lifts it - both prove the transcript
  is compressible/being worked.
- Genuine attempted-but-underperformed verdicts still strike the
  durable ineffective counter unchanged.

Tests: new tests/agent/test_context_compressor_structural_backoff.py;
updated the two tests that asserted the old strike-on-noop behavior.
…ousResearch#93022)

Two suites still encoded the pre-NousResearch#93093 contract that the three
structural no-op branches (insufficient_messages, no_compressible_window,
empty_post_handoff_window) increment _ineffective_compression_count:

- tests/agent/test_compaction_anti_thrash.py::
  TestMinimumMessagesBranch::test_too_few_messages_records_an_ineffective_pass
- tests/run_agent/test_infinite_compaction_loop.py::
  TestCompressNoOpRegistersIneffective::{test_no_op_increments_counter,
  test_two_no_ops_block_should_compress}

Structural no-ops are transcript-shape facts, not evidence of an
incompressible floor, so they now arm _structural_no_op_backoff_until
and leave the strike counter untouched. Update the tests to pin the new
contract (count unchanged, backoff armed via time.monotonic(),
should_compress blocked while it holds) and rename accordingly. The
outcome contract of test_two_no_ops_block_should_compress is preserved:
repeated no-ops still block further automatic compression.
…files

Running `pytest tests/agent/test_prompt_builder.py
tests/agent/test_system_prompt.py` failed
test_build_system_prompt_records_stable_prefix with AttributeError:
'...SimpleNamespace' object has no attribute '_emit_status'
(NousResearch#93018). A truncation warning recorded by test_prompt_builder.py stays
in the shared thread context under plain pytest, so the later file's
build_system_prompt call drains a warning and forwards it to
agent._emit_status - which the test stub lacked.

Harden both sides:

- tests/agent/test_system_prompt.py: _make_agent() stub gains a no-op
  _emit_status, so draining a stray warning is harmless.
- tests/agent/test_prompt_builder.py: autouse fixture drains pending
  truncation warnings after every test, leaving the ContextVar clean.

The order-dependent failure no longer reproduces in either ordering.
…uilder test

Follow-up to the ContextVar-leak fix: the autouse fixture now drains on
both sides (drain(); yield; drain()) so earlier files can't pollute this
file's assertions either.
…under minimal parent PATH

Exercises the real build_subprocess_env()/_resolve_hermes_bin_dir chain (no
helper mocks) under a simulated systemd/cron minimal PATH, the exact call
path cron/scheduler._run_job_script uses. Companion to NousResearch#93082.
The CUA spawn-env tests froze PATH == '/usr/bin:/bin' verbatim.
_sanitize_subprocess_env now (intentionally) prepends the hermes
console-script dir for all sanitized children (NousResearch#92998), so these
assertions flip to the contract: original entries preserved as
suffix, hermes bin dir first when prepended.
…port

ConvertTo-LongPath short-circuits for ordinary long paths (no ~\d alias),
so $script:LastResolver is only assigned when a short path actually needs
expansion. The ResolvedPathReport block read it unconditionally, which is
fatal under Set-StrictMode before any install stage runs (NousResearch#93017: fresh
installs died at line 367 through three different invocation styles).

Initialize it to 'none' — the resolver's own value for "nothing ran" — at
script scope before Set-LongProfileEnvVars can invoke a resolver.
…short-circuits

The ordinary-long-path early return now records why no resolver ran, so
the ResolvedPathReport stays truthful instead of silently inheriting a
stale value from an earlier call in the same session. Diagnostics hunk
taken from PR NousResearch#93100.

Co-authored-by: aniruddhaadak80 <[email protected]>
@coderabbitai

coderabbitai Bot commented Aug 25, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a3cda75f-a21e-4f0e-b4b5-d6313c768b14

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 25, 2026 •

Copy link
Copy Markdown

૮ >ﻌ< ა ci review

ran on cf7cdd5 — merge: sync batumi/live #273 heartbeat supervision into sync

⚠️ Action required

package-lock.json · View job

Locked npm dependency versions changed.

package-lock.json

Package Before After
@playwright/test 1.58.2 1.62.1
nanostores 1.4.0 1.4.2
playwright 1.58.2 1.62.1
playwright-core 1.58.2 1.62.1
➕ @babel/code-frame — 8.0.0
➕ @babel/compat-data — 8.0.0
➕ @babel/core — 8.0.1
➕ semver (nested under @babel/core) — 7.8.5
➕ @babel/generator — 8.0.0
➕ @babel/helper-compilation-targets — 8.0.0
➕ semver (nested under @babel/helper-compilation-targets) — 7.8.5
➕ @babel/helper-globals — 8.0.0
➕ @babel/helper-string-parser — 8.0.0
➕ @babel/helper-validator-identifier — 8.0.4
➕ @babel/helper-validator-option — 8.0.0
➕ @babel/helpers — 8.0.0
➕ @babel/parser — 8.0.4
➕ @babel/template — 8.0.0
➕ @babel/traverse — 8.0.4
➕ @babel/types — 8.0.4
➕ @rolldown/plugin-babel — 0.2.3
➕ blobatar — 2.0.0
➕ js-tokens — 10.0.0
➕ lru-cache — 11.5.2
➕ @types/babel__core — 7.20.5
➕ @types/babel__generator — 7.27.0
➕ @types/babel__template — 7.4.4
➕ @types/babel__traverse — 7.28.0
➕ @types/gensync — 1.0.5
➕ @types/jsesc — 2.5.1
➕ babel-plugin-react-compiler — 1.0.0
➕ driver.js — 1.8.0
➕ empathic — 2.0.1
➕ @babel/code-frame — 8.0.0
➕ @babel/compat-data — 8.0.0
➕ @babel/core — 8.0.1
➕ @babel/generator — 8.0.0
➕ @babel/helper-compilation-targets — 8.0.0
➕ @babel/helper-globals — 8.0.0
➕ @babel/helper-string-parser — 8.0.0
➕ @babel/helper-validator-identifier — 8.0.4
➕ @babel/helper-validator-option — 8.0.0
➕ @babel/helpers — 8.0.0
➕ @babel/parser — 8.0.4
➕ @babel/template — 8.0.0
➕ @babel/traverse — 8.0.4
➕ @babel/types — 8.0.4
➕ @rolldown/plugin-babel — 0.2.3
➕ js-tokens — 10.0.0
➕ lru-cache — 11.5.2
➕ semver — 7.8.5

How to fix:

Add the ci-reviewed label after verifying the version changes are expected.


ℹ️ Info

CI-sensitive file review · View job

PR touches sensitive files, but the ci-reviewed label has been added, approving them.

Sensitive files changed:


debug info

CI timings

CI timings · View report · View job

Wall time 9m34s vs 12m14s (-21.8%). 7 job(s) slower, 4 faster, 1 unchanged.

  • Docs Site / docs-site-checks: -113.0s
  • Python tests / e2e: -13.0s
  • Lint Docker scripts / Lint Dockerfile (hadolint): +11.0s
  • Python lints / Windows footguns (blocking): +8.0s
  • OSV scan / Scan lockfiles / osv-scan: -7.0s

@batumilove batumilove added the ci-reviewed Maintainer reviewed CI-sensitive workflow/action changes label Aug 25, 2026
batumilove and others added 23 commits August 25, 2026 05:27
Upstream commit 69abe41 (fix(desktop): re-home backend after
profile rename) introduced this author; attribution check requires a
mapping file. GitHub login verified via commit author association.
Upstream renamed ci.yml -> ci.yaml (merged in this batch); the
ownership manifest must track the new path so fork delta
classification keeps CI workflow changes owned.
Upstream 693c0e1 removed both case-colliding mapping files (they
cannot coexist on case-insensitive filesystems). Our attribution gate
scans the full upstream range of this sync batch, so the capitalized
variant appeared unmapped. Restore just the capitalized mapping (the
commit e6f59e5 author variant present in the scanned range) — a
single file, no case collision — and own both spellings in the
fork-patch-governance manifest.
[email protected] -> OutThisLife, [email protected]
-> pierrenode, [email protected] -> rroverin, [email protected] -> TomSpoct.
Logins verified via GitHub commit-author associations on upstream commits
in this sync range.
The fork has no larger-runner allocation: ubuntu-latest-96-core,
ubuntu-latest-32-core and windows-latest-32-core jobs queue forever.
Swap all 8 occurrences to ubuntu-latest / windows-latest (free for
public repos). Jobs run slower but complete.
The 74ad422 merge resolution of agent/relay_runtime.py dropped the
fork's logical_llm_contexts field, _run_context_bounded helper, the
context= parameter on _close_scope_handle, and the context-aware
_finish_logical_calls path that relay_llm.py still calls — 28 tests
failed with AttributeError. .github/workflows/ci.yml (fork-owned
patch file) was also dropped, breaking tests/scripts/test_ci_workflow.py.
Both restored from batumi/live onto the upstream-newer file.
The 74ad422 merge dropped RelaySessionCoordinator.finalize_conversation_async
(present on batumi/live); test_relay_shared_metrics_runtime.py async-barrier
tests fail with AttributeError. Restored from batumi/live.
…nish helpers)

RelaySessionCoordinator.finalize_conversation_async calls
host.close_session_async, which was also dropped in the 74ad422
merge. Restored close_session_async with _begin_close_session/
_finish_close_session split from batumi/live, adapted to the
upstream-newer operation-held lifecycle (operation_already_held=True).
… sites

The 74ad422 merge adopted upstream's guardrail_warning field in
_managed_values (6-tuple) but left four sequential-path call sites
(read_preview, drive_preview, annotate_preview, tour et al.) unpacking
5 values — ValueError: too many values to unpack (expected 5).
The merge combined upstream's run_in_session wrapper with the fork's
logical-context design: logical_context.run(run_in_session, ...) re-copies
the session context over the logical one, so the native pop cannot see
the logical scope handle ('not found: scope handle not found') and the
handle leaks (turn.logical_llm_calls != {}). Restore batumi/live's direct
logical_context.run(pop_relay_scope, ...) form.
The merge adopted upstream's 'skip Relay for concurrent turns' guard
(relay_enabled=False on 2nd turn), which breaks the fork's
concurrent-turn design: overlapping logical calls each need their own
turn scope. Restore batumi/live semantics:
- active-turn registry admits concurrent turns (had_active_turn gate
  only defers segment rotation to an idle boundary)
- turn scope pushed in a dedicated turn.context via _run_context_bounded
- RelayTurnContext.context field restored
- end_turn closes the turn scope with context=turn.context
…rm dropped)

The 74ad422 merge took upstream's single-32-core-job js-tests.yml,
which (a) breaks the fork contract test expecting the discovery+matrix
form with two cooldown-protected npm installs, and (b) is tuned for a
paid 32-core runner. The fork's matrix form spreads checks across free
4-core runners.
Both ci.yaml (upstream rename of ci.yml) and ci.yml (restored fork
file) existed at HEAD with workflow name CI and identical triggers and
concurrency group - two live workflows named CI cancelled each other
mid-run (3 consecutive cancelled dispatch runs with zero failing jobs).
Keep the fork's ci.yml, drop the upstream ci.yaml.
The merge replaced the fork's 12-slice matrix tests.yml with upstream's
single-job form, dropping the slice_count workflow input — ci.yml's
'slice_count: 12' then caused workflow startup_failure. Restore the
fork's sliced form (parallel free-runner friendly), keeping
HERMES_TEST_WORKERS: 4 per slice.
Upstream's test reads .github/workflows/ci.yaml; the fork keeps the
workflow at ci.yml. The contract itself passes against ci.yml: every
needs.detect.outputs.* reference is declared.
…-labels

The restored fork ci.yml (and the contract test now pointing at it)
join the free-runner migration patch family after the ci.yaml removal.
Resolve gateway/run.py in favor of batumi/live: #273 replaced the
inline loop-heartbeat block with _start_loop_heartbeat_supervised()
(supervised early start + idempotent revival). CI on the PR head is
green (run 32906328252).
@batumilove
batumilove merged commit b7a04a4 into batumi/live Aug 25, 2026
64 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-reviewed Maintainer reviewed CI-sensitive workflow/action changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.