Commit Graph

90 Commits

Author SHA1 Message Date
Peter Steinberger d2d055b8d4 feat(gateway): auto-suspend idle cloud workers with suspendAfter (#130242)
* feat(gateway): auto-suspend idle cloud workers

* feat(crabbox): enable bounded warm images by default

* docs(gateway): explain idle worker suspension and warm images

* Revert "feat(crabbox): enable bounded warm images by default"

This reverts commit 546466eaa9.

* docs(gateway): keep warm images opt-in pending a proven capture boundary

Review finding: default-on capture would persist setup-created state outside
the scrubbed worker root into provider images for profiles that never opted
in. suspendAfter pairs with warmImage: true for warm wakes.
2026-08-26 11:30:25 -07:00
Peter Steinberger 9d9dc31275 feat(memory): session provenance, admission policy, and openclaw memory forget (#130151)
* feat(state): add memory entry origins and session tombstone tables with session-aware write provenance

Additive same-version per-agent tables (memory_entry_origins, memory_session_tombstones) declared canonically with lazy idempotent ensure; read-only agent DB access exposed through the SDK; memory-write observers and the session-memory hook record the authoring session; archived narrative transcripts classified by authoritative run identity.

* feat(memory): admission policy, entry provenance, and openclaw memory forget

memoryPolicy.excludeSessions keeps configured sources out of the dreaming pipeline with recorded exclusions; promotion writes are marker-addressable and carry per-session origins through consolidation; memory forget purges whole entries and every derived artifact (corpus lines, diary quotes, index/FTS/vec/cache, short-term state, backups), reports curated agent writes from transcripts, and tombstones purged sessions so ingestion, backfill, and transcript indexing never re-admit them.

* docs(memory): document admission policy, memory forget, and provenance boundaries

* fix(memory): open the vec probe through openNodeSqliteDatabase

Kysely guardrail forbids direct node:sqlite constructors in production; the in-memory extension probe now uses the canonical opener.

* fix(memory): resolve archived and explicit sessions in memory forget

Explicit --session selectors union live session windows, transcript archives, and exact unresolved ids so an operator-named session always purges and tombstones instead of silently no-oping after lifecycle archival; reports carry per-session resolution sources. ClawSweeper P1 on #130151.

* fix(memory): reconcile consolidation origins for every workspace agent

Shared workspaces record entry origins per source agent; consolidation now re-keys and prunes origins in each participating agent's database (membership from the authoritative dreaming workspace mapping), so a non-owner agent's later memory forget still finds the live consolidated entry. ClawSweeper re-review P1 on #130151.
2026-08-26 10:57:04 -07:00
Peter Steinberger 2e017baa7b docs(plan): record CUA production vertical, node-channel fix, and channel schema repair (#130117) 2026-08-26 06:13:15 -07:00
Peter Steinberger a82042f204 feat(crabbox): opt-in profile warm images for cloud workers (#130087)
* docs(plan): add worker hibernation design note

Evaluates dormant leases, checkpoint-based warm start, and serverless
backends for a worker-environment hibernation tier; proposes a plugin-only
phase 1 (Crabbox checkpoint fork warm images) with SDK/store phases gated
on maintainer acceptance.

* feat(crabbox): add opt-in profile warm images

* fix(crabbox): preserve warm image machine class

* refactor(crabbox): tighten warm-image seams after review

* fix(crabbox): budget warm-image capture for real snapshot round trips

The 60s command bound starved the scrub and checkpoint-create phases under
coordinator latency, silently degrading every teardown to cold-only.
Live-measured on AWS.

* docs(plan): record worker-hibernation acceptance and live proof

Phase 1 live-proven: local-container full loop (cold 101s vs warm fork 40s,
scrub boundary verified) and AWS cold provisioning with graceful degrade at
the coordinator admin gate; named upstream follow-ups.

* fix(crabbox): make warm-image lifecycle recovery-safe

Delete least-recently-used provider snapshots before image index admission.

Recover stale empty capture reservations without breaking single-flight.

Persist effective machine classes across restarts and revert heartbeat coupling.

Align the hibernation plan with the exact-class warm-image key policy.
2026-08-26 05:58:00 -07:00
Peter Steinberger 8a1ff3966b feat(workers): run OpenClaw and Codex on the same cloud profile (#127752)
* feat(workers): run both harnesses on one cloud node profile

* docs(workers): explain shared OpenClaw and Codex cloud profiles

* fix(workers): preserve trusted Codex cloud enrollment

* docs(codex): clarify bundled cloud plugin eligibility

* fix(workers): honor Crabbox bootstrap retries

* fix(workers): allow cloud profile setup to finish

* fix(workers): reject unsupported cloud execution modes

* refactor(workers): split cloud placement modules

* fix(workers): preserve completed container results
2026-08-25 00:13:29 -07:00
Peter Steinberger 3fa3276381 feat(nodes): opt-in container isolation for node-hosted worker sessions (#128447)
* feat(nodes): opt-in container isolation for node-hosted worker sessions

nodeHost.workerRuns.isolation=container runs each worker session inside a
Docker-compatible container (docker/OrbStack/podman): stdio launch transport,
exactly two bind mounts (bundle read-only, workspace read-write), allowlisted
env, and the container itself as the durable launch identity — created stopped
and journaled before the descriptor is delivered, killed/removed on cancel,
fence, shutdown, and recovery, with an owned-orphan sweep at startup. Missing
or changed engines disable hosting with an explicit diagnostic instead of
falling back to bare processes. Additive nullable worker_container_json column
on node_worker_launches (schema version unchanged).

* fix(test): base-shape fixture skips additive columns of stripped tables

node_worker_launches is excluded from claw-scoped state schemas, so the
read-only compat fixture cannot drop its additive column there; drop only
columns whose owning table exists.

* fix(test): guard split destructuring in base-shape fixture

* test(state): record worker_container_json in the canonical additive-column list

* fix(nodes): harden container isolation per review findings

- Revalidate the engine daemon target immediately before container creation;
  a replaced daemon receives zero create/start requests (regression proves it).
- A pending launch keeps its worker slot until the journaled container is
  killed/removed; cancellation cannot free capacity over a live container.
- Windows node hosts fail closed at startup for isolation=container with an
  actionable diagnostic (native paths cannot be container mount targets).
- Container identity moves from an additive column to the same-version
  companion table node_worker_launch_containers (bare STRICT, lazily ensured
  on first container write, pruned with the launch journal): the launch table
  is contract-optional and shipped readers reject additive columns there. An
  exact v9 predecessor now provably opens and uses the journal after the
  candidate populated container rows.
2026-08-24 00:19:45 -07:00
Peter Steinberger 259a14b83b feat(nodes): derive worker capacity from CPU cores and make it configurable (#128352)
Node session hosting was capped at a hardcoded 2 concurrent worker sessions.
The default is now one worker slot per available CPU core (clamped to 1..1024),
and nodeHost.workerRuns.capacity overrides it explicitly. The capacity option
was already plumbed through the supervisor; this wires it from config and
deletes the hardcoded constant. Docs and config baselines regenerated.
2026-08-23 14:09:06 -07:00
Peter Steinberger 1353ce0995 feat: run Codex sessions on approved paired devices (#127202)
* feat(codex): execute paired-device sessions over node carrier

* fix(node-host): preserve approved invocation session identity

* fix(codex): observe paired-node execution leases before handshake

* fix: fence paired-device placement and Codex execution owners

* fix: satisfy paired-device placement CI ownership guards

* fix(codex): reject credentialed paired-node URL parameters

* fix(codex): fence nested remote HTTP session credentials

* fix(codex): scrub node process URLs and preserve plaintext HTTP

* test(codex): republish node inventory after capability approval
2026-08-21 12:50:26 -07:00
Peter Steinberger 0d555266e4 refactor(nodes): retire legacy runner inventory parsing (#126773) 2026-08-20 11:53:00 -07:00
Peter Steinberger bbbd70542b feat(sessions): recover offline device placements (#126284)
* feat(sessions): recover offline device placements

* chore(protocol): refresh session placement models

* perf(ui): lazy-load session placement recovery

* test(ui): remove dropdown timing assertion

* test(ui): await committed cloud recovery route

* fix(sessions): complete explicit abandonment locally

* fix(sessions): fence lists by runner availability

* fix(ui): preserve canonical session freshness

* fix(sessions): preserve recovery contracts after rebase

* test(ui): await durable cloud recovery entry

* test(gateway): complete current runner fixtures

* fix(gateway): publish runner availability edges

* fix(ui): preserve shared session freshness

* fix(ui): preserve canonical sidebar session state

* fix(sessions): preserve abandoned partials and run-owned replies

* fix(sessions): resume durable abandonment retries

* test(gateway): compose provisioning replay with runner availability

* fix(sessions): publish recovered move transitions
2026-08-20 09:59:59 -07:00
Peter Steinberger 2d13e16705 fix: harden node desktop carrier (#126425) 2026-08-19 12:57:26 -07:00
Peter Steinberger 80934e5639 feat(ui): dispatch sessions to paired devices (#126187) 2026-08-19 01:11:49 -07:00
Peter Steinberger 9924e2d7a7 feat(cli): prepare session-host onboarding (#125879)
* feat(cli): prepare session-host onboarding

* fix(cli): gate session-host installer capability
2026-08-18 16:08:48 -07:00
Peter Steinberger efaa867d93 feat(nodes): publish exact runner slots (#125708)
* feat(nodes): publish exact runner slots

* docs(runners): link slot inventory PR

* fix(ui): keep session menus clickable under previews

* perf(protocol): keep runner slot schema off broad barrel

* test(codex): tolerate elapsed media startup budget

* test(codex): type media client factory mocks

* fix(protocol): reject impossible runner slot counts

* test(ci): stabilize loaded lifecycle checks

* test(ui): allow loaded bulk-delete scheduling

* test(ui): stabilize loaded interaction checks

* test(ui): isolate loaded update notice checks

* test(ui): colocate bulk-delete lifecycle coverage

* test(gateway): publish session config before async setup
2026-08-18 07:08:06 -07:00
Peter Steinberger 9ba8671296 refactor(agents): unify exec approval routing (#125587)
* refactor(agents): unify exec approval routing

* docs(plan): record approval route cleanup
2026-08-17 21:40:31 -07:00
Peter Steinberger 4ed01969e8 refactor(agents): unify exec approval wait outcomes (#125524)
* refactor(agents): unify exec approval wait outcomes

* docs(plan): record approval wait cleanup
2026-08-17 20:23:10 -07:00
Peter Steinberger b485f0c627 refactor(agents): unify exec approval decisions (#125503)
* refactor(agents): unify exec approval decisions

* docs(plan): update runner deletion status
2026-08-17 19:06:28 -07:00
Peter Steinberger bb1ce58514 refactor(gateway): remove obsolete reverse worker tunnel (#125465)
* refactor(gateway): remove reverse worker tunnel

* test(gateway): align worker transport expectations

* docs(gateway): clarify cloud worker ingress
2026-08-17 18:19:52 -07:00
Peter Steinberger a996ea25d9 fix(update): support npm before lifecycle allowlists (#125452) 2026-08-17 17:01:23 -07:00
Peter Steinberger 45e6784338 feat(gateway): run disposable cloud workers through node transport (#125288)
* feat(gateway): converge cloud workers onto nodes

* fix(gateway): honor public URL for cloud enrollment

* fix(crabbox): execute cloud bootstrap package binary

* fix(gateway): bind cloud nodes in pairing transaction

* fix(crabbox): prefer exact installed cloud bootstrap

* fix(gateway): complete cloud node bootstrap

* fix(gateway): enforce cloud worker capability boundaries

* fix(gateway): complete cloud node migration

* fix(gateway): preserve paired node roles on teardown
2026-08-17 11:49:06 -07:00
Peter Steinberger 05bbd48c51 docs(install): clarify lifecycle script trust (#124727)
* docs(install): approve OpenClaw lifecycle scripts

Amp-Thread-ID: https://ampcode.com/threads/T-01a00ae0-190d-718b-8a76-b75f3e8d1fae

* fix(update): bind npm lifecycle policy to install owner

Amp-Thread-ID: https://ampcode.com/threads/T-01a00ae0-190d-718b-8a76-b75f3e8d1fae

* fix(update): gate npm lifecycle policy before mutation

* test(update): cover npm lifecycle ownership

* fix(update): defer backup cleanup until package preflight passes

Amp-Thread-ID: https://ampcode.com/threads/T-01a00ae0-190d-718b-8a76-b75f3e8d1fae

* fix(update): preflight npm policy before service stop

Amp-Thread-ID: https://ampcode.com/threads/T-01a00ae0-190d-718b-8a76-b75f3e8d1fae

* docs(install): avoid unsupported lifecycle claim

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 01:00:17 -07:00
Peter Steinberger 4d872fbfbc feat(nodes): expose installed worker bundle status (#124640)
* feat(nodes): expose installed worker bundle status

* perf(nodes): defer bundle status validation

* fix(nodes): tighten bundle status type contracts

* docs(gateway): document node worker bundle status

* refactor(gateway): split runner inventory runtime

* test(ui): keep healthy device status quiet

* fix(ui): preserve steer target ordering

* test(ui): isolate catalog handoff lifecycle
2026-08-16 10:04:46 -07:00
Peter Steinberger 18d130fc1b fix(workers): bound node bundle retention (#124590)
* fix(workers): bound node bundle retention

* docs(runners): track bundle retention
2026-08-16 06:25:05 -07:00
Peter Steinberger dbad5e385d refactor(workers): separate runner consent from capacity (#124356)
* refactor(workers): separate runner inventory state

* docs(runners): track inventory cleanup

* test(workers): use bundle-only launch wire

* test(workers): update optional inventory fixture

* test(workers): validate prewarm inventory capability

* fix(workers): version runner inventory cutover
2026-08-16 04:46:38 -07:00
Peter Steinberger fff38795e4 docs(plan): W5-REF landed (#124374) (#124403) 2026-08-15 21:24:46 -07:00
Peter Steinberger 527d155055 docs(plan): mark wave-5 computer-use rows landed (#124155)
* docs(plan): mark wave-5 rows landed and record Linux as partial

* docs(plan): record trust-model, tool-split, ref-convergence, and rig root cause

* docs(plan): carry wave-4 rows forward, define partial status, order rows by wave
2026-08-15 20:24:52 -07:00
Peter Steinberger 78502eda6d feat(workers): run device sessions from Gateway bundles (#124037)
* feat(workers): run device sessions from Gateway bundles

Install the current Gateway bundle before a device environment becomes ready, verify it at attach and tunnel boundaries, launch only from the immutable namespaced bundle directory, and retire stale environments for idempotent reprovisioning. Remove the local execution mode and preserve the node-local build claim only as temporary inventory metadata for the final projection/cleanup slice.

* docs(runners): record Gateway bundle cutover

* test(ci): repair runner validation fixtures

# Conflicts:
#	src/scripts/test-projects.test.ts

* fix(workers): surface outdated node recovery

Keep legacy runner inventory diagnostic-only while exposing the update-and-reconnect action through node, environment, provider, placement, and Control UI surfaces.

* fix(workers): reject legacy inventory with recovery

* fix(workers): bundle worker deploy closure

* test(workers): close bundle cutover gates

* fix(workers): compose browser runtime at build

* fix(workers): satisfy bundle cutover gates

* fix(workers): route temp runtime through infra

* docs(workers): align bundle host guidance

* fix(ui): fence outdated session destinations
2026-08-15 17:46:44 -07:00
Peter Steinberger 6d9ea63a87 docs: correct computer use inventory counts (#124074) 2026-08-15 00:13:16 -07:00
Peter Steinberger a8f1a0d345 test(computer-use): live end-to-end gate for both macOS providers (#123991)
* fix(computer-use): preserve semantic click observations

* fix(cua-computer): isolate desktop and window sessions

* fix(cua-computer): route cursor reads through desktop scope

* test(computer-use): add isolated macOS live proof rig

* style(cua-computer): format driver sessions

* fix(cua-computer): forward lazy desktop tools

* fix(computer-use): narrow live proof artifact path

* test(computer-use): split schema contract coverage

* refactor(cua-computer): unify session start state

* build(computer-use): register live proof entrypoint

* style(computer-use): satisfy full lint contract

* fix(computer-use): harden live proof authority

* fix(cua-computer): keep window authority immutable

* fix(computer-use): close partial sessions safely
2026-08-14 23:37:53 -07:00
Peter Steinberger 53074ae91a feat(workers): install Gateway bundles on nodes (#123985)
* feat(workers): install Gateway bundles on nodes

Add a private paired-channel install command backed by a one-use Gateway HTTP capability, bounded archive validation, script-disabled dependency materialization, and atomic gateway-namespaced publication. Existing device provisioning remains on the local-build path until the next cutover slice.

* docs(runners): record node bundle installer
2026-08-14 20:52:39 -07:00
Peter Steinberger 399f5a32e5 fix(workers): bound Gateway bundle cache growth (#123901)
* fix(workers): bound gateway bundle cache

* docs(plan): record Gateway bundle cache cleanup

* fix(workers): exclude terminal bundle diagnostics
2026-08-14 18:27:08 -07:00
Peter Steinberger d913796112 fix(runners): preserve node workspaces across restarts (#123889)
* fix(runners): retain node workspaces from gateway state

* docs(plan): record authoritative node retention
2026-08-14 16:59:19 -07:00
Peter Steinberger 628056b0ba docs(plan): W2-PKB landed (#123801) (#123838) 2026-08-14 14:26:18 -07:00
Peter Steinberger 3c5e2ff296 fix(gateway): retire worker placements without sessions (#123785)
* fix(gateway): retire placements without sessions

* fix(gateway): preserve unreadable placement evidence

* fix(gateway): drain placement retirement on shutdown

* test(sessions): auto-clean identity probe temp dirs

* fix(gateway): join placement sidecar shutdown
2026-08-14 14:07:24 -07:00
Peter Steinberger c6b3394602 docs(plan): computer-use campaign plan (CUA + Peekaboo behind computer.act v2) (#123464)
* docs(plan): computer-use campaign plan — two-provider background computer use (CUA + Peekaboo) behind computer.act v2

* docs(plan): resolve W0-PIN — pinned 0.19.3 already contains inherited IPC and consent adapter

* docs(plan): W0 complete — parity fixtures landed (#123469)

* docs(plan): W1-SEAM landed (#123509)

* docs(plan): W1 complete — v2 contract landed (#123544)

* docs(plan): W2-CUA landed (#123604)

* docs(plan): W2-MAC landed (#123635)

* docs(plan): note picker screenshot evidence belongs to W2-UX

* docs(plan): avoid inline-html placeholder in tracker note
2026-08-14 11:37:11 -07:00
Peter Steinberger e44dde218f fix(gateway): revoke device workers when pairing is removed (#123696)
* fix(gateway): revoke device workers on unpair

* refactor(backup): split sqlite verification

* refactor(backup): narrow sqlite verifier exports

* test(gateway): track worker startup temp state

* refactor(backup): preserve sqlite architecture boundary

* test(gateway): follow worker startup logger binding

* fix(gateway): revoke workers during pairing pruning
2026-08-14 10:10:12 -07:00
Peter Steinberger d9211bf14d fix(runners): bound node workspace disk growth (#123700)
* fix(runners): prune superseded node workspaces

* docs(plan): record node retention progress

* fix(runners): drain workspace retention backlogs

* test(runners): await workspace retention cleanup
2026-08-14 08:27:59 -07:00
Peter Steinberger 7d8f066b81 feat(runners): expire dormant device leases (#123673) 2026-08-14 06:53:29 -07:00
Peter Steinberger 4ac9f4c5ec refactor(runners): prune terminal environments (#123665) 2026-08-14 06:27:49 -07:00
Peter Steinberger bbca520108 refactor(runners): prune terminal launch receipts (#123641)
* refactor(runners): prune terminal launch receipts

* perf(runners): index launch receipt expiry
2026-08-14 05:49:55 -07:00
Peter Steinberger 38379a9a2e feat(runners): enforce node worker capacity (#123612)
* feat(runners): enforce node worker capacity

* test(node-host): mock supervisor initialization

* fix(runners): surface capacity exhaustion
2026-08-14 04:49:47 -07:00
Peter Steinberger 7aac8ee04b fix: preserve device sessions while runner is offline (#123477)
* fix(runners): recover offline device placements

* test(runners): model reclaimed launch dispatch

* ci: serialize macOS Swift test retries

* test: wait for steering subscription readiness

* fix(gateway): restore authority-safe steering

* test(gateway): align authority projector fixture

* fix(gateway): dispatch leaf authority mismatches

* refactor: keep authority overlay contract leaf-only

* test(ui): close place popover before details
2026-08-14 03:31:19 -07:00
Peter Steinberger 860aeed8f6 feat(gateway): transfer node worker workspaces (#123280)
* feat(gateway): transfer node worker workspaces

* fix(gateway): harden node workspace transfer

* fix(gateway): isolate transfer HTTP contract

* fix(gateway): trim transfer HTTP exports
2026-08-13 21:00:44 -07:00
Peter Steinberger 438d035885 feat(gateway): launch workers on paired nodes (#123157)
* feat(gateway): launch workers on paired nodes

* docs(plan): track node worker launch wire

* fix(runners): restore node workspace ownership

Rehydrate durable workspace bindings after Gateway restart, fence timed-out node tunnel starts, and refuse incomplete clone fallback for submodule and Git LFS workspaces.

* test(runners): isolate node launch fixtures
2026-08-13 18:02:18 -07:00
Peter Steinberger 2dcd47d4f4 feat(runners): remember offline devices (#123198)
* feat(runners): remember offline devices

Persist exact node connection end timestamps and keep execution-capable offline devices visible with quiet lifecycle history in the session picker.

* test(ui): keep offline devices disabled
2026-08-13 13:49:00 -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
Peter Steinberger 7a4b5a0a41 feat(gateway): provision paired node session hosts (#122966)
* feat(gateway): provision paired node worker installs

* docs: record node local-install PR chain

* chore(protocol): regenerate node worker manifest models

* fix(gateway): resolve node worker build through the device runtime

Repairs a rebase artifact: startup referenced a stale deviceNodeRegistry
binding; the device runtime now owns the connected-node lookup via
resolveWorkerBuild.
2026-08-13 01:56:19 -07:00
Peter Steinberger 5bdfa69e82 feat(worker): add durable node launch adapter (#123033)
* feat(worker): add durable node launch adapter

* docs(plan): track durable node launch adapter
2026-08-12 23:29:29 -07:00
Peter Steinberger 3f4d89505a feat(worker): expose supervised terminal outcomes (#123013)
* feat(worker): expose supervised terminal outcomes

* docs(plan): track supervisor terminal outcomes
2026-08-12 22:19:49 -07:00
Peter Steinberger 5e67beb02e feat(node-host): add negotiated private worker controls (#122939)
* feat(node-host): add private worker supervisor controls

* refactor(node-host): harden private worker controls

* refactor(node-host): simplify private worker controls

* docs(plan): track private worker controls

* fix(node-host): satisfy private control CI guards

* test(gateway): follow worker service construction boundary

* test(gateway): register private control release train

* fix(gateway): retain worker dialect across reapproval
2026-08-12 21:27:01 -07:00