openclaw/test/test-home-context.mts
Peter Steinberger 80ae248de1
fix(update): preserve configuration and hand failed upgrades to triage (#134490)
* fix(update): preserve configuration and verify upgrade recovery

Prefer npm before ClawHub only among declared plugin identities, preserving explicit source/version intent, artifact integrity and capability consent. Keep the exact installed beta cohort and require typed target absence before fallback.

Preserve authored environment references through both Doctor writers, resolve snapshot destinations at operation time, and keep migration-only metadata out of redacted snapshots. Avoid loading channel runtimes for unused pairing account facts while retaining captured migration-owner attribution.

Record activation safety at package/Git mutation boundaries. Keep installed-CLI recovery, verify runtime/native-service identity, fence Windows autostart, preserve child status, and avoid duplicating consumed notifications or rejecting completed install switches. Surface update-specific disconnect diagnostics without changing explicit-restart guidance in Model Setup.

Retain the upgrade-survivor first-hop, approval and installed-version oracles. Repair CI's type-only Doctor cycle and stale source-policy, final-Doctor and Teams whitespace expectations without weakening timeouts, gates or the main-owned Markdown fix.

PR: https://github.com/openclaw/openclaw/pull/134490

* test(msteams): align the corrected main whitespace fixture

* perf(ui): remove unreachable update translations

Remove superseded version-only verification copy and the unused idle label from the eager catalog. Keep identity-aware verification and all recovery guidance unchanged, align translation fixtures, and restore the existing merged startup budget without increasing its baseline or limits.

* fix(update): retain consent failures and isolate validation homes

Carry unresolved non-retained plugin capability refusals from missing-install
repair through post-core convergence as typed outcomes, preserving the existing
update failure and restart boundary. Keep usable retained artifacts and
transient fetch failures on their existing notice/warning paths.

Give test invocations a native process HOME before config imports and worker
creation. Preserve bounded live/profile context, report selection, installed
tool caches, and process-group/pipe-owned namespace cleanup or truthful
retention. Keep unknown or mixed explicit real-home selections closed.
Resolve the repo-owned staging helper from its owning cwd and await complete
PID readiness before cancelling native report fixtures.

Align the survivor recovery oracle with typed consent errors that intentionally
have no Doctor reason. Preserve strict plugin/code/version/core-step checks and
historical warning-only reports; successful-update admission still rejects
refusals. Keep the local TestHomeMode alias private and satisfy helper lint.

PR: https://github.com/openclaw/openclaw/pull/134490

* fix(plugins): preserve declared catalog identity during upgrade integration

Carry the prepared, provenance-validated ClawHub package instead of discarding
it into a boolean. Suppress the declared installed counterpart without deriving
an npm identity from overlaid display metadata or hiding an npm namesake.
Keep lazy prepared catalog facts and first-normalized-record icon behavior.

Retain explicit ClawHub-only actions and npm-first dual-source actions, and
cover the selected source's pinned inspection metadata with existing tables.
The incoming duplicate-row cases fail before the provenance fact is retained.

PR: https://github.com/openclaw/openclaw/pull/134490

* fix(ci): include home isolation in PR anchor closure

Register the three runtime dependencies in the canonical extraction and trust inventory. Extracted planners and publishers now load the real home policy, context, and selection modules without stubs or weaker assertions. The existing extracted-anchor regression fails before this change and the full wrapper suite passes afterward.

* fix(update): hand failed upgrades to local coding agents

Route interactive update failures through triage after updater ownership is
released. Preserve the captured installation, invocation directory, bounded
diagnostics and original update result while the installed coding agent
repairs and verifies the machine using its existing permissions.

Keep background and JSON guidance consistent, preserve config references,
and fix resolved consent failures and selected catalog source provenance.

Validation: complete combined P2 review, 639 focused tests, 71 UI unit
tests, and four Chromium scenarios passed. Full changed-code checks passed
all typegraphs but stopped on one no-map-spread lint error in a test fixture.

Local integration checkpoint: fix that fixture and combine the current main
triage owner before final review, package proof, publication, or landing.

* fix(update): preserve configuration and verify upgrade recovery

Prefer npm before ClawHub only among declared plugin identities, preserving explicit source/version intent, artifact integrity and capability consent. Keep the exact installed beta cohort and require typed target absence before fallback.

Preserve authored environment references through both Doctor writers, resolve snapshot destinations at operation time, and keep migration-only metadata out of redacted snapshots. Avoid loading channel runtimes for unused pairing account facts while retaining captured migration-owner attribution.

Record activation safety at package/Git mutation boundaries. Keep installed-CLI recovery, verify runtime/native-service identity, fence Windows autostart, preserve child status, and avoid duplicating consumed notifications or rejecting completed install switches. Surface update-specific disconnect diagnostics without changing explicit-restart guidance in Model Setup.

Retain the upgrade-survivor first-hop, approval and installed-version oracles. Repair CI's type-only Doctor cycle and stale source-policy, final-Doctor and Teams whitespace expectations without weakening timeouts, gates or the main-owned Markdown fix.

PR: https://github.com/openclaw/openclaw/pull/134490

* test(msteams): align the corrected main whitespace fixture

* perf(ui): remove unreachable update translations

Remove superseded version-only verification copy and the unused idle label from the eager catalog. Keep identity-aware verification and all recovery guidance unchanged, align translation fixtures, and restore the existing merged startup budget without increasing its baseline or limits.

* fix(update): retain consent failures and isolate validation homes

Carry unresolved non-retained plugin capability refusals from missing-install
repair through post-core convergence as typed outcomes, preserving the existing
update failure and restart boundary. Keep usable retained artifacts and
transient fetch failures on their existing notice/warning paths.

Give test invocations a native process HOME before config imports and worker
creation. Preserve bounded live/profile context, report selection, installed
tool caches, and process-group/pipe-owned namespace cleanup or truthful
retention. Keep unknown or mixed explicit real-home selections closed.
Resolve the repo-owned staging helper from its owning cwd and await complete
PID readiness before cancelling native report fixtures.

Align the survivor recovery oracle with typed consent errors that intentionally
have no Doctor reason. Preserve strict plugin/code/version/core-step checks and
historical warning-only reports; successful-update admission still rejects
refusals. Keep the local TestHomeMode alias private and satisfy helper lint.

PR: https://github.com/openclaw/openclaw/pull/134490

* fix(plugins): preserve declared catalog identity during upgrade integration

Carry the prepared, provenance-validated ClawHub package instead of discarding
it into a boolean. Suppress the declared installed counterpart without deriving
an npm identity from overlaid display metadata or hiding an npm namesake.
Keep lazy prepared catalog facts and first-normalized-record icon behavior.

Retain explicit ClawHub-only actions and npm-first dual-source actions, and
cover the selected source's pinned inspection metadata with existing tables.
The incoming duplicate-row cases fail before the provenance fact is retained.

PR: https://github.com/openclaw/openclaw/pull/134490

* fix(ci): include home isolation in PR anchor closure

Register the three runtime dependencies in the canonical extraction and trust inventory. Extracted planners and publishers now load the real home policy, context, and selection modules without stubs or weaker assertions. The existing extracted-anchor regression fails before this change and the full wrapper suite passes afterward.

* fix(test): preserve source home when loading profiles

Read the explicitly selected profile with a non-login Bash command so
system and user login startup cannot replace the source HOME first.
Keep positional profile quoting, child-only HOME/USERPROFILE, existing
profile opt-in and test/native-home isolation unchanged.

The existing six profile-home matrix cases failed on Linux CI run
33536959196, job 99953769387. New exact-head Linux CI remains required;
this local repair does not refresh or admit the prior native proof.

PR: https://github.com/openclaw/openclaw/pull/134490

* fix(update): complete failure triage integration

Keep landed failure diagnosis after recovery and cleanup decisions without
letting diagnostic exports authorize activation or overwrite updater exits.
Preserve exact unsafe handoff and nested foreground results, consumed
notifications, successful install-root switches, typed consent failures and
update-specific disconnected guidance alongside main's triage takeover.

Contain diagnostic read failures inside the diagnostic owner so a completed
recovery still releases its lease and sensitive files. Retain phase-labelled
updater, recovery and diagnostic exits plus helper terminal completion.
Remove the trivial aggregate-error wrapper while preserving both failures,
and consolidate launchd/notification coverage into canonical test support.

Focused CLI, Doctor, handoff, UI and profile-home proof passed under external
synthetic homes. Complete integrated P0 review is scoped-clean; exact-head
Linux CI and native/package qualification remain with the parent workflow.
The unchanged main models-cli auth-login test-type error remains a follow-up.

PR: https://github.com/openclaw/openclaw/pull/134490

* test(update): split Doctor and service recovery fixtures

Move the existing Windows Doctor recovery matrix and shared fixtures into
focused files, and keep managed terminal-outcome tests in their existing
result helper. Preserve all case bodies, assertions, and hook cleanup.

Keep Windows restore failure in a local variable and narrow the triage
prompt-write fixture path before string matching. Scoped type-aware lint,
all affected existing suites, and independent follow-up review pass.

The full repository gate and final packaged Crabbox recovery and upgrade
proof remain required before landing.

* fix(update): retain plugin attempt spec on consent failure

* test(update): preserve runtime exports in option mocks

---------

Co-authored-by: Jason (Json) <263060202+fuller-stack-dev@users.noreply.github.com>
2026-09-01 17:33:22 -06:00

99 lines
3.4 KiB
TypeScript

import fs from "node:fs";
import os from "node:os";
import path from "node:path";
const CONTEXT_FILE = "vitest-home-source.json";
const MAX_CONTEXT_BYTES = 16 * 1024;
export function resolveTestCorepackHome(env: NodeJS.ProcessEnv, home = os.homedir()): string {
return (
env.COREPACK_HOME ??
path.join(
env.XDG_CACHE_HOME ??
env.LOCALAPPDATA ??
path.join(home, process.platform === "win32" ? "AppData/Local" : ".cache"),
"node/corepack",
)
);
}
/** Installed browser binaries, like Corepack, are tooling rather than application state. */
export function resolveTestBrowserCache(env: NodeJS.ProcessEnv, home: string): string | undefined {
const explicit =
env.PLAYWRIGHT_BROWSERS_PATH ??
env.npm_config_playwright_browsers_path ??
env.npm_package_config_playwright_browsers_path;
if (explicit) {
return explicit;
}
// Playwright's registry resolves this default at import time, before worker setup.
const cache =
process.platform === "darwin"
? path.join(home, "Library", "Caches")
: process.platform === "win32"
? env.LOCALAPPDATA || path.join(home, "AppData", "Local")
: process.platform === "linux"
? env.XDG_CACHE_HOME || path.join(home, ".cache")
: undefined;
return cache === undefined ? undefined : path.join(cache, "ms-playwright");
}
/** Invocation selection data, never consent to load profiles or stage credentials. */
export function writeTestHomeSource(namespace: string, sourceHome: string): void {
const context = JSON.stringify({ version: 1, home: path.join(namespace, "home"), sourceHome });
if (!path.isAbsolute(sourceHome) || Buffer.byteLength(context) > MAX_CONTEXT_BYTES) {
throw new Error("[vitest] invalid invocation home source");
}
fs.writeFileSync(path.join(namespace, CONTEXT_FILE), context, { flag: "wx", mode: 0o600 });
}
/** Only initial live-aware setup uses the launch source; nested fixture homes stay local. */
export function readTestHomeSource(env: NodeJS.ProcessEnv): string | undefined {
const home = env.HOME;
const namespace = env.TMPDIR;
if (
!namespace ||
!path.isAbsolute(namespace) ||
home !== path.join(namespace, "home") ||
env.USERPROFILE !== home ||
env.TMP !== namespace ||
env.TEMP !== namespace
) {
return undefined;
}
let fd: number;
try {
fd = fs.openSync(path.join(namespace, CONTEXT_FILE), "r");
} catch (error) {
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
return undefined;
}
throw error;
}
try {
const buffer = Buffer.alloc(MAX_CONTEXT_BYTES + 1);
const length = fs.readSync(fd, buffer, 0, buffer.length, 0);
if (length > MAX_CONTEXT_BYTES) {
throw new Error("[vitest] oversized invocation home source");
}
const context: unknown = JSON.parse(buffer.toString("utf8", 0, length));
if (
!context ||
typeof context !== "object" ||
Array.isArray(context) ||
Object.keys(context).length !== 3 ||
!("version" in context) ||
context.version !== 1 ||
!("home" in context) ||
context.home !== home ||
!("sourceHome" in context) ||
typeof context.sourceHome !== "string" ||
!path.isAbsolute(context.sourceHome)
) {
throw new Error("[vitest] invalid invocation home source");
}
return context.sourceHome;
} finally {
fs.closeSync(fd);
}
}