jorgex-stack 1.9.63 → 1.9.65

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.
Files changed (2) hide show
  1. package/dist/cli.js +530 -460
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -2115,6 +2115,12 @@ function isManagedOptionalStdioServer(server, value) {
2115
2115
  const expectedCommand = [server.command, ...server.args ?? []];
2116
2116
  return Object.keys(current).length === 2 && current.type === "local" && Array.isArray(current.command) && current.command.length === expectedCommand.length && current.command.every((arg, index) => arg === expectedCommand[index]);
2117
2117
  }
2118
+ function isOwnedDevtoolsServer(name, server, value, ctx) {
2119
+ if (isManagedOptionalStdioServer(server, value)) return true;
2120
+ if (name !== DEVTOOLS_MCP_SERVER) return false;
2121
+ const template = loadCanonicalMcp(ctx.stackDir).servers[DEVTOOLS_MCP_SERVER];
2122
+ return template !== void 0 && isManagedOptionalStdioServer(materializeCanonicalDevtoolsServerForRemoval(template), value);
2123
+ }
2118
2124
  function objectValue(value) {
2119
2125
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
2120
2126
  }
@@ -2654,16 +2660,14 @@ ${gitReadCommands.map((command) => `- \`${command}\``).join("\n")}
2654
2660
  }
2655
2661
  if (!isCanonicalMcpServerEnabled(name, server, ctx.enabledMcpServers)) {
2656
2662
  if (owned) {
2657
- if (isManagedOptionalStdioServer(server, existing)) delete mcp[name];
2663
+ if (isOwnedDevtoolsServer(name, server, existing, ctx)) delete mcp[name];
2658
2664
  mcpOwnership.push({ server: name, owned: false });
2659
2665
  }
2660
2666
  continue;
2661
2667
  }
2662
2668
  if (server.optional && existing !== void 0) {
2663
- if (!owned || !isManagedOptionalStdioServer(server, existing)) {
2664
- if (owned) mcpOwnership.push({ server: name, owned: false });
2665
- ctx.warnings.push(`OpenCode: MCP opcional '${name}' ya pertenece a la configuraci\xF3n del usuario; se conserva.`);
2666
- continue;
2669
+ if (!owned || !isOwnedDevtoolsServer(name, server, existing, ctx)) {
2670
+ throw new Error(`OpenCode: ${name}: conflicto con servidor MCP existente ajeno o modificado; se conserva. Retira esa entrada expl\xEDcitamente antes de activar DevTools gestionado.`);
2667
2671
  }
2668
2672
  }
2669
2673
  if (server.transport === "stdio") {
@@ -2792,7 +2796,7 @@ ${gitReadCommands.map((command) => `- \`${command}\``).join("\n")}
2792
2796
  continue;
2793
2797
  }
2794
2798
  if (ctx.ownedMcpServers?.has(name) === true) {
2795
- if (isManagedOptionalStdioServer(server, mcpBlock[name])) delete mcpBlock[name];
2799
+ if (isOwnedDevtoolsServer(name, server, mcpBlock[name], ctx)) delete mcpBlock[name];
2796
2800
  mcpOwnership.push({ server: name, owned: false });
2797
2801
  }
2798
2802
  }
@@ -2938,6 +2942,12 @@ function isManagedOptionalStdioServer2(server, value) {
2938
2942
  const expectedArgs = server.args ?? [];
2939
2943
  return Object.keys(current).length === 3 && current.type === "stdio" && current.command === server.command && Array.isArray(current.args) && current.args.length === expectedArgs.length && current.args.every((arg, index) => arg === expectedArgs[index]);
2940
2944
  }
2945
+ function isOwnedDevtoolsServer2(name, server, value, ctx) {
2946
+ if (isManagedOptionalStdioServer2(server, value)) return true;
2947
+ if (name !== DEVTOOLS_MCP_SERVER) return false;
2948
+ const template = loadCanonicalMcp(ctx.stackDir).servers[DEVTOOLS_MCP_SERVER];
2949
+ return template !== void 0 && isManagedOptionalStdioServer2(materializeCanonicalDevtoolsServerForRemoval(template), value);
2950
+ }
2941
2951
  function errnoCodeOf(error) {
2942
2952
  return error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : "UNKNOWN";
2943
2953
  }
@@ -3288,16 +3298,14 @@ ${agent.body}`,
3288
3298
  }
3289
3299
  if (!isCanonicalMcpServerEnabled(name, server, ctx.enabledMcpServers)) {
3290
3300
  if (owned) {
3291
- if (isManagedOptionalStdioServer2(server, existing)) delete servers[name];
3301
+ if (isOwnedDevtoolsServer2(name, server, existing, ctx)) delete servers[name];
3292
3302
  mcpOwnership.push({ server: name, owned: false });
3293
3303
  }
3294
3304
  continue;
3295
3305
  }
3296
3306
  if (server.optional && existing !== void 0) {
3297
- if (!owned || !isManagedOptionalStdioServer2(server, existing)) {
3298
- if (owned) mcpOwnership.push({ server: name, owned: false });
3299
- ctx.warnings.push(`Claude Code: MCP opcional '${name}' ya pertenece a la configuraci\xF3n del usuario; se conserva.`);
3300
- continue;
3307
+ if (!owned || !isOwnedDevtoolsServer2(name, server, existing, ctx)) {
3308
+ throw new Error(`Claude Code: ${name}: conflicto con servidor MCP existente ajeno o modificado; se conserva. Retira esa entrada expl\xEDcitamente antes de activar DevTools gestionado.`);
3301
3309
  }
3302
3310
  }
3303
3311
  if (server.transport === "stdio") {
@@ -3378,7 +3386,7 @@ ${agent.body}`,
3378
3386
  continue;
3379
3387
  }
3380
3388
  if (ctx.ownedMcpServers?.has(name) === true) {
3381
- if (isManagedOptionalStdioServer2(server, servers[name])) delete servers[name];
3389
+ if (isOwnedDevtoolsServer2(name, server, servers[name], ctx)) delete servers[name];
3382
3390
  mcpOwnership.push({ server: name, owned: false });
3383
3391
  }
3384
3392
  }
@@ -3427,6 +3435,12 @@ args = [${args}]`;
3427
3435
  function isManagedOptionalStdioServer3(server, section) {
3428
3436
  return server.optional === true && server.transport === "stdio" && section?.trim() === stdioMcpSection(server);
3429
3437
  }
3438
+ function isOwnedDevtoolsServer3(name, server, section, ctx) {
3439
+ if (isManagedOptionalStdioServer3(server, section)) return true;
3440
+ if (name !== DEVTOOLS_MCP_SERVER) return false;
3441
+ const template = loadCanonicalMcp(ctx.stackDir).servers[DEVTOOLS_MCP_SERVER];
3442
+ return template !== void 0 && isManagedOptionalStdioServer3(materializeCanonicalDevtoolsServerForRemoval(template), section);
3443
+ }
3430
3444
  function hasActiveEngramPlugin(configDir) {
3431
3445
  const config = readTextIfExists(path14.join(configDir, "config.toml"));
3432
3446
  if (config === null) return false;
@@ -3953,16 +3967,14 @@ ${body}`
3953
3967
  }
3954
3968
  if (!isCanonicalMcpServerEnabled(name, server, ctx.enabledMcpServers)) {
3955
3969
  if (owned) {
3956
- if (isManagedOptionalStdioServer3(server, existing)) content = removeTomlSection(content, section);
3970
+ if (isOwnedDevtoolsServer3(name, server, existing, ctx)) content = removeTomlSection(content, section);
3957
3971
  mcpOwnership.push({ server: name, owned: false });
3958
3972
  }
3959
3973
  continue;
3960
3974
  }
