@runuai/host 0.9.66 → 0.9.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6199,6 +6199,31 @@ export async function recoverAppleTaskEnvironment(
6199
6199
  );
6200
6200
  return settleFromStatus(after);
6201
6201
  }
6202
+ if (init.exitCode === 127) {
6203
+ // Command-not-found from a read-only bind mount the guest cannot touch:
6204
+ // the initializer itself is unrunnable — live 2026-08-26, containers
6205
+ // whose versioned asset tree a host update had pruned looped here as
6206
+ // "recovered with warnings" while the host sat in checking and the UI
6207
+ // showed Running (so no Resume). An unrunnable initializer is a stopped
6208
+ // task, not a degraded one: stop, settle the durable verdict, and let
6209
+ // Resume recreate the container against current (task-scoped) assets.
6210
+ await environment.stop();
6211
+ const after = await environment.status();
6212
+ if (after.state === "running" || after.state === "unknown") {
6213
+ return {
6214
+ outcome: "deferred",
6215
+ detail:
6216
+ "task initializer is unrunnable (exit 127) and the container could not be proven stopped",
6217
+ };
6218
+ }
6219
+ if (!context.isCurrent()) {
6220
+ return { outcome: "deferred", detail: "runtime generation superseded" };
6221
+ }
6222
+ console.error(
6223
+ `[orchestrator] recovery: ${descriptor.taskId} initializer is unrunnable (exit 127 — usually a host update pruned the versioned assets this pre-0.9.67 container still mounts); task was stopped, Resume recreates it`,
6224
+ );
6225
+ return settleFromStatus(after);
6226
+ }
6202
6227
  if (init.exitCode !== 0) {
6203
6228
  console.warn(
6204
6229
  `[orchestrator] recovery: ${descriptor.taskId} uai-init failed (exit ${init.exitCode}); container is up but Editor may be down`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runuai/host",
3
- "version": "0.9.66",
3
+ "version": "0.9.67",
4
4
  "description": "Uai host — runs ephemeral AI tasks in containers on a machine you control.",
5
5
  "license": "MIT",
6
6
  "author": "Uai Tech <team@runuai.com>",
@@ -1374,6 +1374,48 @@ if [ "$project_count" -gt 0 ]; then
1374
1374
  fi
1375
1375
  fi
1376
1376
 
1377
+ # Containers bind these assets for their whole life, but the packaged
1378
+ # sources live in the VERSIONED runtime tree and the updater keeps only
1379
+ # current+previous — a container surviving two updates found its mounts
1380
+ # pointing at deleted files (uai-init exec 127, recovery wedged the host in
1381
+ # "checking"; live 2026-08-26). Copy the assets into the task's own control
1382
+ # tree and mount THOSE: asset lifetime becomes task lifetime, and a Resume
1383
+ # refreshes the copies to the current version. Atomic rename so a resumed
1384
+ # container can never observe a half-written initializer.
1385
+ task_assets_dir="$task_uai_dir/assets"
1386
+ mkdir -p "$task_assets_dir"
1387
+ copy_task_asset() {
1388
+ copy_src="$1"
1389
+ copy_name="$2"
1390
+ copy_mode="$3"
1391
+ copy_tmp=$(mktemp "$task_assets_dir/.$copy_name.XXXXXX") || return 1
1392
+ cp "$copy_src" "$copy_tmp" || { rm -f "$copy_tmp"; return 1; }
1393
+ chmod "$copy_mode" "$copy_tmp" || { rm -f "$copy_tmp"; return 1; }
1394
+ mv -f "$copy_tmp" "$task_assets_dir/$copy_name"
1395
+ }
1396
+ if ! copy_task_asset "$UAI_INIT_SOURCE" uai-init 0755; then
1397
+ emit_err "CONTAINER_INIT_FAILED" \
1398
+ "Uai could not stage the task initializer into this task's control tree. Check disk space and permissions under the Uai data directory, then retry." \
1399
+ "stage task container assets"
1400
+ fi
1401
+ UAI_INIT_SOURCE="$task_assets_dir/uai-init"
1402
+ if [ -f "$RUNTIME_MATERIALIZER_SOURCE" ]; then
1403
+ if ! copy_task_asset "$RUNTIME_MATERIALIZER_SOURCE" uai-materialize-runtimes 0755; then
1404
+ emit_err "CONTAINER_INIT_FAILED" \
1405
+ "Uai could not stage the runtime materializer into this task's control tree. Check disk space and permissions under the Uai data directory, then retry." \
1406
+ "stage task container assets"
1407
+ fi
1408
+ RUNTIME_MATERIALIZER_SOURCE="$task_assets_dir/uai-materialize-runtimes"
1409
+ fi
1410
+ if [ -f "$COREPACK_VERSION_SOURCE" ]; then
1411
+ if ! copy_task_asset "$COREPACK_VERSION_SOURCE" corepack-version 0644; then
1412
+ emit_err "CONTAINER_INIT_FAILED" \
1413
+ "Uai could not stage the Corepack version pin into this task's control tree. Check disk space and permissions under the Uai data directory, then retry." \
1414
+ "stage task container assets"
1415
+ fi
1416
+ COREPACK_VERSION_SOURCE="$task_assets_dir/corepack-version"
1417
+ fi
1418
+
1377
1419
  # The host-authored allowlist is the single project-set authority shared by
1378
1420
  # pre-start runtime proof and task-local dependency installation. It lives in
1379
1421
  # the container-unmounted .uai control tree and is exposed only as this one