omnius 1.0.892 → 1.0.894
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.
- package/assets/rea/LICENSE +21 -0
- package/assets/rea/UPSTREAM.json +43 -0
- package/assets/rea/skills/manifest.json +14 -0
- package/assets/rea/skills/omnius-rea/SKILL.md +61 -0
- package/assets/rea/skills/reverse-engineer-anything/SKILL.md +356 -0
- package/assets/rea/skills/reverse-engineer-anything/references/android-applications.md +36 -0
- package/assets/rea/skills/reverse-engineer-anything/references/connection-and-recovery.md +127 -0
- package/assets/rea/skills/reverse-engineer-anything/references/evidence-workflows.md +71 -0
- package/assets/rea/skills/reverse-engineer-anything/references/javascript-applications.md +218 -0
- package/assets/rea/skills/reverse-engineer-anything/references/native-and-artifacts.md +297 -0
- package/assets/rea/skills/reverse-engineer-anything/references/runtime-observation.md +78 -0
- package/dist/index.js +2 -2
- package/dist/library.js +5295 -3449
- package/dist/tui/native/worker.js +44 -14
- package/dist/update-worker-runtime.js +463 -27
- package/dist/update-worker.js +3 -1
- package/docs/DISCOVERY.json +132 -0
- package/docs/DISCOVERY.md +4 -0
- package/docs/completion-deliberation-examples-20261022.md +260 -0
- package/docs/live-semantic-completion-validation-20261022.md +91 -0
- package/docs/rea.md +39 -0
- package/docs/test-three-premature-completion-rca-20261021.md +190 -0
- package/npm-shrinkwrap.json +1345 -11
- package/package.json +3 -2
|
@@ -3243,7 +3243,7 @@ var require_util = __commonJS({
|
|
|
3243
3243
|
exports.isAbsolute = function(aPath) {
|
|
3244
3244
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
3245
3245
|
};
|
|
3246
|
-
function
|
|
3246
|
+
function relative3(aRoot, aPath) {
|
|
3247
3247
|
if (aRoot === "") {
|
|
3248
3248
|
aRoot = ".";
|
|
3249
3249
|
}
|
|
@@ -3262,7 +3262,7 @@ var require_util = __commonJS({
|
|
|
3262
3262
|
}
|
|
3263
3263
|
return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
|
|
3264
3264
|
}
|
|
3265
|
-
exports.relative =
|
|
3265
|
+
exports.relative = relative3;
|
|
3266
3266
|
var supportsNullProto = (function() {
|
|
3267
3267
|
var obj = /* @__PURE__ */ Object.create(null);
|
|
3268
3268
|
return !("__proto__" in obj);
|
|
@@ -14693,11 +14693,11 @@ ${lanes.join("\n")}
|
|
|
14693
14693
|
return toComponents;
|
|
14694
14694
|
}
|
|
14695
14695
|
const components = toComponents.slice(start);
|
|
14696
|
-
const
|
|
14696
|
+
const relative3 = [];
|
|
14697
14697
|
for (; start < fromComponents.length; start++) {
|
|
14698
|
-
|
|
14698
|
+
relative3.push("..");
|
|
14699
14699
|
}
|
|
14700
|
-
return ["", ...
|
|
14700
|
+
return ["", ...relative3, ...components];
|
|
14701
14701
|
}
|
|
14702
14702
|
function getRelativePathFromDirectory(fromDirectory, to, getCanonicalFileNameOrIgnoreCase) {
|
|
14703
14703
|
Debug.assert(getRootLength(fromDirectory) > 0 === getRootLength(to) > 0, "Paths must either both be absolute or both be relative");
|
|
@@ -59240,9 +59240,9 @@ ${lanes.join("\n")}
|
|
|
59240
59240
|
if (!startsWithDirectory(target, realPathDirectory, getCanonicalFileName)) {
|
|
59241
59241
|
return;
|
|
59242
59242
|
}
|
|
59243
|
-
const
|
|
59243
|
+
const relative3 = getRelativePathFromDirectory(realPathDirectory, target, getCanonicalFileName);
|
|
59244
59244
|
for (const symlinkDirectory of symlinkDirectories) {
|
|
59245
|
-
const option = resolvePath(symlinkDirectory,
|
|
59245
|
+
const option = resolvePath(symlinkDirectory, relative3);
|
|
59246
59246
|
const result2 = cb(option, target === referenceRedirect);
|
|
59247
59247
|
shouldFilterIgnoredPaths = true;
|
|
59248
59248
|
if (result2) return result2;
|
|
@@ -218843,7 +218843,7 @@ var require_path_browserify = __commonJS({
|
|
|
218843
218843
|
return ".";
|
|
218844
218844
|
return posix.normalize(joined);
|
|
218845
218845
|
},
|
|
218846
|
-
relative: function
|
|
218846
|
+
relative: function relative3(from, to) {
|
|
218847
218847
|
assertPath(from);
|
|
218848
218848
|
assertPath(to);
|
|
218849
218849
|
if (from === to) return "";
|
|
@@ -221673,12 +221673,12 @@ var require_dist2 = __commonJS({
|
|
|
221673
221673
|
return patterns.length > 0 ? buildCrawler(options, patterns) : [];
|
|
221674
221674
|
}
|
|
221675
221675
|
async function glob2(globInput, options) {
|
|
221676
|
-
const [crawler,
|
|
221677
|
-
return crawler ? formatPaths(await crawler.withPromise(),
|
|
221676
|
+
const [crawler, relative3] = getCrawler(globInput, options);
|
|
221677
|
+
return crawler ? formatPaths(await crawler.withPromise(), relative3) : [];
|
|
221678
221678
|
}
|
|
221679
221679
|
function globSync(globInput, options) {
|
|
221680
|
-
const [crawler,
|
|
221681
|
-
return crawler ? formatPaths(crawler.sync(),
|
|
221680
|
+
const [crawler, relative3] = getCrawler(globInput, options);
|
|
221681
|
+
return crawler ? formatPaths(crawler.sync(), relative3) : [];
|
|
221682
221682
|
}
|
|
221683
221683
|
exports.convertPathToPattern = convertPathToPattern;
|
|
221684
221684
|
exports.escapePath = escapePath;
|
|
@@ -300186,18 +300186,20 @@ import {
|
|
|
300186
300186
|
fstatSync as fstatSync2,
|
|
300187
300187
|
fsyncSync as fsyncSync2,
|
|
300188
300188
|
lstatSync as lstatSync2,
|
|
300189
|
+
readlinkSync as readlinkSync2,
|
|
300189
300190
|
mkdirSync as mkdirSync5,
|
|
300190
300191
|
openSync as openSync4,
|
|
300191
300192
|
readFileSync as readFileSync7,
|
|
300192
300193
|
readSync as readSync3,
|
|
300193
300194
|
renameSync as renameSync4,
|
|
300194
300195
|
statSync as statSync3,
|
|
300196
|
+
symlinkSync,
|
|
300195
300197
|
unlinkSync as unlinkSync4,
|
|
300196
300198
|
writeFileSync as writeFileSync5,
|
|
300197
300199
|
writeSync as writeSync2
|
|
300198
300200
|
} from "node:fs";
|
|
300199
300201
|
import { homedir as homedir15 } from "node:os";
|
|
300200
|
-
import { dirname as dirname9, isAbsolute as isAbsolute7, join as join16, resolve as resolve11 } from "node:path";
|
|
300202
|
+
import { dirname as dirname9, isAbsolute as isAbsolute7, join as join16, relative as relative2, resolve as resolve11 } from "node:path";
|
|
300201
300203
|
|
|
300202
300204
|
// packages/cli/src/service-version.ts
|
|
300203
300205
|
var OmniusVersionError = class extends Error {
|
|
@@ -300254,8 +300256,8 @@ function compareOmniusVersions(left, right) {
|
|
|
300254
300256
|
|
|
300255
300257
|
// packages/cli/src/npm-install-recovery.ts
|
|
300256
300258
|
import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
|
|
300257
|
-
import { closeSync as closeSync3, constants, fstatSync, fsyncSync, lstatSync, openSync as openSync3, readFileSync as readFileSync6, readSync as readSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
300258
|
-
import { lstat, realpath, rename, rm } from "node:fs/promises";
|
|
300259
|
+
import { closeSync as closeSync3, constants, fstatSync, fsyncSync, ftruncateSync, lstatSync, openSync as openSync3, readFileSync as readFileSync6, readdirSync, readSync as readSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
300260
|
+
import { chmod, cp, lstat, mkdir, readdir, realpath, rename, rm } from "node:fs/promises";
|
|
300259
300261
|
import { basename as basename8, dirname as dirname8, isAbsolute as isAbsolute6, join as join15, resolve as resolve10 } from "node:path";
|
|
300260
300262
|
var NpmInstallBusyError = class extends Error {
|
|
300261
300263
|
code = "NPM_INSTALL_BUSY";
|
|
@@ -300341,6 +300343,50 @@ async function prepareNpmRetirementSlot(modulesRoot, options = {}) {
|
|
|
300341
300343
|
await rename(retired, backup);
|
|
300342
300344
|
return receipt;
|
|
300343
300345
|
}
|
|
300346
|
+
function bootIdentity() {
|
|
300347
|
+
try {
|
|
300348
|
+
return readFileSync6("/proc/sys/kernel/random/boot_id", "utf8").trim();
|
|
300349
|
+
} catch {
|
|
300350
|
+
return;
|
|
300351
|
+
}
|
|
300352
|
+
}
|
|
300353
|
+
function updateProcessGroupHasLiveMembers(group) {
|
|
300354
|
+
if (process.platform === "linux") {
|
|
300355
|
+
try {
|
|
300356
|
+
for (const pid of readdirSync("/proc")) {
|
|
300357
|
+
if (!/^\d+$/.test(pid)) continue;
|
|
300358
|
+
let raw;
|
|
300359
|
+
try {
|
|
300360
|
+
raw = readFileSync6(`/proc/${pid}/stat`, "utf8");
|
|
300361
|
+
} catch (error) {
|
|
300362
|
+
if (error.code === "ENOENT" || error.code === "ESRCH") continue;
|
|
300363
|
+
throw error;
|
|
300364
|
+
}
|
|
300365
|
+
const fields = raw.slice(raw.lastIndexOf(")") + 2).trim().split(/\s+/);
|
|
300366
|
+
if (Number(fields[2]) === group && fields[0] !== "Z" && fields[0] !== "X") return true;
|
|
300367
|
+
}
|
|
300368
|
+
return false;
|
|
300369
|
+
} catch {
|
|
300370
|
+
return true;
|
|
300371
|
+
}
|
|
300372
|
+
}
|
|
300373
|
+
try {
|
|
300374
|
+
process.kill(-group, 0);
|
|
300375
|
+
return true;
|
|
300376
|
+
} catch (error) {
|
|
300377
|
+
return error.code !== "ESRCH";
|
|
300378
|
+
}
|
|
300379
|
+
}
|
|
300380
|
+
function installerMayStillRun(owner) {
|
|
300381
|
+
if (!owner.unconfirmed_installer) return false;
|
|
300382
|
+
if (!owner.process_group) return true;
|
|
300383
|
+
if (process.platform === "linux") {
|
|
300384
|
+
const boot = bootIdentity();
|
|
300385
|
+
if (!boot || !owner.process_group_boot_id) return true;
|
|
300386
|
+
if (boot !== owner.process_group_boot_id) return false;
|
|
300387
|
+
}
|
|
300388
|
+
return updateProcessGroupHasLiveMembers(owner.process_group);
|
|
300389
|
+
}
|
|
300344
300390
|
function processIdentity(pid) {
|
|
300345
300391
|
if (process.platform !== "linux") return;
|
|
300346
300392
|
try {
|
|
@@ -300374,7 +300420,7 @@ function readInstallOwner(path3) {
|
|
|
300374
300420
|
throw new NpmInstallBusyError("The npm install owner record is malformed; it was retained.");
|
|
300375
300421
|
}
|
|
300376
300422
|
const owner = value;
|
|
300377
|
-
if (!owner || typeof owner !== "object" || Array.isArray(owner) || owner.schema_version !== 1 || typeof owner.nonce !== "string" || !/^[a-f0-9-]{36}$/.test(owner.nonce) || !Number.isSafeInteger(owner.pid) || owner.pid <= 0 || owner.pid > 2147483647 || owner.process_identity !== void 0 && (typeof owner.process_identity !== "string" || !/^[a-f0-9-]{36}:\d+$/.test(owner.process_identity)) || owner.operation_id !== void 0 && (typeof owner.operation_id !== "string" || !/^[a-zA-Z0-9_-]{1,128}$/.test(owner.operation_id)) || Object.keys(owner).some((key) => !["schema_version", "nonce", "pid", "process_identity", "operation_id"].includes(key))) {
|
|
300423
|
+
if (!owner || typeof owner !== "object" || Array.isArray(owner) || owner.schema_version !== 1 || typeof owner.nonce !== "string" || !/^[a-f0-9-]{36}$/.test(owner.nonce) || !Number.isSafeInteger(owner.pid) || owner.pid <= 0 || owner.pid > 2147483647 || owner.process_identity !== void 0 && (typeof owner.process_identity !== "string" || !/^[a-f0-9-]{36}:\d+$/.test(owner.process_identity)) || owner.operation_id !== void 0 && (typeof owner.operation_id !== "string" || !/^[a-zA-Z0-9_-]{1,128}$/.test(owner.operation_id)) || owner.unconfirmed_installer !== void 0 && owner.unconfirmed_installer !== true || owner.process_group !== void 0 && (!Number.isSafeInteger(owner.process_group) || owner.process_group <= 0 || owner.process_group > 2147483647 || owner.unconfirmed_installer !== true) || owner.process_group_boot_id !== void 0 && (typeof owner.process_group_boot_id !== "string" || !/^[a-f0-9-]{36}$/.test(owner.process_group_boot_id) || !owner.process_group) || Object.keys(owner).some((key) => !["schema_version", "nonce", "pid", "process_identity", "operation_id", "unconfirmed_installer", "process_group", "process_group_boot_id"].includes(key))) {
|
|
300378
300424
|
throw new NpmInstallBusyError("The npm install owner identity is unknown; its lock was retained.");
|
|
300379
300425
|
}
|
|
300380
300426
|
return { owner, metadata };
|
|
@@ -300383,6 +300429,7 @@ function readInstallOwner(path3) {
|
|
|
300383
300429
|
}
|
|
300384
300430
|
}
|
|
300385
300431
|
function provedAbsent(owner) {
|
|
300432
|
+
if (installerMayStillRun(owner)) return false;
|
|
300386
300433
|
try {
|
|
300387
300434
|
process.kill(owner.pid, 0);
|
|
300388
300435
|
} catch (error) {
|
|
@@ -300464,10 +300511,35 @@ async function acquireNpmInstallLease(modulesRoot, options = {}) {
|
|
|
300464
300511
|
assertNotCancelled(options.signal);
|
|
300465
300512
|
if (!owns()) throw new Error("npm install lease ownership changed; no installer may proceed.");
|
|
300466
300513
|
},
|
|
300514
|
+
assertOwnedForRecovery() {
|
|
300515
|
+
if (!owns()) throw new Error("npm install lease ownership changed; package recovery was held.");
|
|
300516
|
+
},
|
|
300517
|
+
retainForUnconfirmedInstaller(processGroup) {
|
|
300518
|
+
if (processGroup !== void 0 && (!Number.isSafeInteger(processGroup) || processGroup <= 0 || processGroup > 2147483647))
|
|
300519
|
+
throw new Error("Invalid owned installer process group.");
|
|
300520
|
+
withGuard(() => {
|
|
300521
|
+
if (!owns()) throw new Error("npm install lease ownership changed; installer admission remains held.");
|
|
300522
|
+
const previous = readInstallOwner(lockPath);
|
|
300523
|
+
const owner = {
|
|
300524
|
+
...previous.owner,
|
|
300525
|
+
unconfirmed_installer: true,
|
|
300526
|
+
...processGroup ? { process_group: processGroup, ...bootIdentity() ? { process_group_boot_id: bootIdentity() } : {} } : {}
|
|
300527
|
+
};
|
|
300528
|
+
const fd = openSync3(lockPath, constants.O_WRONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
300529
|
+
try {
|
|
300530
|
+
if (!sameIdentity(lockMetadata, fstatSync(fd))) throw new Error("npm install lease changed before retaining the installer barrier.");
|
|
300531
|
+
ftruncateSync(fd);
|
|
300532
|
+
writeFileSync4(fd, JSON.stringify(owner));
|
|
300533
|
+
fsyncSync(fd);
|
|
300534
|
+
} finally {
|
|
300535
|
+
closeSync3(fd);
|
|
300536
|
+
}
|
|
300537
|
+
});
|
|
300538
|
+
},
|
|
300467
300539
|
async release() {
|
|
300468
300540
|
withGuard(() => {
|
|
300469
300541
|
try {
|
|
300470
|
-
if (owns()) unlinkSync3(lockPath);
|
|
300542
|
+
if (owns() && !installerMayStillRun(readInstallOwner(lockPath).owner)) unlinkSync3(lockPath);
|
|
300471
300543
|
} catch (error) {
|
|
300472
300544
|
if (error.code !== "ENOENT") throw error;
|
|
300473
300545
|
}
|
|
@@ -300475,6 +300547,207 @@ async function acquireNpmInstallLease(modulesRoot, options = {}) {
|
|
|
300475
300547
|
}
|
|
300476
300548
|
};
|
|
300477
300549
|
}
|
|
300550
|
+
var REQUIRED_OMNIUS_RUNTIME_FILES = [
|
|
300551
|
+
"package.json",
|
|
300552
|
+
"dist/index.js",
|
|
300553
|
+
"dist/launcher.cjs",
|
|
300554
|
+
"dist/update-worker.js",
|
|
300555
|
+
"dist/update-worker-runtime.js"
|
|
300556
|
+
];
|
|
300557
|
+
function hashOwnedFile(path3) {
|
|
300558
|
+
const before = lstatSync(path3);
|
|
300559
|
+
const valid = (metadata) => metadata.isFile() && !metadata.isSymbolicLink() && metadata.size > 0 && metadata.size <= 128 * 1024 * 1024 && (process.platform === "win32" || metadata.uid === process.getuid?.() && (metadata.mode & 2) === 0);
|
|
300560
|
+
if (!valid(before)) throw new Error(`Omnius runtime file is missing or unsafe: ${path3}`);
|
|
300561
|
+
const fd = openSync3(path3, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
300562
|
+
try {
|
|
300563
|
+
const metadata = fstatSync(fd);
|
|
300564
|
+
if (!valid(metadata) || !sameIdentity(before, metadata)) throw new Error("Omnius runtime file changed during verification.");
|
|
300565
|
+
const hash = createHash2("sha256"), chunk = Buffer.alloc(64 * 1024);
|
|
300566
|
+
let size = 0;
|
|
300567
|
+
for (; ; ) {
|
|
300568
|
+
const count = readSync2(fd, chunk, 0, chunk.length, null);
|
|
300569
|
+
if (!count) break;
|
|
300570
|
+
size += count;
|
|
300571
|
+
if (size > 128 * 1024 * 1024) throw new Error("Omnius runtime file grew during verification.");
|
|
300572
|
+
hash.update(chunk.subarray(0, count));
|
|
300573
|
+
}
|
|
300574
|
+
const after = fstatSync(fd);
|
|
300575
|
+
if (size !== metadata.size || after.size !== metadata.size || after.mtimeMs !== metadata.mtimeMs || after.ctimeMs !== metadata.ctimeMs)
|
|
300576
|
+
throw new Error("Omnius runtime file changed during verification.");
|
|
300577
|
+
return hash.digest("hex");
|
|
300578
|
+
} finally {
|
|
300579
|
+
closeSync3(fd);
|
|
300580
|
+
}
|
|
300581
|
+
}
|
|
300582
|
+
function inspectNpmRuntimeInstallation(packagePath) {
|
|
300583
|
+
const canonical = resolve10(packagePath), root = dirname8(canonical);
|
|
300584
|
+
if (!isAbsolute6(packagePath) || basename8(canonical) !== "omnius") throw new Error("Runtime verification requires the canonical Omnius package path.");
|
|
300585
|
+
return inspectRuntimeDirectory(canonical, root);
|
|
300586
|
+
}
|
|
300587
|
+
function inspectRuntimeDirectory(canonical, root) {
|
|
300588
|
+
const before = lstatSync(canonical);
|
|
300589
|
+
assertOwnedDirectory(lstatSync(root), "global modules root");
|
|
300590
|
+
assertOwnedDirectory(before, "Omnius package");
|
|
300591
|
+
assertOwnedDirectory(lstatSync(join15(canonical, "dist")), "Omnius runtime");
|
|
300592
|
+
const files = {};
|
|
300593
|
+
for (const file of REQUIRED_OMNIUS_RUNTIME_FILES) files[file] = hashOwnedFile(join15(canonical, file));
|
|
300594
|
+
const manifest = JSON.parse(readFileSync6(join15(canonical, "package.json"), "utf8"));
|
|
300595
|
+
if (manifest.name !== "omnius" || typeof manifest.version !== "string" || !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(manifest.version))
|
|
300596
|
+
throw new Error("Omnius runtime manifest is invalid.");
|
|
300597
|
+
const binTarget = typeof manifest.bin === "string" ? manifest.bin : manifest.bin?.omnius;
|
|
300598
|
+
if (typeof binTarget !== "string" || !/^[A-Za-z0-9_./-]+$/.test(binTarget) || isAbsolute6(binTarget) || binTarget.split("/").some((part) => !part || part === ".." || part === "."))
|
|
300599
|
+
throw new Error("Omnius runtime manifest has no safe declared omnius executable.");
|
|
300600
|
+
for (const directory of binTarget.split("/").slice(0, -1).reduce((paths, part) => [...paths, join15(paths.at(-1) ?? canonical, part)], []))
|
|
300601
|
+
assertOwnedDirectory(lstatSync(directory), "Omnius executable directory");
|
|
300602
|
+
files[binTarget] ??= hashOwnedFile(join15(canonical, binTarget));
|
|
300603
|
+
if (!readFileSync6(join15(canonical, "dist/update-worker.js"), "utf8").includes("omnius.update-worker-bootstrap.v2"))
|
|
300604
|
+
throw new Error("Omnius runtime has no compatible update worker bootstrap.");
|
|
300605
|
+
if (hashOwnedFile(join15(canonical, "package.json")) !== files["package.json"] || !sameIdentity(before, lstatSync(canonical)))
|
|
300606
|
+
throw new Error("Omnius package changed during runtime verification.");
|
|
300607
|
+
return {
|
|
300608
|
+
modulesRoot: root,
|
|
300609
|
+
device: before.dev,
|
|
300610
|
+
inode: before.ino,
|
|
300611
|
+
mode: before.mode & 511,
|
|
300612
|
+
version: manifest.version,
|
|
300613
|
+
packageHash: files["package.json"],
|
|
300614
|
+
binTarget,
|
|
300615
|
+
files
|
|
300616
|
+
};
|
|
300617
|
+
}
|
|
300618
|
+
async function preserveVerifiedNpmInstallation(snapshot, options) {
|
|
300619
|
+
const root = resolve10(snapshot.modulesRoot), source = join15(root, "omnius");
|
|
300620
|
+
const current = () => {
|
|
300621
|
+
options.lease.assertOwnedForRecovery();
|
|
300622
|
+
options.assertOwned();
|
|
300623
|
+
};
|
|
300624
|
+
assertNotCancelled(options.signal);
|
|
300625
|
+
current();
|
|
300626
|
+
if (root !== options.lease.modulesRoot) throw new Error("Package preservation belongs to a different npm lease.");
|
|
300627
|
+
const before = inspectNpmRuntimeInstallation(source);
|
|
300628
|
+
if (before.device !== snapshot.device || before.inode !== snapshot.inode || before.packageHash !== snapshot.packageHash || JSON.stringify(before.files) !== JSON.stringify(snapshot.files)) throw new Error("Prior runtime changed before preservation.");
|
|
300629
|
+
const backupPath = join15(root, `.omnius-update-recovery-${randomUUID2()}`);
|
|
300630
|
+
await mkdir(backupPath, { mode: 448 });
|
|
300631
|
+
const metadata = await lstat(backupPath);
|
|
300632
|
+
const backup = { modulesRoot: root, retiredPath: retiredNpmPackagePath(source), backupPath, device: metadata.dev, inode: metadata.ino };
|
|
300633
|
+
await options.onPrepare?.({ ...backup });
|
|
300634
|
+
assertNotCancelled(options.signal);
|
|
300635
|
+
current();
|
|
300636
|
+
for (const name of await readdir(source)) {
|
|
300637
|
+
assertNotCancelled(options.signal);
|
|
300638
|
+
current();
|
|
300639
|
+
if (!sameIdentity(metadata, await lstat(backupPath))) throw new Error("Package preservation directory changed during copying.");
|
|
300640
|
+
await cp(join15(source, name), join15(backupPath, name), {
|
|
300641
|
+
recursive: true,
|
|
300642
|
+
errorOnExist: true,
|
|
300643
|
+
force: false,
|
|
300644
|
+
preserveTimestamps: true,
|
|
300645
|
+
verbatimSymlinks: true,
|
|
300646
|
+
mode: constants.COPYFILE_FICLONE
|
|
300647
|
+
});
|
|
300648
|
+
}
|
|
300649
|
+
await chmod(backupPath, 448);
|
|
300650
|
+
current();
|
|
300651
|
+
const installation = inspectRuntimeDirectory(backupPath, root);
|
|
300652
|
+
const original = inspectNpmRuntimeInstallation(source);
|
|
300653
|
+
if (installation.device !== backup.device || installation.inode !== backup.inode || installation.packageHash !== snapshot.packageHash || JSON.stringify(installation.files) !== JSON.stringify(snapshot.files) || original.device !== snapshot.device || original.inode !== snapshot.inode || JSON.stringify(original.files) !== JSON.stringify(snapshot.files)) throw new Error("Copied runtime differs from the verified prior installation.");
|
|
300654
|
+
if (process.platform !== "win32") {
|
|
300655
|
+
const fd = openSync3(root, constants.O_RDONLY);
|
|
300656
|
+
try {
|
|
300657
|
+
fsyncSync(fd);
|
|
300658
|
+
} finally {
|
|
300659
|
+
closeSync3(fd);
|
|
300660
|
+
}
|
|
300661
|
+
}
|
|
300662
|
+
installation.mode = snapshot.mode;
|
|
300663
|
+
return { backup, installation };
|
|
300664
|
+
}
|
|
300665
|
+
async function restoreVerifiedNpmInstallation(snapshot, options) {
|
|
300666
|
+
const root = resolve10(snapshot.modulesRoot), canonical = join15(root, "omnius");
|
|
300667
|
+
const current = () => {
|
|
300668
|
+
options.lease.assertOwnedForRecovery();
|
|
300669
|
+
options.assertOwned();
|
|
300670
|
+
};
|
|
300671
|
+
current();
|
|
300672
|
+
if (root !== options.lease.modulesRoot || !isAbsolute6(snapshot.modulesRoot)) throw new Error("Package recovery belongs to a different npm lease.");
|
|
300673
|
+
const rootBefore = await lstat(root);
|
|
300674
|
+
assertOwnedDirectory(rootBefore, "global modules root");
|
|
300675
|
+
const validPath = (path3) => path3 === canonical || path3 === retiredNpmPackagePath(canonical) || options.backups?.some((backup) => backup.modulesRoot === root && backup.backupPath === path3 && dirname8(path3) === root && /^\.omnius-update-recovery-[a-f0-9-]{36}$/.test(basename8(path3)));
|
|
300676
|
+
const matches = (path3) => {
|
|
300677
|
+
if (!validPath(path3)) return false;
|
|
300678
|
+
let metadata;
|
|
300679
|
+
try {
|
|
300680
|
+
metadata = lstatSync(path3);
|
|
300681
|
+
} catch (error) {
|
|
300682
|
+
if (error.code === "ENOENT") return false;
|
|
300683
|
+
throw error;
|
|
300684
|
+
}
|
|
300685
|
+
if (metadata.dev !== snapshot.device || metadata.ino !== snapshot.inode) return false;
|
|
300686
|
+
assertOwnedDirectory(metadata, "prior Omnius package");
|
|
300687
|
+
assertOwnedDirectory(lstatSync(join15(path3, "dist")), "prior Omnius runtime");
|
|
300688
|
+
for (const [file, digest] of Object.entries(snapshot.files)) {
|
|
300689
|
+
if (!/^[A-Za-z0-9_./-]+$/.test(file) || isAbsolute6(file) || file.split("/").some((part) => !part || part === "." || part === "..") || hashOwnedFile(join15(path3, file)) !== digest) throw new Error("Prior Omnius runtime changed; restoration was held.");
|
|
300690
|
+
}
|
|
300691
|
+
for (const directory of snapshot.binTarget.split("/").slice(0, -1).reduce((paths, part) => [...paths, join15(paths.at(-1) ?? path3, part)], []))
|
|
300692
|
+
assertOwnedDirectory(lstatSync(directory), "prior Omnius executable directory");
|
|
300693
|
+
return true;
|
|
300694
|
+
};
|
|
300695
|
+
const source = [canonical, retiredNpmPackagePath(canonical), ...(options.backups ?? []).map((backup) => backup.backupPath)].find(matches);
|
|
300696
|
+
if (!source) return null;
|
|
300697
|
+
const recovery = {
|
|
300698
|
+
packagePath: canonical,
|
|
300699
|
+
sourcePath: source,
|
|
300700
|
+
version: snapshot.version,
|
|
300701
|
+
packageHash: snapshot.packageHash,
|
|
300702
|
+
status: source === canonical ? "unchanged" : "restored"
|
|
300703
|
+
};
|
|
300704
|
+
if (source === canonical) return recovery;
|
|
300705
|
+
let partial;
|
|
300706
|
+
try {
|
|
300707
|
+
partial = await lstat(canonical);
|
|
300708
|
+
assertOwnedDirectory(partial, "failed Omnius replacement");
|
|
300709
|
+
} catch (error) {
|
|
300710
|
+
if (error.code !== "ENOENT") throw error;
|
|
300711
|
+
}
|
|
300712
|
+
if (partial) recovery.partialPath = join15(root, `.omnius-update-recovery-${randomUUID2()}`);
|
|
300713
|
+
await options.onPrepare?.({ ...recovery });
|
|
300714
|
+
current();
|
|
300715
|
+
if (!sameIdentity(rootBefore, await lstat(root)) || !matches(source)) throw new Error("npm recovery identity changed before restoration.");
|
|
300716
|
+
if (partial) {
|
|
300717
|
+
const now = await lstat(canonical);
|
|
300718
|
+
if (!sameIdentity(partial, now)) throw new Error("Failed Omnius replacement changed before preservation.");
|
|
300719
|
+
try {
|
|
300720
|
+
await lstat(recovery.partialPath);
|
|
300721
|
+
throw new Error("Failed-package preservation path is already occupied.");
|
|
300722
|
+
} catch (error) {
|
|
300723
|
+
if (error.code !== "ENOENT") throw error;
|
|
300724
|
+
}
|
|
300725
|
+
current();
|
|
300726
|
+
await rename(canonical, recovery.partialPath);
|
|
300727
|
+
}
|
|
300728
|
+
current();
|
|
300729
|
+
try {
|
|
300730
|
+
await lstat(canonical);
|
|
300731
|
+
throw new Error("Canonical Omnius path changed before restoration.");
|
|
300732
|
+
} catch (error) {
|
|
300733
|
+
if (error.code !== "ENOENT") throw error;
|
|
300734
|
+
}
|
|
300735
|
+
if (!matches(source)) throw new Error("Prior Omnius runtime changed before restoration.");
|
|
300736
|
+
current();
|
|
300737
|
+
await rename(source, canonical);
|
|
300738
|
+
if (process.platform !== "win32") {
|
|
300739
|
+
const fd = openSync3(root, constants.O_RDONLY);
|
|
300740
|
+
try {
|
|
300741
|
+
fsyncSync(fd);
|
|
300742
|
+
} finally {
|
|
300743
|
+
closeSync3(fd);
|
|
300744
|
+
}
|
|
300745
|
+
}
|
|
300746
|
+
current();
|
|
300747
|
+
if (!matches(canonical)) throw new Error("Restored Omnius runtime failed identity verification.");
|
|
300748
|
+
if (process.platform !== "win32") await chmod(canonical, snapshot.mode);
|
|
300749
|
+
return recovery;
|
|
300750
|
+
}
|
|
300478
300751
|
async function removeVerifiedNpmRetirementBackup(backup) {
|
|
300479
300752
|
const root = resolve10(backup.modulesRoot);
|
|
300480
300753
|
if (!isAbsolute6(backup.modulesRoot) || dirname8(backup.backupPath) !== root || !/^\.omnius-update-recovery-[a-f0-9-]{36}$/.test(basename8(backup.backupPath)) || backup.retiredPath !== retiredNpmPackagePath(join15(root, "omnius"))) {
|
|
@@ -300788,6 +301061,41 @@ async function runUpdateCommand(command, args, options = {}) {
|
|
|
300788
301061
|
const onAbort = () => {
|
|
300789
301062
|
terminate(new Error("command cancelled"));
|
|
300790
301063
|
};
|
|
301064
|
+
let settlement;
|
|
301065
|
+
const settleOwnedTree = (result) => settlement ??= (async () => {
|
|
301066
|
+
if (!child.pid) {
|
|
301067
|
+
finish({ ...result, processGroupSettled: true });
|
|
301068
|
+
return;
|
|
301069
|
+
}
|
|
301070
|
+
if (process.platform === "win32") {
|
|
301071
|
+
if (stopping || result.error || result.status !== 0 || result.signal) signalChild("SIGKILL");
|
|
301072
|
+
finish({
|
|
301073
|
+
...result,
|
|
301074
|
+
processGroupSettled: false,
|
|
301075
|
+
error: result.error ?? new Error("The owned Windows installer tree could not be confirmed stopped; package recovery was held.")
|
|
301076
|
+
});
|
|
301077
|
+
return;
|
|
301078
|
+
}
|
|
301079
|
+
const outlivedParent = updateProcessGroupHasLiveMembers(child.pid);
|
|
301080
|
+
if (outlivedParent || stopping || result.error || result.status !== 0 || result.signal) signalChild("SIGKILL");
|
|
301081
|
+
const deadline = Date.now() + 2e3;
|
|
301082
|
+
while (updateProcessGroupHasLiveMembers(child.pid) && Date.now() < deadline)
|
|
301083
|
+
await new Promise((resolveWait) => setTimeout(resolveWait, 20));
|
|
301084
|
+
if (updateProcessGroupHasLiveMembers(child.pid)) {
|
|
301085
|
+
finish({
|
|
301086
|
+
...result,
|
|
301087
|
+
processGroupSettled: false,
|
|
301088
|
+
processGroup: child.pid,
|
|
301089
|
+
error: new Error("The owned installer process group could not be confirmed stopped; package recovery was held.")
|
|
301090
|
+
});
|
|
301091
|
+
return;
|
|
301092
|
+
}
|
|
301093
|
+
finish({
|
|
301094
|
+
...result,
|
|
301095
|
+
processGroupSettled: true,
|
|
301096
|
+
...outlivedParent && !result.error && result.status === 0 ? { error: new Error("The command exited before its owned subprocess group settled.") } : {}
|
|
301097
|
+
});
|
|
301098
|
+
})();
|
|
300791
301099
|
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
300792
301100
|
if (options.signal?.aborted) onAbort();
|
|
300793
301101
|
child.stdout?.on("data", (chunk) => {
|
|
@@ -300798,10 +301106,11 @@ async function runUpdateCommand(command, args, options = {}) {
|
|
|
300798
301106
|
stderr = capture(stderr, chunk);
|
|
300799
301107
|
options.onStderr?.(chunk.toString());
|
|
300800
301108
|
});
|
|
300801
|
-
child.once("error", (error) =>
|
|
301109
|
+
child.once("error", (error) => {
|
|
301110
|
+
void settleOwnedTree({ status: null, stdout, stderr, signal: null, error });
|
|
301111
|
+
});
|
|
300802
301112
|
child.once("close", (status, signal) => {
|
|
300803
|
-
|
|
300804
|
-
finish({ status, stdout, stderr, signal, ...stopError ? { error: stopError } : {} });
|
|
301113
|
+
void settleOwnedTree({ status, stdout, stderr, signal, ...stopError ? { error: stopError } : {} });
|
|
300805
301114
|
});
|
|
300806
301115
|
timer = setTimeout(() => {
|
|
300807
301116
|
terminate(new Error(`command timed out after ${options.timeout ?? 15e3}ms`));
|
|
@@ -300830,6 +301139,9 @@ async function inspectGlobalOmniusInstall(expectedVersion, options = {}) {
|
|
|
300830
301139
|
if (installedVersion !== expectedVersion) {
|
|
300831
301140
|
throw new Error(`Global package verification failed: expected ${expectedVersion}, found ${installedVersion || "unknown"}`);
|
|
300832
301141
|
}
|
|
301142
|
+
const runtime = inspectNpmRuntimeInstallation(dirname9(packageJsonPath));
|
|
301143
|
+
if (runtime.packageHash !== createHash3("sha256").update(packageJsonRaw).digest("hex"))
|
|
301144
|
+
throw new Error("Global Omnius manifest changed during runtime verification");
|
|
300833
301145
|
const executablePath = globalExecutableCandidates(npmPrefix).find(existsSync6);
|
|
300834
301146
|
if (!executablePath) throw new Error(`Global Omnius executable not found under ${npmPrefix}`);
|
|
300835
301147
|
const versionResult = await runCommand(executablePath, ["--version"], { env: options.env, cwd: options.cwd, timeout: 1e4 });
|
|
@@ -300895,16 +301207,41 @@ async function installGlobalPackageStreaming(input) {
|
|
|
300895
301207
|
onStdout: (text2) => process.stdout.write(text2),
|
|
300896
301208
|
onStderr: (text2) => process.stderr.write(text2)
|
|
300897
301209
|
});
|
|
300898
|
-
const exitCode = result.status ?? -1;
|
|
301210
|
+
const exitCode = result.error && result.status === 0 ? -1 : result.status ?? -1;
|
|
300899
301211
|
const renameCollision = parseNpmRenameCollision(result.stderr);
|
|
300900
|
-
return { exitCode, ...result.error || exitCode !== 0 ? {
|
|
301212
|
+
return { exitCode, settled: result.processGroupSettled !== false, ...result.processGroup ? { processGroup: result.processGroup } : {}, ...result.error || exitCode !== 0 ? {
|
|
300901
301213
|
error: result.error?.message || result.stderr.slice(-8e3).trim() || `npm install exited with ${result.signal || exitCode}`
|
|
300902
301214
|
} : {}, ...renameCollision ? { renameCollision } : {} };
|
|
300903
301215
|
}
|
|
301216
|
+
function restoreOmniusExecutableLink(prefix, installation) {
|
|
301217
|
+
const executable = globalExecutableCandidates(prefix)[0];
|
|
301218
|
+
const target = join16(installation.modulesRoot, "omnius", installation.binTarget);
|
|
301219
|
+
if (process.platform === "win32") {
|
|
301220
|
+
if (!existsSync6(executable)) throw new Error("The restored Omnius Windows executable shim is missing.");
|
|
301221
|
+
return;
|
|
301222
|
+
}
|
|
301223
|
+
const directory = dirname9(executable);
|
|
301224
|
+
if (!existsSync6(directory)) mkdirSync5(directory, { recursive: false, mode: 493 });
|
|
301225
|
+
const metadata = lstatSync2(directory);
|
|
301226
|
+
if (!metadata.isDirectory() || metadata.isSymbolicLink() || metadata.uid !== process.getuid?.() || (metadata.mode & 2) !== 0)
|
|
301227
|
+
throw new Error("The Omnius executable directory is unsafe; no link was changed.");
|
|
301228
|
+
try {
|
|
301229
|
+
const existing = lstatSync2(executable);
|
|
301230
|
+
if (!existing.isSymbolicLink() || existing.uid !== process.getuid?.() || resolve11(directory, readlinkSync2(executable)) !== target)
|
|
301231
|
+
throw new Error("A different executable occupies the Omnius bin path; it was retained.");
|
|
301232
|
+
} catch (error) {
|
|
301233
|
+
if (error.code !== "ENOENT") throw error;
|
|
301234
|
+
symlinkSync(relative2(directory, target), executable);
|
|
301235
|
+
}
|
|
301236
|
+
}
|
|
300904
301237
|
async function runVerifiedUpdateTransaction(initial, dependencies, paths = resolveUpdatePaths()) {
|
|
300905
301238
|
let state = initial;
|
|
300906
301239
|
let daemonQuiesced = false;
|
|
300907
301240
|
let installStarted = false;
|
|
301241
|
+
let installerSettled = true;
|
|
301242
|
+
let packageVerified = false;
|
|
301243
|
+
let previousInstallation;
|
|
301244
|
+
let previousInstallationCopy;
|
|
300908
301245
|
const retirementBackups = [];
|
|
300909
301246
|
let installLease;
|
|
300910
301247
|
let cancelPublication;
|
|
@@ -300942,6 +301279,12 @@ async function runVerifiedUpdateTransaction(initial, dependencies, paths = resol
|
|
|
300942
301279
|
throw new Error("Update ownership changed before package preparation; no directory was moved.");
|
|
300943
301280
|
}
|
|
300944
301281
|
};
|
|
301282
|
+
const assertRecoveryOwned = () => {
|
|
301283
|
+
installLease?.assertOwnedForRecovery();
|
|
301284
|
+
const persisted = readUpdateState(paths);
|
|
301285
|
+
if (!persisted || persisted.operation_id !== state.operation_id || persisted.status !== "running" || state.worker_adopted_at && !ownsAdoptedWorker(persisted, state.operation_id, state.pid, paths))
|
|
301286
|
+
throw new Error("Update ownership changed; package recovery was held.");
|
|
301287
|
+
};
|
|
300945
301288
|
const preserveRetirement = async (stage, collision) => {
|
|
300946
301289
|
const options = {
|
|
300947
301290
|
signal: dependencies.signal,
|
|
@@ -300985,8 +301328,33 @@ async function runVerifiedUpdateTransaction(initial, dependencies, paths = resol
|
|
|
300985
301328
|
installLease = await acquireNpmInstallLease(npmRoot, { signal: dependencies.signal, operationId: state.operation_id });
|
|
300986
301329
|
state = await transition(state, { npm_modules_root: installLease.modulesRoot }, paths);
|
|
300987
301330
|
assertOwned();
|
|
301331
|
+
try {
|
|
301332
|
+
previousInstallation = inspectNpmRuntimeInstallation(join16(installLease.modulesRoot, "omnius"));
|
|
301333
|
+
} catch {
|
|
301334
|
+
}
|
|
300988
301335
|
await preserveRetirement("before_install");
|
|
300989
301336
|
throwIfCancelled();
|
|
301337
|
+
if (previousInstallation) {
|
|
301338
|
+
const preserved = await preserveVerifiedNpmInstallation(previousInstallation, {
|
|
301339
|
+
lease: installLease,
|
|
301340
|
+
signal: dependencies.signal,
|
|
301341
|
+
assertOwned: assertRecoveryOwned,
|
|
301342
|
+
async onPrepare(backup) {
|
|
301343
|
+
state = await transition(state, { npm_recoveries: [...state.npm_recoveries ?? [], {
|
|
301344
|
+
retired_path: backup.retiredPath,
|
|
301345
|
+
backup_path: backup.backupPath,
|
|
301346
|
+
status: "planned",
|
|
301347
|
+
stage: "previous_install",
|
|
301348
|
+
device: backup.device,
|
|
301349
|
+
inode: backup.inode
|
|
301350
|
+
}] }, paths);
|
|
301351
|
+
}
|
|
301352
|
+
});
|
|
301353
|
+
retirementBackups.push(preserved.backup);
|
|
301354
|
+
previousInstallationCopy = preserved.installation;
|
|
301355
|
+
state = await transition(state, { npm_recoveries: state.npm_recoveries.map((item) => item.backup_path === preserved.backup.backupPath ? { ...item, status: "retained" } : item) }, paths);
|
|
301356
|
+
throwIfCancelled();
|
|
301357
|
+
}
|
|
300990
301358
|
state = await transition(state, { npm_preparation: "ready" }, paths);
|
|
300991
301359
|
if (dependencies.quiesceDaemon) {
|
|
300992
301360
|
state = await transition(state, { phase: "daemon_quiescing" }, paths);
|
|
@@ -301007,8 +301375,18 @@ async function runVerifiedUpdateTransaction(initial, dependencies, paths = resol
|
|
|
301007
301375
|
throwIfCancelled();
|
|
301008
301376
|
installStarted = true;
|
|
301009
301377
|
const installResult = await installer({ npmPath, targetVersion: target, env, cwd, signal: dependencies.signal });
|
|
301010
|
-
|
|
301378
|
+
installerSettled = installResult.settled !== false;
|
|
301379
|
+
if (!installerSettled) {
|
|
301380
|
+
assertRecoveryOwned();
|
|
301381
|
+
installLease.retainForUnconfirmedInstaller(installResult.processGroup);
|
|
301382
|
+
}
|
|
301383
|
+
state = await transition(state, {
|
|
301384
|
+
installer_exit_code: installResult.exitCode,
|
|
301385
|
+
installer_settled: installerSettled,
|
|
301386
|
+
...installResult.processGroup ? { installer_process_group: installResult.processGroup } : {}
|
|
301387
|
+
}, paths);
|
|
301011
301388
|
throwIfCancelled();
|
|
301389
|
+
if (!installerSettled) throw new Error(installResult.error || "The owned installer has not settled; package recovery was held.");
|
|
301012
301390
|
if (installResult.exitCode === 0) break;
|
|
301013
301391
|
const collision = installResult.renameCollision ?? parseNpmRenameCollision(installResult.error ?? "");
|
|
301014
301392
|
if (attempt === 1 && collision) {
|
|
@@ -301022,6 +301400,7 @@ async function runVerifiedUpdateTransaction(initial, dependencies, paths = resol
|
|
|
301022
301400
|
}
|
|
301023
301401
|
const evidence = dependencies.inspectInstall ? await dependencies.inspectInstall(target, npmPath, env) : await inspectGlobalOmniusInstall(target, { npmPath, env, cwd });
|
|
301024
301402
|
throwIfCancelled();
|
|
301403
|
+
packageVerified = true;
|
|
301025
301404
|
state = await transition(state, {
|
|
301026
301405
|
phase: "package_verified",
|
|
301027
301406
|
npm_prefix: evidence.npmPrefix,
|
|
@@ -301117,7 +301496,61 @@ async function runVerifiedUpdateTransaction(initial, dependencies, paths = resol
|
|
|
301117
301496
|
const cancelled = error instanceof UpdateCancelledError || dependencies.signal?.aborted === true;
|
|
301118
301497
|
const message = error instanceof Error ? error.message : String(error);
|
|
301119
301498
|
let recoveryNote;
|
|
301120
|
-
|
|
301499
|
+
let packageRecoveryNote;
|
|
301500
|
+
let restoredPackageVerified = false;
|
|
301501
|
+
if (installStarted && installerSettled && !packageVerified && installLease && previousInstallation) {
|
|
301502
|
+
state = await transition(state, { phase: "recovering" }, paths);
|
|
301503
|
+
const journal = (recovery) => ({
|
|
301504
|
+
version: recovery.version,
|
|
301505
|
+
package_hash: recovery.packageHash,
|
|
301506
|
+
source_path: recovery.sourcePath,
|
|
301507
|
+
...recovery.partialPath ? { partial_path: recovery.partialPath } : {}
|
|
301508
|
+
});
|
|
301509
|
+
try {
|
|
301510
|
+
const recoveryOptions = {
|
|
301511
|
+
lease: installLease,
|
|
301512
|
+
backups: retirementBackups,
|
|
301513
|
+
assertOwned: assertRecoveryOwned,
|
|
301514
|
+
async onPrepare(recovery) {
|
|
301515
|
+
state = await transition(state, { package_recovery: { status: "planned", ...journal(recovery) } }, paths);
|
|
301516
|
+
}
|
|
301517
|
+
};
|
|
301518
|
+
let recovered;
|
|
301519
|
+
try {
|
|
301520
|
+
recovered = await restoreVerifiedNpmInstallation(previousInstallation, recoveryOptions);
|
|
301521
|
+
} catch (restoreError) {
|
|
301522
|
+
if (!previousInstallationCopy) throw restoreError;
|
|
301523
|
+
recovered = null;
|
|
301524
|
+
}
|
|
301525
|
+
if (!recovered && previousInstallationCopy) recovered = await restoreVerifiedNpmInstallation(previousInstallationCopy, recoveryOptions);
|
|
301526
|
+
if (recovered) {
|
|
301527
|
+
assertRecoveryOwned();
|
|
301528
|
+
restoreOmniusExecutableLink(state.npm_prefix, previousInstallation);
|
|
301529
|
+
const verified = await inspectGlobalOmniusInstall(previousInstallation.version, { npmPath, env, cwd });
|
|
301530
|
+
assertRecoveryOwned();
|
|
301531
|
+
if (verified.packageHash !== previousInstallation.packageHash) throw new Error("Restored Omnius manifest differs from the pre-install verification.");
|
|
301532
|
+
restoredPackageVerified = true;
|
|
301533
|
+
state = await transition(state, {
|
|
301534
|
+
package_recovery: { status: recovered.status, ...journal(recovered) },
|
|
301535
|
+
npm_recoveries: state.npm_recoveries?.map((item) => item.backup_path === recovered.sourcePath ? { ...item, status: "restored" } : item),
|
|
301536
|
+
package_json_path: verified.packageJsonPath,
|
|
301537
|
+
global_executable: verified.executablePath,
|
|
301538
|
+
installed_version: verified.installedVersion,
|
|
301539
|
+
executable_version: verified.executableVersion,
|
|
301540
|
+
installed_package_hash: verified.packageHash
|
|
301541
|
+
}, paths);
|
|
301542
|
+
packageRecoveryNote = recovered.status === "restored" ? `The previous verified Omnius v${verified.installedVersion} installation was restored.${recovered.partialPath ? ` Failed replacement files remain at ${recovered.partialPath}.` : ""}` : `The previous verified Omnius v${verified.installedVersion} installation remains available.`;
|
|
301543
|
+
} else {
|
|
301544
|
+
state = await transition(state, { package_recovery: { status: "unavailable", version: previousInstallation.version } }, paths);
|
|
301545
|
+
packageRecoveryNote = "The exact previous installation was not available for restoration. No rollback was performed.";
|
|
301546
|
+
}
|
|
301547
|
+
} catch (packageError) {
|
|
301548
|
+
const detail = packageError instanceof Error ? packageError.message : String(packageError);
|
|
301549
|
+
state = await transition(state, { package_recovery: { ...state.package_recovery, status: "failed", error: detail } }, paths);
|
|
301550
|
+
packageRecoveryNote = `Package recovery could not be verified: ${detail}`;
|
|
301551
|
+
}
|
|
301552
|
+
}
|
|
301553
|
+
if (daemonQuiesced && dependencies.recoverDaemon && installerSettled && (!installStarted || packageVerified || restoredPackageVerified)) {
|
|
301121
301554
|
state = await transition(state, { phase: "recovering" }, paths);
|
|
301122
301555
|
try {
|
|
301123
301556
|
const recovered = await dependencies.recoverDaemon();
|
|
@@ -301125,15 +301558,18 @@ async function runVerifiedUpdateTransaction(initial, dependencies, paths = resol
|
|
|
301125
301558
|
} catch (recoveryError) {
|
|
301126
301559
|
recoveryNote = `Daemon recovery failed: ${recoveryError instanceof Error ? recoveryError.message : String(recoveryError)}`;
|
|
301127
301560
|
}
|
|
301561
|
+
} else if (daemonQuiesced && dependencies.recoverDaemon) {
|
|
301562
|
+
recoveryNote = "Daemon recovery was held because the installed runtime could not be verified.";
|
|
301128
301563
|
}
|
|
301129
301564
|
state = await transition(state, {
|
|
301130
301565
|
status: cancelled ? "cancelled" : "failed",
|
|
301131
301566
|
phase: cancelled ? "cancelled" : "failed",
|
|
301132
301567
|
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
301133
|
-
error: cancelled ? "Update cancelled after the owned operation settled." : message,
|
|
301568
|
+
error: cancelled ? installerSettled ? "Update cancelled after the owned operation settled." : "Update cancellation requested; owned installer shutdown could not be confirmed." : message,
|
|
301134
301569
|
remediation: [
|
|
301135
|
-
|
|
301136
|
-
|
|
301570
|
+
packageRecoveryNote,
|
|
301571
|
+
cancelled && installStarted && !restoredPackageVerified ? "Package files may have changed. No rollback was performed; verify the installed version before retrying." : void 0,
|
|
301572
|
+
...(state.npm_recoveries ?? []).filter((item) => item.status === "retained").map((item) => item.stage === "previous_install" ? `The verified prior installation backup is preserved at ${item.backup_path}.` : `The prior npm retirement directory is preserved at ${item.backup_path}.`),
|
|
301137
301573
|
permissionRemediation(message),
|
|
301138
301574
|
recoveryNote
|
|
301139
301575
|
].filter(Boolean).join(" ") || void 0
|