3961
3975
  if (server.optional && existing !== null) {
3962
- if (!owned || !isManagedOptionalStdioServer3(server, existing)) {
3963
- if (owned) mcpOwnership.push({ server: name, owned: false });
3964
- ctx.warnings.push(`Codex: MCP opcional '${name}' ya pertenece a la configuraci\xF3n del usuario; se conserva.`);
3965
- continue;
3976
+ if (!owned || !isOwnedDevtoolsServer3(name, server, existing, ctx)) {
3977
+ throw new Error(`Codex: ${name}: conflicto con servidor MCP existente ajeno o modificado; se conserva. Retira esa entrada expl\xEDcitamente antes de activar DevTools gestionado.`);
3966
3978
  }
3967
3979
  }
3968
3980
  if (server.transport === "stdio") {
@@ -4054,7 +4066,7 @@ args = [${(server.args ?? []).map(tomlString).join(", ")}]`);
4054
4066
  continue;
4055
4067
  }
4056
4068
  if (ctx.ownedMcpServers?.has(name) === true) {
4057
- if (isManagedOptionalStdioServer3(server, readTomlSection(content, section))) {
4069
+ if (isOwnedDevtoolsServer3(name, server, readTomlSection(content, section), ctx)) {
4058
4070
  content = removeTomlSection(content, section);
4059
4071
  }
4060
4072
  mcpOwnership.push({ server: name, owned: false });
@@ -4330,7 +4342,7 @@ var init_pi = __esm({
4330
4342
 
4331
4343
  // src/cli.ts
4332
4344
  import * as p6 from "@clack/prompts";
4333
- import fs43 from "fs";
4345
+ import fs44 from "fs";
4334
4346
  import { pathToFileURL as pathToFileURL2 } from "url";
4335
4347
 
4336
4348
  // src/install.ts
@@ -7568,10 +7580,16 @@ function enabledMcpServers(runtime, explicitDevtoolsEnabled, useBrowserPreferenc
7568
7580
  const devtoolsEnabled = explicitDevtoolsEnabled ?? (useBrowserPreferences && loadDevtoolsMcpPreference(devtoolsMcpPreferenceFile(), runtime));
7569
7581
  return devtoolsEnabled ? /* @__PURE__ */ new Set([DEVTOOLS_MCP_SERVER]) : /* @__PURE__ */ new Set();
7570
7582
  }
7571
- function ownedMcpServers(runtime, useBrowserPreferences = true) {
7583
+ function ownedMcpServers(runtime, configDir, useBrowserPreferences = true) {
7572
7584
  if (!useBrowserPreferences) return /* @__PURE__ */ new Set();
7573
7585
  const file = devtoolsMcpPreferenceFile();
7574
- return new Set([DEVTOOLS_MCP_SERVER, "context7"].filter((server) => loadDevtoolsMcpOwnership(file, runtime, server)));
7586
+ const marked = [DEVTOOLS_MCP_SERVER, "context7"].filter((server) => loadDevtoolsMcpOwnership(file, runtime, server));
7587
+ if (marked.length === 0) return /* @__PURE__ */ new Set();
7588
+ const recordedDir = readManifest().runtimes[runtime]?.configDir;
7589
+ if (typeof recordedDir !== "string" || !samePath(recordedDir, configDir)) {
7590
+ throw new Error(`${runtime}: MCP ownership configDir no coincide con el perfil actual; se conserva la configuraci\xF3n. Vuelve al perfil anterior o revisa el estado gestionado antes de reintentar.`);
7591
+ }
7592
+ return new Set(marked);
7575
7593
  }
7576
7594
  function persistConfigurationOwnershipChanges(runtime, configDir, plan) {
7577
7595
  const latest = /* @__PURE__ */ new Map();
@@ -7600,7 +7618,7 @@ function makeContext(adapter, configDir, mode = DEFAULT_INSTALL_MODE_PREFERENCE,
7600
7618
  const models = loadModelMap()[adapter.id];
7601
7619
  if (!models) return null;
7602
7620
  const enabled = enabledMcpServers(adapter.id, void 0, useBrowserPreferences);
7603
- const owned = ownedMcpServers(adapter.id, useBrowserPreferences);
7621
+ const owned = ownedMcpServers(adapter.id, configDir, useBrowserPreferences);
7604
7622
  let devtoolsMcpObservedVersion;
7605
7623
  let devtoolsMcpInvocation;
7606
7624
  if (useBrowserPreferences && (enabled.has(DEVTOOLS_MCP_SERVER) || owned.has(DEVTOOLS_MCP_SERVER))) {
@@ -7849,7 +7867,12 @@ async function runInstall(opts) {
7849
7867
  }
7850
7868
  }
7851
7869
  const anyDevtoolsEnabled = opts.runtimes.some((id) => enabledMcpServers(id, opts.devtoolsMcpSelection?.[id], useManifest).has(DEVTOOLS_MCP_SERVER));
7852
- const anyDevtoolsOwned = useManifest && opts.runtimes.some((id) => ownedMcpServers(id, true).has(DEVTOOLS_MCP_SERVER));
7870
+ const anyDevtoolsOwned = useManifest && opts.runtimes.some((id) => {
7871
+ const adapter = ADAPTERS[id];
7872
+ if (adapter === void 0) return false;
7873
+ const detection = adapter.detect();
7874
+ return detection.installed && ownedMcpServers(id, detection.configDir, true).has(DEVTOOLS_MCP_SERVER);
7875
+ });
7853
7876
  if (anyDevtoolsEnabled && devtoolsManagedInvocation === void 0) {
7854
7877
  const observed = isDevtoolsTargetDir ? devtoolsTargetDirObserved : devtoolsPersistedObserved;
7855
7878
  try {
@@ -7955,7 +7978,7 @@ async function runInstall(opts) {
7955
7978
  }
7956
7979
  }
7957
7980
  const enabledForRuntime = enabledMcpServers(id, opts.devtoolsMcpSelection?.[id], useManifest);
7958
- const ownedForRuntime = ownedMcpServers(id, useManifest);
7981
+ const ownedForRuntime = ownedMcpServers(id, configDir, useManifest);
7959
7982
  let devtoolsObservedForRuntime;
7960
7983
  if (isDevtoolsTargetDir) {
7961
7984
  if (enabledForRuntime.has(DEVTOOLS_MCP_SERVER)) {
@@ -8114,7 +8137,15 @@ async function runInstall(opts) {
8114
8137
  const backup = useManifest ? createBackup([...updates.map((c) => c.action.target), ...orphans], `install-${id}`) : null;
8115
8138
  if (backup) p.log.info(`Backup: ${backup.id} (${backup.files.length} archivos)`);
8116
8139
  applyChanges(changes, useManifest ? (action) => persistConfigurationOwnershipChanges(id, configDir, [action]) : void 0);
8117
- const verifyCtx = { ...ctx, warnings: [] };
8140
+ const verifiedOwnedMcpServers = new Set(ctx.ownedMcpServers ?? []);
8141
+ for (const action of plan) {
8142
+ if (action.kind !== "write") continue;
8143
+ for (const change of action.mcpOwnership ?? []) {
8144
+ if (change.owned) verifiedOwnedMcpServers.add(change.server);
8145
+ else verifiedOwnedMcpServers.delete(change.server);
8146
+ }
8147
+ }
8148
+ const verifyCtx = { ...ctx, warnings: [], ownedMcpServers: verifiedOwnedMcpServers };
8118
8149
  const dirty = diffPlan(buildPlan(adapter, verifyCtx)).filter((d) => d.status !== "unchanged");
8119
8150
  if (dirty.length > 0) {
8120
8151
  p.log.error(`${adapter.name}: verificaci\xF3n de idempotencia FALL\xD3 (${dirty.length} acciones inestables).`);
@@ -12734,8 +12765,8 @@ init_model_map();
12734
12765
 
12735
12766
  // src/lib/pi-runtime.ts
12736
12767
  import os6 from "os";
12737
- import path47 from "path";
12738
- import fs39 from "fs";
12768
+ import path48 from "path";
12769
+ import fs40 from "fs";
12739
12770
  import { spawnSync as spawnSync5 } from "child_process";
12740
12771
 
12741
12772
  // src/lib/pi-runtime-pin.json
@@ -12789,8 +12820,8 @@ init_paths();
12789
12820
 
12790
12821
  // src/lib/pi-install-preflight.ts
12791
12822
  init_npm_provider();
12792
- import fs35 from "fs";
12793
- import path43 from "path";
12823
+ import fs36 from "fs";
12824
+ import path44 from "path";
12794
12825
 
12795
12826
  // src/lib/pi-candidate.ts
12796
12827
  import fs33 from "fs";
@@ -13490,18 +13521,121 @@ async function stageVerifiedPiTarball(input, run) {
13490
13521
  return { stageDir, evidence, sourceAlias };
13491
13522
  }
13492
13523
 
13493
- // src/lib/pi-install-preflight.ts
13524
+ // src/lib/pi-host-version.ts
13525
+ import fs35 from "fs";
13526
+ import path43 from "path";
13494
13527
  var PI_PACKAGE_NAME = "@earendil-works/pi-coding-agent";
13528
+ function invalidManagedPi(diagnostic) {
13529
+ return { version: null, diagnostic };
13530
+ }
13531
+ function readJsonFile(file) {
13532
+ try {
13533
+ const stat = fs35.lstatSync(file, { throwIfNoEntry: false });
13534
+ if (!stat?.isFile() || stat.isSymbolicLink() || stat.size > 1024 * 1024) return null;
13535
+ return JSON.parse(fs35.readFileSync(file, "utf8"));
13536
+ } catch {
13537
+ return null;
13538
+ }
13539
+ }
13540
+ function piPackageVersion(file) {
13541
+ try {
13542
+ const value = readJsonFile(file);
13543
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
13544
+ const packageName = Reflect.get(value, "name");
13545
+ const version = Reflect.get(value, "version");
13546
+ return packageName === PI_PACKAGE_NAME && typeof version === "string" && version !== "" && !/\s/.test(version) ? version : null;
13547
+ } catch {
13548
+ return null;
13549
+ }
13550
+ }
13551
+ function managedPiVersion(executable, resolved2) {
13552
+ const binDir = path43.dirname(resolved2);
13553
+ if (path43.basename(resolved2) !== "pi" || path43.basename(binDir) !== "bin") {
13554
+ return invalidManagedPi("launcher gestionado de Pi no reconocido");
13555
+ }
13556
+ const agentDir = path43.dirname(binDir);
13557
+ const installDir = path43.join(agentDir, "install");
13558
+ try {
13559
+ if (!fs35.lstatSync(executable).isSymbolicLink()) {
13560
+ return invalidManagedPi("el entrypoint gestionado de Pi no es un symlink");
13561
+ }
13562
+ const metadata = readJsonFile(path43.join(installDir, "managed-install.json"));
13563
+ if (metadata === null || typeof metadata !== "object" || Array.isArray(metadata)) {
13564
+ return invalidManagedPi("install/managed-install.json falta o no es JSON v\xE1lido");
13565
+ }
13566
+ const entrypoint = Reflect.get(metadata, "entrypoint");
13567
+ if (Reflect.get(metadata, "kind") !== "pi-managed-install" || Reflect.get(metadata, "schemaVersion") !== 1 || Reflect.get(metadata, "layout") !== "releases-v1" || entrypoint === null || typeof entrypoint !== "object" || Array.isArray(entrypoint) || Reflect.get(entrypoint, "type") !== "symlink" || Reflect.get(entrypoint, "path") !== executable) {
13568
+ return invalidManagedPi("install/managed-install.json no coincide con el entrypoint de Pi");
13569
+ }
13570
+ const currentPath = path43.join(installDir, "current-version");
13571
+ const currentStat = fs35.lstatSync(currentPath, { throwIfNoEntry: false });
13572
+ if (!currentStat?.isFile() || currentStat.isSymbolicLink() || currentStat.size > 128) {
13573
+ return invalidManagedPi("install/current-version falta o no es un archivo regular acotado");
13574
+ }
13575
+ const version = fs35.readFileSync(currentPath, "utf8").trim();
13576
+ if (version === "." || version === ".." || !/^[0-9A-Za-z._+-]+$/.test(version)) {
13577
+ return invalidManagedPi("install/current-version contiene una versi\xF3n inv\xE1lida");
13578
+ }
13579
+ const releaseDir = path43.join(installDir, "releases", version);
13580
+ if (fs35.realpathSync(releaseDir) !== releaseDir) {
13581
+ return invalidManagedPi("install/releases contiene un enlace fuera del release gestionado");
13582
+ }
13583
+ const packageDir = path43.join(releaseDir, "node_modules", "@earendil-works", "pi-coding-agent");
13584
+ if (fs35.realpathSync(packageDir) !== packageDir) {
13585
+ return invalidManagedPi("el paquete Pi del release gestionado es un symlink");
13586
+ }
13587
+ const packageVersion = piPackageVersion(path43.join(packageDir, "package.json"));
13588
+ return packageVersion === version ? { version, diagnostic: null } : invalidManagedPi("el manifest de @earendil-works/pi-coding-agent no coincide con install/current-version");
13589
+ } catch {
13590
+ return invalidManagedPi("no se pudo leer la metadata del release Pi gestionado");
13591
+ }
13592
+ }
13593
+ function hasManagedPiMarker(resolved2) {
13594
+ const binDir = path43.dirname(resolved2);
13595
+ if (path43.basename(resolved2) !== "pi" || path43.basename(binDir) !== "bin") return false;
13596
+ const installDir = path43.join(path43.dirname(binDir), "install");
13597
+ try {
13598
+ return fs35.lstatSync(path43.join(installDir, "managed-install.json"), { throwIfNoEntry: false }) !== void 0 || fs35.lstatSync(path43.join(installDir, "current-version"), { throwIfNoEntry: false }) !== void 0;
13599
+ } catch {
13600
+ return true;
13601
+ }
13602
+ }
13603
+ function inspectPiHostVersion(executable) {
13604
+ const absoluteExecutable = path43.resolve(executable);
13605
+ let resolved2;
13606
+ try {
13607
+ resolved2 = fs35.realpathSync(absoluteExecutable);
13608
+ } catch {
13609
+ return { version: null, diagnostic: "no se pudo resolver el ejecutable Pi" };
13610
+ }
13611
+ if (hasManagedPiMarker(resolved2)) return managedPiVersion(absoluteExecutable, resolved2);
13612
+ let current = path43.dirname(resolved2);
13613
+ for (let depth = 0; depth < 8; depth += 1) {
13614
+ for (const manifest of [
13615
+ path43.join(current, "package.json"),
13616
+ path43.join(current, "node_modules", "@earendil-works", "pi-coding-agent", "package.json")
13617
+ ]) {
13618
+ const version = piPackageVersion(manifest);
13619
+ if (version !== null) return { version, diagnostic: null };
13620
+ }
13621
+ const parent = path43.dirname(current);
13622
+ if (parent === current) break;
13623
+ current = parent;
13624
+ }
13625
+ return { version: null, diagnostic: "no se encontr\xF3 el manifest del paquete Pi instalado" };
13626
+ }
13627
+
13628
+ // src/lib/pi-install-preflight.ts
13495
13629
  function fail9(message) {
13496
13630
  throw new Error(`pi-install-preflight: ${message}`);
13497
13631
  }
13498
13632
  function isStrictChild3(child, root) {
13499
- const rel = path43.relative(path43.resolve(root), path43.resolve(child));
13500
- return rel !== "" && rel !== ".." && !rel.startsWith(`..${path43.sep}`) && !path43.isAbsolute(rel);
13633
+ const rel = path44.relative(path44.resolve(root), path44.resolve(child));
13634
+ return rel !== "" && rel !== ".." && !rel.startsWith(`..${path44.sep}`) && !path44.isAbsolute(rel);
13501
13635
  }
13502
13636
  function lstatOrNull4(p7) {
13503
13637
  try {
13504
- return fs35.lstatSync(p7);
13638
+ return fs36.lstatSync(p7);
13505
13639
  } catch {
13506
13640
  return null;
13507
13641
  }
@@ -13517,24 +13651,24 @@ function validatePaths(paths) {
13517
13651
  fail9("paths must be an object");
13518
13652
  }
13519
13653
  const { homeDir, agentDir, piExecutable, downloadsDir } = paths;
13520
- if (typeof homeDir !== "string" || homeDir === "" || !path43.isAbsolute(homeDir)) {
13654
+ if (typeof homeDir !== "string" || homeDir === "" || !path44.isAbsolute(homeDir)) {
13521
13655
  fail9("homeDir must be a non-empty absolute path");
13522
13656
  }
13523
- if (typeof agentDir !== "string" || agentDir === "" || !path43.isAbsolute(agentDir)) {
13657
+ if (typeof agentDir !== "string" || agentDir === "" || !path44.isAbsolute(agentDir)) {
13524
13658
  fail9("agentDir must be a non-empty absolute path");
13525
13659
  }
13526
- if (typeof piExecutable !== "string" || piExecutable === "" || !path43.isAbsolute(piExecutable)) {
13660
+ if (typeof piExecutable !== "string" || piExecutable === "" || !path44.isAbsolute(piExecutable)) {
13527
13661
  fail9("piExecutable must be a non-empty absolute path");
13528
13662
  }
13529
13663
  if (piExecutable === "npm") {
13530
13664
  fail9("piExecutable must be the detected Pi CLI, never npm");
13531
13665
  }
13532
- if (typeof downloadsDir !== "string" || downloadsDir === "" || !path43.isAbsolute(downloadsDir)) {
13666
+ if (typeof downloadsDir !== "string" || downloadsDir === "" || !path44.isAbsolute(downloadsDir)) {
13533
13667
  fail9("downloadsDir must be a non-empty absolute path");
13534
13668
  }
13535
- const homeResolved = path43.resolve(homeDir);
13536
- const agentResolved = path43.resolve(agentDir);
13537
- const downloadsResolved = path43.resolve(downloadsDir);
13669
+ const homeResolved = path44.resolve(homeDir);
13670
+ const agentResolved = path44.resolve(agentDir);
13671
+ const downloadsResolved = path44.resolve(downloadsDir);
13538
13672
  assertRealDir2(homeResolved, "homeDir");
13539
13673
  assertRealDir2(agentResolved, "agentDir");
13540
13674
  assertRealDir2(downloadsResolved, "downloadsDir");
@@ -13562,43 +13696,6 @@ function validateDeps(deps) {
13562
13696
  }
13563
13697
  return { fetchImpl, run };
13564
13698
  }
13565
- function readJsonFile(file) {
13566
- return JSON.parse(fs35.readFileSync(file, "utf8"));
13567
- }
13568
- function detectPiHostVersion(piExecutable) {
13569
- let current;
13570
- try {
13571
- current = path43.dirname(fs35.realpathSync(piExecutable));
13572
- } catch {
13573
- fail9(`cannot resolve Pi executable: ${piExecutable}`);
13574
- }
13575
- for (let depth = 0; depth < 8; depth++) {
13576
- const manifests = [
13577
- path43.join(current, "package.json"),
13578
- path43.join(current, "node_modules", PI_PACKAGE_NAME, "package.json")
13579
- ];
13580
- for (const manifest of manifests) {
13581
- let parsed;
13582
- try {
13583
- parsed = readJsonFile(manifest);
13584
- } catch {
13585
- continue;
13586
- }
13587
- if (parsed !== null && typeof parsed === "object" && Reflect.get(parsed, "name") === PI_PACKAGE_NAME && typeof Reflect.get(parsed, "version") === "string") {
13588
- const version = Reflect.get(parsed, "version");
13589
- if (version !== "" && !/\s/.test(version)) {
13590
- return version;
13591
- }
13592
- }
13593
- }
13594
- const parent = path43.dirname(current);
13595
- if (parent === current) {
13596
- break;
13597
- }
13598
- current = parent;
13599
- }
13600
- fail9(`cannot detect Pi host version from executable: ${piExecutable}`);
13601
- }
13602
13699
  async function preparePiManagedInstall(paths, deps) {
13603
13700
  const { homeDir, agentDir, piExecutable, downloadsDir } = validatePaths(paths);
13604
13701
  const { fetchImpl, run } = validateDeps(deps);
@@ -13627,8 +13724,8 @@ async function preparePiManagedInstall(paths, deps) {
13627
13724
  `pi-install-preflight: producer commit resolution failed: ${error instanceof Error ? error.message : String(error)}`
13628
13725
  );
13629
13726
  }
13630
- const downloadsResolved = path43.resolve(downloadsDir);
13631
- const destination = path43.join(downloadsResolved, `jorgex-pi-${release.version}.tgz`);
13727
+ const downloadsResolved = path44.resolve(downloadsDir);
13728
+ const destination = path44.join(downloadsResolved, `jorgex-pi-${release.version}.tgz`);
13632
13729
  if (!isStrictChild3(destination, downloadsResolved)) {
13633
13730
  fail9(`tarball destination escapes downloadsDir: ${destination}`);
13634
13731
  }
@@ -13657,7 +13754,8 @@ async function preparePiManagedInstall(paths, deps) {
13657
13754
  } catch (error) {
13658
13755
  throw error;
13659
13756
  }
13660
- const hostVersion = detectPiHostVersion(piExecutable);
13757
+ const hostInspection = inspectPiHostVersion(piExecutable);
13758
+ const hostVersion = hostInspection.version ?? fail9(`cannot detect Pi host version: ${hostInspection.diagnostic ?? "unknown reason"}`);
13661
13759
  let candidate;
13662
13760
  try {
13663
13761
  candidate = await buildStagedPiCandidate({
@@ -13679,16 +13777,16 @@ import { createHash as createHash8 } from "crypto";
13679
13777
 
13680
13778
  // src/lib/pi-private-release.ts
13681
13779
  import crypto2 from "crypto";
13682
- import fs36 from "fs";
13683
- import path44 from "path";
13780
+ import fs37 from "fs";
13781
+ import path45 from "path";
13684
13782
  var RELEASE_ID_PATTERN = /^[0-9a-f]{64}$/;
13685
13783
  var EXPECTED_ENTRY = "jorgex-pi";
13686
13784
  function resolved(p7) {
13687
- return path44.resolve(p7);
13785
+ return path45.resolve(p7);
13688
13786
  }
13689
13787
  function isStrictChild4(child, root) {
13690
- const rel = path44.relative(resolved(root), resolved(child));
13691
- return rel !== "" && rel !== ".." && !rel.startsWith(`..${path44.sep}`) && !path44.isAbsolute(rel);
13788
+ const rel = path45.relative(resolved(root), resolved(child));
13789
+ return rel !== "" && rel !== ".." && !rel.startsWith(`..${path45.sep}`) && !path45.isAbsolute(rel);
13692
13790
  }
13693
13791
  function assertStrictChild(child, root, label) {
13694
13792
  if (!isStrictChild4(child, root)) {
@@ -13697,7 +13795,7 @@ function assertStrictChild(child, root, label) {
13697
13795
  }
13698
13796
  function lstatOrNull5(p7) {
13699
13797
  try {
13700
- return fs36.lstatSync(p7);
13798
+ return fs37.lstatSync(p7);
13701
13799
  } catch {
13702
13800
  return null;
13703
13801
  }
@@ -13719,7 +13817,7 @@ function assertAncestorsClean(dir, stop, label) {
13719
13817
  throw new Error(`${label} ancestor is a symlink: ${cur}`);
13720
13818
  }
13721
13819
  if (cur === stopResolved) break;
13722
- const parent = path44.dirname(cur);
13820
+ const parent = path45.dirname(cur);
13723
13821
  if (parent === cur) break;
13724
13822
  cur = parent;
13725
13823
  if (cur.length < stopResolved.length) break;
@@ -13731,7 +13829,7 @@ function assertFilePathClean(file, stop, label) {
13731
13829
  if (st !== null && st.isSymbolicLink()) {
13732
13830
  throw new Error(`${label} is a symlink: ${file}`);
13733
13831
  }
13734
- assertAncestorsClean(path44.dirname(resolved(file)), stop, label);
13832
+ assertAncestorsClean(path45.dirname(resolved(file)), stop, label);
13735
13833
  }
13736
13834
  function assertDirClean(dir, stop, label) {
13737
13835
  assertStrictChild(dir, stop, label);
@@ -13743,17 +13841,17 @@ function assertDirClean(dir, stop, label) {
13743
13841
  }
13744
13842
  function assertLinkInsideRoot(linkPath, allowedRoot, label, finalKind) {
13745
13843
  const allowedResolved = resolved(allowedRoot);
13746
- const linkParent = path44.dirname(resolved(linkPath));
13844
+ const linkParent = path45.dirname(resolved(linkPath));
13747
13845
  if (linkParent !== allowedResolved && !isStrictChild4(linkParent, allowedResolved)) {
13748
13846
  throw new Error(`${label} escapes owner root: ${linkPath}`);
13749
13847
  }
13750
13848
  let target;
13751
13849
  try {
13752
- target = fs36.readlinkSync(linkPath);
13850
+ target = fs37.readlinkSync(linkPath);
13753
13851
  } catch {
13754
13852
  throw new Error(`${label} is broken or unreadable: ${linkPath}`);
13755
13853
  }
13756
- if (target === "" || path44.isAbsolute(target)) {
13854
+ if (target === "" || path45.isAbsolute(target)) {
13757
13855
  throw new Error(`${label} must be a relative symlink: ${linkPath}`);
13758
13856
  }
13759
13857
  const parentStat = lstatOrNull5(linkParent);
@@ -13769,7 +13867,7 @@ function assertLinkInsideRoot(linkPath, allowedRoot, label, finalKind) {
13769
13867
  const part = ops[i];
13770
13868
  const isLast = i === ops.length - 1;
13771
13869
  if (part === "..") {
13772
- cur = path44.dirname(cur);
13870
+ cur = path45.dirname(cur);
13773
13871
  if (cur !== allowedResolved && !isStrictChild4(cur, allowedResolved)) {
13774
13872
  throw new Error(`${label} escapes owner root: ${linkPath} -> ${target}`);
13775
13873
  }
@@ -13792,7 +13890,7 @@ function assertLinkInsideRoot(linkPath, allowedRoot, label, finalKind) {
13792
13890
  }
13793
13891
  continue;
13794
13892
  }
13795
- const next = path44.join(cur, part);
13893
+ const next = path45.join(cur, part);
13796
13894
  if (next !== allowedResolved && !isStrictChild4(next, allowedResolved)) {
13797
13895
  throw new Error(`${label} escapes owner root: ${linkPath} -> ${target}`);
13798
13896
  }
@@ -13832,12 +13930,12 @@ function validateStageTree(stagedNpm) {
13832
13930
  const dir = stack.pop();
13833
13931
  let entries;
13834
13932
  try {
13835
- entries = fs36.readdirSync(dir, { withFileTypes: true });
13933
+ entries = fs37.readdirSync(dir, { withFileTypes: true });
13836
13934
  } catch {
13837
13935
  throw new Error(`staged tree unreadable: ${dir}`);
13838
13936
  }
13839
13937
  for (const entry of entries) {
13840
- const full = path44.join(dir, entry.name);
13938
+ const full = path45.join(dir, entry.name);
13841
13939
  if (entry.isSymbolicLink()) {
13842
13940
  assertInternalSymlink(full, root, "staged symlink");
13843
13941
  continue;
@@ -13849,39 +13947,39 @@ function validateStageTree(stagedNpm) {
13849
13947
  }
13850
13948
  }
13851
13949
  function atomicWritePrivate(target, content) {
13852
- const dir = path44.dirname(resolved(target));
13853
- fs36.mkdirSync(dir, { recursive: true });
13854
- const tmp = path44.join(dir, `.tmp-${crypto2.randomBytes(16).toString("hex")}`);
13950
+ const dir = path45.dirname(resolved(target));
13951
+ fs37.mkdirSync(dir, { recursive: true });
13952
+ const tmp = path45.join(dir, `.tmp-${crypto2.randomBytes(16).toString("hex")}`);
13855
13953
  let fd = null;
13856
13954
  try {
13857
- fd = fs36.openSync(tmp, "wx", 384);
13858
- fs36.writeFileSync(fd, content, "utf8");
13859
- fs36.fsyncSync(fd);
13860
- fs36.closeSync(fd);
13955
+ fd = fs37.openSync(tmp, "wx", 384);
13956
+ fs37.writeFileSync(fd, content, "utf8");
13957
+ fs37.fsyncSync(fd);
13958
+ fs37.closeSync(fd);
13861
13959
  fd = null;
13862
13960
  } finally {
13863
13961
  if (fd !== null) {
13864
13962
  try {
13865
- fs36.closeSync(fd);
13963
+ fs37.closeSync(fd);
13866
13964
  } catch {
13867
13965
  }
13868
- fs36.rmSync(tmp, { force: true });
13966
+ fs37.rmSync(tmp, { force: true });
13869
13967
  }
13870
13968
  }
13871
13969
  const tmpStat = lstatOrNull5(tmp);
13872
13970
  if (tmpStat === null || !tmpStat.isFile()) {
13873
13971
  try {
13874
- fs36.rmSync(tmp, { force: true });
13972
+ fs37.rmSync(tmp, { force: true });
13875
13973
  } catch {
13876
13974
  failIncomplete(`cannot clean private temp (recovery incomplete): ${tmp}`);
13877
13975
  }
13878
13976
  throw new Error(`private temp is not a regular file: ${target}`);
13879
13977
  }
13880
13978
  try {
13881
- fs36.renameSync(tmp, target);
13979
+ fs37.renameSync(tmp, target);
13882
13980
  } catch (err) {
13883
13981
  try {
13884
- fs36.rmSync(tmp, { force: true });
13982
+ fs37.rmSync(tmp, { force: true });
13885
13983
  } catch {
13886
13984
  const original = err instanceof Error ? err.message : String(err ?? "rename failed");
13887
13985
  failIncomplete(`cannot clean private temp after rename failure (recovery incomplete): ${tmp}: ${original}`);
@@ -13898,7 +13996,7 @@ async function activateVerifiedPiRelease(input) {
13898
13996
  if (typeof input.homeDir !== "string" || input.homeDir === "") {
13899
13997
  throw new Error(`homeDir must be a non-empty absolute path`);
13900
13998
  }
13901
- if (!path44.isAbsolute(input.homeDir)) {
13999
+ if (!path45.isAbsolute(input.homeDir)) {
13902
14000
  throw new Error(`homeDir must be absolute: ${input.homeDir}`);
13903
14001
  }
13904
14002
  if (!RELEASE_ID_PATTERN.test(releaseId)) {
@@ -13934,22 +14032,22 @@ async function activateVerifiedPiRelease(input) {
13934
14032
  if (stageStat === null || !stageStat.isDirectory() || stageStat.isSymbolicLink()) {
13935
14033
  throw new Error(`stageDir must be a real directory: ${input.stageDir}`);
13936
14034
  }
13937
- const settingsPath = path44.join(agentDir, "settings.json");
13938
- const npmDir = path44.join(agentDir, "npm");
13939
- const nodeModules = path44.join(npmDir, "node_modules");
13940
- const linkPath = path44.join(nodeModules, EXPECTED_ENTRY);
13941
- const stagedNpm = path44.join(stageDir, "npm");
13942
- const stagedModules = path44.join(stagedNpm, "node_modules");
13943
- const stagedEntry = path44.join(stagedModules, EXPECTED_ENTRY);
13944
- const releaseRoot = path44.join(npmDir, "jorgex-pi-managed", "releases");
13945
- const releaseDir = path44.join(releaseRoot, releaseId);
13946
- const managedRoot = path44.join(npmDir, "jorgex-pi-managed");
13947
- const markerPath = path44.join(managedRoot, "active-transaction.json");
13948
- const lockPath = path44.join(managedRoot, "transaction.lock");
13949
- const backupDir = path44.join(stageDir, ".activate-backup");
13950
- const backupEntry = path44.join(backupDir, "entry");
13951
- const backupSettings = path44.join(backupDir, "settings.json");
13952
- const backupReceipt = path44.join(backupDir, "receipt.json");
14035
+ const settingsPath = path45.join(agentDir, "settings.json");
14036
+ const npmDir = path45.join(agentDir, "npm");
14037
+ const nodeModules = path45.join(npmDir, "node_modules");
14038
+ const linkPath = path45.join(nodeModules, EXPECTED_ENTRY);
14039
+ const stagedNpm = path45.join(stageDir, "npm");
14040
+ const stagedModules = path45.join(stagedNpm, "node_modules");
14041
+ const stagedEntry = path45.join(stagedModules, EXPECTED_ENTRY);
14042
+ const releaseRoot = path45.join(npmDir, "jorgex-pi-managed", "releases");
14043
+ const releaseDir = path45.join(releaseRoot, releaseId);
14044
+ const managedRoot = path45.join(npmDir, "jorgex-pi-managed");
14045
+ const markerPath = path45.join(managedRoot, "active-transaction.json");
14046
+ const lockPath = path45.join(managedRoot, "transaction.lock");
14047
+ const backupDir = path45.join(stageDir, ".activate-backup");
14048
+ const backupEntry = path45.join(backupDir, "entry");
14049
+ const backupSettings = path45.join(backupDir, "settings.json");
14050
+ const backupReceipt = path45.join(backupDir, "receipt.json");
13953
14051
  const expectedTarget = `../jorgex-pi-managed/releases/${releaseId}/node_modules/${EXPECTED_ENTRY}`;
13954
14052
  assertStrictChild(agentDir, homeDir, "agentDir");
13955
14053
  assertStrictChild(receiptPath, homeDir, "receiptPath");
@@ -14002,7 +14100,7 @@ async function activateVerifiedPiRelease(input) {
14002
14100
  let oldEntryExisted = false;
14003
14101
  if (linkStat !== null) {
14004
14102
  oldEntryExisted = true;
14005
- assertAncestorsClean(path44.dirname(linkPath), homeDir, "managed entry");
14103
+ assertAncestorsClean(path45.dirname(linkPath), homeDir, "managed entry");
14006
14104
  if (linkStat.isSymbolicLink()) {
14007
14105
  assertManagedEntrySymlink(linkPath, npmDir, "managed entry");
14008
14106
  } else if (!linkStat.isDirectory()) {
@@ -14019,10 +14117,10 @@ async function activateVerifiedPiRelease(input) {
14019
14117
  let oldReceipt = null;
14020
14118
  try {
14021
14119
  if (lstatOrNull5(settingsPath) !== null) {
14022
- oldSettings = fs36.readFileSync(settingsPath, "utf8");
14120
+ oldSettings = fs37.readFileSync(settingsPath, "utf8");
14023
14121
  }
14024
14122
  if (lstatOrNull5(receiptPath) !== null) {
14025
- oldReceipt = fs36.readFileSync(receiptPath, "utf8");
14123
+ oldReceipt = fs37.readFileSync(receiptPath, "utf8");
14026
14124
  }
14027
14125
  } catch {
14028
14126
  throw new Error(`cannot read previous settings/receipt`);
@@ -14034,7 +14132,7 @@ async function activateVerifiedPiRelease(input) {
14034
14132
  const ownedBackupFiles = /* @__PURE__ */ new Map();
14035
14133
  const releaseLock = () => {
14036
14134
  if (!lockAcquired) return;
14037
- fs36.rmSync(lockPath, { force: true });
14135
+ fs37.rmSync(lockPath, { force: true });
14038
14136
  lockAcquired = false;
14039
14137
  };
14040
14138
  const captureBackupDirIdentity = () => {
@@ -14060,7 +14158,7 @@ async function activateVerifiedPiRelease(input) {
14060
14158
  if (dirStat.dev !== backupDirDev || dirStat.ino !== backupDirIno) return "backup dir replaced";
14061
14159
  let entries;
14062
14160
  try {
14063
- entries = fs36.readdirSync(backupDir);
14161
+ entries = fs37.readdirSync(backupDir);
14064
14162
  } catch {
14065
14163
  return "cannot list backup";
14066
14164
  }
@@ -14070,7 +14168,7 @@ async function activateVerifiedPiRelease(input) {
14070
14168
  if (!allowed.has(entry)) return `unknown backup entry: ${entry}`;
14071
14169
  }
14072
14170
  for (const entry of entries) {
14073
- const full = resolved(path44.join(backupDir, entry));
14171
+ const full = resolved(path45.join(backupDir, entry));
14074
14172
  const owned = ownedBackupFiles.get(full);
14075
14173
  if (!owned) return `unowned backup file: ${entry}`;
14076
14174
  const st = lstatOrNull5(full);
@@ -14078,14 +14176,14 @@ async function activateVerifiedPiRelease(input) {
14078
14176
  if (st.dev !== owned.dev || st.ino !== owned.ino) return `backup file replaced: ${entry}`;
14079
14177
  let cur;
14080
14178
  try {
14081
- cur = fs36.readFileSync(full, "utf8");
14179
+ cur = fs37.readFileSync(full, "utf8");
14082
14180
  } catch {
14083
14181
  return `cannot read backup file: ${entry}`;
14084
14182
  }
14085
14183
  if (cur !== owned.content) return `backup file bytes drifted: ${entry}`;
14086
14184
  }
14087
14185
  for (const [fullPath] of ownedBackupFiles) {
14088
- const base = path44.basename(fullPath);
14186
+ const base = path45.basename(fullPath);
14089
14187
  if (!entries.includes(base)) return `owned backup file missing: ${base}`;
14090
14188
  }
14091
14189
  return null;
@@ -14107,7 +14205,7 @@ async function activateVerifiedPiRelease(input) {
14107
14205
  }
14108
14206
  let cur;
14109
14207
  try {
14110
- cur = fs36.readFileSync(fullPath, "utf8");
14208
+ cur = fs37.readFileSync(fullPath, "utf8");
14111
14209
  } catch {
14112
14210
  failIncomplete(
14113
14211
  `backup drifted during cleanup, preserving foreign state (recovery incomplete): ${fullPath}: ${original}`
@@ -14119,7 +14217,7 @@ async function activateVerifiedPiRelease(input) {
14119
14217
  `backup drifted during cleanup, preserving foreign state (recovery incomplete): ${fullPath}: ${original}`
14120
14218
  );
14121
14219
  }
14122
- fs36.unlinkSync(fullPath);
14220
+ fs37.unlinkSync(fullPath);
14123
14221
  }
14124
14222
  } catch (err) {
14125
14223
  if (err instanceof Error && err.recovery === "incomplete") throw err;
@@ -14129,13 +14227,13 @@ async function activateVerifiedPiRelease(input) {
14129
14227
  );
14130
14228
  }
14131
14229
  try {
14132
- const remaining = fs36.readdirSync(backupDir);
14230
+ const remaining = fs37.readdirSync(backupDir);
14133
14231
  if (remaining.length !== 0) {
14134
14232
  failIncomplete(
14135
14233
  `backup dir not empty after owned cleanup, preserving foreign state (recovery incomplete): ${backupDir}: ${original}`
14136
14234
  );
14137
14235
  }
14138
- fs36.rmdirSync(backupDir);
14236
+ fs37.rmdirSync(backupDir);
14139
14237
  } catch (err) {
14140
14238
  if (err instanceof Error && err.recovery === "incomplete") throw err;
14141
14239
  const msg = err instanceof Error ? err.message : String(err ?? "rmdir failed");
@@ -14144,7 +14242,7 @@ async function activateVerifiedPiRelease(input) {
14144
14242
  );
14145
14243
  }
14146
14244
  try {
14147
- fs36.rmSync(markerPath, { force: true });
14245
+ fs37.rmSync(markerPath, { force: true });
14148
14246
  releaseLock();
14149
14247
  } catch {
14150
14248
  failIncomplete(`cannot clear transaction state after rollback: ${original}`);
@@ -14160,7 +14258,7 @@ async function activateVerifiedPiRelease(input) {
14160
14258
  if (!backupCreated) {
14161
14259
  const problems = [];
14162
14260
  try {
14163
- fs36.rmSync(markerPath, { force: true });
14261
+ fs37.rmSync(markerPath, { force: true });
14164
14262
  } catch {
14165
14263
  problems.push("cannot remove marker");
14166
14264
  }
@@ -14179,7 +14277,7 @@ async function activateVerifiedPiRelease(input) {
14179
14277
  if (err instanceof Error) throw err;
14180
14278
  throw new Error(original);
14181
14279
  };
14182
- fs36.mkdirSync(managedRoot, { recursive: true });
14280
+ fs37.mkdirSync(managedRoot, { recursive: true });
14183
14281
  assertAncestorsClean(managedRoot, homeDir, "managed root");
14184
14282
  const managedRootStat = lstatOrNull5(managedRoot);
14185
14283
  if (managedRootStat === null || !managedRootStat.isDirectory() || managedRootStat.isSymbolicLink()) {
@@ -14188,14 +14286,14 @@ async function activateVerifiedPiRelease(input) {
14188
14286
  const lockToken = `${JSON.stringify({ pid: process.pid, stageDir, releaseId, startedAt: (/* @__PURE__ */ new Date()).toISOString() })}
14189
14287
  `;
14190
14288
  try {
14191
- fs36.writeFileSync(lockPath, lockToken, { encoding: "utf8", flag: "wx", mode: 384 });
14289
+ fs37.writeFileSync(lockPath, lockToken, { encoding: "utf8", flag: "wx", mode: 384 });
14192
14290
  lockAcquired = true;
14193
14291
  } catch {
14194
14292
  failIncomplete(`transaction lock busy: concurrent activation holds the exclusive lock (recovery incomplete): ${lockPath}`);
14195
14293
  }
14196
14294
  if (lstatOrNull5(markerPath) !== null) {
14197
14295
  try {
14198
- fs36.rmSync(lockPath, { force: true });
14296
+ fs37.rmSync(lockPath, { force: true });
14199
14297
  lockAcquired = false;
14200
14298
  } catch {
14201
14299
  }
@@ -14204,10 +14302,10 @@ async function activateVerifiedPiRelease(input) {
14204
14302
  const markerContent = `${JSON.stringify({ stageDir, backupDir, releaseId, releaseDir, phase: "prepared", pid: process.pid }, null, 2)}
14205
14303
  `;
14206
14304
  try {
14207
- fs36.writeFileSync(markerPath, markerContent, { encoding: "utf8", flag: "wx", mode: 384 });
14305
+ fs37.writeFileSync(markerPath, markerContent, { encoding: "utf8", flag: "wx", mode: 384 });
14208
14306
  } catch {
14209
14307
  try {
14210
- fs36.rmSync(lockPath, { force: true });
14308
+ fs37.rmSync(lockPath, { force: true });
14211
14309
  lockAcquired = false;
14212
14310
  } catch {
14213
14311
  }
@@ -14225,7 +14323,7 @@ async function activateVerifiedPiRelease(input) {
14225
14323
  }
14226
14324
  }
14227
14325
  try {
14228
- fs36.mkdirSync(backupDir);
14326
+ fs37.mkdirSync(backupDir);
14229
14327
  backupCreated = true;
14230
14328
  captureBackupDirIdentity();
14231
14329
  } catch (err) {
@@ -14245,7 +14343,7 @@ async function activateVerifiedPiRelease(input) {
14245
14343
  }
14246
14344
  const persistBackupCopy = (target, content) => {
14247
14345
  if (content === null) return;
14248
- fs36.writeFileSync(target, content, { encoding: "utf8", flag: "wx", mode: 384 });
14346
+ fs37.writeFileSync(target, content, { encoding: "utf8", flag: "wx", mode: 384 });
14249
14347
  trackOwnedBackupFile(target, content);
14250
14348
  };
14251
14349
  let entryMoved = false;
@@ -14255,10 +14353,10 @@ async function activateVerifiedPiRelease(input) {
14255
14353
  try {
14256
14354
  persistBackupCopy(backupSettings, oldSettings);
14257
14355
  persistBackupCopy(backupReceipt, oldReceipt);
14258
- const metaPath = path44.join(backupDir, "meta.json");
14356
+ const metaPath = path45.join(backupDir, "meta.json");
14259
14357
  const metaContent = `${JSON.stringify({ releaseId, oldEntryExisted }, null, 2)}
14260
14358
  `;
14261
- fs36.writeFileSync(metaPath, metaContent, { encoding: "utf8", flag: "wx", mode: 384 });
14359
+ fs37.writeFileSync(metaPath, metaContent, { encoding: "utf8", flag: "wx", mode: 384 });
14262
14360
  trackOwnedBackupFile(metaPath, metaContent);
14263
14361
  } catch {
14264
14362
  abortBeforePublish(new Error(`cannot persist private backup`));
@@ -14274,7 +14372,7 @@ async function activateVerifiedPiRelease(input) {
14274
14372
  } else {
14275
14373
  let target = null;
14276
14374
  try {
14277
- target = fs36.readlinkSync(linkPath);
14375
+ target = fs37.readlinkSync(linkPath);
14278
14376
  } catch {
14279
14377
  target = null;
14280
14378
  }
@@ -14286,7 +14384,7 @@ async function activateVerifiedPiRelease(input) {
14286
14384
  if (drift === null && wroteSettings) {
14287
14385
  let cur = null;
14288
14386
  try {
14289
- cur = fs36.readFileSync(settingsPath, "utf8");
14387
+ cur = fs37.readFileSync(settingsPath, "utf8");
14290
14388
  } catch {
14291
14389
  cur = null;
14292
14390
  }
@@ -14295,7 +14393,7 @@ async function activateVerifiedPiRelease(input) {
14295
14393
  if (drift === null && wroteReceipt) {
14296
14394
  let cur = null;
14297
14395
  try {
14298
- cur = fs36.readFileSync(receiptPath, "utf8");
14396
+ cur = fs37.readFileSync(receiptPath, "utf8");
14299
14397
  } catch {
14300
14398
  cur = null;
14301
14399
  }
@@ -14311,7 +14409,7 @@ async function activateVerifiedPiRelease(input) {
14311
14409
  if (cur === null || !cur.isSymbolicLink()) {
14312
14410
  problems.push("published entry link missing");
14313
14411
  } else {
14314
- fs36.unlinkSync(linkPath);
14412
+ fs37.unlinkSync(linkPath);
14315
14413
  }
14316
14414
  } else if (lstatOrNull5(linkPath) !== null) {
14317
14415
  problems.push("unexpected managed entry");
@@ -14327,7 +14425,7 @@ async function activateVerifiedPiRelease(input) {
14327
14425
  } else if (lstatOrNull5(linkPath) !== null) {
14328
14426
  problems.push("managed entry still present");
14329
14427
  } else {
14330
- fs36.renameSync(backupEntry, linkPath);
14428
+ fs37.renameSync(backupEntry, linkPath);
14331
14429
  }
14332
14430
  } else if (lstatOrNull5(linkPath) !== null) {
14333
14431
  problems.push("unexpected managed entry");
@@ -14340,7 +14438,7 @@ async function activateVerifiedPiRelease(input) {
14340
14438
  if (oldSettings !== null) {
14341
14439
  atomicWritePrivate(settingsPath, oldSettings);
14342
14440
  } else {
14343
- fs36.rmSync(settingsPath, { force: true });
14441
+ fs37.rmSync(settingsPath, { force: true });
14344
14442
  }
14345
14443
  }
14346
14444
  } catch {
@@ -14351,7 +14449,7 @@ async function activateVerifiedPiRelease(input) {
14351
14449
  if (oldReceipt !== null) {
14352
14450
  atomicWritePrivate(receiptPath, oldReceipt);
14353
14451
  } else {
14354
- fs36.rmSync(receiptPath, { force: true });
14452
+ fs37.rmSync(receiptPath, { force: true });
14355
14453
  }
14356
14454
  }
14357
14455
  } catch {
@@ -14361,7 +14459,7 @@ async function activateVerifiedPiRelease(input) {
14361
14459
  const destStat = lstatOrNull5(releaseDir);
14362
14460
  const stagedStat = lstatOrNull5(stagedNpm);
14363
14461
  if (destStat !== null && stagedStat === null) {
14364
- fs36.renameSync(releaseDir, stagedNpm);
14462
+ fs37.renameSync(releaseDir, stagedNpm);
14365
14463
  } else if (destStat !== null && stagedStat !== null) {
14366
14464
  problems.push("staged tree and promoted release both present");
14367
14465
  } else if (destStat === null && stagedStat === null) {
@@ -14381,7 +14479,7 @@ async function activateVerifiedPiRelease(input) {
14381
14479
  clearOwnedBackupThenCooperativeState(original);
14382
14480
  } else {
14383
14481
  try {
14384
- fs36.rmSync(markerPath, { force: true });
14482
+ fs37.rmSync(markerPath, { force: true });
14385
14483
  releaseLock();
14386
14484
  } catch {
14387
14485
  failIncomplete(`cannot clear transaction state after rollback: ${original}`);
@@ -14397,14 +14495,14 @@ async function activateVerifiedPiRelease(input) {
14397
14495
  };
14398
14496
  try {
14399
14497
  if (oldEntryExisted) {
14400
- fs36.renameSync(linkPath, backupEntry);
14498
+ fs37.renameSync(linkPath, backupEntry);
14401
14499
  entryMoved = true;
14402
14500
  }
14403
14501
  } catch {
14404
14502
  abortBeforePublish(new Error(`cannot backup previous managed entry`));
14405
14503
  }
14406
14504
  try {
14407
- fs36.mkdirSync(releaseRoot, { recursive: true });
14505
+ fs37.mkdirSync(releaseRoot, { recursive: true });
14408
14506
  assertAncestorsClean(releaseRoot, homeDir, "release root");
14409
14507
  const rootStat = lstatOrNull5(releaseRoot);
14410
14508
  if (rootStat === null || !rootStat.isDirectory() || rootStat.isSymbolicLink()) {
@@ -14413,8 +14511,8 @@ async function activateVerifiedPiRelease(input) {
14413
14511
  if (lstatOrNull5(releaseDir) !== null) {
14414
14512
  throw new Error(`release already exists: ${releaseDir}`);
14415
14513
  }
14416
- fs36.renameSync(stagedNpm, releaseDir);
14417
- fs36.symlinkSync(expectedTarget, linkPath, "dir");
14514
+ fs37.renameSync(stagedNpm, releaseDir);
14515
+ fs37.symlinkSync(expectedTarget, linkPath, "dir");
14418
14516
  publishedLink = true;
14419
14517
  atomicWritePrivate(settingsPath, input.nextSettings);
14420
14518
  wroteSettings = true;
@@ -14432,7 +14530,7 @@ async function activateVerifiedPiRelease(input) {
14432
14530
  rollback(err);
14433
14531
  }
14434
14532
  try {
14435
- fs36.rmSync(markerPath, { force: true });
14533
+ fs37.rmSync(markerPath, { force: true });
14436
14534
  releaseLock();
14437
14535
  } catch {
14438
14536
  failIncomplete(`cannot clear transaction state after activation (recovery incomplete): ${markerPath}`);
@@ -14448,14 +14546,14 @@ function isManagedDependency(value) {
14448
14546
  }
14449
14547
  function readTextOrNull(p7) {
14450
14548
  try {
14451
- return fs36.readFileSync(p7, "utf8");
14549
+ return fs37.readFileSync(p7, "utf8");
14452
14550
  } catch {
14453
14551
  return null;
14454
14552
  }
14455
14553
  }
14456
14554
  function safeReadlink(p7) {
14457
14555
  try {
14458
- return fs36.readlinkSync(p7);
14556
+ return fs37.readlinkSync(p7);
14459
14557
  } catch {
14460
14558
  return null;
14461
14559
  }
@@ -14471,7 +14569,7 @@ function deactivateVerifiedPiRelease(input) {
14471
14569
  if (typeof input.homeDir !== "string" || input.homeDir === "" || typeof input.agentDir !== "string" || input.agentDir === "" || typeof input.receiptPath !== "string" || input.receiptPath === "" || typeof mp.releaseDir !== "string" || mp.releaseDir === "" || typeof mp.linkPath !== "string" || mp.linkPath === "" || typeof mp.backupDir !== "string" || mp.backupDir === "") {
14472
14570
  throw new Error(`homeDir, agentDir, receiptPath and managedPackage paths must be non-empty strings`);
14473
14571
  }
14474
- if (!path44.isAbsolute(input.homeDir)) {
14572
+ if (!path45.isAbsolute(input.homeDir)) {
14475
14573
  throw new Error(`homeDir must be absolute: ${input.homeDir}`);
14476
14574
  }
14477
14575
  if (typeof mp.lockSha256 !== "string" || !HEX64_PATTERN.test(mp.lockSha256)) {
@@ -14512,23 +14610,23 @@ function deactivateVerifiedPiRelease(input) {
14512
14610
  if (agentStat === null || !agentStat.isDirectory() || agentStat.isSymbolicLink()) {
14513
14611
  throw new Error(`agentDir must be a real directory: ${input.agentDir}`);
14514
14612
  }
14515
- const settingsPath = path44.join(agentDir, "settings.json");
14516
- const npmDir = path44.join(agentDir, "npm");
14517
- const nodeModules = path44.join(npmDir, "node_modules");
14518
- const expectedLink = path44.join(nodeModules, EXPECTED_ENTRY);
14519
- const releaseRoot = path44.join(npmDir, "jorgex-pi-managed", "releases");
14520
- const managedRoot = path44.join(npmDir, "jorgex-pi-managed");
14521
- const markerPath = path44.join(managedRoot, "active-transaction.json");
14522
- const lockPath = path44.join(managedRoot, "transaction.lock");
14613
+ const settingsPath = path45.join(agentDir, "settings.json");
14614
+ const npmDir = path45.join(agentDir, "npm");
14615
+ const nodeModules = path45.join(npmDir, "node_modules");
14616
+ const expectedLink = path45.join(nodeModules, EXPECTED_ENTRY);
14617
+ const releaseRoot = path45.join(npmDir, "jorgex-pi-managed", "releases");
14618
+ const managedRoot = path45.join(npmDir, "jorgex-pi-managed");
14619
+ const markerPath = path45.join(managedRoot, "active-transaction.json");
14620
+ const lockPath = path45.join(managedRoot, "transaction.lock");
14523
14621
  if (linkPath !== expectedLink) {
14524
14622
  throw new Error(`managed link must be the owned entry: ${expectedLink}`);
14525
14623
  }
14526
- const releaseId = path44.basename(releaseDir);
14527
- if (path44.dirname(releaseDir) !== releaseRoot || !HEX64_PATTERN.test(releaseId)) {
14624
+ const releaseId = path45.basename(releaseDir);
14625
+ if (path45.dirname(releaseDir) !== releaseRoot || !HEX64_PATTERN.test(releaseId)) {
14528
14626
  throw new Error(`managed release must live under the private releases root: ${releaseDir}`);
14529
14627
  }
14530
14628
  const expectedTarget = `../jorgex-pi-managed/releases/${releaseId}/node_modules/${EXPECTED_ENTRY}`;
14531
- const packageRoot = path44.join(releaseDir, "node_modules", EXPECTED_ENTRY);
14629
+ const packageRoot = path45.join(releaseDir, "node_modules", EXPECTED_ENTRY);
14532
14630
  assertStrictChild(agentDir, homeDir, "agentDir");
14533
14631
  assertStrictChild(receiptPath, homeDir, "receiptPath");
14534
14632
  assertStrictChild(releaseDir, agentDir, "managed release");
@@ -14567,7 +14665,7 @@ function deactivateVerifiedPiRelease(input) {
14567
14665
  if (linkStat === null || !linkStat.isSymbolicLink()) {
14568
14666
  throw new Error(`managed entry must be the owned symlink: ${linkPath}`);
14569
14667
  }
14570
- assertAncestorsClean(path44.dirname(linkPath), homeDir, "managed entry");
14668
+ assertAncestorsClean(path45.dirname(linkPath), homeDir, "managed entry");
14571
14669
  const observedTarget = safeReadlink(linkPath);
14572
14670
  if (observedTarget === null || observedTarget !== expectedTarget) {
14573
14671
  throw new Error(`managed entry points outside the owned release: ${linkPath}`);
@@ -14579,7 +14677,7 @@ function deactivateVerifiedPiRelease(input) {
14579
14677
  }
14580
14678
  let liveRealpath = null;
14581
14679
  try {
14582
- liveRealpath = fs36.realpathSync(linkPath);
14680
+ liveRealpath = fs37.realpathSync(linkPath);
14583
14681
  } catch {
14584
14682
  liveRealpath = null;
14585
14683
  }
@@ -14596,7 +14694,7 @@ function deactivateVerifiedPiRelease(input) {
14596
14694
  throw new Error(`activation backup must be a real directory: ${mp.backupDir}`);
14597
14695
  }
14598
14696
  assertAncestorsClean(activationBackupDir, homeDir, "activation backup");
14599
- const lockFile = path44.join(releaseDir, "package-lock.json");
14697
+ const lockFile = path45.join(releaseDir, "package-lock.json");
14600
14698
  const lockStat = lstatOrNull5(lockFile);
14601
14699
  if (lockStat === null || lockStat.isSymbolicLink() || !lockStat.isFile()) {
14602
14700
  throw new Error(`managed lock must be a regular file: ${lockFile}`);
@@ -14606,7 +14704,7 @@ function deactivateVerifiedPiRelease(input) {
14606
14704
  }
14607
14705
  let lockBytes;
14608
14706
  try {
14609
- lockBytes = fs36.readFileSync(lockFile);
14707
+ lockBytes = fs37.readFileSync(lockFile);
14610
14708
  } catch {
14611
14709
  throw new Error(`cannot read managed lock: ${lockFile}`);
14612
14710
  }
@@ -14624,19 +14722,19 @@ function deactivateVerifiedPiRelease(input) {
14624
14722
  let oldReceipt = null;
14625
14723
  try {
14626
14724
  if (lstatOrNull5(settingsPath) !== null) {
14627
- oldSettings = fs36.readFileSync(settingsPath, "utf8");
14725
+ oldSettings = fs37.readFileSync(settingsPath, "utf8");
14628
14726
  }
14629
- oldReceipt = fs36.readFileSync(receiptPath, "utf8");
14727
+ oldReceipt = fs37.readFileSync(receiptPath, "utf8");
14630
14728
  } catch {
14631
14729
  throw new Error(`cannot read previous settings/receipt`);
14632
14730
  }
14633
14731
  let lockAcquired = false;
14634
14732
  const releaseLock = () => {
14635
14733
  if (!lockAcquired) return;
14636
- fs36.rmSync(lockPath, { force: true });
14734
+ fs37.rmSync(lockPath, { force: true });
14637
14735
  lockAcquired = false;
14638
14736
  };
14639
- fs36.mkdirSync(managedRoot, { recursive: true });
14737
+ fs37.mkdirSync(managedRoot, { recursive: true });
14640
14738
  assertAncestorsClean(managedRoot, homeDir, "managed root");
14641
14739
  const managedRootStat = lstatOrNull5(managedRoot);
14642
14740
  if (managedRootStat === null || !managedRootStat.isDirectory() || managedRootStat.isSymbolicLink()) {
@@ -14644,7 +14742,7 @@ function deactivateVerifiedPiRelease(input) {
14644
14742
  }
14645
14743
  let uninstallBackupDir = "";
14646
14744
  for (let i = 0; i < 5 && uninstallBackupDir === ""; i++) {
14647
- const candidateDir = path44.join(managedRoot, `uninstall-backup-${crypto2.randomBytes(8).toString("hex")}`);
14745
+ const candidateDir = path45.join(managedRoot, `uninstall-backup-${crypto2.randomBytes(8).toString("hex")}`);
14648
14746
  if (lstatOrNull5(candidateDir) === null) uninstallBackupDir = candidateDir;
14649
14747
  }
14650
14748
  if (uninstallBackupDir === "") {
@@ -14654,14 +14752,14 @@ function deactivateVerifiedPiRelease(input) {
14654
14752
  const lockToken = `${JSON.stringify({ op: "uninstall", pid: process.pid, agentDir, releaseId, startedAt: (/* @__PURE__ */ new Date()).toISOString() })}
14655
14753
  `;
14656
14754
  try {
14657
- fs36.writeFileSync(lockPath, lockToken, { encoding: "utf8", flag: "wx", mode: 384 });
14755
+ fs37.writeFileSync(lockPath, lockToken, { encoding: "utf8", flag: "wx", mode: 384 });
14658
14756
  lockAcquired = true;
14659
14757
  } catch {
14660
14758
  failIncomplete(`transaction lock busy: concurrent operation holds the exclusive lock (recovery incomplete): ${lockPath}`);
14661
14759
  }
14662
14760
  if (lstatOrNull5(markerPath) !== null) {
14663
14761
  try {
14664
- fs36.rmSync(lockPath, { force: true });
14762
+ fs37.rmSync(lockPath, { force: true });
14665
14763
  lockAcquired = false;
14666
14764
  } catch {
14667
14765
  }
@@ -14670,10 +14768,10 @@ function deactivateVerifiedPiRelease(input) {
14670
14768
  const markerContent = `${JSON.stringify({ phase: "uninstall", releaseDir, linkPath, receiptPath, backupDir: uninstallBackupDir, activationBackupDir, releaseId, pid: process.pid }, null, 2)}
14671
14769
  `;
14672
14770
  try {
14673
- fs36.writeFileSync(markerPath, markerContent, { encoding: "utf8", flag: "wx", mode: 384 });
14771
+ fs37.writeFileSync(markerPath, markerContent, { encoding: "utf8", flag: "wx", mode: 384 });
14674
14772
  } catch {
14675
14773
  try {
14676
- fs36.rmSync(lockPath, { force: true });
14774
+ fs37.rmSync(lockPath, { force: true });
14677
14775
  lockAcquired = false;
14678
14776
  } catch {
14679
14777
  }
@@ -14682,7 +14780,7 @@ function deactivateVerifiedPiRelease(input) {
14682
14780
  const abortOwnTransaction = (err) => {
14683
14781
  const problems = [];
14684
14782
  try {
14685
- fs36.rmSync(markerPath, { force: true });
14783
+ fs37.rmSync(markerPath, { force: true });
14686
14784
  } catch {
14687
14785
  problems.push("cannot remove marker");
14688
14786
  }
@@ -14692,7 +14790,7 @@ function deactivateVerifiedPiRelease(input) {
14692
14790
  problems.push("cannot release lock");
14693
14791
  }
14694
14792
  try {
14695
- fs36.rmSync(uninstallBackupDir, { recursive: true, force: true });
14793
+ fs37.rmSync(uninstallBackupDir, { recursive: true, force: true });
14696
14794
  } catch {
14697
14795
  problems.push("cannot clear backup");
14698
14796
  }
@@ -14728,7 +14826,7 @@ function deactivateVerifiedPiRelease(input) {
14728
14826
  }
14729
14827
  if (drift !== null) {
14730
14828
  try {
14731
- fs36.rmSync(markerPath, { force: true });
14829
+ fs37.rmSync(markerPath, { force: true });
14732
14830
  releaseLock();
14733
14831
  } catch {
14734
14832
  }
@@ -14737,7 +14835,7 @@ function deactivateVerifiedPiRelease(input) {
14737
14835
  };
14738
14836
  recheckLiveState();
14739
14837
  try {
14740
- fs36.mkdirSync(uninstallBackupDir, { recursive: true });
14838
+ fs37.mkdirSync(uninstallBackupDir, { recursive: true });
14741
14839
  } catch (err) {
14742
14840
  abortOwnTransaction(err);
14743
14841
  }
@@ -14747,22 +14845,22 @@ function deactivateVerifiedPiRelease(input) {
14747
14845
  }
14748
14846
  let backupEntries = [];
14749
14847
  try {
14750
- backupEntries = fs36.readdirSync(uninstallBackupDir);
14848
+ backupEntries = fs37.readdirSync(uninstallBackupDir);
14751
14849
  } catch {
14752
14850
  abortOwnTransaction(new Error(`cannot inspect uninstall backup: ${uninstallBackupDir}`));
14753
14851
  }
14754
14852
  if (backupEntries.length !== 0) {
14755
14853
  abortOwnTransaction(new Error(`uninstall backup is not empty: ${uninstallBackupDir}`));
14756
14854
  }
14757
- const backupReleaseDir = path44.join(uninstallBackupDir, "release");
14758
- const backupReceiptFile = path44.join(uninstallBackupDir, "pi-receipt.json");
14759
- const backupSettingsFile = path44.join(uninstallBackupDir, "settings.json");
14855
+ const backupReleaseDir = path45.join(uninstallBackupDir, "release");
14856
+ const backupReceiptFile = path45.join(uninstallBackupDir, "pi-receipt.json");
14857
+ const backupSettingsFile = path45.join(uninstallBackupDir, "settings.json");
14760
14858
  try {
14761
14859
  if (oldSettings !== null) {
14762
- fs36.writeFileSync(backupSettingsFile, oldSettings, { encoding: "utf8", flag: "wx", mode: 384 });
14860
+ fs37.writeFileSync(backupSettingsFile, oldSettings, { encoding: "utf8", flag: "wx", mode: 384 });
14763
14861
  }
14764
- fs36.writeFileSync(
14765
- path44.join(uninstallBackupDir, "meta.json"),
14862
+ fs37.writeFileSync(
14863
+ path45.join(uninstallBackupDir, "meta.json"),
14766
14864
  `${JSON.stringify({ phase: "uninstall", releaseDir, linkPath, receiptPath, linkTarget: observedTarget }, null, 2)}
14767
14865
  `,
14768
14866
  { encoding: "utf8", flag: "wx", mode: 384 }
@@ -14815,14 +14913,14 @@ function deactivateVerifiedPiRelease(input) {
14815
14913
  const problems = [];
14816
14914
  if (movedRelease) {
14817
14915
  try {
14818
- fs36.renameSync(backupReleaseDir, releaseDir);
14916
+ fs37.renameSync(backupReleaseDir, releaseDir);
14819
14917
  } catch {
14820
14918
  problems.push("cannot restore release");
14821
14919
  }
14822
14920
  }
14823
14921
  if (removedLink) {
14824
14922
  try {
14825
- fs36.symlinkSync(observedTarget, linkPath, "dir");
14923
+ fs37.symlinkSync(observedTarget, linkPath, "dir");
14826
14924
  } catch {
14827
14925
  problems.push("cannot restore managed entry");
14828
14926
  }
@@ -14832,7 +14930,7 @@ function deactivateVerifiedPiRelease(input) {
14832
14930
  if (oldSettings !== null) {
14833
14931
  atomicWritePrivate(settingsPath, oldSettings);
14834
14932
  } else {
14835
- fs36.rmSync(settingsPath, { force: true });
14933
+ fs37.rmSync(settingsPath, { force: true });
14836
14934
  }
14837
14935
  } catch {
14838
14936
  problems.push("cannot restore previous settings");
@@ -14840,7 +14938,7 @@ function deactivateVerifiedPiRelease(input) {
14840
14938
  }
14841
14939
  if (movedReceipt) {
14842
14940
  try {
14843
- fs36.renameSync(backupReceiptFile, receiptPath);
14941
+ fs37.renameSync(backupReceiptFile, receiptPath);
14844
14942
  } catch {
14845
14943
  problems.push("cannot restore receipt");
14846
14944
  }
@@ -14849,9 +14947,9 @@ function deactivateVerifiedPiRelease(input) {
14849
14947
  failIncomplete(`uninstall rollback incomplete (${problems.join("; ")}): ${original}`);
14850
14948
  }
14851
14949
  try {
14852
- fs36.rmSync(markerPath, { force: true });
14950
+ fs37.rmSync(markerPath, { force: true });
14853
14951
  releaseLock();
14854
- fs36.rmSync(uninstallBackupDir, { recursive: true, force: true });
14952
+ fs37.rmSync(uninstallBackupDir, { recursive: true, force: true });
14855
14953
  } catch {
14856
14954
  failIncomplete(`cannot clear transaction state after rollback: ${original}`);
14857
14955
  }
@@ -14864,11 +14962,11 @@ function deactivateVerifiedPiRelease(input) {
14864
14962
  throw wrapped;
14865
14963
  };
14866
14964
  try {
14867
- fs36.unlinkSync(linkPath);
14965
+ fs37.unlinkSync(linkPath);
14868
14966
  removedLink = true;
14869
- fs36.renameSync(releaseDir, backupReleaseDir);
14967
+ fs37.renameSync(releaseDir, backupReleaseDir);
14870
14968
  movedRelease = true;
14871
- fs36.renameSync(receiptPath, backupReceiptFile);
14969
+ fs37.renameSync(receiptPath, backupReceiptFile);
14872
14970
  movedReceipt = true;
14873
14971
  atomicWritePrivate(settingsPath, input.nextSettings);
14874
14972
  wroteSettings = true;
@@ -14890,7 +14988,7 @@ function deactivateVerifiedPiRelease(input) {
14890
14988
  rollbackDeactivate(new Error(`verify must be synchronous and return void, got thenable`));
14891
14989
  }
14892
14990
  try {
14893
- fs36.rmSync(markerPath, { force: true });
14991
+ fs37.rmSync(markerPath, { force: true });
14894
14992
  releaseLock();
14895
14993
  } catch {
14896
14994
  failIncomplete(`cannot clear transaction state after uninstall (recovery incomplete): ${markerPath}`);
@@ -14931,7 +15029,7 @@ function readRegularTextLegacy(file, label) {
14931
15029
  throw new Error(`${label} exceeds size bound: ${file}`);
14932
15030
  }
14933
15031
  try {
14934
- return fs36.readFileSync(file, "utf8");
15032
+ return fs37.readFileSync(file, "utf8");
14935
15033
  } catch {
14936
15034
  throw new Error(`cannot read ${label}: ${file}`);
14937
15035
  }
@@ -14943,7 +15041,7 @@ function deactivateVerifiedLegacyPiEntry(input) {
14943
15041
  if (typeof input.homeDir !== "string" || input.homeDir === "" || typeof input.agentDir !== "string" || input.agentDir === "" || typeof input.receiptPath !== "string" || input.receiptPath === "" || typeof input.source !== "string" || input.source === "") {
14944
15042
  throw new Error(`homeDir, agentDir, receiptPath and source must be non-empty strings`);
14945
15043
  }
14946
- if (!path44.isAbsolute(input.homeDir)) {
15044
+ if (!path45.isAbsolute(input.homeDir)) {
14947
15045
  throw new Error(`homeDir must be absolute: ${input.homeDir}`);
14948
15046
  }
14949
15047
  const sourceMatch = LEGACY_SOURCE_PATTERN.exec(input.source);
@@ -14977,13 +15075,13 @@ function deactivateVerifiedLegacyPiEntry(input) {
14977
15075
  if (agentStat === null || !agentStat.isDirectory() || agentStat.isSymbolicLink()) {
14978
15076
  throw new Error(`agentDir must be a real directory: ${input.agentDir}`);
14979
15077
  }
14980
- const settingsPath = path44.join(agentDir, "settings.json");
14981
- const npmDir = path44.join(agentDir, "npm");
14982
- const nodeModules = path44.join(npmDir, "node_modules");
14983
- const legacyEntry = path44.join(nodeModules, EXPECTED_ENTRY);
14984
- const managedRoot = path44.join(npmDir, "jorgex-pi-managed");
14985
- const markerPath = path44.join(managedRoot, "active-transaction.json");
14986
- const lockPath = path44.join(managedRoot, "transaction.lock");
15078
+ const settingsPath = path45.join(agentDir, "settings.json");
15079
+ const npmDir = path45.join(agentDir, "npm");
15080
+ const nodeModules = path45.join(npmDir, "node_modules");
15081
+ const legacyEntry = path45.join(nodeModules, EXPECTED_ENTRY);
15082
+ const managedRoot = path45.join(npmDir, "jorgex-pi-managed");
15083
+ const markerPath = path45.join(managedRoot, "active-transaction.json");
15084
+ const lockPath = path45.join(managedRoot, "transaction.lock");
14987
15085
  assertStrictChild(agentDir, homeDir, "agentDir");
14988
15086
  assertStrictChild(receiptPath, homeDir, "receiptPath");
14989
15087
  assertStrictChild(managedRoot, agentDir, "managed root");
@@ -15016,8 +15114,8 @@ function deactivateVerifiedLegacyPiEntry(input) {
15016
15114
  if (entryStat === null || !entryStat.isDirectory() || entryStat.isSymbolicLink()) {
15017
15115
  throw new Error(`managed entry must be a real directory, not a symlink: ${legacyEntry}`);
15018
15116
  }
15019
- assertAncestorsClean(path44.dirname(legacyEntry), homeDir, "managed entry");
15020
- const manifestPath = path44.join(legacyEntry, "package.json");
15117
+ assertAncestorsClean(path45.dirname(legacyEntry), homeDir, "managed entry");
15118
+ const manifestPath = path45.join(legacyEntry, "package.json");
15021
15119
  const manifestStat = lstatOrNull5(manifestPath);
15022
15120
  if (manifestStat === null || !manifestStat.isFile() || manifestStat.isSymbolicLink()) {
15023
15121
  throw new Error(`managed entry manifest must be a regular file: ${manifestPath}`);
@@ -15114,10 +15212,10 @@ function deactivateVerifiedLegacyPiEntry(input) {
15114
15212
  let lockAcquired = false;
15115
15213
  const releaseLock = () => {
15116
15214
  if (!lockAcquired) return;
15117
- fs36.rmSync(lockPath, { force: true });
15215
+ fs37.rmSync(lockPath, { force: true });
15118
15216
  lockAcquired = false;
15119
15217
  };
15120
- fs36.mkdirSync(managedRoot, { recursive: true });
15218
+ fs37.mkdirSync(managedRoot, { recursive: true });
15121
15219
  assertAncestorsClean(managedRoot, homeDir, "managed root");
15122
15220
  const managedRootStat = lstatOrNull5(managedRoot);
15123
15221
  if (managedRootStat === null || !managedRootStat.isDirectory() || managedRootStat.isSymbolicLink()) {
@@ -15125,7 +15223,7 @@ function deactivateVerifiedLegacyPiEntry(input) {
15125
15223
  }
15126
15224
  let uninstallBackupDir = "";
15127
15225
  for (let i = 0; i < 5 && uninstallBackupDir === ""; i++) {
15128
- const candidateDir = path44.join(managedRoot, `uninstall-backup-${crypto2.randomBytes(8).toString("hex")}`);
15226
+ const candidateDir = path45.join(managedRoot, `uninstall-backup-${crypto2.randomBytes(8).toString("hex")}`);
15129
15227
  if (lstatOrNull5(candidateDir) === null) uninstallBackupDir = candidateDir;
15130
15228
  }
15131
15229
  if (uninstallBackupDir === "") {
@@ -15135,14 +15233,14 @@ function deactivateVerifiedLegacyPiEntry(input) {
15135
15233
  const lockToken = `${JSON.stringify({ op: "uninstall-legacy", pid: process.pid, agentDir, source: input.source, startedAt: (/* @__PURE__ */ new Date()).toISOString() })}
15136
15234
  `;
15137
15235
  try {
15138
- fs36.writeFileSync(lockPath, lockToken, { encoding: "utf8", flag: "wx", mode: 384 });
15236
+ fs37.writeFileSync(lockPath, lockToken, { encoding: "utf8", flag: "wx", mode: 384 });
15139
15237
  lockAcquired = true;
15140
15238
  } catch {
15141
15239
  failIncomplete(`transaction lock busy: concurrent operation holds the exclusive lock (recovery incomplete): ${lockPath}`);
15142
15240
  }
15143
15241
  if (lstatOrNull5(markerPath) !== null) {
15144
15242
  try {
15145
- fs36.rmSync(lockPath, { force: true });
15243
+ fs37.rmSync(lockPath, { force: true });
15146
15244
  lockAcquired = false;
15147
15245
  } catch {
15148
15246
  }
@@ -15151,10 +15249,10 @@ function deactivateVerifiedLegacyPiEntry(input) {
15151
15249
  const markerContent = `${JSON.stringify({ phase: "uninstall-legacy", legacyEntry, receiptPath, backupDir: uninstallBackupDir, source: input.source, pid: process.pid }, null, 2)}
15152
15250
  `;
15153
15251
  try {
15154
- fs36.writeFileSync(markerPath, markerContent, { encoding: "utf8", flag: "wx", mode: 384 });
15252
+ fs37.writeFileSync(markerPath, markerContent, { encoding: "utf8", flag: "wx", mode: 384 });
15155
15253
  } catch {
15156
15254
  try {
15157
- fs36.rmSync(lockPath, { force: true });
15255
+ fs37.rmSync(lockPath, { force: true });
15158
15256
  lockAcquired = false;
15159
15257
  } catch {
15160
15258
  }
@@ -15163,7 +15261,7 @@ function deactivateVerifiedLegacyPiEntry(input) {
15163
15261
  const abortOwnTransaction = (err) => {
15164
15262
  const problems = [];
15165
15263
  try {
15166
- fs36.rmSync(markerPath, { force: true });
15264
+ fs37.rmSync(markerPath, { force: true });
15167
15265
  } catch {
15168
15266
  problems.push("cannot remove marker");
15169
15267
  }
@@ -15173,7 +15271,7 @@ function deactivateVerifiedLegacyPiEntry(input) {
15173
15271
  problems.push("cannot release lock");
15174
15272
  }
15175
15273
  try {
15176
- fs36.rmSync(uninstallBackupDir, { recursive: true, force: true });
15274
+ fs37.rmSync(uninstallBackupDir, { recursive: true, force: true });
15177
15275
  } catch {
15178
15276
  problems.push("cannot clear backup");
15179
15277
  }
@@ -15192,7 +15290,7 @@ function deactivateVerifiedLegacyPiEntry(input) {
15192
15290
  abortOwnTransaction(new Error(`receipt or settings drifted before uninstall: ${legacyEntry}`));
15193
15291
  }
15194
15292
  try {
15195
- fs36.mkdirSync(uninstallBackupDir, { recursive: true });
15293
+ fs37.mkdirSync(uninstallBackupDir, { recursive: true });
15196
15294
  } catch (err) {
15197
15295
  abortOwnTransaction(err);
15198
15296
  }
@@ -15202,20 +15300,20 @@ function deactivateVerifiedLegacyPiEntry(input) {
15202
15300
  }
15203
15301
  let backupEntries = [];
15204
15302
  try {
15205
- backupEntries = fs36.readdirSync(uninstallBackupDir);
15303
+ backupEntries = fs37.readdirSync(uninstallBackupDir);
15206
15304
  } catch {
15207
15305
  abortOwnTransaction(new Error(`cannot inspect uninstall backup: ${uninstallBackupDir}`));
15208
15306
  }
15209
15307
  if (backupEntries.length !== 0) {
15210
15308
  abortOwnTransaction(new Error(`uninstall backup is not empty: ${uninstallBackupDir}`));
15211
15309
  }
15212
- const backupEntryDir = path44.join(uninstallBackupDir, "entry");
15213
- const backupReceiptFile = path44.join(uninstallBackupDir, "pi-receipt.json");
15214
- const backupSettingsFile = path44.join(uninstallBackupDir, "settings.json");
15310
+ const backupEntryDir = path45.join(uninstallBackupDir, "entry");
15311
+ const backupReceiptFile = path45.join(uninstallBackupDir, "pi-receipt.json");
15312
+ const backupSettingsFile = path45.join(uninstallBackupDir, "settings.json");
15215
15313
  try {
15216
- fs36.writeFileSync(backupSettingsFile, oldSettings, { encoding: "utf8", flag: "wx", mode: 384 });
15217
- fs36.writeFileSync(
15218
- path44.join(uninstallBackupDir, "meta.json"),
15314
+ fs37.writeFileSync(backupSettingsFile, oldSettings, { encoding: "utf8", flag: "wx", mode: 384 });
15315
+ fs37.writeFileSync(
15316
+ path45.join(uninstallBackupDir, "meta.json"),
15219
15317
  `${JSON.stringify({ phase: "uninstall-legacy", legacyEntry, receiptPath, source: input.source }, null, 2)}
15220
15318
  `,
15221
15319
  { encoding: "utf8", flag: "wx", mode: 384 }
@@ -15259,14 +15357,14 @@ function deactivateVerifiedLegacyPiEntry(input) {
15259
15357
  const problems = [];
15260
15358
  if (movedReceipt) {
15261
15359
  try {
15262
- fs36.renameSync(backupReceiptFile, receiptPath);
15360
+ fs37.renameSync(backupReceiptFile, receiptPath);
15263
15361
  } catch {
15264
15362
  problems.push("cannot restore receipt");
15265
15363
  }
15266
15364
  }
15267
15365
  if (movedEntry) {
15268
15366
  try {
15269
- fs36.renameSync(backupEntryDir, legacyEntry);
15367
+ fs37.renameSync(backupEntryDir, legacyEntry);
15270
15368
  } catch {
15271
15369
  problems.push("cannot restore previous entry");
15272
15370
  }
@@ -15282,9 +15380,9 @@ function deactivateVerifiedLegacyPiEntry(input) {
15282
15380
  failIncomplete(`uninstall rollback incomplete (${problems.join("; ")}): ${original}`);
15283
15381
  }
15284
15382
  try {
15285
- fs36.rmSync(markerPath, { force: true });
15383
+ fs37.rmSync(markerPath, { force: true });
15286
15384
  releaseLock();
15287
- fs36.rmSync(uninstallBackupDir, { recursive: true, force: true });
15385
+ fs37.rmSync(uninstallBackupDir, { recursive: true, force: true });
15288
15386
  } catch {
15289
15387
  failIncomplete(`cannot clear transaction state after rollback: ${original}`);
15290
15388
  }
@@ -15297,9 +15395,9 @@ function deactivateVerifiedLegacyPiEntry(input) {
15297
15395
  throw wrapped;
15298
15396
  };
15299
15397
  try {
15300
- fs36.renameSync(legacyEntry, backupEntryDir);
15398
+ fs37.renameSync(legacyEntry, backupEntryDir);
15301
15399
  movedEntry = true;
15302
- fs36.renameSync(receiptPath, backupReceiptFile);
15400
+ fs37.renameSync(receiptPath, backupReceiptFile);
15303
15401
  movedReceipt = true;
15304
15402
  atomicWritePrivate(settingsPath, input.nextSettings);
15305
15403
  wroteSettings = true;
@@ -15321,7 +15419,7 @@ function deactivateVerifiedLegacyPiEntry(input) {
15321
15419
  rollbackLegacy(new Error(`verify must be synchronous and return void, got thenable`));
15322
15420
  }
15323
15421
  try {
15324
- fs36.rmSync(markerPath, { force: true });
15422
+ fs37.rmSync(markerPath, { force: true });
15325
15423
  releaseLock();
15326
15424
  } catch {
15327
15425
  failIncomplete(`cannot clear transaction state after uninstall (recovery incomplete): ${markerPath}`);
@@ -15377,8 +15475,8 @@ async function activatePreparedPiInstall(input, deps) {
15377
15475
  // src/lib/pi-stage-smoke.ts
15378
15476
  init_detect();
15379
15477
  import { spawn, spawnSync as spawnSync4 } from "child_process";
15380
- import fs37 from "fs";
15381
- import path45 from "path";
15478
+ import fs38 from "fs";
15479
+ import path46 from "path";
15382
15480
  var REQUIRED_COMMANDS = ["goal", "subagents", "permission-system", "websearch", "jorgex:header"];
15383
15481
  var EXPECTED_ARGV = ["--mode", "rpc", "--no-session", "--no-approve", "--offline", "--no-context-files"];
15384
15482
  var KNOWN_STDERR_WARNING = "[pi-web-access] Dynamic tool activation requires Pi 0.86.1 or newer; web tools remain eagerly available.";
@@ -15395,13 +15493,13 @@ function isRecord12(value) {
15395
15493
  }
15396
15494
  function lstatOrNull6(p7) {
15397
15495
  try {
15398
- return fs37.lstatSync(p7);
15496
+ return fs38.lstatSync(p7);
15399
15497
  } catch {
15400
15498
  return null;
15401
15499
  }
15402
15500
  }
15403
15501
  function assertPiExecutable(piExecutable) {
15404
- const absolute = path45.resolve(piExecutable);
15502
+ const absolute = path46.resolve(piExecutable);
15405
15503
  const linkStat = lstatOrNull6(absolute);
15406
15504
  if (linkStat === null) {
15407
15505
  fail10(`piExecutable must exist: ${piExecutable}`);
@@ -15409,13 +15507,13 @@ function assertPiExecutable(piExecutable) {
15409
15507
  if (linkStat.isSymbolicLink()) {
15410
15508
  let real;
15411
15509
  try {
15412
- real = fs37.realpathSync(absolute);
15510
+ real = fs38.realpathSync(absolute);
15413
15511
  } catch {
15414
15512
  fail10(`piExecutable symlink is broken: ${piExecutable}`);
15415
15513
  }
15416
15514
  let targetStat;
15417
15515
  try {
15418
- targetStat = fs37.statSync(real);
15516
+ targetStat = fs38.statSync(real);
15419
15517
  } catch {
15420
15518
  fail10(`piExecutable symlink target is missing: ${piExecutable}`);
15421
15519
  }
@@ -15424,7 +15522,7 @@ function assertPiExecutable(piExecutable) {
15424
15522
  }
15425
15523
  if (process.platform !== "win32") {
15426
15524
  try {
15427
- fs37.accessSync(real, fs37.constants.X_OK);
15525
+ fs38.accessSync(real, fs38.constants.X_OK);
15428
15526
  } catch {
15429
15527
  fail10(`piExecutable symlink target is not executable: ${piExecutable}`);
15430
15528
  }
@@ -15436,7 +15534,7 @@ function assertPiExecutable(piExecutable) {
15436
15534
  }
15437
15535
  if (process.platform !== "win32") {
15438
15536
  try {
15439
- fs37.accessSync(absolute, fs37.constants.X_OK);
15537
+ fs38.accessSync(absolute, fs38.constants.X_OK);
15440
15538
  } catch {
15441
15539
  fail10(`piExecutable is not executable: ${piExecutable}`);
15442
15540
  }
@@ -15444,7 +15542,7 @@ function assertPiExecutable(piExecutable) {
15444
15542
  return absolute;
15445
15543
  }
15446
15544
  function assertRealDir3(p7, label) {
15447
- const resolved2 = path45.resolve(p7);
15545
+ const resolved2 = path46.resolve(p7);
15448
15546
  const st = lstatOrNull6(resolved2);
15449
15547
  if (st === null || !st.isDirectory() || st.isSymbolicLink()) {
15450
15548
  fail10(`${label} must be a real directory: ${p7}`);
@@ -15459,24 +15557,24 @@ function sleep(ms) {
15459
15557
  }
15460
15558
  function runtimePath2(piExecutable) {
15461
15559
  const entries = process.platform === "win32" ? [
15462
- path45.dirname(piExecutable),
15463
- path45.dirname(process.execPath),
15464
- process.env.SystemRoot ? path45.join(process.env.SystemRoot, "System32") : null
15465
- ] : [path45.dirname(piExecutable), path45.dirname(process.execPath), "/usr/local/bin", "/usr/bin", "/bin"];
15466
- return [...new Set(entries.filter((entry) => entry !== null))].join(path45.delimiter);
15560
+ path46.dirname(piExecutable),
15561
+ path46.dirname(process.execPath),
15562
+ process.env.SystemRoot ? path46.join(process.env.SystemRoot, "System32") : null
15563
+ ] : [path46.dirname(piExecutable), path46.dirname(process.execPath), "/usr/local/bin", "/usr/bin", "/bin"];
15564
+ return [...new Set(entries.filter((entry) => entry !== null))].join(path46.delimiter);
15467
15565
  }
15468
15566
  function buildSandboxEnv(stageRoot, stageDir, piExecutable) {
15469
- const home = path45.join(stageRoot, "home");
15470
- const appdata = path45.join(stageRoot, "appdata");
15471
- const localappdata = path45.join(stageRoot, "localappdata");
15472
- const xdgConfig = path45.join(stageRoot, "xdg-config");
15473
- const xdgData = path45.join(stageRoot, "xdg-data");
15474
- const xdgCache = path45.join(stageRoot, "xdg-cache");
15475
- const temporary = path45.join(stageRoot, "tmp");
15476
- const npmCache = path45.join(stageRoot, "npm-cache");
15567
+ const home = path46.join(stageRoot, "home");
15568
+ const appdata = path46.join(stageRoot, "appdata");
15569
+ const localappdata = path46.join(stageRoot, "localappdata");
15570
+ const xdgConfig = path46.join(stageRoot, "xdg-config");
15571
+ const xdgData = path46.join(stageRoot, "xdg-data");
15572
+ const xdgCache = path46.join(stageRoot, "xdg-cache");
15573
+ const temporary = path46.join(stageRoot, "tmp");
15574
+ const npmCache = path46.join(stageRoot, "npm-cache");
15477
15575
  for (const dir of [home, appdata, localappdata, xdgConfig, xdgData, xdgCache, temporary, npmCache]) {
15478
15576
  try {
15479
- fs37.mkdirSync(dir, { recursive: true, mode: 448 });
15577
+ fs38.mkdirSync(dir, { recursive: true, mode: 448 });
15480
15578
  } catch {
15481
15579
  fail10(`cannot prepare isolated stage dir: ${dir}`);
15482
15580
  }
@@ -15553,7 +15651,7 @@ async function stopOwned(child) {
15553
15651
  if (process.platform === "win32") {
15554
15652
  try {
15555
15653
  const systemRoot = process.env.SystemRoot ?? process.env.WINDIR ?? "C:\\Windows";
15556
- const taskkill = path45.join(systemRoot, "System32", "taskkill.exe");
15654
+ const taskkill = path46.join(systemRoot, "System32", "taskkill.exe");
15557
15655
  spawnSync4(taskkill, ["/pid", String(pid), "/t", "/f"], {
15558
15656
  shell: false,
15559
15657
  stdio: "ignore",
@@ -15702,26 +15800,26 @@ async function smokeStagedPiRuntime(input) {
15702
15800
  async function runSmoke(input) {
15703
15801
  if (!isRecord12(input)) fail10("input must be an object");
15704
15802
  const { piExecutable, stageDir, timeoutMs } = input;
15705
- if (typeof piExecutable !== "string" || piExecutable === "" || !path45.isAbsolute(piExecutable)) {
15803
+ if (typeof piExecutable !== "string" || piExecutable === "" || !path46.isAbsolute(piExecutable)) {
15706
15804
  fail10("piExecutable must be a non-empty absolute path");
15707
15805
  }
15708
- if (typeof stageDir !== "string" || stageDir === "" || !path45.isAbsolute(stageDir)) {
15806
+ if (typeof stageDir !== "string" || stageDir === "" || !path46.isAbsolute(stageDir)) {
15709
15807
  fail10("stageDir must be a non-empty absolute path");
15710
15808
  }
15711
15809
  const piResolved = assertPiExecutable(piExecutable);
15712
15810
  const stageResolved = assertRealDir3(stageDir, "stageDir");
15713
- if (path45.basename(stageResolved) !== "pi-agent") {
15811
+ if (path46.basename(stageResolved) !== "pi-agent") {
15714
15812
  fail10("stageDir must be the staged pi-agent dir (stageRoot/pi-agent)");
15715
15813
  }
15716
- const stageRoot = path45.dirname(stageResolved);
15814
+ const stageRoot = path46.dirname(stageResolved);
15717
15815
  const stageRootStat = lstatOrNull6(stageRoot);
15718
15816
  if (stageRootStat === null || !stageRootStat.isDirectory() || stageRootStat.isSymbolicLink()) {
15719
15817
  fail10("stageRoot must be a real directory");
15720
15818
  }
15721
- if (!path45.basename(stageRoot).startsWith("stage-")) {
15819
+ if (!path46.basename(stageRoot).startsWith("stage-")) {
15722
15820
  fail10("stageRoot must be a private stage- dir");
15723
15821
  }
15724
- const workspace = path45.join(stageRoot, "workspace");
15822
+ const workspace = path46.join(stageRoot, "workspace");
15725
15823
  assertRealDir3(workspace, "stage workspace");
15726
15824
  let timeout = DEFAULT_TIMEOUT_MS;
15727
15825
  if (timeoutMs !== void 0) {
@@ -15900,8 +15998,8 @@ ${JSON.stringify({ id: commandsId, type: "get_commands" })}
15900
15998
  // src/lib/pi-cached-artifact.ts
15901
15999
  init_npm_provider();
15902
16000
  import { createHash as createHash9, timingSafeEqual as timingSafeEqual6 } from "crypto";
15903
- import fs38 from "fs";
15904
- import path46 from "path";
16001
+ import fs39 from "fs";
16002
+ import path47 from "path";
15905
16003
  var PACKAGE_NAME5 = "jorgex-pi";
15906
16004
  var HEX643 = /^[0-9a-f]{64}$/;
15907
16005
  var HEX1283 = /^[0-9a-f]{128}$/;
@@ -15912,14 +16010,14 @@ function isRecord13(value) {
15912
16010
  }
15913
16011
  function lstatOrNull7(p7) {
15914
16012
  try {
15915
- return fs38.lstatSync(p7);
16013
+ return fs39.lstatSync(p7);
15916
16014
  } catch {
15917
16015
  return null;
15918
16016
  }
15919
16017
  }
15920
16018
  function isStrictChild5(child, root) {
15921
- const rel = path46.relative(root, child);
15922
- return rel !== "" && rel !== ".." && !rel.startsWith(`..${path46.sep}`) && !path46.isAbsolute(rel);
16019
+ const rel = path47.relative(root, child);
16020
+ return rel !== "" && rel !== ".." && !rel.startsWith(`..${path47.sep}`) && !path47.isAbsolute(rel);
15923
16021
  }
15924
16022
  function equalHex2(aHex, bHex) {
15925
16023
  let a;
@@ -15936,12 +16034,12 @@ function verifyCachedPiArtifact(input) {
15936
16034
  try {
15937
16035
  if (!isRecord13(input)) return false;
15938
16036
  const { receipt, homeDir, downloadsDir } = input;
15939
- if (typeof homeDir !== "string" || homeDir === "" || !path46.isAbsolute(homeDir)) return false;
15940
- if (typeof downloadsDir !== "string" || downloadsDir === "" || !path46.isAbsolute(downloadsDir)) {
16037
+ if (typeof homeDir !== "string" || homeDir === "" || !path47.isAbsolute(homeDir)) return false;
16038
+ if (typeof downloadsDir !== "string" || downloadsDir === "" || !path47.isAbsolute(downloadsDir)) {
15941
16039
  return false;
15942
16040
  }
15943
- const homeResolved = path46.resolve(homeDir);
15944
- const downloadsResolved = path46.resolve(downloadsDir);
16041
+ const homeResolved = path47.resolve(homeDir);
16042
+ const downloadsResolved = path47.resolve(downloadsDir);
15945
16043
  const homeStat = lstatOrNull7(homeResolved);
15946
16044
  if (homeStat === null || !homeStat.isDirectory() || homeStat.isSymbolicLink()) return false;
15947
16045
  const downloadsStat = lstatOrNull7(downloadsResolved);
@@ -15949,12 +16047,12 @@ function verifyCachedPiArtifact(input) {
15949
16047
  return false;
15950
16048
  }
15951
16049
  if (!isStrictChild5(downloadsResolved, homeResolved)) return false;
15952
- const rel = path46.relative(homeResolved, downloadsResolved);
15953
- const parts = rel.split(path46.sep);
16050
+ const rel = path47.relative(homeResolved, downloadsResolved);
16051
+ const parts = rel.split(path47.sep);
15954
16052
  let cursor = homeResolved;
15955
16053
  for (const part of parts) {
15956
16054
  if (part === "" || part === "." || part === "..") return false;
15957
- cursor = path46.join(cursor, part);
16055
+ cursor = path47.join(cursor, part);
15958
16056
  const st2 = lstatOrNull7(cursor);
15959
16057
  if (st2 === null || !st2.isDirectory() || st2.isSymbolicLink()) return false;
15960
16058
  }
@@ -15980,8 +16078,8 @@ function verifyCachedPiArtifact(input) {
15980
16078
  if (typeof sha2562 !== "string" || !HEX643.test(sha2562)) return false;
15981
16079
  if (typeof sha512 !== "string" || !HEX1283.test(sha512)) return false;
15982
16080
  const fileName = `${PACKAGE_NAME5}-${version}.tgz`;
15983
- const target = path46.join(downloadsResolved, fileName);
15984
- if (path46.dirname(target) !== downloadsResolved) return false;
16081
+ const target = path47.join(downloadsResolved, fileName);
16082
+ if (path47.dirname(target) !== downloadsResolved) return false;
15985
16083
  const st = lstatOrNull7(target);
15986
16084
  if (st === null) return false;
15987
16085
  if (st.isSymbolicLink()) return false;
@@ -15990,7 +16088,7 @@ function verifyCachedPiArtifact(input) {
15990
16088
  if (st.size > MAX_TARBALL_BYTES4) return false;
15991
16089
  let fd;
15992
16090
  try {
15993
- fd = fs38.openSync(target, "r");
16091
+ fd = fs39.openSync(target, "r");
15994
16092
  } catch {
15995
16093
  return false;
15996
16094
  }
@@ -16002,7 +16100,7 @@ function verifyCachedPiArtifact(input) {
16002
16100
  for (; ; ) {
16003
16101
  let read;
16004
16102
  try {
16005
- read = fs38.readSync(fd, buffer, 0, buffer.length, null);
16103
+ read = fs39.readSync(fd, buffer, 0, buffer.length, null);
16006
16104
  } catch {
16007
16105
  return false;
16008
16106
  }
@@ -16014,7 +16112,7 @@ function verifyCachedPiArtifact(input) {
16014
16112
  }
16015
16113
  } finally {
16016
16114
  try {
16017
- fs38.closeSync(fd);
16115
+ fs39.closeSync(fd);
16018
16116
  } catch {
16019
16117
  }
16020
16118
  }
@@ -16176,30 +16274,30 @@ async function resolvePiEngramRequirement(input, deps) {
16176
16274
  } : { kind: "existing", bin: detected, scope: "host" };
16177
16275
  }
16178
16276
  function runtimePath3(piExecutable) {
16179
- const entries = process.platform === "win32" ? [piExecutable === void 0 ? null : path47.dirname(piExecutable), path47.dirname(process.execPath), process.env.SystemRoot ? path47.join(process.env.SystemRoot, "System32") : null] : [piExecutable === void 0 ? null : path47.dirname(piExecutable), path47.dirname(process.execPath), "/usr/local/bin", "/usr/bin", "/bin"];
16180
- return [...new Set(entries.filter((entry) => entry !== null))].join(path47.delimiter);
16277
+ const entries = process.platform === "win32" ? [piExecutable === void 0 ? null : path48.dirname(piExecutable), path48.dirname(process.execPath), process.env.SystemRoot ? path48.join(process.env.SystemRoot, "System32") : null] : [piExecutable === void 0 ? null : path48.dirname(piExecutable), path48.dirname(process.execPath), "/usr/local/bin", "/usr/bin", "/bin"];
16278
+ return [...new Set(entries.filter((entry) => entry !== null))].join(path48.delimiter);
16181
16279
  }
16182
16280
  function targetPaths(targetDir, engramBin, piExecutable) {
16183
- const root = path47.resolve(targetDir);
16184
- const codingAgentDir = path47.join(root, "pi-agent");
16185
- const home = path47.join(root, "home");
16186
- const temporary = path47.join(root, "tmp");
16281
+ const root = path48.resolve(targetDir);
16282
+ const codingAgentDir = path48.join(root, "pi-agent");
16283
+ const home = path48.join(root, "home");
16284
+ const temporary = path48.join(root, "tmp");
16187
16285
  return {
16188
16286
  codingAgentDir,
16189
- receiptPath: path47.join(root, "state", "pi-receipt.json"),
16190
- packageRunner: path47.join(codingAgentDir, "npm", "node_modules", "jorgex-pi", "bin", "jorgex-pi.mjs"),
16287
+ receiptPath: path48.join(root, "state", "pi-receipt.json"),
16288
+ packageRunner: path48.join(codingAgentDir, "npm", "node_modules", "jorgex-pi", "bin", "jorgex-pi.mjs"),
16191
16289
  environment: {
16192
16290
  HOME: home,
16193
16291
  USERPROFILE: home,
16194
- APPDATA: path47.join(root, "appdata"),
16195
- LOCALAPPDATA: path47.join(root, "localappdata"),
16196
- XDG_CONFIG_HOME: path47.join(root, "xdg-config"),
16197
- XDG_DATA_HOME: path47.join(root, "xdg-data"),
16198
- XDG_CACHE_HOME: path47.join(root, "xdg-cache"),
16292
+ APPDATA: path48.join(root, "appdata"),
16293
+ LOCALAPPDATA: path48.join(root, "localappdata"),
16294
+ XDG_CONFIG_HOME: path48.join(root, "xdg-config"),
16295
+ XDG_DATA_HOME: path48.join(root, "xdg-data"),
16296
+ XDG_CACHE_HOME: path48.join(root, "xdg-cache"),
16199
16297
  TEMP: temporary,
16200
16298
  TMP: temporary,
16201
16299
  TMPDIR: temporary,
16202
- npm_config_cache: path47.join(root, "npm-cache"),
16300
+ npm_config_cache: path48.join(root, "npm-cache"),
16203
16301
  NPM_CONFIG_IGNORE_SCRIPTS: "true",
16204
16302
  NPM_CONFIG_UPDATE_NOTIFIER: "false",
16205
16303
  PI_CODING_AGENT_DIR: codingAgentDir,
@@ -16210,15 +16308,15 @@ function targetPaths(targetDir, engramBin, piExecutable) {
16210
16308
  }
16211
16309
  function userPaths(engramBin, piExecutable) {
16212
16310
  const home = os6.homedir();
16213
- const codingAgentDir = process.env.PI_CODING_AGENT_DIR ?? path47.join(home, ".pi", "agent");
16311
+ const codingAgentDir = process.env.PI_CODING_AGENT_DIR ?? path48.join(home, ".pi", "agent");
16214
16312
  return {
16215
16313
  codingAgentDir,
16216
- receiptPath: path47.join(dataDir(), "pi-receipt.json"),
16217
- packageRunner: path47.join(codingAgentDir, "npm", "node_modules", "jorgex-pi", "bin", "jorgex-pi.mjs"),
16314
+ receiptPath: path48.join(dataDir(), "pi-receipt.json"),
16315
+ packageRunner: path48.join(codingAgentDir, "npm", "node_modules", "jorgex-pi", "bin", "jorgex-pi.mjs"),
16218
16316
  environment: {
16219
16317
  HOME: home,
16220
- XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME ?? path47.join(home, ".config"),
16221
- XDG_CACHE_HOME: process.env.XDG_CACHE_HOME ?? path47.join(home, ".cache"),
16318
+ XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME ?? path48.join(home, ".config"),
16319
+ XDG_CACHE_HOME: process.env.XDG_CACHE_HOME ?? path48.join(home, ".cache"),
16222
16320
  TMPDIR: os6.tmpdir(),
16223
16321
  NPM_CONFIG_IGNORE_SCRIPTS: "true",
16224
16322
  NPM_CONFIG_UPDATE_NOTIFIER: "false",
@@ -16254,7 +16352,7 @@ function runPiRuntime(input, deps) {
16254
16352
  }
16255
16353
  const candidate = input.candidate ?? PI_RUNTIME_CANDIDATE;
16256
16354
  const paths = input.targetDir === void 0 ? userPaths(input.engramBin, input.detected.executable) : targetPaths(input.targetDir, input.engramBin, input.detected.executable);
16257
- const settingsJson = deps.readSettings(path47.join(paths.codingAgentDir, "settings.json"));
16355
+ const settingsJson = deps.readSettings(path48.join(paths.codingAgentDir, "settings.json"));
16258
16356
  const receiptJson = deps.readReceipt(paths.receiptPath);
16259
16357
  const lifecycleInput = {
16260
16358
  candidate,
@@ -16319,60 +16417,32 @@ function runPiRuntime(input, deps) {
16319
16417
  persistReturnedReceipt(result, paths, deps);
16320
16418
  return result;
16321
16419
  }
16322
- function readJsonFile2(file) {
16323
- return JSON.parse(fs39.readFileSync(file, "utf8"));
16324
- }
16325
- function packageVersionFromExecutable(executable) {
16326
- let current;
16327
- try {
16328
- current = path47.dirname(fs39.realpathSync(executable));
16329
- } catch {
16330
- return null;
16331
- }
16332
- for (let depth = 0; depth < 8; depth++) {
16333
- const manifests = [
16334
- path47.join(current, "package.json"),
16335
- path47.join(current, "node_modules", "@earendil-works", "pi-coding-agent", "package.json")
16336
- ];
16337
- for (const manifest of manifests) {
16338
- try {
16339
- const parsed = readJsonFile2(manifest);
16340
- if (parsed !== null && typeof parsed === "object" && Reflect.get(parsed, "name") === "@earendil-works/pi-coding-agent" && typeof Reflect.get(parsed, "version") === "string") {
16341
- return Reflect.get(parsed, "version");
16342
- }
16343
- } catch {
16344
- }
16345
- }
16346
- const parent = path47.dirname(current);
16347
- if (parent === current) break;
16348
- current = parent;
16349
- }
16350
- return null;
16351
- }
16352
16420
  function detectPiRuntime() {
16353
16421
  const executable = lookPath("pi");
16354
16422
  const home = os6.homedir();
16423
+ const inspection = executable === null ? null : inspectPiHostVersion(executable);
16355
16424
  return {
16356
16425
  id: "pi",
16357
16426
  name: "Pi",
16358
16427
  installed: executable !== null,
16359
16428
  executable,
16360
- version: executable === null ? null : packageVersionFromExecutable(executable),
16361
- codingAgentDir: process.env.PI_CODING_AGENT_DIR ?? path47.join(home, ".pi", "agent")
16429
+ version: inspection?.version ?? null,
16430
+ versionDiagnostic: inspection?.diagnostic ?? null,
16431
+ codingAgentDir: process.env.PI_CODING_AGENT_DIR ?? path48.join(home, ".pi", "agent")
16362
16432
  };
16363
16433
  }
16364
16434
  function hasManagedPiRuntime(targetDir) {
16365
- const receipt = targetDir === void 0 ? path47.join(dataDir(), "pi-receipt.json") : path47.join(path47.resolve(targetDir), "state", "pi-receipt.json");
16366
- return fs39.statSync(receipt, { throwIfNoEntry: false })?.isFile() === true;
16435
+ const receipt = targetDir === void 0 ? path48.join(dataDir(), "pi-receipt.json") : path48.join(path48.resolve(targetDir), "state", "pi-receipt.json");
16436
+ return fs40.statSync(receipt, { throwIfNoEntry: false })?.isFile() === true;
16367
16437
  }
16368
16438
  function resolvePiEngramBin(targetDir) {
16369
16439
  if (targetDir === void 0) return detectEngram();
16370
- const candidate = path47.join(path47.resolve(targetDir), "bin", process.platform === "win32" ? "engram.exe" : "engram");
16371
- return fs39.statSync(candidate, { throwIfNoEntry: false })?.isFile() ? candidate : null;
16440
+ const candidate = path48.join(path48.resolve(targetDir), "bin", process.platform === "win32" ? "engram.exe" : "engram");
16441
+ return fs40.statSync(candidate, { throwIfNoEntry: false })?.isFile() ? candidate : null;
16372
16442
  }
16373
16443
  function readOptional(file, fallback) {
16374
16444
  try {
16375
- return fs39.readFileSync(file, "utf8");
16445
+ return fs40.readFileSync(file, "utf8");
16376
16446
  } catch (error) {
16377
16447
  if (error.code === "ENOENT") return fallback;
16378
16448
  throw error;
@@ -16438,7 +16508,7 @@ function preparedInstallMismatch(candidate, prepared) {
16438
16508
  return "la release preparada no coincide con la versi\xF3n/SRI del candidato";
16439
16509
  }
16440
16510
  const stageDir = prepared?.stageDir;
16441
- if (typeof stageDir !== "string" || stageDir === "" || !/(^|[\\/])stage-[0-9a-f]{32}[\\/]pi-agent$/.test(path47.resolve(stageDir))) {
16511
+ if (typeof stageDir !== "string" || stageDir === "" || !/(^|[\\/])stage-[0-9a-f]{32}[\\/]pi-agent$/.test(path48.resolve(stageDir))) {
16442
16512
  return "el stage preparado no tiene el layout aislado esperado (stage-<hex>/pi-agent)";
16443
16513
  }
16444
16514
  const evidence = prepared?.evidence;
@@ -16513,12 +16583,12 @@ function backupLegacyMigrationState(settingsPath, receiptPath, backupRoot) {
16513
16583
  }
16514
16584
  }
16515
16585
  function verifyActivePiRelease(input) {
16516
- const agentDir = path47.resolve(input.agentDir);
16517
- const npmDir = path47.join(agentDir, "npm");
16518
- const managedRoot = path47.join(npmDir, "jorgex-pi-managed");
16586
+ const agentDir = path48.resolve(input.agentDir);
16587
+ const npmDir = path48.join(agentDir, "npm");
16588
+ const managedRoot = path48.join(npmDir, "jorgex-pi-managed");
16519
16589
  let receiptRaw;
16520
16590
  try {
16521
- receiptRaw = fs39.readFileSync(input.receiptPath, "utf8");
16591
+ receiptRaw = fs40.readFileSync(input.receiptPath, "utf8");
16522
16592
  } catch {
16523
16593
  throw new Error(`pi-verify-active: no se pudo leer el receipt promovido: ${input.receiptPath}`);
16524
16594
  }
@@ -16547,7 +16617,7 @@ function verifyActivePiRelease(input) {
16547
16617
  throw new Error("pi-verify-active: el scope del receipt promovido no coincide con el esperado");
16548
16618
  }
16549
16619
  const scopeDir = scopeRecord["codingAgentDir"];
16550
- if (typeof scopeDir !== "string" || !path47.isAbsolute(scopeDir) || path47.resolve(scopeDir) !== agentDir) {
16620
+ if (typeof scopeDir !== "string" || !path48.isAbsolute(scopeDir) || path48.resolve(scopeDir) !== agentDir) {
16551
16621
  throw new Error("pi-verify-active: el codingAgentDir del receipt promovido no coincide con el agentDir");
16552
16622
  }
16553
16623
  const receiptEngram = record["engram"];
@@ -16578,40 +16648,40 @@ function verifyActivePiRelease(input) {
16578
16648
  throw new Error("pi-verify-active: el receipt promovido no conserva las seis dependencias de la evidencia");
16579
16649
  }
16580
16650
  const linkPath = managedRecord["linkPath"];
16581
- if (typeof linkPath !== "string" || !path47.isAbsolute(linkPath)) {
16651
+ if (typeof linkPath !== "string" || !path48.isAbsolute(linkPath)) {
16582
16652
  throw new Error("pi-verify-active: el receipt promovido no trae un linkPath absoluto");
16583
16653
  }
16584
- const linkResolved = path47.resolve(linkPath);
16585
- if (linkResolved !== path47.join(npmDir, "node_modules", "jorgex-pi")) {
16654
+ const linkResolved = path48.resolve(linkPath);
16655
+ if (linkResolved !== path48.join(npmDir, "node_modules", "jorgex-pi")) {
16586
16656
  throw new Error("pi-verify-active: el enlace publicado sale del entry propio");
16587
16657
  }
16588
16658
  const releaseDir = managedRecord["releaseDir"];
16589
- if (typeof releaseDir !== "string" || !path47.isAbsolute(releaseDir)) {
16659
+ if (typeof releaseDir !== "string" || !path48.isAbsolute(releaseDir)) {
16590
16660
  throw new Error("pi-verify-active: el receipt promovido no trae un releaseDir absoluto");
16591
16661
  }
16592
- const releaseResolved = path47.resolve(releaseDir);
16593
- const releaseRel = path47.relative(managedRoot, releaseResolved);
16594
- if (releaseRel === "" || releaseRel === ".." || releaseRel.startsWith(`..${path47.sep}`) || path47.isAbsolute(releaseRel)) {
16662
+ const releaseResolved = path48.resolve(releaseDir);
16663
+ const releaseRel = path48.relative(managedRoot, releaseResolved);
16664
+ if (releaseRel === "" || releaseRel === ".." || releaseRel.startsWith(`..${path48.sep}`) || path48.isAbsolute(releaseRel)) {
16595
16665
  throw new Error("pi-verify-active: el release promovido sale del root gestionado");
16596
16666
  }
16597
16667
  let target;
16598
16668
  try {
16599
- const linkStat = fs39.lstatSync(linkResolved);
16669
+ const linkStat = fs40.lstatSync(linkResolved);
16600
16670
  if (!linkStat.isSymbolicLink()) {
16601
16671
  throw new Error("pi-verify-active: el entry publicado no es un enlace");
16602
16672
  }
16603
- target = fs39.readlinkSync(linkResolved);
16673
+ target = fs40.readlinkSync(linkResolved);
16604
16674
  } catch (error) {
16605
16675
  if (error instanceof Error && error.message.startsWith("pi-verify-active: ")) throw error;
16606
16676
  throw new Error("pi-verify-active: no se pudo leer el enlace publicado");
16607
16677
  }
16608
- const packageRoot = path47.join(releaseResolved, "node_modules", "jorgex-pi");
16609
- if (target === "" || path47.isAbsolute(target) || path47.resolve(path47.dirname(linkResolved), target) !== packageRoot) {
16678
+ const packageRoot = path48.join(releaseResolved, "node_modules", "jorgex-pi");
16679
+ if (target === "" || path48.isAbsolute(target) || path48.resolve(path48.dirname(linkResolved), target) !== packageRoot) {
16610
16680
  throw new Error("pi-verify-active: el enlace publicado no apunta al release promovido");
16611
16681
  }
16612
16682
  let realRoot;
16613
16683
  try {
16614
- realRoot = fs39.realpathSync(linkResolved);
16684
+ realRoot = fs40.realpathSync(linkResolved);
16615
16685
  } catch {
16616
16686
  throw new Error("pi-verify-active: no se pudo resolver el realpath del enlace publicado");
16617
16687
  }
@@ -16629,8 +16699,8 @@ function verifyActivePiRelease(input) {
16629
16699
  }
16630
16700
  }
16631
16701
  function isStrictChildPath(child, root) {
16632
- const rel = path47.relative(path47.resolve(root), path47.resolve(child));
16633
- return rel !== "" && rel !== ".." && !rel.startsWith(`..${path47.sep}`) && !path47.isAbsolute(rel);
16702
+ const rel = path48.relative(path48.resolve(root), path48.resolve(child));
16703
+ return rel !== "" && rel !== ".." && !rel.startsWith(`..${path48.sep}`) && !path48.isAbsolute(rel);
16634
16704
  }
16635
16705
  async function preparePiRuntimeSystem(input) {
16636
16706
  if (input.operation !== "install" && input.operation !== "update") {
@@ -16648,7 +16718,7 @@ async function preparePiRuntimeSystem(input) {
16648
16718
  remedy: "El update con --target-dir nunca ejecuta preflight de red; aporta un stage preverificado o usa update real."
16649
16719
  };
16650
16720
  }
16651
- if (typeof input.engramBin !== "string" || input.engramBin === "" || !path47.isAbsolute(input.engramBin)) {
16721
+ if (typeof input.engramBin !== "string" || input.engramBin === "" || !path48.isAbsolute(input.engramBin)) {
16652
16722
  return {
16653
16723
  kind: "blocked",
16654
16724
  reason: "engram-required",
@@ -16656,7 +16726,7 @@ async function preparePiRuntimeSystem(input) {
16656
16726
  };
16657
16727
  }
16658
16728
  const updateExecutable = input.detected.executable;
16659
- if (typeof updateExecutable !== "string" || updateExecutable === "" || !path47.isAbsolute(updateExecutable)) {
16729
+ if (typeof updateExecutable !== "string" || updateExecutable === "" || !path48.isAbsolute(updateExecutable)) {
16660
16730
  return {
16661
16731
  kind: "blocked",
16662
16732
  reason: "pi-executable-missing",
@@ -16671,16 +16741,16 @@ async function preparePiRuntimeSystem(input) {
16671
16741
  };
16672
16742
  }
16673
16743
  const updateHomeDir = os6.homedir();
16674
- if (typeof updateHomeDir !== "string" || updateHomeDir === "" || !path47.isAbsolute(updateHomeDir)) {
16744
+ if (typeof updateHomeDir !== "string" || updateHomeDir === "" || !path48.isAbsolute(updateHomeDir)) {
16675
16745
  return {
16676
16746
  kind: "blocked",
16677
16747
  reason: "preflight-failed",
16678
16748
  remedy: "HOME ilegible para el preflight Pi; Pi no qued\xF3 activado."
16679
16749
  };
16680
16750
  }
16681
- const updateAgentDir = process.env.PI_CODING_AGENT_DIR ?? path47.join(updateHomeDir, ".pi", "agent");
16682
- const updateReceiptPath = path47.join(updateHomeDir, ".jorgex-stack", "pi-receipt.json");
16683
- const updateDownloadsDir = path47.join(updateHomeDir, ".jorgex-stack", "packages");
16751
+ const updateAgentDir = process.env.PI_CODING_AGENT_DIR ?? path48.join(updateHomeDir, ".pi", "agent");
16752
+ const updateReceiptPath = path48.join(updateHomeDir, ".jorgex-stack", "pi-receipt.json");
16753
+ const updateDownloadsDir = path48.join(updateHomeDir, ".jorgex-stack", "packages");
16684
16754
  if (!isStrictChildPath(updateAgentDir, updateHomeDir)) {
16685
16755
  return {
16686
16756
  kind: "blocked",
@@ -16688,7 +16758,7 @@ async function preparePiRuntimeSystem(input) {
16688
16758
  remedy: `PI_CODING_AGENT_DIR (${updateAgentDir}) est\xE1 fuera de la frontera de restore HOME (${updateHomeDir}); corrige el destino antes de reintentar; Pi no qued\xF3 activado.`
16689
16759
  };
16690
16760
  }
16691
- const updateSettingsPath = path47.join(updateAgentDir, "settings.json");
16761
+ const updateSettingsPath = path48.join(updateAgentDir, "settings.json");
16692
16762
  let updateReceiptRaw;
16693
16763
  let updateSettingsRaw;
16694
16764
  try {
@@ -16704,7 +16774,7 @@ async function preparePiRuntimeSystem(input) {
16704
16774
  const stripUpdateGateNewline = (value) => value.endsWith("\n") ? value.slice(0, -1) : value;
16705
16775
  const updateReceiptJson = updateReceiptRaw === null ? null : stripUpdateGateNewline(updateReceiptRaw);
16706
16776
  const updateSettingsJson = stripUpdateGateNewline(updateSettingsRaw);
16707
- const updatePackageRunner = path47.join(updateAgentDir, "npm", "node_modules", "jorgex-pi", "bin", "jorgex-pi.mjs");
16777
+ const updatePackageRunner = path48.join(updateAgentDir, "npm", "node_modules", "jorgex-pi", "bin", "jorgex-pi.mjs");
16708
16778
  const updateGate = verifyOfflineManagedPiRelease(
16709
16779
  {
16710
16780
  detected: {
@@ -16732,7 +16802,7 @@ async function preparePiRuntimeSystem(input) {
16732
16802
  return "remedy" in updateGate && typeof updateGate.remedy === "string" ? updateGate : { kind: "blocked", reason: updateGate.reason, remedy: `Verificaci\xF3n offline del receipt Pi fall\xF3 (${updateGate.reason}); sin preflight ni cambios. Pi no qued\xF3 activado.` };
16733
16803
  }
16734
16804
  try {
16735
- fs39.mkdirSync(updateDownloadsDir, { recursive: true });
16805
+ fs40.mkdirSync(updateDownloadsDir, { recursive: true });
16736
16806
  } catch (error) {
16737
16807
  return {
16738
16808
  kind: "blocked",
@@ -16788,7 +16858,7 @@ async function preparePiRuntimeSystem(input) {
16788
16858
  };
16789
16859
  }
16790
16860
  const piExecutable = input.detected.executable;
16791
- if (typeof piExecutable !== "string" || piExecutable === "" || !path47.isAbsolute(piExecutable)) {
16861
+ if (typeof piExecutable !== "string" || piExecutable === "" || !path48.isAbsolute(piExecutable)) {
16792
16862
  return {
16793
16863
  kind: "blocked",
16794
16864
  reason: "pi-executable-missing",
@@ -16804,7 +16874,7 @@ async function preparePiRuntimeSystem(input) {
16804
16874
  }
16805
16875
  const homeDir = os6.homedir();
16806
16876
  const agentDir = userPaths(input.engramBin, piExecutable).codingAgentDir;
16807
- const downloadsDir = path47.join(dataDir(), "packages");
16877
+ const downloadsDir = path48.join(dataDir(), "packages");
16808
16878
  if (!isStrictChildPath(agentDir, homeDir)) {
16809
16879
  return {
16810
16880
  kind: "blocked",
@@ -16814,7 +16884,7 @@ async function preparePiRuntimeSystem(input) {
16814
16884
  }
16815
16885
  let preflightReceipt;
16816
16886
  try {
16817
- preflightReceipt = fs39.lstatSync(path47.join(dataDir(), "pi-receipt.json"), { throwIfNoEntry: false });
16887
+ preflightReceipt = fs40.lstatSync(path48.join(dataDir(), "pi-receipt.json"), { throwIfNoEntry: false });
16818
16888
  } catch (error) {
16819
16889
  if (error.code === "ENOENT") {
16820
16890
  preflightReceipt = void 0;
@@ -16829,7 +16899,7 @@ async function preparePiRuntimeSystem(input) {
16829
16899
  if (preflightReceipt === void 0) {
16830
16900
  let preflightEntry;
16831
16901
  try {
16832
- preflightEntry = fs39.lstatSync(path47.join(agentDir, "npm", "node_modules", "jorgex-pi"), {
16902
+ preflightEntry = fs40.lstatSync(path48.join(agentDir, "npm", "node_modules", "jorgex-pi"), {
16833
16903
  throwIfNoEntry: false
16834
16904
  });
16835
16905
  } catch (error) {
@@ -16852,7 +16922,7 @@ async function preparePiRuntimeSystem(input) {
16852
16922
  }
16853
16923
  }
16854
16924
  try {
16855
- fs39.mkdirSync(downloadsDir, { recursive: true });
16925
+ fs40.mkdirSync(downloadsDir, { recursive: true });
16856
16926
  } catch (error) {
16857
16927
  return {
16858
16928
  kind: "blocked",
@@ -16948,7 +17018,7 @@ async function runPiRuntimeSystem(input) {
16948
17018
  remedy: `${mismatch}; Pi no qued\xF3 activado y no se descarg\xF3 ni modific\xF3 nada.`
16949
17019
  };
16950
17020
  }
16951
- const settingsPath = path47.join(paths.codingAgentDir, "settings.json");
17021
+ const settingsPath = path48.join(paths.codingAgentDir, "settings.json");
16952
17022
  let settingsJson = readOptional(settingsPath, '{"packages":[]}');
16953
17023
  const receiptJson = readOptional(paths.receiptPath, null);
16954
17024
  const scopeKind = input.targetDir === void 0 ? "real" : "target-dir";
@@ -16991,8 +17061,8 @@ async function runPiRuntimeSystem(input) {
16991
17061
  };
16992
17062
  }
16993
17063
  try {
16994
- const freshEntry = path47.join(paths.codingAgentDir, "npm", "node_modules", "jorgex-pi");
16995
- if (fs39.lstatSync(freshEntry, { throwIfNoEntry: false }) !== void 0) {
17064
+ const freshEntry = path48.join(paths.codingAgentDir, "npm", "node_modules", "jorgex-pi");
17065
+ if (fs40.lstatSync(freshEntry, { throwIfNoEntry: false }) !== void 0) {
16996
17066
  return {
16997
17067
  kind: "blocked",
16998
17068
  reason: "unowned-entry",
@@ -17102,7 +17172,7 @@ async function runPiRuntimeSystem(input) {
17102
17172
  backupLegacyMigrationState(
17103
17173
  settingsPath,
17104
17174
  paths.receiptPath,
17105
- input.targetDir === void 0 ? void 0 : path47.join(path47.resolve(input.targetDir), "backups")
17175
+ input.targetDir === void 0 ? void 0 : path48.join(path48.resolve(input.targetDir), "backups")
17106
17176
  );
17107
17177
  } catch (error) {
17108
17178
  return {
@@ -17112,7 +17182,7 @@ async function runPiRuntimeSystem(input) {
17112
17182
  };
17113
17183
  }
17114
17184
  }
17115
- const homeDir = input.targetDir === void 0 ? os6.homedir() : path47.resolve(input.targetDir);
17185
+ const homeDir = input.targetDir === void 0 ? os6.homedir() : path48.resolve(input.targetDir);
17116
17186
  const agentDir = paths.codingAgentDir;
17117
17187
  const receiptPath = paths.receiptPath;
17118
17188
  const stageDir = prepared.stageDir;
@@ -17165,7 +17235,7 @@ async function runPiRuntimeSystem(input) {
17165
17235
  }
17166
17236
  if (input.operation === "update") {
17167
17237
  const engramBinForUpdate = input.engramBin;
17168
- if (engramBinForUpdate === null || !path47.isAbsolute(engramBinForUpdate)) {
17238
+ if (engramBinForUpdate === null || !path48.isAbsolute(engramBinForUpdate)) {
17169
17239
  return {
17170
17240
  kind: "blocked",
17171
17241
  reason: "engram-required",
@@ -17196,10 +17266,10 @@ async function runPiRuntimeSystem(input) {
17196
17266
  remedy: `${updateMismatch}; Pi no qued\xF3 activado y no se descarg\xF3 ni modific\xF3 nada.`
17197
17267
  };
17198
17268
  }
17199
- const updateSettingsPath = path47.join(paths.codingAgentDir, "settings.json");
17269
+ const updateSettingsPath = path48.join(paths.codingAgentDir, "settings.json");
17200
17270
  const updateScopeKind = input.targetDir === void 0 ? "real" : "target-dir";
17201
- const updateHomeDir = input.targetDir === void 0 ? os6.homedir() : path47.resolve(input.targetDir);
17202
- const updateDownloadsDir = input.targetDir === void 0 ? path47.join(dataDir(), "packages") : path47.join(path47.resolve(input.targetDir), "downloads");
17271
+ const updateHomeDir = input.targetDir === void 0 ? os6.homedir() : path48.resolve(input.targetDir);
17272
+ const updateDownloadsDir = input.targetDir === void 0 ? path48.join(dataDir(), "packages") : path48.join(path48.resolve(input.targetDir), "downloads");
17203
17273
  const stripUpdateNewline = (value) => value.endsWith("\n") ? value.slice(0, -1) : value;
17204
17274
  let updateSettingsRaw;
17205
17275
  let updateReceiptRaw;
@@ -17378,13 +17448,13 @@ async function runPiRuntimeSystem(input) {
17378
17448
  };
17379
17449
  }
17380
17450
  }
17381
- const packageRoot = path47.dirname(path47.dirname(paths.packageRunner));
17451
+ const packageRoot = path48.dirname(path48.dirname(paths.packageRunner));
17382
17452
  const writeReceipt = (receipt) => {
17383
17453
  writeText(paths.receiptPath, `${JSON.stringify(receipt, null, 2)}
17384
17454
  `);
17385
17455
  };
17386
17456
  if (input.operation === "sync") {
17387
- const settingsJson = readOptional(path47.join(paths.codingAgentDir, "settings.json"), '{"packages":[]}');
17457
+ const settingsJson = readOptional(path48.join(paths.codingAgentDir, "settings.json"), '{"packages":[]}');
17388
17458
  const receiptJson = readOptional(paths.receiptPath, null);
17389
17459
  if (receiptJson === null) {
17390
17460
  return {
@@ -17435,11 +17505,11 @@ async function runPiRuntimeSystem(input) {
17435
17505
  run: runProcess,
17436
17506
  verifyManagedArtifact: (receipt) => verifyCachedPiArtifact({
17437
17507
  receipt,
17438
- homeDir: input.targetDir === void 0 ? os6.homedir() : path47.resolve(input.targetDir),
17439
- downloadsDir: input.targetDir === void 0 ? path47.join(dataDir(), "packages") : path47.join(path47.resolve(input.targetDir), "downloads")
17508
+ homeDir: input.targetDir === void 0 ? os6.homedir() : path48.resolve(input.targetDir),
17509
+ downloadsDir: input.targetDir === void 0 ? path48.join(dataDir(), "packages") : path48.join(path48.resolve(input.targetDir), "downloads")
17440
17510
  }),
17441
- isPackageAbsent: () => !fs39.existsSync(packageRoot),
17442
- deleteReceipt: () => fs39.rmSync(paths.receiptPath, { force: true })
17511
+ isPackageAbsent: () => !fs40.existsSync(packageRoot),
17512
+ deleteReceipt: () => fs40.rmSync(paths.receiptPath, { force: true })
17443
17513
  }
17444
17514
  );
17445
17515
  }
@@ -17451,7 +17521,7 @@ async function runPiRuntimeSystem(input) {
17451
17521
  }
17452
17522
  }
17453
17523
  if (input.operation === "models") {
17454
- const settingsJson = readOptional(path47.join(paths.codingAgentDir, "settings.json"), '{"packages":[]}');
17524
+ const settingsJson = readOptional(path48.join(paths.codingAgentDir, "settings.json"), '{"packages":[]}');
17455
17525
  const receiptJson = readOptional(paths.receiptPath, null);
17456
17526
  if (receiptJson === null) {
17457
17527
  return {
@@ -17502,11 +17572,11 @@ async function runPiRuntimeSystem(input) {
17502
17572
  run: runProcess,
17503
17573
  verifyManagedArtifact: (receipt) => verifyCachedPiArtifact({
17504
17574
  receipt,
17505
- homeDir: input.targetDir === void 0 ? os6.homedir() : path47.resolve(input.targetDir),
17506
- downloadsDir: input.targetDir === void 0 ? path47.join(dataDir(), "packages") : path47.join(path47.resolve(input.targetDir), "downloads")
17575
+ homeDir: input.targetDir === void 0 ? os6.homedir() : path48.resolve(input.targetDir),
17576
+ downloadsDir: input.targetDir === void 0 ? path48.join(dataDir(), "packages") : path48.join(path48.resolve(input.targetDir), "downloads")
17507
17577
  }),
17508
- isPackageAbsent: () => !fs39.existsSync(packageRoot),
17509
- deleteReceipt: () => fs39.rmSync(paths.receiptPath, { force: true })
17578
+ isPackageAbsent: () => !fs40.existsSync(packageRoot),
17579
+ deleteReceipt: () => fs40.rmSync(paths.receiptPath, { force: true })
17510
17580
  }
17511
17581
  );
17512
17582
  }
@@ -17523,17 +17593,17 @@ async function runPiRuntimeSystem(input) {
17523
17593
  value,
17524
17594
  {
17525
17595
  backupSettings: () => createBackup(
17526
- [path47.join(paths.codingAgentDir, "settings.json")],
17596
+ [path48.join(paths.codingAgentDir, "settings.json")],
17527
17597
  "pi-package-uninstall",
17528
- input.targetDir === void 0 ? void 0 : path47.join(path47.resolve(input.targetDir), "backups")
17598
+ input.targetDir === void 0 ? void 0 : path48.join(path48.resolve(input.targetDir), "backups")
17529
17599
  ),
17530
17600
  run: runProcess,
17531
17601
  verifyManagedArtifact: (receipt) => verifyCachedPiArtifact({
17532
17602
  receipt,
17533
- homeDir: input.targetDir === void 0 ? os6.homedir() : path47.resolve(input.targetDir),
17534
- downloadsDir: input.targetDir === void 0 ? path47.join(dataDir(), "packages") : path47.join(path47.resolve(input.targetDir), "downloads")
17603
+ homeDir: input.targetDir === void 0 ? os6.homedir() : path48.resolve(input.targetDir),
17604
+ downloadsDir: input.targetDir === void 0 ? path48.join(dataDir(), "packages") : path48.join(path48.resolve(input.targetDir), "downloads")
17535
17605
  }),
17536
- readSettings: () => fs39.readFileSync(path47.join(paths.codingAgentDir, "settings.json"), "utf8"),
17606
+ readSettings: () => fs40.readFileSync(path48.join(paths.codingAgentDir, "settings.json"), "utf8"),
17537
17607
  verifyLegacyPackage: (receipt) => {
17538
17608
  const op = value;
17539
17609
  let effectiveEngram = op.engramBin;
@@ -17542,7 +17612,7 @@ async function runPiRuntimeSystem(input) {
17542
17612
  const engram = Reflect.get(receipt, "engram");
17543
17613
  if (engram === null || typeof engram !== "object" || Array.isArray(engram)) return false;
17544
17614
  const binary = Reflect.get(engram, "binary");
17545
- if (typeof binary !== "string" || binary === "" || !path47.isAbsolute(binary)) return false;
17615
+ if (typeof binary !== "string" || binary === "" || !path48.isAbsolute(binary)) return false;
17546
17616
  effectiveEngram = binary;
17547
17617
  }
17548
17618
  if (typeof effectiveEngram !== "string" || effectiveEngram === "") return false;
@@ -17566,17 +17636,17 @@ async function runPiRuntimeSystem(input) {
17566
17636
  }
17567
17637
  let currentReceiptRaw = null;
17568
17638
  try {
17569
- currentReceiptRaw = fs39.readFileSync(paths.receiptPath, "utf8");
17639
+ currentReceiptRaw = fs40.readFileSync(paths.receiptPath, "utf8");
17570
17640
  } catch {
17571
17641
  return { kind: "blocked", reason: "remove-failed" };
17572
17642
  }
17573
17643
  if (typeof op.receiptJson === "string" && currentReceiptRaw !== op.receiptJson) {
17574
17644
  return { kind: "blocked", reason: "receipt-untrusted" };
17575
17645
  }
17576
- const settingsPath = path47.join(paths.codingAgentDir, "settings.json");
17577
- const legacyEntry = path47.join(paths.codingAgentDir, "npm", "node_modules", "jorgex-pi");
17646
+ const settingsPath = path48.join(paths.codingAgentDir, "settings.json");
17647
+ const legacyEntry = path48.join(paths.codingAgentDir, "npm", "node_modules", "jorgex-pi");
17578
17648
  return deactivateVerifiedLegacyPiEntry({
17579
- homeDir: input.targetDir === void 0 ? os6.homedir() : path47.resolve(input.targetDir),
17649
+ homeDir: input.targetDir === void 0 ? os6.homedir() : path48.resolve(input.targetDir),
17580
17650
  agentDir: paths.codingAgentDir,
17581
17651
  receiptPath: paths.receiptPath,
17582
17652
  source,
@@ -17584,19 +17654,19 @@ async function runPiRuntimeSystem(input) {
17584
17654
  verify: () => {
17585
17655
  let entryStat = null;
17586
17656
  try {
17587
- entryStat = fs39.lstatSync(legacyEntry);
17657
+ entryStat = fs40.lstatSync(legacyEntry);
17588
17658
  } catch (error) {
17589
17659
  if (error.code !== "ENOENT") throw error;
17590
17660
  }
17591
17661
  if (entryStat !== null) throw new Error("managed entry still present after uninstall");
17592
17662
  let receiptStat = null;
17593
17663
  try {
17594
- receiptStat = fs39.lstatSync(paths.receiptPath);
17664
+ receiptStat = fs40.lstatSync(paths.receiptPath);
17595
17665
  } catch (error) {
17596
17666
  if (error.code !== "ENOENT") throw error;
17597
17667
  }
17598
17668
  if (receiptStat !== null) throw new Error("receipt still present after uninstall");
17599
- if (fs39.readFileSync(settingsPath, "utf8") !== nextSettings) {
17669
+ if (fs40.readFileSync(settingsPath, "utf8") !== nextSettings) {
17600
17670
  throw new Error("settings mismatch after uninstall");
17601
17671
  }
17602
17672
  }
@@ -17611,9 +17681,9 @@ async function runPiRuntimeSystem(input) {
17611
17681
  if (typeof mp.releaseDir !== "string" || typeof mp.linkPath !== "string" || typeof mp.backupDir !== "string") {
17612
17682
  return { kind: "blocked", reason: "remove-failed" };
17613
17683
  }
17614
- const settingsPath = path47.join(paths.codingAgentDir, "settings.json");
17684
+ const settingsPath = path48.join(paths.codingAgentDir, "settings.json");
17615
17685
  return deactivateVerifiedPiRelease({
17616
- homeDir: input.targetDir === void 0 ? os6.homedir() : path47.resolve(input.targetDir),
17686
+ homeDir: input.targetDir === void 0 ? os6.homedir() : path48.resolve(input.targetDir),
17617
17687
  agentDir: paths.codingAgentDir,
17618
17688
  receiptPath: paths.receiptPath,
17619
17689
  managedPackage: mp,
@@ -17621,33 +17691,33 @@ async function runPiRuntimeSystem(input) {
17621
17691
  verify: () => {
17622
17692
  let entryStat = null;
17623
17693
  try {
17624
- entryStat = fs39.lstatSync(mp.linkPath);
17694
+ entryStat = fs40.lstatSync(mp.linkPath);
17625
17695
  } catch (error) {
17626
17696
  if (error.code !== "ENOENT") throw error;
17627
17697
  }
17628
17698
  if (entryStat !== null) throw new Error("managed entry still present after uninstall");
17629
17699
  let releaseStat = null;
17630
17700
  try {
17631
- releaseStat = fs39.lstatSync(mp.releaseDir);
17701
+ releaseStat = fs40.lstatSync(mp.releaseDir);
17632
17702
  } catch (error) {
17633
17703
  if (error.code !== "ENOENT") throw error;
17634
17704
  }
17635
17705
  if (releaseStat !== null) throw new Error("managed release still present after uninstall");
17636
17706
  let receiptStat = null;
17637
17707
  try {
17638
- receiptStat = fs39.lstatSync(paths.receiptPath);
17708
+ receiptStat = fs40.lstatSync(paths.receiptPath);
17639
17709
  } catch (error) {
17640
17710
  if (error.code !== "ENOENT") throw error;
17641
17711
  }
17642
17712
  if (receiptStat !== null) throw new Error("receipt still present after uninstall");
17643
- if (fs39.readFileSync(settingsPath, "utf8") !== nextSettings) {
17713
+ if (fs40.readFileSync(settingsPath, "utf8") !== nextSettings) {
17644
17714
  throw new Error("settings mismatch after uninstall");
17645
17715
  }
17646
17716
  }
17647
17717
  });
17648
17718
  },
17649
- isPackageAbsent: () => !fs39.existsSync(packageRoot),
17650
- deleteReceipt: () => fs39.rmSync(paths.receiptPath, { force: true })
17719
+ isPackageAbsent: () => !fs40.existsSync(packageRoot),
17720
+ deleteReceipt: () => fs40.rmSync(paths.receiptPath, { force: true })
17651
17721
  }
17652
17722
  )
17653
17723
  };
@@ -17660,8 +17730,8 @@ init_pi();
17660
17730
  init_system_prompt_sections();
17661
17731
 
17662
17732
  // src/lib/pi-browser-contract.ts
17663
- import fs40 from "fs";
17664
- import path48 from "path";
17733
+ import fs41 from "fs";
17734
+ import path49 from "path";
17665
17735
  var CONTRACT_FILE = "browser-handoffs.v1.json";
17666
17736
  var MAX_CONTRACT_BYTES = 4 * 1024;
17667
17737
  function fail11(message) {
@@ -17672,23 +17742,23 @@ function validSchemas(value) {
17672
17742
  }
17673
17743
  function requirePiBrowserHandoffSchemas(packageRoot, required) {
17674
17744
  if (required.playwright === void 0 && required.devtools === void 0) return;
17675
- if (typeof packageRoot !== "string" || !path48.isAbsolute(packageRoot)) fail11("package root is not absolute");
17745
+ if (typeof packageRoot !== "string" || !path49.isAbsolute(packageRoot)) fail11("package root is not absolute");
17676
17746
  let realRoot;
17677
17747
  try {
17678
- realRoot = fs40.realpathSync(packageRoot);
17679
- if (!fs40.statSync(realRoot).isDirectory()) fail11("package root is not a directory");
17748
+ realRoot = fs41.realpathSync(packageRoot);
17749
+ if (!fs41.statSync(realRoot).isDirectory()) fail11("package root is not a directory");
17680
17750
  } catch {
17681
17751
  fail11("installed Pi package root is unavailable");
17682
17752
  }
17683
- const contractDir = path48.join(realRoot, "contract");
17684
- const file = path48.join(contractDir, CONTRACT_FILE);
17753
+ const contractDir = path49.join(realRoot, "contract");
17754
+ const file = path49.join(contractDir, CONTRACT_FILE);
17685
17755
  let raw;
17686
17756
  try {
17687
- const dirStat = fs40.lstatSync(contractDir);
17688
- const stat = fs40.lstatSync(file);
17757
+ const dirStat = fs41.lstatSync(contractDir);
17758
+ const stat = fs41.lstatSync(file);
17689
17759
  if (!dirStat.isDirectory() || dirStat.isSymbolicLink() || !stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_CONTRACT_BYTES) fail11("contract is not a bounded regular file");
17690
- if (fs40.realpathSync(file) !== file) fail11("contract path is not canonical");
17691
- raw = fs40.readFileSync(file);
17760
+ if (fs41.realpathSync(file) !== file) fail11("contract path is not canonical");
17761
+ raw = fs41.readFileSync(file);
17692
17762
  if (raw.byteLength > MAX_CONTRACT_BYTES || !Buffer.from(raw.toString("utf8"), "utf8").equals(raw)) {
17693
17763
  fail11("contract is not bounded UTF-8");
17694
17764
  }
@@ -17717,8 +17787,8 @@ function requirePiBrowserHandoffSchemas(packageRoot, required) {
17717
17787
 
17718
17788
  // src/lib/pi-managed-runtime.ts
17719
17789
  init_paths();
17720
- import fs41 from "fs";
17721
- import path49 from "path";
17790
+ import fs42 from "fs";
17791
+ import path50 from "path";
17722
17792
  function projectionOperation(operation) {
17723
17793
  return operation === "update" ? "sync" : operation;
17724
17794
  }
@@ -17876,7 +17946,7 @@ async function runManagedPiSystem(input) {
17876
17946
  const needsDevtoolsObservation = devtoolsMcpEnabled === true && input.operation !== "uninstall" && input.operation !== "models";
17877
17947
  let devtoolsMcpObservedVersion = null;
17878
17948
  let devtoolsVerifiedForPersist;
17879
- const devtoolsManagedStateDir = input.targetDir === void 0 ? dataDir() : path49.join(input.targetDir, "home", ".jorgex-stack");
17949
+ const devtoolsManagedStateDir = input.targetDir === void 0 ? dataDir() : path50.join(input.targetDir, "home", ".jorgex-stack");
17880
17950
  if (needsDevtoolsObservation) {
17881
17951
  if (input.targetDir !== void 0) {
17882
17952
  devtoolsMcpObservedVersion = isValidObservedVersion(injectedDevtoolsObserved) ? { version: injectedDevtoolsObserved.version, integrity: injectedDevtoolsObserved.integrity } : null;
@@ -17924,8 +17994,8 @@ async function runManagedPiSystem(input) {
17924
17994
  if (needsDevtoolsObservation) {
17925
17995
  try {
17926
17996
  if (input.targetDir !== void 0) {
17927
- const target = fs41.lstatSync(input.targetDir);
17928
- const home = fs41.lstatSync(path49.join(input.targetDir, "home"));
17997
+ const target = fs42.lstatSync(input.targetDir);
17998
+ const home = fs42.lstatSync(path50.join(input.targetDir, "home"));
17929
17999
  if (!target.isDirectory() || target.isSymbolicLink() || !home.isDirectory() || home.isSymbolicLink()) {
17930
18000
  throw new Error("HOME del target Pi no es un directorio real aislado");
17931
18001
  }
@@ -17949,7 +18019,7 @@ async function runManagedPiSystem(input) {
17949
18019
  const playwrightCapabilityEffective = playwrightCapability?.effective === true;
17950
18020
  const playwrightCliEnabled = input.targetDir === void 0 && supportsPlaywright && selectedPlaywright && playwrightCapabilityEffective;
17951
18021
  const playwrightManagedStateDir = playwrightCliEnabled && input.operation !== "uninstall" && input.operation !== "models" ? dataDir() : void 0;
17952
- const playwrightDispatcherPath = playwrightManagedStateDir === void 0 ? void 0 : path49.join(path49.dirname(stackRoot()), "dist", "browser-playwright.js");
18022
+ const playwrightDispatcherPath = playwrightManagedStateDir === void 0 ? void 0 : path50.join(path50.dirname(stackRoot()), "dist", "browser-playwright.js");
17953
18023
  let effectivePackageSource = PI_RUNTIME_CANDIDATE.package.source;
17954
18024
  const projectionInput = {
17955
18025
  writingStyle,
@@ -18006,7 +18076,7 @@ async function runManagedPiSystem(input) {
18006
18076
  },
18007
18077
  runProjection(operation) {
18008
18078
  if (playwrightCliEnabled || devtoolsMcpEnabled) {
18009
- const packageRoot = path49.join(path49.dirname(piSystemPromptFile(input.targetDir)), "npm", "node_modules", "jorgex-pi");
18079
+ const packageRoot = path50.join(path50.dirname(piSystemPromptFile(input.targetDir)), "npm", "node_modules", "jorgex-pi");
18010
18080
  try {
18011
18081
  requirePiBrowserHandoffSchemas(packageRoot, {
18012
18082
  ...playwrightCliEnabled ? { playwright: 2 } : {},
@@ -18059,7 +18129,7 @@ init_fsx();
18059
18129
 
18060
18130
  // src/lib/quality-runner.ts
18061
18131
  init_detect();
18062
- import path50 from "path";
18132
+ import path51 from "path";
18063
18133
  import { spawn as spawn2, spawnSync as spawnSync6 } from "child_process";
18064
18134
 
18065
18135
  // src/lib/quality-policy.ts
@@ -18652,7 +18722,7 @@ function killProcessTree(child) {
18652
18722
  if (pid === void 0) return;
18653
18723
  if (process.platform === "win32") {
18654
18724
  const systemRoot = process.env.SystemRoot ?? process.env.WINDIR ?? "C:\\Windows";
18655
- const taskkill = path50.join(systemRoot, "System32", "taskkill.exe");
18725
+ const taskkill = path51.join(systemRoot, "System32", "taskkill.exe");
18656
18726
  const result = spawnSync6(taskkill, ["/pid", String(pid), "/t", "/f"], {
18657
18727
  shell: false,
18658
18728
  stdio: "ignore",
@@ -18898,9 +18968,9 @@ async function runQualityPlan(input) {
18898
18968
  }
18899
18969
 
18900
18970
  // src/lib/engram-install.ts
18901
- import fs42 from "fs";
18971
+ import fs43 from "fs";
18902
18972
  import os7 from "os";
18903
- import path51 from "path";
18973
+ import path52 from "path";
18904
18974
  import { execFileSync as execFileSync8 } from "child_process";
18905
18975
  import { createHash as createHash11 } from "crypto";
18906
18976
  var MAX_ENGRAM_ARCHIVE_BYTES = 64 * 1024 * 1024;
@@ -18909,16 +18979,16 @@ var DIGEST_RE = /^sha256:[0-9a-f]{64}$/;
18909
18979
  async function installMissingEngram(options = {}) {
18910
18980
  const platform = options.platform ?? process.platform;
18911
18981
  const homeDir = options.homeDir ?? os7.homedir();
18912
- if (!path51.isAbsolute(homeDir)) return { ok: false, reason: "El directorio personal debe ser absoluto." };
18982
+ if (!path52.isAbsolute(homeDir)) return { ok: false, reason: "El directorio personal debe ser absoluto." };
18913
18983
  const binaryName = platform === "win32" ? "engram.exe" : "engram";
18914
- const bin = path51.join(homeDir, ".local", "bin", binaryName);
18984
+ const bin = path52.join(homeDir, ".local", "bin", binaryName);
18915
18985
  let staging;
18916
18986
  let outcome;
18917
18987
  try {
18918
- const existing = fs42.lstatSync(bin, { throwIfNoEntry: false });
18988
+ const existing = fs43.lstatSync(bin, { throwIfNoEntry: false });
18919
18989
  if (existing) {
18920
- if (!fs42.statSync(bin).isFile()) throw new Error(`El destino Engram no es un archivo: ${bin}`);
18921
- fs42.accessSync(bin, platform === "win32" ? fs42.constants.F_OK : fs42.constants.X_OK);
18990
+ if (!fs43.statSync(bin).isFile()) throw new Error(`El destino Engram no es un archivo: ${bin}`);
18991
+ fs43.accessSync(bin, platform === "win32" ? fs43.constants.F_OK : fs43.constants.X_OK);
18922
18992
  outcome = { ok: true, bin };
18923
18993
  } else {
18924
18994
  const fetchFn = options.fetch ?? globalThis.fetch;
@@ -19031,19 +19101,19 @@ async function installMissingEngram(options = {}) {
19031
19101
  if (size !== approvedSize || createHash11("sha256").update(archive).digest("hex") !== approvedSha) {
19032
19102
  throw new Error("Engram: tama\xF1o o hash SHA-256 no coincide con el artefacto aprobado.");
19033
19103
  }
19034
- fs42.mkdirSync(path51.dirname(bin), { recursive: true });
19035
- staging = fs42.mkdtempSync(path51.join(path51.dirname(bin), ".engram-install-"));
19036
- const archivePath = path51.join(staging, expectedName);
19037
- fs42.writeFileSync(archivePath, archive, { flag: "wx", mode: 384 });
19104
+ fs43.mkdirSync(path52.dirname(bin), { recursive: true });
19105
+ staging = fs43.mkdtempSync(path52.join(path52.dirname(bin), ".engram-install-"));
19106
+ const archivePath = path52.join(staging, expectedName);
19107
+ fs43.writeFileSync(archivePath, archive, { flag: "wx", mode: 384 });
19038
19108
  const binary = execFileSync8(resolveTarBin(), ["-xOf", archivePath, binaryName], {
19039
19109
  maxBuffer: 64 * 1024 * 1024,
19040
19110
  timeout: 3e4,
19041
19111
  stdio: ["ignore", "pipe", "pipe"]
19042
19112
  });
19043
19113
  if (binary.length === 0) throw new Error("El artefacto Engram no contiene un binario v\xE1lido.");
19044
- const stagedBin = path51.join(staging, binaryName);
19045
- fs42.writeFileSync(stagedBin, binary, { flag: "wx", mode: 493 });
19046
- fs42.linkSync(stagedBin, bin);
19114
+ const stagedBin = path52.join(staging, binaryName);
19115
+ fs43.writeFileSync(stagedBin, binary, { flag: "wx", mode: 493 });
19116
+ fs43.linkSync(stagedBin, bin);
19047
19117
  outcome = { ok: true, bin };
19048
19118
  }
19049
19119
  } catch (error) {
@@ -19051,7 +19121,7 @@ async function installMissingEngram(options = {}) {
19051
19121
  }
19052
19122
  if (staging !== void 0) {
19053
19123
  try {
19054
- fs42.rmSync(staging, { recursive: true, force: true });
19124
+ fs43.rmSync(staging, { recursive: true, force: true });
19055
19125
  } catch (cleanupError) {
19056
19126
  const cleanupMsg = cleanupError instanceof Error ? cleanupError.message : String(cleanupError);
19057
19127
  if (outcome !== void 0 && outcome.ok) {
@@ -19447,7 +19517,7 @@ async function runSelectedPi(options) {
19447
19517
  return 1;
19448
19518
  }
19449
19519
  if (detected.version === null) {
19450
- console.error("No se pudo verificar la versi\xF3n instalada de Pi sin ejecutarlo; revisa la instalaci\xF3n de Pi.");
19520
+ console.error(`No se pudo verificar la versi\xF3n instalada de Pi sin ejecutarlo: ${detected.versionDiagnostic ?? "causa desconocida"}. Repara Pi con su instalador oficial antes de reintentar.`);
19451
19521
  return 1;
19452
19522
  }
19453
19523
  let engramBin = resolvedEngramBin === void 0 ? resolvePiEngramBin(targetDir) : resolvedEngramBin;
@@ -19618,7 +19688,7 @@ Flags disponibles: jorgex-stack --help`
19618
19688
  return;
19619
19689
  }
19620
19690
  try {
19621
- const plan = JSON.parse(fs43.readFileSync(flags.positional[0], "utf8"));
19691
+ const plan = JSON.parse(fs44.readFileSync(flags.positional[0], "utf8"));
19622
19692
  const result = await runQualityPlan(plan);
19623
19693
  const serialized = serializeQualityReceipt(result.receipt);
19624
19694
  if (flags.receipt === void 0) process.stdout.write(`${serialized}