Commit Graph

7814 Commits

Author SHA1 Message Date
Peter Steinberger 7a378f1f8e improve(ci): rebalance GitHub-hosted compact test lanes (#123383)
* perf(ci): rebalance GitHub-hosted compact hints

* test(ci): exclude failed hosted timing samples

* fix(ci): keep Codex state test in one Vitest lane
2026-08-13 17:45:33 -07:00
Peter Steinberger 20be26cfe2 refactor(test): remove residual test-only seams (#123168)
* refactor(test): remove residual test-only seams

* fix(test): fresh-load Vitest ownership configs

* test(infra): repair boundary test routing

* test(infra): use landed Codex test owner
2026-08-13 17:16:55 -07:00
Peter Steinberger 1348387076 refactor(plugins): replace node-llama-cpp with managed llama-server (#123105)
Move llama.cpp chat and local embeddings onto a verified externally managed llama-server runtime. Remove the in-process native runtime, forked embedding workers, and node-llama-cpp dependency while preserving guided setup, local GGUF models, tool-capable agent runs, diagnostics, and operator docs.
2026-08-13 16:58:20 -07:00
joshavant 1cb9f70cb3 fix(gateway): isolate full model catalog discovery 2026-08-13 18:57:50 -05:00
Peter Steinberger 1287befae7 fix(release): preserve upgrade diagnostic probe (#123338)
* fix(release): preserve upgrade diagnostic probe

* test(vitest): reinstantiate contract projects for audits

* style(test): format upgrade diagnostic assertions

* test(ui): isolate route transition outlet fixture
2026-08-13 16:56:43 -07:00
Peter Steinberger 4a5aeb8dd2 improve(ci): shorten GitHub-hosted outage runs (#123294)
* ci: run push compacts without tooling lanes and stripe giants three-way

* fix(ci): keep CompactNodeTestPlanMode internal

knip --production flags the exported type as unused; no external module
imports it.

* ci: shard hosted lint and node tests

Split core oxlint across hosted runners and use backend-specific compact Node admission caps while preserving Blacksmith behavior.

* test(ci): guard plugin prerelease planner isolation
2026-08-13 15:19:15 -07:00
Peter Steinberger f8bca11d77 chore(ui): add dead-CSS audit script and delete unreferenced stylesheet rules (#123178)
* chore(ui): add dead-CSS audit script and delete unreferenced stylesheet rules

* fix(scripts): type-safe AST walking in the dead-CSS audit

* fix(scripts): detect ternary-headed class stems and restore live wizard rules
2026-08-13 14:53:17 -07:00
Peter Steinberger e7aa4d203e fix(ci): run complete plugin tests for direct changes (#123314) 2026-08-13 14:29:24 -07:00
Peter Steinberger ffa8a1d892 fix(release): print post-update config diagnostics (#123221) 2026-08-13 14:24:22 -07:00
Peter Steinberger b3d5265f58 fix(docker): harden runtime images against CVE surface (#123282)
* fix(docker): harden runtime image dependencies

* chore(deps): update container security dependencies

* docs(docker): explain image security contents

* test(browser): align file-chooser and install tests with #114506 contract

* test(browser): restore extension install test isolation

* test(browser): add temporary CI diagnostics for pre-registration refusal

* test(browser): make install fixture interpreter hermetic

The suite passed process.execPath as the native-host interpreter; on
GitHub-hosted runners the hostedtoolcache node binary is group/world-
writable, which installChromeExtensionBootstrap correctly refuses, so
every registration test failed CI-only. The fixture now provides an
owned 0700 interpreter; only the launcher-exec test keeps the real
node it must spawn.

* fix(qa-lab): stop re-polling after a probe consumes the discovery deadline

The Matrix health-probe loop re-entered when the probe timeout fired
marginally before Date.now() crossed the deadline, starting a doomed
extra probe. Flaked on contended CI runners as 'expected 1 fetch, got
2'. A timed-out probe now ends discovery.

* test(ui): poll the callout inset invariant in device-scope E2E

One-shot boundingBox reads raced the nav-collapse transition and
intermittently measured a 20px stale offset on CI.
2026-08-13 14:02:39 -07:00
Peter Steinberger 9415181b75 fix(ui): make active visibility pill distinct from its hover state (#123173)
* fix(ui): make active visibility pill distinct from its hover state

* test(ui): advertise sessions.create in the control-ui mock harness

* ci: refresh pull_request run after zombie-queued Blacksmith jobs
2026-08-13 12:42:40 -07:00
Peter Steinberger d805562a84 fix(ui): verify referenced translation keys (#123279) 2026-08-13 11:32:56 -07:00
Peter Steinberger 2a70d849e8 improve(ci): stripe giant compact test groups (#123142)
* ci: stripe media-ui, gateway-core, and security compact groups

* fix(ci): preserve compact stripe config ownership
2026-08-13 10:46:38 -07:00
Peter Steinberger 6c9916a48a feat(runners): publish atomic device runner inventory (#123094)
* feat(runners): publish atomic node inventory

# Conflicts:
#	docs/.generated/plugin-sdk-api-baseline/agent-harness-runtime.json
#	src/gateway/server-methods/environments.ts
#	src/gateway/worker-environments/device-provider.test.ts

* fix(runners): refresh topology on inventory removal

* fix(runners): resolve session host type overlap

* fix(protocol): document mobile runner inventory event

* fix(runners): project authoritative session host state

* docs(nodes): clarify prepared session host status
2026-08-13 04:54:26 -07:00
Vincent Koc 57fabb2c9c fix(release): allow ANSI in reusable job logs (#123129)
Preserve ANSI output for reusable validation job-log reads while retaining a bounded fallback for GitHub CLI versions that do not support the raw-output flag.
2026-08-13 19:19:03 +08:00
Peter Steinberger c218187244 fix(ci): stop killing healthy discord Vitest runs and repair partial runtime-env mocks (#123131)
The discord extension shard's silent transform/import startup (~210s measured
on a loaded macOS host) exceeded the run-vitest wrapper's 120s default
no-output timeout, so the watchdog killed healthy runs (#123025). The config
now gets the extra-long budget like the other large shards.

Three discord tests mocked openclaw/plugin-sdk/runtime-env with bare factories
missing most exports; under isolate=false they poison the shared worker module
cache and break later files that bind logVerbose/sleepWithAbort through the
shared process test harness. They now spread importOriginal and override only
their stubs.

Fixes #123025
2026-08-13 03:54:22 -07:00
Ayaan Zaidi d2afbd05ad refactor(plugin-sdk): replace API baselines with diffs (#123036)
* refactor(plugin-sdk): replace API baselines with diffs

* perf(plugin-sdk): bound API diff resources

* fix(plugin-sdk): isolate API diff dependencies

* fix(release): forward Plugin SDK acknowledgement

* fix(release): enforce SDK acknowledgement on publish

* chore: preserve generated-doc ignore policy

* fix(release): freeze SDK API evidence before publish

* fix(ci): satisfy SDK evidence guards

* fix(release): bind complete SDK evidence

* fix(release): authenticate plugin SDK evidence

* fix(plugin-sdk): abort interrupted API diffs

* test(ui): freeze page clock in background-tasks rail e2e

The rail transcript is compared byte-for-byte across the detail-panel
round-trip while it renders live relative ages; on slow CI runners the
second boundary ticks between the two reads (11s -> 12s) and fails the
equality assertion. Fix the page Date with Playwright setFixedTime while
keeping timers running so the tasks.list polling assertions still hold.

Repro: a 1.5s stall between the reads fails pre-fix with the exact CI
diff and passes post-fix.

* fix(scripts): drop unused export on dependency-evidence CLI main

Knip's workflow scan re-roots script references after an actions/checkout
step that sets path:, so the new trusted-tooling checkout in
openclaw-npm-release.yml stops marking this CLI as a workflow entry and
its exported main() surfaces as an unused export in check-dependencies.
Nothing imports main; the module invokes it through its own entry guard,
so the export keyword was dead surface either way.

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-13 03:45:36 -07:00
Vincent Koc 9794a4a49c fix(release): bind reusable evidence verifier source (#123115) 2026-08-13 18:19:28 +08:00
Peter Steinberger 581e67e887 ci: refresh compact shard packing hints from current main runtimes (#123100) 2026-08-13 02:38:50 -07:00
Vincent Koc 93cdb610b3 fix(release): keep validation evidence reuse dependency-free
* fix(release): keep evidence reuse dependency-free

* fix(release): preserve preflight failure trailer
2026-08-13 17:26:31 +08:00
Peter Steinberger ccc1920068 improve(telegram): cut cold channel setup import latency (#122955)
* perf(telegram): keep setup entry on light graph

* fix(plugin-sdk): complete private UI hint boundaries
2026-08-13 01:55:47 -07:00
Peter Steinberger 7235943790 fix(release): align survivor session metadata assertion (#123068)
* fix(release): align survivor session metadata assertion

* test(release): cover SQLite survivor metadata
2026-08-13 01:41:53 -07:00
Peter Steinberger 3b6e54041f ci: replace dependency sticky disk with exact cache (#123040)
Amp-Thread-ID: https://ampcode.com/threads/T-019ff3db-c467-70ad-8ed3-81f2ba94b0c0

Co-authored-by: Amp <amp@ampcode.com>
2026-08-13 01:13:25 -07:00
Peter Steinberger cc2fc55f9b feat: portals — expose agent-run dev servers to the operator (#122536)
* feat(protocol): add portal methods and event

Bump the reviewed protocol owner-module count from 55 to 56.

* feat(gateway): add portal service and reverse proxy

* feat(agents): add portal tool

* fix(gateway): refine portal URL and proxy auth

* refactor(gateway): keep portal helper types private

* fix(gateway): declare portal transport service

* test(gateway): satisfy portal proxy lint

* test(gateway): narrow websocket payload types

* refactor(protocol): compact portal schema exports

* fix(gateway): export portal protocol types

* feat(ui): add portals page

* docs(gateway): add portals guide

* fix(gateway): dial portal targets via localhost dual-stack

Vite and other Node >=17 dev servers bind ::1 only for localhost, so a
fixed 127.0.0.1 dial 502s on the default path. Use hostname localhost
with family autoselection and rewrite Host to match.

* fix(gateway): type portal dual-stack connection

* fix: satisfy portal integration gates

* fix(gateway): isolate portal cookie jars per target

Cookies are hostname-scoped, not port-scoped, so the per-port origin
split alone let Gateway plugin-auth cookies reach agent-run targets.
Forward only cookies carrying this portal's own name prefix (stripped),
rewrite target Set-Cookie names to the prefixed form incl. the WS 101
handshake, and drop Domain attributes.

* fix(ui): detect unreachable portals behind proxied gateways

Probe the portal origin from the browser (no-cors, 4s timeout) and show
a recovery notice with the gateway-host URL instead of a dead iframe
when only the gateway port is exposed (Serve/Funnel/reverse proxy).
Docs: cookie isolation + reachability; zh-CN glossary entry.

* test(ui): satisfy portal reachability lint

* test(gateway): provide control UI request hosts

* chore(protocol): regenerate after rebase

* fix(gateway): namespace portal auth cookies by listener

* fix(gateway): scope portal token URLs to write-capable clients

The portal bearer token rides in the summary url/tokenQuery; portal.list
is operator.read and portal.changed fans out to read subscribers, so a
read-only client could harvest an openable URL. Make those fields
optional, redact them from read-scope list responses, and drop them from
every portal.changed broadcast; write/admin clients still receive them
and the UI refetches the list on change.

* docs(web): list the portals route

* fix(gateway): type portal open credentials

* docs(gateway): clarify portals PORT/PUBLIC_URL are agent-set

Opening a portal creates only the proxy listener; the agent sets PORT
and PUBLIC_URL in its own exec command, matching the portal tool
contract. Removes the implication of an automatic env handoff.

* chore(protocol): regenerate portal models

* style(gateway): format portal method-order assertions

Rebase union-merge left the portal.list assertion wrapped; oxfmt fits it
on one line.

* chore(plugin-sdk): refresh API baseline after rebase

* chore(plugin-sdk): refresh API baseline after rebase

* chore(protocol): refresh portal event order after rebase

* chore(plugin-sdk): refresh API baseline after rebase

* fix(gateway): pin portal referrer policy to no-referrer

The portal URL carries its bearer token in the query, and upstream
response headers are copied verbatim, so a target answering with
Referrer-Policy: unsafe-url could leak that URL to every third-party
origin it references. Force no-referrer after the copy and drop any
inbound Referer that still carries the token before forwarding.
2026-08-13 00:46:11 -07:00
Peter Steinberger fce5b6688a refactor(tooling): enforce zero wrapper and export debt (#123020) 2026-08-13 00:40:32 -07:00
Jesse Merhi b2e023adc6 test(perf): benchmark gateway plugin snapshot load 2026-08-13 17:03:19 +10:00
Vincent Koc ac110917e1 fix(ci): stream npm pack receipt to disk (#123019) 2026-08-13 14:30:27 +08:00
Leon-SK668 cc2ed816be fix(mac): preserve Xcode preflight failure diagnostics (#121170) 2026-08-13 14:17:32 +08:00
Vincent Koc fd353ee5d7 fix(parallels): recover migration-refused gateway startup 2026-08-13 13:14:22 +08:00
Vincent Koc 1e7a76f49c fix(e2e): declare agents-delete fixture owners (#123000) 2026-08-13 13:07:55 +08:00
Vincent Koc 3bc665f6ae fix(ci): sanitize AI manifest during installer pack (#122952) 2026-08-13 13:02:43 +08:00
Peter Steinberger 9bf9bcebc4 refactor(gateway): remove suspension mock replay (#122977)
* test(gateway): remove suspension mock replay

* test(agents): stabilize headless timeout assertion
2026-08-12 21:24:50 -07:00
Peter Steinberger e45a9460ce docs: repair spellcheck and anchor drift (#122960)
* docs: repair spellcheck and anchor drift

* docs: satisfy markdown anchor lint
2026-08-12 20:50:56 -07:00
Peter Steinberger 2c3e537cb8 fix(deploy): repair probes that silently pass and a blueprint that cannot boot (#122963)
Three defects proven by running the shipped configs:

Kubernetes probes checked only the status code against /startupz, but the
pinned image predates that route and the Control UI answers unknown paths
with a catch-all 200. A wedged pod was therefore marked Ready forever.
Probes now assert the JSON probe contract and target routes the pinned
image actually serves; verified in a kind cluster where the old command
exits 0 on the missing route and the new one exits 1.

render.yaml set no dockerCommand, so the image CMD ran without
--allow-unconfigured and a fresh Render disk exited 78 with 'Missing
config' before binding. Reproduced locally with Render's exact env.

The Cloudflare Container readiness poll had the same route mismatch
against operator-supplied official image digests; it now polls /healthz,
which every published image serves.

Also replaces an R2 verification step that could never fail: wrangler
cannot list object keys, so the documented command 404'd into || true.
2026-08-12 20:49:54 -07:00
Peter Steinberger 4d54c3f1a1 refactor(config): retire dead streaming.progress.render key (#122927)
* refactor(config): retire dead streaming.progress.render key

The key had zero runtime consumers after #122552. Core doctor now strips it via stripRetiredTuningKnobs, and production LOC is net -13.

* fix(tooling): pin plugin SDK surface counts to the reduced export set

The retired progress-draft render reader counted twice via channel-outbound and channel-message's wildcard re-export.
2026-08-12 20:36:40 -07:00
Peter Steinberger f5ad8735d1 feat(ui): open subagent details in chat sidebar (#122941)
* feat(ui): open subagent details in chat sidebar

* chore: drop changelog edit (release generation owns it)

* refactor(ui): drop duplicate close in subagent detail panel

The sidebar region header already owns a Close Details control in both
wide and narrow layouts; the panel-local X duplicated it 40px away.

* fix(ui): stop subagent transcript loader when pane presentation retires

Pane retention wipes sidebarContent directly, so the detail slot's
render-time reset can never run again; a pending refresh timer plus
incoming task events kept refetching chat.history for a hidden panel.

* docs(ui): note close-control ownership in subagent detail header

* fix(ui): break transcript renderer import cycle

* fix(ui): use shared action cursor for subagent rows
2026-08-12 20:11:13 -07:00
Peter Steinberger 812bbd8884 docs(deploy): add verification, cost, observability, and troubleshooting to the Cloudflare guide (#122932)
The template shipped without the operator-facing half: no way to prove the
restore path works before depending on it, no cost signal for the always-on
versus webhook-only choice, no log surfaces, and no failure-mode index.

Adds an architecture diagram, a restore rehearsal, measured recovery numbers
from the real-R2 proof, provisioned-resource cost guidance, wrangler tail
observability, and a troubleshooting index covering image architecture,
Litestream S3 credentials, the startupz/readyz split, and ephemeral-disk
config loss.
2026-08-12 20:00:09 -07:00
Vincent Koc 3eef8ebfd5 fix(parallels): preserve plugin inventory during updates (#122912)
* fix(parallels): preserve plugin inventory during updates

* fix(parallels): preserve dev update plugin inventory
2026-08-13 10:26:02 +08:00
Vincent Koc d00e4ee324 fix(e2e): verify suspend control over WebSocket (#122888) 2026-08-13 09:56:26 +08:00
Peter Steinberger fba9ad43bc fix(ci): run affected extension suites when changed-test planning falls back (#122885)
The PR-changed test planner fails safe to the compact full-suite plan for any diff touching packages/**, but that compact plan excludes all extension test configs, so mixed package+extension PRs landed with zero extension test execution (escapes: PR #120534 breaking extensions/codex run-attempt.native-hook-relay.test.ts, PRs #122163/#121522 and cd7b7f639d breaking media-understanding-provider.test.ts and thread-lifecycle.test.ts on main full runs). The preflight now appends whole-config shards for the diff's touched extensions whenever the precise plan fails safe; whole configs (not precise targets) because the fail-safe cause leaves the non-extension diff's extension impact unbounded.
2026-08-12 18:51:00 -07:00
Vincent Koc af49764206 fix(ci): ignore zombie-only Vitest process groups (#122759) 2026-08-13 08:46:22 +08:00
Vincent Koc 8733dcd05f fix(ci): expose AI pack diagnostics (#122786) 2026-08-13 08:25:58 +08:00
Peter Steinberger 1ca60fbc3a refactor(agents): make multi-agent ownership explicit (H2-1 core) (#114388)
* refactor(agents): make roster ownership explicit

* feat(config): materialize legacy agent roles

* fix(cron): migrate legacy owners at startup

* feat(gateway): expose agent selection contracts

* fix(gateway): enforce agent-scoped authorization

* docs(config): document explicit agent ownership

* fix(config): pin retained owner workspace

* fix(gateway): target hook wakes at effective agent

* fix(sessions): preserve fixed-store ownership

* fix: preserve retained agent ownership

* fix: preserve legacy agent ownership across runtime surfaces

* fix: fail closed on ambiguous session ownership

* fix: preserve compatibility owners across dispatch and writes

* fix: preserve retained agent projections

* fix: preserve agent ownership compatibility

* fix: preserve per-agent heartbeat guidance

* fix: preserve compatibility owners in generic paths

* fix: enforce configured ownership in session paths

* fix: defer remote roster selection

* fix: preserve ownership across session and config writes

* fix: fail closed on ambiguous restored ownership

* fix: preserve explicit ACP and legacy ownership

* fix: honor durable fixed-store ownership

* fix: enforce fixed-store owner authority

* fix: preserve ownership evidence boundaries

* fix: honor resolved session ownership

* fix: align compatibility ownership paths

* fix: persist legacy main store ownership

* fix: close ownership fallback gaps

* fix(agents): close retained owner compatibility gaps

* fix(agents): enforce session owner resolution

* fix(agents): complete session owner resolution sweep

* fix(agents): preserve durable session ownership

* fix: complete persisted session owner routing

* fix: thread prepared session owners

* fix: preserve stable session ownership

* fix: enforce session ownership boundaries

* fix: close session ownership delta gaps

* fix: reconcile session ownership after rebase

* fix: reconcile ownership with current main

* fix: align session store path imports

* fix: align session store config path import

* fix: reconcile explicit ownership CI

* fix: reconcile ownership rebase checks

* fix: align ownership ci contracts

* fix: align ownership rebase checks

* fix: preserve compatibility owner during setup

* fix(doctor): migrate ownerless heartbeat monitors

* fix(gateway): preserve explicit session ownership

* test: align ownership fixtures after rebase

* test: complete plugin manifest fixture

* test: align runtime context mocks

* fix(gateway): preserve alias routing for existing sessions

* style: format agent routing update

* fix(gateway): preserve selected owner during alias routing

* style: normalize rebased ownership files

* fix(gateway): preserve owner through global alias routing

* fix(gateway): preserve explicit ownership at HTTP boundaries

* fix(gateway): validate compatibility model ownership

* fix(agents): reconcile strict session ownership

* fix(agents): contain media yield callback failures

* fix(agents): avoid eager bare-key owner resolution

* chore: refresh rebased ownership baselines

* chore: align hosted plugin SDK baseline

* chore: refresh ownership baselines after main sync

* chore: refresh ownership baselines after main sync

* test: align routed event owner fixtures

* chore: retrigger CI after runner startup failure

* chore: refresh ownership SDK budgets after main sync

* fix(tasks): require agent identity for bare owners

* chore: align Linux plugin SDK baseline

* chore: remove release-owned changelog entry
2026-08-12 15:55:16 -07:00
Peter Steinberger 93f5e0f1f6 fix(build): restore exact cache output snapshots (#122837) 2026-08-12 15:20:11 -07:00
Peter Steinberger 25121bdb45 perf(ci): tail-balance compact large shards (#122818)
Amp-Thread-ID: https://ampcode.com/threads/T-019ff3db-c467-70ad-8ed3-81f2ba94b0c0

Co-authored-by: Amp <amp@ampcode.com>
2026-08-12 14:25:14 -07:00
Peter Steinberger 5fda9d09f0 feat(deploy): add experimental Cloudflare deployment template (#122768)
* feat(deploy): add experimental Cloudflare template

* fix(deploy): keep container SSH debug access opt-in

* fix(deploy): satisfy scripts tsgo lane and model wrangler entrypoint in knip

* fix(deploy): model wrangler-consumed exports and isolated dependency in knip

The Worker default export and Durable Object class are instantiated by
wrangler from wrangler.jsonc, and @cloudflare/containers lives in the
template's isolated package.json — modeled per the deadcode checks' own
guidance rather than root-manifest changes.

* docs(deploy): align SSH bootstrap flow with the disabled-by-default policy
2026-08-12 14:07:48 -07:00
Peter Steinberger 7595d6f432 test(tooling): remove helper replays (#122790)
* test(tooling): remove helper replays

* refactor(tooling): inline fixture json serialization
2026-08-12 13:31:23 -07:00
Peter Steinberger 3edc9c2be5 perf(ci): route compact queue tails to 8-vCPU runners (#122666)
Amp-Thread-ID: https://ampcode.com/threads/T-019ff3db-c467-70ad-8ed3-81f2ba94b0c0

Co-authored-by: Amp <amp@ampcode.com>
2026-08-12 12:57:29 -07:00
Peter Steinberger dceb2c343c refactor: retire due compat-ledger surfaces (context-engine host params, deactivate alias, logging internals) (#121845)
* refactor(plugins): retire deactivate hook alias

* refactor(plugin-sdk): prune retired facade exports

* test(logging): isolate logger test controls

* refactor(logging): internalize file transport controls

* test(plugin-sdk): preserve retired facade coverage

* test(auto-reply): remove stale diagnostic imports

* refactor(logging): delete dead config-read guard

shouldSkipMutatingLoggingConfigRead had no production caller even on main;
it survived the dead-export scan only via logger's testApi re-export. The
test-isolation commit removed that mask, exposing the fossil. Delete the
guard, its test-only re-export, its mock entry, and its dedicated test file.

* refactor(plugin-sdk): retire due compatibility subpaths

* test(plugin-sdk): type group policy predicates

* refactor(plugin-sdk): split removed subpath records

* refactor(secrets): remove retired collector barrel

* test(plugin-sdk): tighten wildcard surface pin

* refactor(plugin-sdk): retire matrix facade metadata

* style(plugin-sdk): format facade metadata

* fix(ci): load channel setup contracts from source

Repair the main-owned regression from 99d662473c (Peter Steinberger): the new env-contract test could consume stale ignored dist metadata instead of the checked-in plugin declaration.

* test(plugin-sdk): refresh API baseline after rebase
2026-08-12 12:41:27 -07:00
Peter Steinberger 2c5f024145 refactor(tooling): simplify plugin boundary checks (#122781) 2026-08-12 12:39:09 -07:00