jorgex-stack 1.9.59 → 1.9.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -12,32 +12,27 @@ import {
12
12
  inspectOpencodePluginFile,
13
13
  opencodeAdapter,
14
14
  shouldRetireLegacyEngram
15
- } from "./chunk-M6QX2F3A.js";
15
+ } from "./chunk-BSHTDTJL.js";
16
16
  import {
17
17
  claudeCodeAdapter
18
- } from "./chunk-NNPFC6QV.js";
18
+ } from "./chunk-4USZMJ3I.js";
19
19
  import {
20
20
  codexAdapter
21
- } from "./chunk-GOLJ5PA3.js";
21
+ } from "./chunk-KKN4OYHD.js";
22
22
  import {
23
23
  DEFAULT_MODEL_MAP,
24
24
  DEVTOOLS_MCP_SERVER,
25
+ LEGACY_SYSTEM_PROMPT_SECTIONS,
25
26
  SYSTEM_PROMPT_SECTIONS,
26
27
  assertSystemPromptFile,
27
28
  assertSystemPromptMarkers,
28
- copyFile,
29
- createBackup,
30
29
  detectClaudeCode,
31
30
  detectCodex,
32
31
  detectEngram,
33
32
  detectOpenCode,
34
33
  engramVersion,
35
- ensureDir,
36
34
  ensureModelMapFile,
37
35
  hasHealthyManagedMarkdownMarkers,
38
- isContainedIn,
39
- listBackups,
40
- listFilesRecursive,
41
36
  loadCanonicalAgents,
42
37
  loadCanonicalHooks,
43
38
  loadCanonicalMcp,
@@ -46,26 +41,37 @@ import {
46
41
  lookPath,
47
42
  modelMapFile,
48
43
  planDetectedBinCommand,
49
- pruneEmptyDirs,
50
44
  readSystemPromptFile,
51
- readTextIfExists,
52
45
  removeMarkdownSection,
53
46
  removeSystemPromptSections,
54
47
  resolveAgentModel,
55
- restoreBackup,
56
48
  runDetectedBin,
49
+ stripLeadingHtmlComments,
50
+ upsertMarkdownSection
51
+ } from "./chunk-66WVKOU4.js";
52
+ import {
53
+ piAdapter,
54
+ piSystemPromptFile
55
+ } from "./chunk-2CBCBOP7.js";
56
+ import {
57
+ copyFile,
58
+ createBackup,
59
+ ensureDir,
60
+ isContainedIn,
61
+ listBackups,
62
+ listFilesRecursive,
63
+ pruneEmptyDirs,
64
+ readTextIfExists,
65
+ restoreBackup,
57
66
  runOfficialSetupIfNeeded,
58
67
  sameFileContent,
59
68
  shouldRunOfficialSetup,
60
- stripLeadingHtmlComments,
61
- upsertMarkdownSection,
62
69
  validateOfficialSetupDestination,
63
70
  writeText
64
- } from "./chunk-KB5IQEKL.js";
71
+ } from "./chunk-B76ZJXXD.js";
65
72
  import {
66
73
  HOME,
67
74
  dataDir,
68
- samePath,
69
75
  stackRoot
70
76
  } from "./chunk-NQZVJFV2.js";
71
77
 
@@ -355,7 +361,6 @@ function planSystemPrompt(adapter, ctx) {
355
361
  );
356
362
  const modules = {
357
363
  "system-prompt": composeProgrammaticSystemPrompt(ctx.stackDir, readModule("AGENTS.md"), ctx.mode),
358
- "engram-protocol": adapter.injectEngramProtocol(ctx) ? readModule("engram-protocol.md") : void 0,
359
364
  context7: readModule("context7.md"),
360
365
  playwright: ctx.playwrightCliEnabled ? readModule("browser-playwright.md") : void 0,
361
366
  "chrome-devtools": ctx.enabledMcpServers?.has(DEVTOOLS_MCP_SERVER) ? readModule("browser-chrome-devtools.md") : void 0,
@@ -367,6 +372,9 @@ function planSystemPrompt(adapter, ctx) {
367
372
  const body = sections[section];
368
373
  content = body ? upsertMarkdownSection(content, section, body) : removeMarkdownSection(content, section);
369
374
  }
375
+ for (const section of LEGACY_SYSTEM_PROMPT_SECTIONS) {
376
+ content = removeMarkdownSection(content, section);
377
+ }
370
378
  return [{ kind: "write", target, content }];
371
379
  }
372
380
 
@@ -457,12 +465,6 @@ function planPlugins(adapter, ctx) {
457
465
  if (content.includes('"{{ENGRAM_BIN}}"')) {
458
466
  content = content.replace(/"\{\{ENGRAM_BIN\}\}"/g, JSON.stringify(ctx.engramBin ?? "engram"));
459
467
  }
460
- if (content.includes('"{{ENGRAM_PROTOCOL}}"')) {
461
- const protocol = stripLeadingHtmlComments(
462
- fs7.readFileSync(path9.join(ctx.stackDir, "system-prompt", "engram-protocol.md"), "utf8").replace(/\r\n/g, "\n")
463
- );
464
- content = content.replace(/"\{\{ENGRAM_PROTOCOL\}\}"/g, JSON.stringify(protocol));
465
- }
466
468
  content = content.replace(/(from\s+["'])(\.{1,2}\/[^"']+?)\.js(["'])/g, "$1$2.ts$3");
467
469
  if (content === raw) return { kind: "copy", source: sourceFile, target };
468
470
  return { kind: "write", target, content };
@@ -1491,52 +1493,16 @@ async function runInstall(opts) {
1491
1493
 
1492
1494
  // src/uninstall.ts
1493
1495
  import fs12 from "fs";
1494
- import path16 from "path";
1496
+ import path15 from "path";
1495
1497
  import * as p2 from "@clack/prompts";
1496
1498
 
1497
1499
  // src/lib/pi-projection-lifecycle.ts
1498
1500
  import fs11 from "fs";
1499
- import path15 from "path";
1501
+ import path14 from "path";
1500
1502
  import { createHash } from "crypto";
1501
1503
 
1502
- // src/adapters/pi.ts
1503
- import path13 from "path";
1504
- function piSystemPromptFile(targetDir) {
1505
- const configDir = targetDir === void 0 ? process.env.PI_CODING_AGENT_DIR ?? path13.join(HOME, ".pi", "agent") : path13.join(path13.resolve(targetDir), "pi-agent");
1506
- return path13.join(configDir, "AGENTS.md");
1507
- }
1508
- var piAdapter = {
1509
- id: "pi",
1510
- paths(configDir) {
1511
- const piConfigDir = path13.dirname(piSystemPromptFile());
1512
- const agentsHome = samePath(configDir, piConfigDir) ? HOME : path13.join(path13.dirname(configDir), "home");
1513
- return {
1514
- systemPromptFile: path13.join(configDir, "AGENTS.md"),
1515
- agentsDir: path13.join(configDir, "agents"),
1516
- skillsDir: path13.join(agentsHome, ".agents", "skills"),
1517
- commandsDir: path13.join(configDir, "prompts"),
1518
- pluginsDir: null,
1519
- scriptsDir: path13.join(configDir, "scripts"),
1520
- outputStylesDir: null,
1521
- profilesDir: null
1522
- };
1523
- },
1524
- renderCommand(file, content) {
1525
- return { file, content: content.replace(/\{\{input\}\}/g, "$ARGUMENTS") };
1526
- },
1527
- injectEngramProtocol() {
1528
- return true;
1529
- },
1530
- // La guía Context7 se habilita al adoptar su registro HTTP en Pi.
1531
- adaptSystemPromptSections(sections) {
1532
- const modular = { ...sections };
1533
- delete modular.context7;
1534
- return modular;
1535
- }
1536
- };
1537
-
1538
1504
  // src/lib/pi-package-lifecycle.ts
1539
- import path14 from "path";
1505
+ import path13 from "path";
1540
1506
  var REQUIRED_CAPABILITIES = /* @__PURE__ */ new Set([
1541
1507
  "foundation-contract-v1",
1542
1508
  "runner-json-v1",
@@ -1688,7 +1654,7 @@ function parseReceiptShape(receiptJson) {
1688
1654
  return null;
1689
1655
  }
1690
1656
  if (engram === void 0) return "upgrade-required";
1691
- if (engram === null || typeof engram !== "object" || Array.isArray(engram) || typeof Reflect.get(engram, "binary") !== "string" || !path14.isAbsolute(Reflect.get(engram, "binary"))) {
1657
+ if (engram === null || typeof engram !== "object" || Array.isArray(engram) || typeof Reflect.get(engram, "binary") !== "string" || !path13.isAbsolute(Reflect.get(engram, "binary"))) {
1692
1658
  return null;
1693
1659
  }
1694
1660
  return parsed;
@@ -1725,7 +1691,7 @@ function planPiPackageLifecycle(input) {
1725
1691
  if (input.receiptJson !== null) {
1726
1692
  const parsedReceipt = parseReceipt(input.receiptJson, input.candidate, {
1727
1693
  kind: input.scope.kind,
1728
- codingAgentDir: path14.resolve(input.scope.codingAgentDir)
1694
+ codingAgentDir: path13.resolve(input.scope.codingAgentDir)
1729
1695
  }, input.engramBin);
1730
1696
  if (parsedReceipt === "upgrade-required") return blocked(input, "receipt-upgrade-required");
1731
1697
  if (parsedReceipt === null) return blocked(input, "receipt-corrupt");
@@ -1760,7 +1726,7 @@ function planPiPackageLifecycle(input) {
1760
1726
  },
1761
1727
  receipt: expectedReceipt(input.candidate, "installing", {
1762
1728
  kind: input.scope.kind,
1763
- codingAgentDir: path14.resolve(input.scope.codingAgentDir)
1729
+ codingAgentDir: path13.resolve(input.scope.codingAgentDir)
1764
1730
  }, input.engramBin),
1765
1731
  ownership: ownership(true)
1766
1732
  };
@@ -1775,7 +1741,7 @@ function parseRunnerRecord(stdout, stderr, command, candidate, packageRunner) {
1775
1741
  const parsed = JSON.parse(body);
1776
1742
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return null;
1777
1743
  const record = parsed;
1778
- if (record.schemaVersion !== candidate.contract.runner.schemaVersion || record.command !== command || record.ok !== true || record.package === null || typeof record.package !== "object" || record.package.name !== candidate.package.name || record.package.version !== candidate.package.version || typeof record.package.root !== "string" || !path14.isAbsolute(record.package.root) || path14.resolve(packageRunner) !== path14.resolve(record.package.root, "bin", "jorgex-pi.mjs")) {
1744
+ if (record.schemaVersion !== candidate.contract.runner.schemaVersion || record.command !== command || record.ok !== true || record.package === null || typeof record.package !== "object" || record.package.name !== candidate.package.name || record.package.version !== candidate.package.version || typeof record.package.root !== "string" || !path13.isAbsolute(record.package.root) || path13.resolve(packageRunner) !== path13.resolve(record.package.root, "bin", "jorgex-pi.mjs")) {
1779
1745
  return null;
1780
1746
  }
1781
1747
  return record;
@@ -1923,10 +1889,10 @@ function validateOwnedOperationState(input) {
1923
1889
  }))) {
1924
1890
  return { kind: "blocked", reason: "receipt-untrusted" };
1925
1891
  }
1926
- if (receipt.scope.kind !== (input.paths.targetDir ? "target-dir" : "real") || path14.resolve(receipt.scope.codingAgentDir) !== path14.resolve(input.paths.codingAgentDir)) {
1892
+ if (receipt.scope.kind !== (input.paths.targetDir ? "target-dir" : "real") || path13.resolve(receipt.scope.codingAgentDir) !== path13.resolve(input.paths.codingAgentDir)) {
1927
1893
  return { kind: "blocked", reason: "source-divergent" };
1928
1894
  }
1929
- if (input.engramBin !== null && path14.resolve(receipt.engram.binary) !== path14.resolve(input.engramBin)) {
1895
+ if (input.engramBin !== null && path13.resolve(receipt.engram.binary) !== path13.resolve(input.engramBin)) {
1930
1896
  return { kind: "blocked", reason: "receipt-corrupt" };
1931
1897
  }
1932
1898
  const source = receipt.candidate.package.source;
@@ -2033,7 +1999,7 @@ var RETIRED_PLAYWRIGHT_FILES = [
2033
1999
  "references/video-recording.md"
2034
2000
  ];
2035
2001
  function retiredPlaywrightFiles(scope) {
2036
- return RETIRED_PLAYWRIGHT_FILES.map((file) => path15.resolve(scope.home, ".agents", "skills", "playwright-cli", file));
2002
+ return RETIRED_PLAYWRIGHT_FILES.map((file) => path14.resolve(scope.home, ".agents", "skills", "playwright-cli", file));
2037
2003
  }
2038
2004
  function handoffEnabled(input, kind) {
2039
2005
  return (kind === "devtools" ? input.devtoolsMcpEnabled : input.playwrightHandoffEnabled) === true;
@@ -2042,18 +2008,18 @@ var preparedPiProjectionUninstalls = /* @__PURE__ */ new WeakMap();
2042
2008
  function projectionScope(scope) {
2043
2009
  return {
2044
2010
  ...scope,
2045
- settingsFile: path15.join(scope.codingAgentDir, "settings.json")
2011
+ settingsFile: path14.join(scope.codingAgentDir, "settings.json")
2046
2012
  };
2047
2013
  }
2048
2014
  function isInside(root, file) {
2049
- const relative = path15.relative(path15.resolve(root), path15.resolve(file));
2050
- return relative === "" || relative !== ".." && !relative.startsWith(`..${path15.sep}`) && !path15.isAbsolute(relative);
2015
+ const relative = path14.relative(path14.resolve(root), path14.resolve(file));
2016
+ return relative === "" || relative !== ".." && !relative.startsWith(`..${path14.sep}`) && !path14.isAbsolute(relative);
2051
2017
  }
2052
2018
  function isManagedPath(scope, file) {
2053
2019
  return isInside(scope.home, file) || isInside(scope.codingAgentDir, file);
2054
2020
  }
2055
2021
  function isAllowedPath(scope, file) {
2056
- return isManagedPath(scope, file) || path15.resolve(file) === path15.resolve(scope.receiptFile);
2022
+ return isManagedPath(scope, file) || path14.resolve(file) === path14.resolve(scope.receiptFile);
2057
2023
  }
2058
2024
  function projectedPiAdapter(scope) {
2059
2025
  const paths = piAdapter.paths(scope.codingAgentDir);
@@ -2061,7 +2027,7 @@ function projectedPiAdapter(scope) {
2061
2027
  ...piAdapter,
2062
2028
  paths: () => ({
2063
2029
  ...paths,
2064
- skillsDir: path15.join(scope.home, ".agents", "skills")
2030
+ skillsDir: path14.join(scope.home, ".agents", "skills")
2065
2031
  })
2066
2032
  };
2067
2033
  }
@@ -2105,7 +2071,7 @@ function projectionPlan(input, scope, includePrompt = true) {
2105
2071
  return actions;
2106
2072
  }
2107
2073
  function handoffPath(scope, kind) {
2108
- return path15.resolve(scope.codingAgentDir, "jorgex-pi", `${kind}.v1.json`);
2074
+ return path14.resolve(scope.codingAgentDir, "jorgex-pi", `${kind}.v1.json`);
2109
2075
  }
2110
2076
  function contentHash(content) {
2111
2077
  return createHash("sha256").update(content).digest("hex");
@@ -2118,7 +2084,7 @@ function hasActionDrift(action, deps) {
2118
2084
  }
2119
2085
  function applyActions(actions, deps, handoffs = []) {
2120
2086
  for (const action of actions) {
2121
- const handoff = handoffs.find((entry) => path15.resolve(action.target) === entry.file);
2087
+ const handoff = handoffs.find((entry) => path14.resolve(action.target) === entry.file);
2122
2088
  if (handoff) {
2123
2089
  try {
2124
2090
  if (deps.readText(handoff.file) !== handoff.previous) return handoffConflict(handoff.kind, handoff.file);
@@ -2138,9 +2104,9 @@ function assertPlanContained(plan, scope) {
2138
2104
  }
2139
2105
  }
2140
2106
  function receiptFor(plan, scope) {
2141
- const systemPrompt = path15.join(scope.codingAgentDir, "AGENTS.md");
2107
+ const systemPrompt = path14.join(scope.codingAgentDir, "AGENTS.md");
2142
2108
  const owned = [...new Set(
2143
- plan.map((action) => path15.resolve(action.target)).filter((target) => target !== systemPrompt)
2109
+ plan.map((action) => path14.resolve(action.target)).filter((target) => target !== systemPrompt)
2144
2110
  )];
2145
2111
  const receipt = {
2146
2112
  schemaVersion: 1,
@@ -2153,7 +2119,7 @@ function receiptFor(plan, scope) {
2153
2119
  owned
2154
2120
  };
2155
2121
  for (const kind of HANDOFF_KINDS) {
2156
- const action = plan.find((entry) => path15.resolve(entry.target) === handoffPath(scope, kind));
2122
+ const action = plan.find((entry) => path14.resolve(entry.target) === handoffPath(scope, kind));
2157
2123
  if (action) receipt[kind] = { sha256: contentHash(canonicalActionContent(action)) };
2158
2124
  }
2159
2125
  return receipt;
@@ -2194,7 +2160,7 @@ function parseReceipt2(raw, expected) {
2194
2160
  if (matches(expectedOwned)) return { schemaVersion: 1, scope: expected.scope, owned: expectedOwned, ...digests };
2195
2161
  const retired = retiredPlaywrightFiles(expected.scope);
2196
2162
  if (retired.some((file) => expectedOwned.includes(file))) return null;
2197
- const skillsRoot = `${path15.resolve(expected.scope.home, ".agents", "skills")}${path15.sep}`;
2163
+ const skillsRoot = `${path14.resolve(expected.scope.home, ".agents", "skills")}${path14.sep}`;
2198
2164
  const insertion = expectedOwned.findIndex((file) => !file.startsWith(skillsRoot) || file > retired[0]);
2199
2165
  const legacyOwned = [...expectedOwned];
2200
2166
  legacyOwned.splice(insertion === -1 ? legacyOwned.length : insertion, 0, ...retired);
@@ -2213,8 +2179,8 @@ function realPiProjectionScope() {
2213
2179
  return {
2214
2180
  kind: "real",
2215
2181
  home: HOME,
2216
- codingAgentDir: path15.dirname(piSystemPromptFile()),
2217
- receiptFile: path15.join(dataDir(), "pi-projection-receipt.json")
2182
+ codingAgentDir: path14.dirname(piSystemPromptFile()),
2183
+ receiptFile: path14.join(dataDir(), "pi-projection-receipt.json")
2218
2184
  };
2219
2185
  }
2220
2186
  function readTextOnlyIfMissing(file) {
@@ -2252,13 +2218,13 @@ function manifestOwned(manifest) {
2252
2218
  return new Set([
2253
2219
  ...manifest.runtimes.codex?.owned ?? [],
2254
2220
  ...manifest.runtimes.opencode?.owned ?? []
2255
- ].map((file) => path15.resolve(file)));
2221
+ ].map((file) => path14.resolve(file)));
2256
2222
  }
2257
2223
  function withoutManagedPromptSections(content) {
2258
2224
  return removeSystemPromptSections(content);
2259
2225
  }
2260
2226
  function uniquePaths(paths) {
2261
- return [...new Set(paths.map((file) => path15.resolve(file)))];
2227
+ return [...new Set(paths.map((file) => path14.resolve(file)))];
2262
2228
  }
2263
2229
  function blocked2(reason, paths, remedy) {
2264
2230
  return { kind: "blocked", reason, paths: uniquePaths(paths), remedy };
@@ -2365,7 +2331,7 @@ function preparePiProjectionUninstall(input, deps) {
2365
2331
  }
2366
2332
  const scope = projectionScope(input.scope);
2367
2333
  const expectedReceipt2 = expectedProjectionReceipt(input, scope);
2368
- const prompt = path15.join(scope.codingAgentDir, "AGENTS.md");
2334
+ const prompt = path14.join(scope.codingAgentDir, "AGENTS.md");
2369
2335
  let existingPrompt;
2370
2336
  try {
2371
2337
  existingPrompt = deps.readText(prompt);
@@ -2378,7 +2344,7 @@ function preparePiProjectionUninstall(input, deps) {
2378
2344
  return blocked2("projection-prompt-markers", [prompt], error instanceof Error ? error.message : String(error));
2379
2345
  }
2380
2346
  const promptContent = existingPrompt === null ? null : withoutManagedPromptSections(existingPrompt);
2381
- const promptUpdate = promptContent === null || promptContent === existingPrompt ? null : { file: path15.resolve(prompt), content: promptContent };
2347
+ const promptUpdate = promptContent === null || promptContent === existingPrompt ? null : { file: path14.resolve(prompt), content: promptContent };
2382
2348
  const receiptRead = readProjectionReceipt(scope.receiptFile, deps);
2383
2349
  if (receiptRead.kind === "unreadable") return receiptUnreadable(scope.receiptFile);
2384
2350
  let ownedToRemove = [];
@@ -2396,7 +2362,7 @@ function preparePiProjectionUninstall(input, deps) {
2396
2362
  return cleanupFailure([scope.receiptFile]);
2397
2363
  }
2398
2364
  ownedToRemove = receipt.owned.filter((owned) => !retained.has(owned));
2399
- receiptFile = path15.resolve(scope.receiptFile);
2365
+ receiptFile = path14.resolve(scope.receiptFile);
2400
2366
  backupTargets = [...backupTargets, ...receipt.owned, receiptFile];
2401
2367
  }
2402
2368
  const handoffs = [];
@@ -2474,16 +2440,16 @@ function runPiProjectionLifecycle(input, deps) {
2474
2440
  const prepared = preparePiProjectionUninstall(input, deps);
2475
2441
  return prepared.kind === "blocked" ? prepared : completePiProjectionUninstall(prepared.plan, deps);
2476
2442
  }
2477
- const prompt = path15.join(scope.codingAgentDir, "AGENTS.md");
2443
+ const prompt = path14.join(scope.codingAgentDir, "AGENTS.md");
2478
2444
  try {
2479
2445
  assertSystemPromptMarkers(deps.readText(prompt), prompt);
2480
2446
  } catch (error) {
2481
2447
  return blocked2("projection-prompt-markers", [prompt], error instanceof Error ? error.message : String(error));
2482
2448
  }
2483
- if (input.devtoolsMcpEnabled && (!input.pnpmBin || !path15.isAbsolute(input.pnpmBin))) {
2449
+ if (input.devtoolsMcpEnabled && (!input.pnpmBin || !path14.isAbsolute(input.pnpmBin))) {
2484
2450
  return blocked2("projection-devtools-command", [handoffPath(scope, "devtools")], "DevTools requiere un ejecutable pnpm absoluto disponible en PATH.");
2485
2451
  }
2486
- if (input.playwrightHandoffEnabled && (!input.playwrightCliCommand || !path15.isAbsolute(input.playwrightCliCommand) || /[\u0000-\u001f\u007f]/.test(input.playwrightCliCommand))) {
2452
+ if (input.playwrightHandoffEnabled && (!input.playwrightCliCommand || !path14.isAbsolute(input.playwrightCliCommand) || /[\u0000-\u001f\u007f]/.test(input.playwrightCliCommand))) {
2487
2453
  return blocked2("projection-playwright-command", [handoffPath(scope, "playwright")], "Playwright requiere un ejecutable absoluto verificado. Abre una terminal nueva tras pnpm setup y reintenta install --playwright.");
2488
2454
  }
2489
2455
  const plan = projectionPlan(input, scope);
@@ -2496,12 +2462,12 @@ function runPiProjectionLifecycle(input, deps) {
2496
2462
  const expectedReceipt2 = receiptContent(receipt);
2497
2463
  const drifted = plan.filter((action) => hasActionDrift(action, deps));
2498
2464
  for (const { kind, file } of checked.handoffs) {
2499
- if (handoffEnabled(input, kind) && checked.previous?.[kind]?.sha256 !== receipt[kind]?.sha256 && !drifted.some((action) => path15.resolve(action.target) === file)) {
2465
+ if (handoffEnabled(input, kind) && checked.previous?.[kind]?.sha256 !== receipt[kind]?.sha256 && !drifted.some((action) => path14.resolve(action.target) === file)) {
2500
2466
  return input.operation === "doctor" ? { kind: "drift", paths: [file] } : handoffConflict(kind, file);
2501
2467
  }
2502
2468
  }
2503
2469
  if (input.operation === "doctor") {
2504
- const paths = drifted.map((action) => path15.resolve(action.target));
2470
+ const paths = drifted.map((action) => path14.resolve(action.target));
2505
2471
  paths.push(...removedHandoffs.map(({ file }) => file), ...retiredSkills);
2506
2472
  const currentSettings2 = deps.readText(scope.settingsFile);
2507
2473
  if (currentSettings2 === null || filterProjectedPiPackage(currentSettings2, input.packageSource) !== currentSettings2) {
@@ -2560,12 +2526,12 @@ function runPiProjectionLifecycle(input, deps) {
2560
2526
  return { kind: "synced", changed: drifted.length > 0 || packageWillChange || receiptChanged || removedHandoffs.length > 0 };
2561
2527
  }
2562
2528
  function systemProjectionLifecycle(input) {
2563
- const targetRoot = input.targetDir === void 0 ? null : path15.resolve(input.targetDir);
2529
+ const targetRoot = input.targetDir === void 0 ? null : path14.resolve(input.targetDir);
2564
2530
  const scope = targetRoot === null ? realPiProjectionScope() : {
2565
2531
  kind: "target-dir",
2566
- home: path15.join(targetRoot, "home"),
2567
- codingAgentDir: path15.dirname(piSystemPromptFile(targetRoot)),
2568
- receiptFile: path15.join(targetRoot, "state", "pi-projection-receipt.json")
2532
+ home: path14.join(targetRoot, "home"),
2533
+ codingAgentDir: path14.dirname(piSystemPromptFile(targetRoot)),
2534
+ receiptFile: path14.join(targetRoot, "state", "pi-projection-receipt.json")
2569
2535
  };
2570
2536
  return {
2571
2537
  input: {
@@ -2586,14 +2552,14 @@ function systemProjectionLifecycle(input) {
2586
2552
  backup: (paths) => createBackup(
2587
2553
  paths,
2588
2554
  `pi-projection-${input.operation}`,
2589
- targetRoot === null ? void 0 : path15.join(targetRoot, "backups")
2555
+ targetRoot === null ? void 0 : path14.join(targetRoot, "backups")
2590
2556
  ),
2591
2557
  writeText,
2592
2558
  copyFile,
2593
2559
  removeFile: (file) => {
2594
2560
  fs11.rmSync(file, { force: true });
2595
- if (retiredPlaywrightFiles(scope).includes(path15.resolve(file))) {
2596
- pruneEmptyDirs(file, path15.join(scope.home, ".agents", "skills"));
2561
+ if (retiredPlaywrightFiles(scope).includes(path14.resolve(file))) {
2562
+ pruneEmptyDirs(file, path14.join(scope.home, ".agents", "skills"));
2597
2563
  }
2598
2564
  },
2599
2565
  readManifest: targetRoot === null ? readManifest : () => ({ runtimes: {} })
@@ -2696,7 +2662,7 @@ async function runUninstall(opts) {
2696
2662
  if (!detection.installed) continue;
2697
2663
  const keepCtx = makeContext(keep, detection.configDir);
2698
2664
  if (!keepCtx) continue;
2699
- for (const action of buildContentPlan(keep, keepCtx)) retained.add(path16.resolve(action.target));
2665
+ for (const action of buildContentPlan(keep, keepCtx)) retained.add(path15.resolve(action.target));
2700
2666
  }
2701
2667
  }
2702
2668
  for (const id of opts.runtimes) {
@@ -2722,16 +2688,16 @@ async function runUninstall(opts) {
2722
2688
  exitCode = 1;
2723
2689
  continue;
2724
2690
  }
2725
- const mergedTargets = new Set(unmerge.map((a) => path16.resolve(a.target)));
2691
+ const mergedTargets = new Set(unmerge.map((a) => path15.resolve(a.target)));
2726
2692
  const usingRealConfig = opts.targetDir === void 0;
2727
2693
  const prevOwned = usingRealConfig ? readManifest().runtimes[id]?.owned ?? [] : [];
2728
- const pruneRoot = usingRealConfig ? HOME : path16.dirname(configDir);
2694
+ const pruneRoot = usingRealConfig ? HOME : path15.dirname(configDir);
2729
2695
  const planTargets = [
2730
- .../* @__PURE__ */ new Set([...buildContentPlan(adapter, ctx).map((a) => path16.resolve(a.target)), ...prevOwned.map((t) => path16.resolve(t))])
2696
+ .../* @__PURE__ */ new Set([...buildContentPlan(adapter, ctx).map((a) => path15.resolve(a.target)), ...prevOwned.map((t) => path15.resolve(t))])
2731
2697
  ].filter((t) => !mergedTargets.has(t) && fs12.existsSync(t));
2732
2698
  const deleteTargets = planTargets.filter((t) => {
2733
2699
  if (retained.has(t) || !isContainedIn(t, pruneRoot)) return false;
2734
- if (path16.basename(t) !== "engram.ts") return true;
2700
+ if (path15.basename(t) !== "engram.ts") return true;
2735
2701
  const state = inspectOpencodePluginFile(t);
2736
2702
  if (state === "official" || state === "unknown") return false;
2737
2703
  return !ctx.preserveEngram;
@@ -2814,7 +2780,7 @@ async function runUninstall(opts) {
2814
2780
  }
2815
2781
 
2816
2782
  // src/doctor.ts
2817
- import path17 from "path";
2783
+ import path16 from "path";
2818
2784
  import fs13 from "fs";
2819
2785
  import * as p3 from "@clack/prompts";
2820
2786
  function readDoctorTextIfExists(file) {
@@ -2828,12 +2794,12 @@ function readDoctorTextIfExists(file) {
2828
2794
  var STALE_PERMISSIONS_MARKER = "differs from the stack default and was left untouched";
2829
2795
  var UPGRADE_PERMISSIONS_REMEDY = "jorgex-stack sync --upgrade-permissions --dry-run";
2830
2796
  function piAgentDir(targetDir) {
2831
- return targetDir === void 0 ? process.env.PI_CODING_AGENT_DIR ?? path17.join(HOME, ".pi", "agent") : path17.join(targetDir, "pi-agent");
2797
+ return targetDir === void 0 ? process.env.PI_CODING_AGENT_DIR ?? path16.join(HOME, ".pi", "agent") : path16.join(targetDir, "pi-agent");
2832
2798
  }
2833
2799
  function reportPiPermissions(targetDir) {
2834
2800
  const agentDir = piAgentDir(targetDir);
2835
- const configFile = path17.join(agentDir, "extensions", "pi-permission-system", "config.json");
2836
- const receiptFile = path17.join(agentDir, "jorgex-pi", "permissions-lifecycle.v1.json");
2801
+ const configFile = path16.join(agentDir, "extensions", "pi-permission-system", "config.json");
2802
+ const receiptFile = path16.join(agentDir, "jorgex-pi", "permissions-lifecycle.v1.json");
2837
2803
  let config;
2838
2804
  let receipt;
2839
2805
  try {
@@ -2870,7 +2836,7 @@ function resolvePlaywrightDoctorState(input) {
2870
2836
  return { status: "healthy" };
2871
2837
  }
2872
2838
  function context7KeyConfigured(id, configDir) {
2873
- const file = id === "codex" ? path17.join(configDir, "config.toml") : id === "claude-code" ? path17.join(path17.dirname(configDir), `${path17.basename(configDir)}.json`) : path17.join(configDir, "opencode.json");
2839
+ const file = id === "codex" ? path16.join(configDir, "config.toml") : id === "claude-code" ? path16.join(path16.dirname(configDir), `${path16.basename(configDir)}.json`) : path16.join(configDir, "opencode.json");
2874
2840
  const content = readTextIfExists(file);
2875
2841
  if (content === null) return null;
2876
2842
  const match = /CONTEXT7_API_KEY"?\s*[:=]\s*"([^"]*)"/.exec(content);
@@ -2890,7 +2856,7 @@ function reportWritingStyle(options, style, mode) {
2890
2856
  for (const id of runtimes) {
2891
2857
  const adapter = id === "pi" ? piAdapter : ADAPTERS[id];
2892
2858
  if (adapter === void 0) continue;
2893
- const configDir = id === "pi" ? options.targetDir === void 0 ? process.env.PI_CODING_AGENT_DIR ?? path17.join(HOME, ".pi", "agent") : path17.join(options.targetDir, "pi-agent") : options.targetDir ?? ADAPTERS[id].detect().configDir;
2859
+ const configDir = id === "pi" ? options.targetDir === void 0 ? process.env.PI_CODING_AGENT_DIR ?? path16.join(HOME, ".pi", "agent") : path16.join(options.targetDir, "pi-agent") : options.targetDir ?? ADAPTERS[id].detect().configDir;
2894
2860
  const file = adapter.paths(configDir).systemPromptFile;
2895
2861
  try {
2896
2862
  const content = readDoctorTextIfExists(file) ?? "";
@@ -2905,7 +2871,7 @@ function reportWritingStyle(options, style, mode) {
2905
2871
  problems++;
2906
2872
  }
2907
2873
  if (id === "codex") {
2908
- const override = path17.join(configDir, "AGENTS.override.md");
2874
+ const override = path16.join(configDir, "AGENTS.override.md");
2909
2875
  if ((readDoctorTextIfExists(override) ?? "").trim() !== "") {
2910
2876
  p3.log.warn(`Codex: ${override} no vac\xEDo puede ocultar el AGENTS.md gestionado; rev\xEDsalo sin modificarlo autom\xE1ticamente.`);
2911
2877
  problems++;
@@ -2920,7 +2886,7 @@ function reportWritingStyle(options, style, mode) {
2920
2886
  }
2921
2887
  async function verifyOfficialForRuntime(runtime, configDir, engramBin, homeDir, isExplicitClaudeConfigDir) {
2922
2888
  if (runtime === "claude-code") {
2923
- const { verifyOfficialSetup: verifyOfficialSetup2 } = await import("./claude-code-WY4JJAXP.js");
2889
+ const { verifyOfficialSetup: verifyOfficialSetup2 } = await import("./claude-code-BBHLN5TD.js");
2924
2890
  const explicit = isExplicitClaudeConfigDir ?? process.env.CLAUDE_CONFIG_DIR !== void 0;
2925
2891
  const report2 = await verifyOfficialSetup2({ configDir, engramBin, homeDir, isExplicitClaudeConfigDir: explicit });
2926
2892
  return {
@@ -2930,7 +2896,7 @@ async function verifyOfficialForRuntime(runtime, configDir, engramBin, homeDir,
2930
2896
  };
2931
2897
  }
2932
2898
  if (runtime === "codex") {
2933
- const { verifyOfficialSetup: verifyOfficialSetup2 } = await import("./codex-WSWHXYJ3.js");
2899
+ const { verifyOfficialSetup: verifyOfficialSetup2 } = await import("./codex-ALGP2YBC.js");
2934
2900
  const report2 = await verifyOfficialSetup2({ configDir, engramBin });
2935
2901
  return {
2936
2902
  ok: report2.ok,
@@ -2938,7 +2904,16 @@ async function verifyOfficialForRuntime(runtime, configDir, engramBin, homeDir,
2938
2904
  ...report2.reason === void 0 ? {} : { reason: report2.reason }
2939
2905
  };
2940
2906
  }
2941
- const { verifyOfficialSetup } = await import("./opencode-NUDGK6J7.js");
2907
+ if (runtime === "pi") {
2908
+ const { verifyOfficialSetup: verifyOfficialSetup2 } = await import("./pi-CKFSPGJU.js");
2909
+ const report2 = await verifyOfficialSetup2({ configDir, engramBin, homeDir });
2910
+ return {
2911
+ ok: report2.ok,
2912
+ layers: report2.layers,
2913
+ ...report2.reason === void 0 ? {} : { reason: report2.reason }
2914
+ };
2915
+ }
2916
+ const { verifyOfficialSetup } = await import("./opencode-VG2IZRRF.js");
2942
2917
  const report = await verifyOfficialSetup({ configDir, engramBin });
2943
2918
  return {
2944
2919
  ok: report.ok,
@@ -2981,8 +2956,8 @@ async function runDoctor(options = {}) {
2981
2956
  engramBinAvailable = true;
2982
2957
  }
2983
2958
  }
2984
- const engramDataDir = process.env.ENGRAM_DATA_DIR ?? path17.join(HOME, ".engram");
2985
- const engramDb = path17.join(engramDataDir, "engram.db");
2959
+ const engramDataDir = process.env.ENGRAM_DATA_DIR ?? path16.join(HOME, ".engram");
2960
+ const engramDb = path16.join(engramDataDir, "engram.db");
2986
2961
  if (fs13.existsSync(engramDb)) {
2987
2962
  const sizeMb = (fs13.statSync(engramDb).size / 1024 / 1024).toFixed(1);
2988
2963
  p3.log.info(`Engram DB: ${engramDb} (${sizeMb} MB de memorias \u2014 el stack no la toca JAM\xC1S).`);
@@ -3087,7 +3062,7 @@ async function runDoctor(options = {}) {
3087
3062
  p3.log.warn(`${adapter.name}: ${orphans.length} archivos hu\xE9rfanos de versiones previas \u2192 ejecuta 'sync'.`);
3088
3063
  problems++;
3089
3064
  }
3090
- if (adapter.id === "codex" && fs13.existsSync(path17.join(detection.configDir, "hooks.json"))) {
3065
+ if (adapter.id === "codex" && fs13.existsSync(path16.join(detection.configDir, "hooks.json"))) {
3091
3066
  p3.log.info("Codex: recuerda que los hooks requieren aprobaci\xF3n manual \u2014 verifica con /hooks dentro de codex.");
3092
3067
  }
3093
3068
  const key = context7KeyConfigured(adapter.id, detection.configDir);
@@ -3136,14 +3111,14 @@ async function runDoctor(options = {}) {
3136
3111
 
3137
3112
  // src/update.ts
3138
3113
  import fs16 from "fs";
3139
- import path20 from "path";
3114
+ import path19 from "path";
3140
3115
  import os3 from "os";
3141
3116
  import { execFileSync as execFileSync4 } from "child_process";
3142
3117
  import * as p4 from "@clack/prompts";
3143
3118
 
3144
3119
  // src/lib/github.ts
3145
3120
  import fs14 from "fs";
3146
- import path18 from "path";
3121
+ import path17 from "path";
3147
3122
  import { execFileSync as execFileSync2 } from "child_process";
3148
3123
  import os2 from "os";
3149
3124
  import { Readable } from "stream";
@@ -3225,7 +3200,7 @@ async function latestGithubCommit(repo) {
3225
3200
  }
3226
3201
  }
3227
3202
  function validateExtractedTree(destDir) {
3228
- const resolved = path18.resolve(destDir);
3203
+ const resolved = path17.resolve(destDir);
3229
3204
  const walk = (dir) => {
3230
3205
  let entries;
3231
3206
  try {
@@ -3234,7 +3209,7 @@ function validateExtractedTree(destDir) {
3234
3209
  return false;
3235
3210
  }
3236
3211
  for (const entry of entries) {
3237
- const full = path18.join(dir, entry.name);
3212
+ const full = path17.join(dir, entry.name);
3238
3213
  let stat;
3239
3214
  try {
3240
3215
  stat = fs14.lstatSync(full);
@@ -3253,12 +3228,12 @@ function validateExtractedTree(destDir) {
3253
3228
  }
3254
3229
  function resolveTarBin() {
3255
3230
  if (process.platform !== "win32") return "tar";
3256
- const winTar = path18.join(process.env["SystemRoot"] ?? "C:\\Windows", "System32", "tar.exe");
3231
+ const winTar = path17.join(process.env["SystemRoot"] ?? "C:\\Windows", "System32", "tar.exe");
3257
3232
  return fs14.existsSync(winTar) ? winTar : "tar";
3258
3233
  }
3259
3234
  async function downloadRepoTarball(repo, sha, destDir, validateSubdir) {
3260
3235
  const url = `https://codeload.github.com/${repo}/tar.gz/${sha}`;
3261
- const tmp = path18.join(os2.tmpdir(), `jorgex-tarball-${Date.now()}.tar.gz`);
3236
+ const tmp = path17.join(os2.tmpdir(), `jorgex-tarball-${Date.now()}.tar.gz`);
3262
3237
  const fail = (reason) => {
3263
3238
  try {
3264
3239
  fs14.rmSync(destDir, { recursive: true, force: true });
@@ -3291,8 +3266,8 @@ async function downloadRepoTarball(repo, sha, destDir, validateSubdir) {
3291
3266
  const detail = (e.stderr?.toString().trim() || e.message || "").split("\n")[0];
3292
3267
  return fail(detail ? `tar fall\xF3: ${detail}` : "tar no disponible o fall\xF3 la extracci\xF3n");
3293
3268
  }
3294
- const resolvedDest = path18.resolve(destDir);
3295
- const validateRoot = validateSubdir ? path18.resolve(resolvedDest, validateSubdir) : resolvedDest;
3269
+ const resolvedDest = path17.resolve(destDir);
3270
+ const validateRoot = validateSubdir ? path17.resolve(resolvedDest, validateSubdir) : resolvedDest;
3296
3271
  if (validateRoot !== resolvedDest && !isContainedIn(validateRoot, resolvedDest)) {
3297
3272
  return fail(`la ruta de validaci\xF3n "${validateSubdir}" escapa del destino`);
3298
3273
  }
@@ -3314,7 +3289,7 @@ async function downloadRepoTarball(repo, sha, destDir, validateSubdir) {
3314
3289
 
3315
3290
  // src/lib/skill-update.ts
3316
3291
  import fs15 from "fs";
3317
- import path19 from "path";
3292
+ import path18 from "path";
3318
3293
  import { execFileSync as execFileSync3 } from "child_process";
3319
3294
  var PROTECTED_SKILLS = /* @__PURE__ */ new Set([
3320
3295
  "agent-delegation",
@@ -3334,10 +3309,10 @@ function sameTextContentNormalized(a, b) {
3334
3309
  }
3335
3310
  function diffSkillDirs(upstreamDir, localDir) {
3336
3311
  const upstreamFiles = new Set(
3337
- listFilesRecursive(upstreamDir).map((f) => path19.relative(upstreamDir, f))
3312
+ listFilesRecursive(upstreamDir).map((f) => path18.relative(upstreamDir, f))
3338
3313
  );
3339
3314
  const localFiles = new Set(
3340
- listFilesRecursive(localDir).map((f) => path19.relative(localDir, f))
3315
+ listFilesRecursive(localDir).map((f) => path18.relative(localDir, f))
3341
3316
  );
3342
3317
  const added = [];
3343
3318
  const modified = [];
@@ -3345,7 +3320,7 @@ function diffSkillDirs(upstreamDir, localDir) {
3345
3320
  for (const rel of upstreamFiles) {
3346
3321
  if (!localFiles.has(rel)) {
3347
3322
  added.push(rel);
3348
- } else if (!sameTextContentNormalized(path19.join(upstreamDir, rel), path19.join(localDir, rel))) {
3323
+ } else if (!sameTextContentNormalized(path18.join(upstreamDir, rel), path18.join(localDir, rel))) {
3349
3324
  modified.push(rel);
3350
3325
  }
3351
3326
  }
@@ -3407,7 +3382,7 @@ function replaceSkill(name, upstreamSkillDir, newCommit, opts) {
3407
3382
  if (PROTECTED_SKILLS.has(name)) {
3408
3383
  throw new Error(`La skill "${name}" es propia del stack y no se actualiza desde upstream.`);
3409
3384
  }
3410
- const upstreamsFile = upstreamsFilePath ?? path19.join(path19.dirname(stackRoot()), "upstreams.json");
3385
+ const upstreamsFile = upstreamsFilePath ?? path18.join(path18.dirname(stackRoot()), "upstreams.json");
3411
3386
  const raw = fs15.readFileSync(upstreamsFile, "utf8");
3412
3387
  const data = JSON.parse(raw);
3413
3388
  const skillEntry = data?.skills?.[name];
@@ -3417,8 +3392,8 @@ function replaceSkill(name, upstreamSkillDir, newCommit, opts) {
3417
3392
  if (skillEntry.kind === "release") {
3418
3393
  throw new Error(`La skill "${name}" es de tipo release y no se actualiza con replaceSkill.`);
3419
3394
  }
3420
- const skillsRoot = localSkillsRoot ?? path19.join(stackRoot(), "skills");
3421
- const localSkillDir = path19.join(skillsRoot, name);
3395
+ const skillsRoot = localSkillsRoot ?? path18.join(stackRoot(), "skills");
3396
+ const localSkillDir = path18.join(skillsRoot, name);
3422
3397
  const localFiles = listFilesRecursive(localSkillDir);
3423
3398
  if (localFiles.length > 0) {
3424
3399
  createBackup(localFiles, `skill-update-${name}`, backupsRoot);
@@ -3431,9 +3406,9 @@ function replaceSkill(name, upstreamSkillDir, newCommit, opts) {
3431
3406
  if (st.isSymbolicLink()) {
3432
3407
  throw new Error(`Symlink rechazado en upstream de skill "${name}": ${src}`);
3433
3408
  }
3434
- const rel = path19.relative(upstreamSkillDir, src);
3435
- const dest = path19.join(stagingDir, rel);
3436
- ensureDir(path19.dirname(dest));
3409
+ const rel = path18.relative(upstreamSkillDir, src);
3410
+ const dest = path18.join(stagingDir, rel);
3411
+ ensureDir(path18.dirname(dest));
3437
3412
  copyFile(src, dest);
3438
3413
  }
3439
3414
  const oldDir = `${localSkillDir}.old-${process.pid}`;
@@ -3458,7 +3433,7 @@ function rateLimitHint(prefix) {
3458
3433
  return ghPresentButTokenFailed() ? `${prefix} Tienes gh instalado pero \`gh auth token\` no devolvi\xF3 credencial (\xBFsesi\xF3n caducada?) \u2014 prueba \`gh auth login\` o define GH_TOKEN.` : `${prefix} Define GH_TOKEN o inicia sesi\xF3n en gh CLI.`;
3459
3434
  }
3460
3435
  function loadUpstreams() {
3461
- const file = path20.join(path20.dirname(stackRoot()), "upstreams.json");
3436
+ const file = path19.join(path19.dirname(stackRoot()), "upstreams.json");
3462
3437
  return JSON.parse(fs16.readFileSync(file, "utf8"));
3463
3438
  }
3464
3439
  function skillsToScan(maintainer, upstreams) {
@@ -3690,8 +3665,8 @@ function isEngramRunning() {
3690
3665
  return null;
3691
3666
  }
3692
3667
  }
3693
- function isGitClone(projectRoot = path20.dirname(stackRoot())) {
3694
- return fs16.existsSync(path20.join(projectRoot, ".git"));
3668
+ function isGitClone(projectRoot = path19.dirname(stackRoot())) {
3669
+ return fs16.existsSync(path19.join(projectRoot, ".git"));
3695
3670
  }
3696
3671
  var STACK_METHOD_CLONE = "git pull + pnpm install + pnpm build";
3697
3672
  function resolvePnpm() {
@@ -3706,7 +3681,7 @@ function cleanupTmp(dir) {
3706
3681
  }
3707
3682
  }
3708
3683
  function updateStackGitClone() {
3709
- const projectRoot = path20.dirname(stackRoot());
3684
+ const projectRoot = path19.dirname(stackRoot());
3710
3685
  const git = lookPath("git");
3711
3686
  if (!git) throw new Error("git no encontrado en PATH.");
3712
3687
  const pnpm = resolvePnpm();
@@ -3723,7 +3698,7 @@ function updateStackGlobal() {
3723
3698
  execFileSync4(pnpm, ["add", "-g", "jorgex-stack@latest"], { stdio: "inherit" });
3724
3699
  }
3725
3700
  async function downloadSkillToTemp(repo, sha, skillPath) {
3726
- const root = fs16.mkdtempSync(path20.join(os3.tmpdir(), "jorgex-skill-"));
3701
+ const root = fs16.mkdtempSync(path19.join(os3.tmpdir(), "jorgex-skill-"));
3727
3702
  try {
3728
3703
  const result = await downloadRepoTarball(repo, sha, root, skillPath);
3729
3704
  if (!result.ok) {
@@ -3731,14 +3706,14 @@ async function downloadSkillToTemp(repo, sha, skillPath) {
3731
3706
  return { error: result.reason };
3732
3707
  }
3733
3708
  if (skillPath) {
3734
- const sub = path20.resolve(path20.join(root, skillPath));
3709
+ const sub = path19.resolve(path19.join(root, skillPath));
3735
3710
  if (!isContainedIn(sub, root)) {
3736
3711
  cleanupTmp(root);
3737
3712
  return { error: `la ruta "${skillPath}" escapa del directorio temporal` };
3738
3713
  }
3739
3714
  if (fs16.existsSync(sub)) return { dir: sub, root };
3740
3715
  const lastSeg = skillPath.split("/").pop();
3741
- const sub2 = path20.resolve(path20.join(root, lastSeg));
3716
+ const sub2 = path19.resolve(path19.join(root, lastSeg));
3742
3717
  if (isContainedIn(sub2, root) && fs16.existsSync(sub2)) {
3743
3718
  if (!validateExtractedTree(sub2)) {
3744
3719
  cleanupTmp(root);
@@ -3759,10 +3734,10 @@ function pruneEngramDbBackups() {
3759
3734
  try {
3760
3735
  const dir = dataDir();
3761
3736
  if (!fs16.existsSync(dir)) return;
3762
- const backups = fs16.readdirSync(dir).filter((f) => f.startsWith("engram-db-backup-") && f.endsWith(".db")).map((f) => ({ name: f, mtime: fs16.statSync(path20.join(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
3737
+ const backups = fs16.readdirSync(dir).filter((f) => f.startsWith("engram-db-backup-") && f.endsWith(".db")).map((f) => ({ name: f, mtime: fs16.statSync(path19.join(dir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
3763
3738
  for (const old of backups.slice(3)) {
3764
3739
  try {
3765
- fs16.rmSync(path20.join(dir, old.name));
3740
+ fs16.rmSync(path19.join(dir, old.name));
3766
3741
  } catch {
3767
3742
  }
3768
3743
  }
@@ -3771,17 +3746,17 @@ function pruneEngramDbBackups() {
3771
3746
  }
3772
3747
  function rotateLockedBinary(binPath, sweepRoot = HOME) {
3773
3748
  if (!fs16.existsSync(binPath)) return null;
3774
- const dir = path20.dirname(binPath);
3775
- const base = path20.basename(binPath);
3749
+ const dir = path19.dirname(binPath);
3750
+ const base = path19.basename(binPath);
3776
3751
  const escapedBase = base.replace(/[.*+?^$()|[\]{}\\]/g, "\\$&");
3777
3752
  const oldPattern = new RegExp("^" + escapedBase + "\\.old-\\d+$");
3778
- const resolvedDir = path20.resolve(dir);
3779
- if (resolvedDir === path20.resolve(sweepRoot) || isContainedIn(resolvedDir, sweepRoot)) {
3753
+ const resolvedDir = path19.resolve(dir);
3754
+ if (resolvedDir === path19.resolve(sweepRoot) || isContainedIn(resolvedDir, sweepRoot)) {
3780
3755
  try {
3781
3756
  for (const entry of fs16.readdirSync(dir)) {
3782
3757
  if (oldPattern.test(entry)) {
3783
3758
  try {
3784
- fs16.rmSync(path20.join(dir, entry), { force: true });
3759
+ fs16.rmSync(path19.join(dir, entry), { force: true });
3785
3760
  } catch {
3786
3761
  }
3787
3762
  }
@@ -3789,7 +3764,7 @@ function rotateLockedBinary(binPath, sweepRoot = HOME) {
3789
3764
  } catch {
3790
3765
  }
3791
3766
  }
3792
- const rotated = path20.join(dir, `${base}.old-${Date.now()}`);
3767
+ const rotated = path19.join(dir, `${base}.old-${Date.now()}`);
3793
3768
  fs16.renameSync(binPath, rotated);
3794
3769
  return rotated;
3795
3770
  }
@@ -3799,8 +3774,8 @@ async function updateEngram(engramRepo, latestVersion) {
3799
3774
  "Engram est\xE1 en ejecuci\xF3n: los procesos vivos seguir\xE1n usando la versi\xF3n antigua hasta que reinicies los clientes (Claude Code/OpenCode/Codex)."
3800
3775
  );
3801
3776
  }
3802
- const engramDataDir = process.env.ENGRAM_DATA_DIR ?? path20.join(HOME, ".engram");
3803
- const engramDb = path20.join(engramDataDir, "engram.db");
3777
+ const engramDataDir = process.env.ENGRAM_DATA_DIR ?? path19.join(HOME, ".engram");
3778
+ const engramDb = path19.join(engramDataDir, "engram.db");
3804
3779
  if (fs16.existsSync(engramDb)) {
3805
3780
  const doBackup = await p4.confirm({
3806
3781
  message: `\xBFHacer backup de la DB de Engram antes de actualizar? (${engramDb})`,
@@ -3808,7 +3783,7 @@ async function updateEngram(engramRepo, latestVersion) {
3808
3783
  });
3809
3784
  if (!p4.isCancel(doBackup) && doBackup) {
3810
3785
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
3811
- const dest = path20.join(dataDir(), `engram-db-backup-${ts}.db`);
3786
+ const dest = path19.join(dataDir(), `engram-db-backup-${ts}.db`);
3812
3787
  try {
3813
3788
  if (!fs16.existsSync(dataDir())) fs16.mkdirSync(dataDir(), { recursive: true });
3814
3789
  fs16.copyFileSync(engramDb, dest);
@@ -4146,7 +4121,7 @@ async function runInteractiveUpdate(localVersion, yes, dryRun = false, includeBr
4146
4121
  continue;
4147
4122
  }
4148
4123
  const { dir: tmpDir, root: tmpRoot } = tmpResult;
4149
- const localSkillDir = path20.join(stackRoot(), "skills", skillInfo.name);
4124
+ const localSkillDir = path19.join(stackRoot(), "skills", skillInfo.name);
4150
4125
  const diff = renderSkillDiff(tmpDir, localSkillDir);
4151
4126
  if (diff) {
4152
4127
  p4.log.info(`Diff de ${skillInfo.name}:
@@ -4238,7 +4213,7 @@ ${diff}`);
4238
4213
  }
4239
4214
 
4240
4215
  // src/models-picker.ts
4241
- import path21 from "path";
4216
+ import path20 from "path";
4242
4217
  import * as p5 from "@clack/prompts";
4243
4218
  var TIERS = ["strong", "standard", "cheap"];
4244
4219
  var EFFORTS = ["low", "medium", "high", "xhigh"];
@@ -4264,7 +4239,7 @@ function opencodeLiveModels(binPath) {
4264
4239
  }
4265
4240
  function agentsByTier() {
4266
4241
  const grouped = { strong: [], standard: [], cheap: [] };
4267
- for (const agent of loadCanonicalAgents(path21.join(stackRoot(), "agents"))) {
4242
+ for (const agent of loadCanonicalAgents(path20.join(stackRoot(), "agents"))) {
4268
4243
  if (agent.mode === "subagent") grouped[agent.tier].push(agent.name);
4269
4244
  }
4270
4245
  return grouped;
@@ -4450,15 +4425,15 @@ function cancelled() {
4450
4425
 
4451
4426
  // src/lib/release.ts
4452
4427
  import fs17 from "fs";
4453
- import path22 from "path";
4428
+ import path21 from "path";
4454
4429
  import { execFileSync as execFileSync5 } from "child_process";
4455
4430
  import { fileURLToPath } from "url";
4456
4431
  function findPackageJson() {
4457
- let dir = path22.dirname(fileURLToPath(import.meta.url));
4432
+ let dir = path21.dirname(fileURLToPath(import.meta.url));
4458
4433
  for (let i = 0; i < 6; i++) {
4459
- const candidate = path22.join(dir, "package.json");
4434
+ const candidate = path21.join(dir, "package.json");
4460
4435
  if (fs17.existsSync(candidate)) return candidate;
4461
- dir = path22.dirname(dir);
4436
+ dir = path21.dirname(dir);
4462
4437
  }
4463
4438
  throw new Error("No se encontr\xF3 package.json cerca del CLI.");
4464
4439
  }
@@ -4479,7 +4454,7 @@ function readPackageMetadata() {
4479
4454
 
4480
4455
  // src/lib/pi-runtime.ts
4481
4456
  import os4 from "os";
4482
- import path23 from "path";
4457
+ import path22 from "path";
4483
4458
  import fs18 from "fs";
4484
4459
  import { spawnSync } from "child_process";
4485
4460
  import { createHash as createHash2 } from "crypto";
@@ -4488,16 +4463,16 @@ import { createHash as createHash2 } from "crypto";
4488
4463
  var pi_runtime_pin_default = {
4489
4464
  package: {
4490
4465
  name: "jorgex-pi",
4491
- version: "0.8.27",
4492
- source: "npm:jorgex-pi@0.8.27"
4466
+ version: "0.8.28",
4467
+ source: "npm:jorgex-pi@0.8.28"
4493
4468
  },
4494
4469
  provenance: {
4495
- commit: "97fb35c88c484f264cbd9dc1f0a3c65da2f9dba1"
4470
+ commit: "056fbc7eeea07466c3ce3a6f85723e94bcf38577"
4496
4471
  },
4497
4472
  tarball: {
4498
- bytes: 89140773,
4499
- sha256: "2ac1ed88c419de87d7a519aa269cac7015e477f6c5250fe7d7090a4c40e3fa17",
4500
- sha512: "6adbdb8dcf35bd7b6eba63ac6b1c7fc2ccf2063f5768a16bdb462104143a09039be629c8d67ab0e058533d882a27fbbc3d753c769297ed9ac1c04775a2f0b614"
4473
+ bytes: 17993987,
4474
+ sha256: "3490845ad6d67c82cb0828847d0c9510a58958f068c4e8408161aadfe6f28ed9",
4475
+ sha512: "7ec1c46ccbafe8052effca13ef5e2bdff2ad09a2624bbe4ad7884622e231bbe25119b7124b6ba8f96916be34d99e511bfd83a9c16708d6f828ccf9f9d705bd7c"
4501
4476
  }
4502
4477
  };
4503
4478
 
@@ -4518,7 +4493,7 @@ var PI_RUNTIME_CANDIDATE = {
4518
4493
  "structured-questions-v1",
4519
4494
  "web-access-v1",
4520
4495
  "goal-continuation-v1",
4521
- "mcp-adapter-v1",
4496
+ "engram-official-bridge-v1",
4522
4497
  "engram-runtime-tools-v1",
4523
4498
  "context7-http-v1",
4524
4499
  "permissions-policy-v1",
@@ -4677,7 +4652,7 @@ function healthyDoctor(stdout, stderr, packageRunner, candidate) {
4677
4652
  if (record === null || typeof record !== "object" || Array.isArray(record)) return false;
4678
4653
  const packageValue = Reflect.get(record, "package");
4679
4654
  const result = Reflect.get(record, "result");
4680
- return Reflect.get(record, "schemaVersion") === 1 && Reflect.get(record, "command") === "doctor" && Reflect.get(record, "ok") === true && packageValue !== null && typeof packageValue === "object" && Reflect.get(packageValue, "name") === "jorgex-pi" && Reflect.get(packageValue, "version") === (candidate.package?.version ?? /^npm:jorgex-pi@([^\s]+)$/.exec(candidate.source)?.[1]) && path23.resolve(packageRunner) === path23.resolve(String(Reflect.get(packageValue, "root")), "bin", "jorgex-pi.mjs") && result !== null && typeof result === "object" && Reflect.get(result, "healthy") === true;
4655
+ return Reflect.get(record, "schemaVersion") === 1 && Reflect.get(record, "command") === "doctor" && Reflect.get(record, "ok") === true && packageValue !== null && typeof packageValue === "object" && Reflect.get(packageValue, "name") === "jorgex-pi" && Reflect.get(packageValue, "version") === (candidate.package?.version ?? /^npm:jorgex-pi@([^\s]+)$/.exec(candidate.source)?.[1]) && path22.resolve(packageRunner) === path22.resolve(String(Reflect.get(packageValue, "root")), "bin", "jorgex-pi.mjs") && result !== null && typeof result === "object" && Reflect.get(result, "healthy") === true;
4681
4656
  } catch {
4682
4657
  return false;
4683
4658
  }
@@ -4698,7 +4673,7 @@ function provisionalPendingDoctor(exitCode, stdout, stderr, packageRunner, candi
4698
4673
  if (JSON.stringify(Object.keys(packageValue).sort()) !== JSON.stringify(["name", "root", "version"])) return false;
4699
4674
  if (Reflect.get(packageValue, "name") !== "jorgex-pi") return false;
4700
4675
  if (Reflect.get(packageValue, "version") !== (candidate.package?.version ?? /^npm:jorgex-pi@([^\s]+)$/.exec(candidate.source)?.[1])) return false;
4701
- if (path23.resolve(packageRunner) !== path23.resolve(String(Reflect.get(packageValue, "root")), "bin", "jorgex-pi.mjs")) return false;
4676
+ if (path22.resolve(packageRunner) !== path22.resolve(String(Reflect.get(packageValue, "root")), "bin", "jorgex-pi.mjs")) return false;
4702
4677
  const result = Reflect.get(record, "result");
4703
4678
  if (result === null || typeof result !== "object" || Array.isArray(result)) return false;
4704
4679
  if (JSON.stringify(Object.keys(result).sort()) !== JSON.stringify(["checks", "healthy"])) return false;
@@ -4727,7 +4702,7 @@ function provisionalPendingDoctor(exitCode, stdout, stderr, packageRunner, candi
4727
4702
  }
4728
4703
  function installPiFromVerifiedTarball(input, deps) {
4729
4704
  const paths = input.targetDir === void 0 ? userPaths(input.engramBin, input.piExecutable) : targetPaths(input.targetDir, input.engramBin, input.piExecutable);
4730
- const destination = input.targetDir === void 0 ? path23.join(dataDir(), "packages", `jorgex-pi-${PI_RUNTIME_CANDIDATE.package.version}.tgz`) : path23.join(path23.resolve(input.targetDir), "downloads", `jorgex-pi-${PI_RUNTIME_CANDIDATE.package.version}.tgz`);
4705
+ const destination = input.targetDir === void 0 ? path22.join(dataDir(), "packages", `jorgex-pi-${PI_RUNTIME_CANDIDATE.package.version}.tgz`) : path22.join(path22.resolve(input.targetDir), "downloads", `jorgex-pi-${PI_RUNTIME_CANDIDATE.package.version}.tgz`);
4731
4706
  const artifact = deps.download(destination);
4732
4707
  if (artifact.bytes !== input.candidate.bytes || artifact.sha256 !== input.candidate.sha256 || artifact.sha512 !== input.candidate.sha512) {
4733
4708
  return { kind: "blocked", reason: "tarball-integrity" };
@@ -4735,7 +4710,7 @@ function installPiFromVerifiedTarball(input, deps) {
4735
4710
  deps.backupSettings();
4736
4711
  const scope = {
4737
4712
  kind: input.targetDir === void 0 ? "real" : "target-dir",
4738
- codingAgentDir: path23.resolve(paths.codingAgentDir)
4713
+ codingAgentDir: path22.resolve(paths.codingAgentDir)
4739
4714
  };
4740
4715
  const installing = flatCandidateReceipt(input.candidate, scope, "installing", input.engramBin);
4741
4716
  deps.writeReceiptAtomic(`${JSON.stringify(installing)}
@@ -4766,30 +4741,30 @@ function installPiFromVerifiedTarball(input, deps) {
4766
4741
  return { kind: "installed", receipt };
4767
4742
  }
4768
4743
  function runtimePath(piExecutable) {
4769
- const entries = process.platform === "win32" ? [piExecutable === void 0 ? null : path23.dirname(piExecutable), path23.dirname(process.execPath), process.env.SystemRoot ? path23.join(process.env.SystemRoot, "System32") : null] : [piExecutable === void 0 ? null : path23.dirname(piExecutable), path23.dirname(process.execPath), "/usr/local/bin", "/usr/bin", "/bin"];
4770
- return [...new Set(entries.filter((entry) => entry !== null))].join(path23.delimiter);
4744
+ const entries = process.platform === "win32" ? [piExecutable === void 0 ? null : path22.dirname(piExecutable), path22.dirname(process.execPath), process.env.SystemRoot ? path22.join(process.env.SystemRoot, "System32") : null] : [piExecutable === void 0 ? null : path22.dirname(piExecutable), path22.dirname(process.execPath), "/usr/local/bin", "/usr/bin", "/bin"];
4745
+ return [...new Set(entries.filter((entry) => entry !== null))].join(path22.delimiter);
4771
4746
  }
4772
4747
  function targetPaths(targetDir, engramBin, piExecutable) {
4773
- const root = path23.resolve(targetDir);
4774
- const codingAgentDir = path23.join(root, "pi-agent");
4775
- const home = path23.join(root, "home");
4776
- const temporary = path23.join(root, "tmp");
4748
+ const root = path22.resolve(targetDir);
4749
+ const codingAgentDir = path22.join(root, "pi-agent");
4750
+ const home = path22.join(root, "home");
4751
+ const temporary = path22.join(root, "tmp");
4777
4752
  return {
4778
4753
  codingAgentDir,
4779
- receiptPath: path23.join(root, "state", "pi-receipt.json"),
4780
- packageRunner: path23.join(codingAgentDir, "npm", "node_modules", "jorgex-pi", "bin", "jorgex-pi.mjs"),
4754
+ receiptPath: path22.join(root, "state", "pi-receipt.json"),
4755
+ packageRunner: path22.join(codingAgentDir, "npm", "node_modules", "jorgex-pi", "bin", "jorgex-pi.mjs"),
4781
4756
  environment: {
4782
4757
  HOME: home,
4783
4758
  USERPROFILE: home,
4784
- APPDATA: path23.join(root, "appdata"),
4785
- LOCALAPPDATA: path23.join(root, "localappdata"),
4786
- XDG_CONFIG_HOME: path23.join(root, "xdg-config"),
4787
- XDG_DATA_HOME: path23.join(root, "xdg-data"),
4788
- XDG_CACHE_HOME: path23.join(root, "xdg-cache"),
4759
+ APPDATA: path22.join(root, "appdata"),
4760
+ LOCALAPPDATA: path22.join(root, "localappdata"),
4761
+ XDG_CONFIG_HOME: path22.join(root, "xdg-config"),
4762
+ XDG_DATA_HOME: path22.join(root, "xdg-data"),
4763
+ XDG_CACHE_HOME: path22.join(root, "xdg-cache"),
4789
4764
  TEMP: temporary,
4790
4765
  TMP: temporary,
4791
4766
  TMPDIR: temporary,
4792
- npm_config_cache: path23.join(root, "npm-cache"),
4767
+ npm_config_cache: path22.join(root, "npm-cache"),
4793
4768
  NPM_CONFIG_IGNORE_SCRIPTS: "true",
4794
4769
  NPM_CONFIG_UPDATE_NOTIFIER: "false",
4795
4770
  PI_CODING_AGENT_DIR: codingAgentDir,
@@ -4800,15 +4775,15 @@ function targetPaths(targetDir, engramBin, piExecutable) {
4800
4775
  }
4801
4776
  function userPaths(engramBin, piExecutable) {
4802
4777
  const home = os4.homedir();
4803
- const codingAgentDir = process.env.PI_CODING_AGENT_DIR ?? path23.join(home, ".pi", "agent");
4778
+ const codingAgentDir = process.env.PI_CODING_AGENT_DIR ?? path22.join(home, ".pi", "agent");
4804
4779
  return {
4805
4780
  codingAgentDir,
4806
- receiptPath: path23.join(dataDir(), "pi-receipt.json"),
4807
- packageRunner: path23.join(codingAgentDir, "npm", "node_modules", "jorgex-pi", "bin", "jorgex-pi.mjs"),
4781
+ receiptPath: path22.join(dataDir(), "pi-receipt.json"),
4782
+ packageRunner: path22.join(codingAgentDir, "npm", "node_modules", "jorgex-pi", "bin", "jorgex-pi.mjs"),
4808
4783
  environment: {
4809
4784
  HOME: home,
4810
- XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME ?? path23.join(home, ".config"),
4811
- XDG_CACHE_HOME: process.env.XDG_CACHE_HOME ?? path23.join(home, ".cache"),
4785
+ XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME ?? path22.join(home, ".config"),
4786
+ XDG_CACHE_HOME: process.env.XDG_CACHE_HOME ?? path22.join(home, ".cache"),
4812
4787
  TMPDIR: os4.tmpdir(),
4813
4788
  NPM_CONFIG_IGNORE_SCRIPTS: "true",
4814
4789
  NPM_CONFIG_UPDATE_NOTIFIER: "false",
@@ -4836,7 +4811,7 @@ function runPiRuntime(input, deps) {
4836
4811
  return { kind: "blocked", reason: "tarball-integrity" };
4837
4812
  }
4838
4813
  const paths = input.targetDir === void 0 ? userPaths(input.engramBin, input.detected.executable) : targetPaths(input.targetDir, input.engramBin, input.detected.executable);
4839
- const settingsJson = deps.readSettings(path23.join(paths.codingAgentDir, "settings.json"));
4814
+ const settingsJson = deps.readSettings(path22.join(paths.codingAgentDir, "settings.json"));
4840
4815
  const receiptJson = deps.readReceipt(paths.receiptPath);
4841
4816
  const lifecycleInput = {
4842
4817
  candidate: PI_RUNTIME_CANDIDATE,
@@ -4900,14 +4875,14 @@ function readJsonFile(file) {
4900
4875
  function packageVersionFromExecutable(executable) {
4901
4876
  let current;
4902
4877
  try {
4903
- current = path23.dirname(fs18.realpathSync(executable));
4878
+ current = path22.dirname(fs18.realpathSync(executable));
4904
4879
  } catch {
4905
4880
  return null;
4906
4881
  }
4907
4882
  for (let depth = 0; depth < 8; depth++) {
4908
4883
  const manifests = [
4909
- path23.join(current, "package.json"),
4910
- path23.join(current, "node_modules", "@earendil-works", "pi-coding-agent", "package.json")
4884
+ path22.join(current, "package.json"),
4885
+ path22.join(current, "node_modules", "@earendil-works", "pi-coding-agent", "package.json")
4911
4886
  ];
4912
4887
  for (const manifest of manifests) {
4913
4888
  try {
@@ -4918,7 +4893,7 @@ function packageVersionFromExecutable(executable) {
4918
4893
  } catch {
4919
4894
  }
4920
4895
  }
4921
- const parent = path23.dirname(current);
4896
+ const parent = path22.dirname(current);
4922
4897
  if (parent === current) break;
4923
4898
  current = parent;
4924
4899
  }
@@ -4933,16 +4908,16 @@ function detectPiRuntime() {
4933
4908
  installed: executable !== null,
4934
4909
  executable,
4935
4910
  version: executable === null ? null : packageVersionFromExecutable(executable),
4936
- codingAgentDir: process.env.PI_CODING_AGENT_DIR ?? path23.join(home, ".pi", "agent")
4911
+ codingAgentDir: process.env.PI_CODING_AGENT_DIR ?? path22.join(home, ".pi", "agent")
4937
4912
  };
4938
4913
  }
4939
4914
  function hasManagedPiRuntime(targetDir) {
4940
- const receipt = targetDir === void 0 ? path23.join(dataDir(), "pi-receipt.json") : path23.join(path23.resolve(targetDir), "state", "pi-receipt.json");
4915
+ const receipt = targetDir === void 0 ? path22.join(dataDir(), "pi-receipt.json") : path22.join(path22.resolve(targetDir), "state", "pi-receipt.json");
4941
4916
  return fs18.statSync(receipt, { throwIfNoEntry: false })?.isFile() === true;
4942
4917
  }
4943
4918
  function resolvePiEngramBin(targetDir) {
4944
4919
  if (targetDir === void 0) return detectEngram();
4945
- const candidate = path23.join(path23.resolve(targetDir), "bin", process.platform === "win32" ? "engram.exe" : "engram");
4920
+ const candidate = path22.join(path22.resolve(targetDir), "bin", process.platform === "win32" ? "engram.exe" : "engram");
4946
4921
  return fs18.statSync(candidate, { throwIfNoEntry: false })?.isFile() ? candidate : null;
4947
4922
  }
4948
4923
  function readOptional(file, fallback) {
@@ -4982,7 +4957,7 @@ async function acquirePiTarball(destination) {
4982
4957
  }
4983
4958
  fs18.rmSync(destination, { force: true });
4984
4959
  }
4985
- fs18.mkdirSync(path23.dirname(destination), { recursive: true });
4960
+ fs18.mkdirSync(path22.dirname(destination), { recursive: true });
4986
4961
  const partial = `${destination}.partial-${process.pid}`;
4987
4962
  const response = await fetch(`https://registry.npmjs.org/jorgex-pi/-/jorgex-pi-${PI_RUNTIME_CANDIDATE.package.version}.tgz`, {
4988
4963
  redirect: "error",
@@ -5025,6 +5000,21 @@ function runProcess(invocation) {
5025
5000
  stderr: result.stderr ?? (result.error?.message ?? "")
5026
5001
  };
5027
5002
  }
5003
+ function setupPiFailedRemedy(setup) {
5004
+ const detail = setup.reason ?? setup.stderr ?? "setup oficial Pi fall\xF3";
5005
+ const recovery = setup.recovery ?? "none";
5006
+ const backupId = setup.backupId ?? null;
5007
+ if (recovery === "complete") {
5008
+ return backupId !== null ? `${detail}. Se restaur\xF3 el backup ${backupId}; Pi no qued\xF3 activado.` : `${detail}. Se restaur\xF3 el backup previo; Pi no qued\xF3 activado.`;
5009
+ }
5010
+ if (recovery === "incomplete") {
5011
+ const id2 = backupId !== null ? ` (backup ${backupId})` : " (sin backup v\xE1lido)";
5012
+ const cause = setup.restoreError !== void 0 ? ` ${setup.restoreError}.` : "";
5013
+ return `${detail}. Recuperaci\xF3n incompleta${id2};${cause} revisa manualmente el estado y corrige la causa antes de reintentar; Pi no qued\xF3 activado.`;
5014
+ }
5015
+ const id = backupId !== null ? ` (backup ${backupId})` : " (sin backup v\xE1lido)";
5016
+ return `${detail}. Sin recuperaci\xF3n autom\xE1tica${id}; revisa manualmente el estado y corrige la causa antes de reintentar; Pi no qued\xF3 activado.`;
5017
+ }
5028
5018
  async function runPiRuntimeSystem(input) {
5029
5019
  if (input.engramBin === null && input.operation !== "uninstall") return runPiRuntime(input, {
5030
5020
  readSettings: () => {
@@ -5055,7 +5045,32 @@ async function runPiRuntimeSystem(input) {
5055
5045
  remedy: "Instala Engram o configura un ENGRAM_BIN absoluto antes de reintentar."
5056
5046
  };
5057
5047
  }
5058
- const destination = input.targetDir === void 0 ? path23.join(dataDir(), "packages", `jorgex-pi-${PI_RUNTIME_CANDIDATE.package.version}.tgz`) : path23.join(path23.resolve(input.targetDir), "downloads", `jorgex-pi-${PI_RUNTIME_CANDIDATE.package.version}.tgz`);
5048
+ if (input.targetDir === void 0) {
5049
+ const { runOfficialSetupIfNeeded: runOfficialSetupIfNeeded2 } = await import("./official-engram-setup-4WIXM4EF.js");
5050
+ const setup = await runOfficialSetupIfNeeded2("pi", {
5051
+ command: "install",
5052
+ dryRun: false,
5053
+ targetDir: void 0,
5054
+ engramBin: input.engramBin,
5055
+ configDir: paths.codingAgentDir,
5056
+ homeDir: os4.homedir()
5057
+ });
5058
+ if (!setup.ran || !setup.ok) {
5059
+ if (!setup.ran) {
5060
+ return {
5061
+ kind: "blocked",
5062
+ reason: "setup-pi-failed",
5063
+ remedy: "setup oficial Pi omitido en install real. Sin recuperaci\xF3n autom\xE1tica (sin backup v\xE1lido); revisa manualmente el estado y corrige la causa antes de reintentar; Pi no qued\xF3 activado."
5064
+ };
5065
+ }
5066
+ return {
5067
+ kind: "blocked",
5068
+ reason: "setup-pi-failed",
5069
+ remedy: setupPiFailedRemedy(setup)
5070
+ };
5071
+ }
5072
+ }
5073
+ const destination = input.targetDir === void 0 ? path22.join(dataDir(), "packages", `jorgex-pi-${PI_RUNTIME_CANDIDATE.package.version}.tgz`) : path22.join(path22.resolve(input.targetDir), "downloads", `jorgex-pi-${PI_RUNTIME_CANDIDATE.package.version}.tgz`);
5059
5074
  let artifact;
5060
5075
  try {
5061
5076
  artifact = await acquirePiTarball(destination);
@@ -5076,18 +5091,18 @@ async function runPiRuntimeSystem(input) {
5076
5091
  }, {
5077
5092
  download: () => artifact,
5078
5093
  backupSettings: () => createBackup(
5079
- [path23.join(paths.codingAgentDir, "settings.json")],
5094
+ [path22.join(paths.codingAgentDir, "settings.json")],
5080
5095
  "pi-package-install",
5081
- input.targetDir === void 0 ? void 0 : path23.join(path23.resolve(input.targetDir), "backups")
5096
+ input.targetDir === void 0 ? void 0 : path22.join(path22.resolve(input.targetDir), "backups")
5082
5097
  ),
5083
5098
  run: runProcess,
5084
- readSettings: () => readOptional(path23.join(paths.codingAgentDir, "settings.json"), '{"packages":[]}'),
5085
- rewriteSettings: (content) => writeText(path23.join(paths.codingAgentDir, "settings.json"), `${content}
5099
+ readSettings: () => readOptional(path22.join(paths.codingAgentDir, "settings.json"), '{"packages":[]}'),
5100
+ rewriteSettings: (content) => writeText(path22.join(paths.codingAgentDir, "settings.json"), `${content}
5086
5101
  `),
5087
5102
  writeReceiptAtomic: (content) => writeText(paths.receiptPath, content)
5088
5103
  });
5089
5104
  }
5090
- const packageRoot = path23.dirname(path23.dirname(paths.packageRunner));
5105
+ const packageRoot = path22.dirname(path22.dirname(paths.packageRunner));
5091
5106
  const writeReceipt = (receipt) => {
5092
5107
  writeText(paths.receiptPath, `${JSON.stringify(receipt, null, 2)}
5093
5108
  `);
@@ -5105,9 +5120,9 @@ async function runPiRuntimeSystem(input) {
5105
5120
  value,
5106
5121
  {
5107
5122
  backupSettings: () => createBackup(
5108
- [path23.join(paths.codingAgentDir, "settings.json")],
5123
+ [path22.join(paths.codingAgentDir, "settings.json")],
5109
5124
  "pi-package-uninstall",
5110
- input.targetDir === void 0 ? void 0 : path23.join(path23.resolve(input.targetDir), "backups")
5125
+ input.targetDir === void 0 ? void 0 : path22.join(path22.resolve(input.targetDir), "backups")
5111
5126
  ),
5112
5127
  run: runProcess,
5113
5128
  isPackageAbsent: () => !fs18.existsSync(packageRoot),
@@ -5286,7 +5301,7 @@ async function runManagedPiSystem(input) {
5286
5301
  }
5287
5302
 
5288
5303
  // src/lib/quality-runner.ts
5289
- import path24 from "path";
5304
+ import path23 from "path";
5290
5305
  import { spawn, spawnSync as spawnSync2 } from "child_process";
5291
5306
  function normalizeLimit(value, name) {
5292
5307
  if (value === void 0) return void 0;
@@ -5418,7 +5433,7 @@ function killProcessTree(child) {
5418
5433
  if (pid === void 0) return;
5419
5434
  if (process.platform === "win32") {
5420
5435
  const systemRoot = process.env.SystemRoot ?? process.env.WINDIR ?? "C:\\Windows";
5421
- const taskkill = path24.join(systemRoot, "System32", "taskkill.exe");
5436
+ const taskkill = path23.join(systemRoot, "System32", "taskkill.exe");
5422
5437
  const result = spawnSync2(taskkill, ["/pid", String(pid), "/t", "/f"], {
5423
5438
  shell: false,
5424
5439
  stdio: "ignore",
@@ -5666,7 +5681,7 @@ async function runQualityPlan(input) {
5666
5681
  // src/lib/engram-install.ts
5667
5682
  import fs19 from "fs";
5668
5683
  import os5 from "os";
5669
- import path25 from "path";
5684
+ import path24 from "path";
5670
5685
  import { execFileSync as execFileSync6 } from "child_process";
5671
5686
  import { createHash as createHash3 } from "crypto";
5672
5687
  var MAX_ENGRAM_ARCHIVE_BYTES = 64 * 1024 * 1024;
@@ -5675,9 +5690,9 @@ var DIGEST_RE = /^sha256:[0-9a-f]{64}$/;
5675
5690
  async function installMissingEngram(options = {}) {
5676
5691
  const platform = options.platform ?? process.platform;
5677
5692
  const homeDir = options.homeDir ?? os5.homedir();
5678
- if (!path25.isAbsolute(homeDir)) return { ok: false, reason: "El directorio personal debe ser absoluto." };
5693
+ if (!path24.isAbsolute(homeDir)) return { ok: false, reason: "El directorio personal debe ser absoluto." };
5679
5694
  const binaryName = platform === "win32" ? "engram.exe" : "engram";
5680
- const bin = path25.join(homeDir, ".local", "bin", binaryName);
5695
+ const bin = path24.join(homeDir, ".local", "bin", binaryName);
5681
5696
  let staging;
5682
5697
  let outcome;
5683
5698
  try {
@@ -5797,9 +5812,9 @@ async function installMissingEngram(options = {}) {
5797
5812
  if (size !== approvedSize || createHash3("sha256").update(archive).digest("hex") !== approvedSha) {
5798
5813
  throw new Error("Engram: tama\xF1o o hash SHA-256 no coincide con el artefacto aprobado.");
5799
5814
  }
5800
- fs19.mkdirSync(path25.dirname(bin), { recursive: true });
5801
- staging = fs19.mkdtempSync(path25.join(path25.dirname(bin), ".engram-install-"));
5802
- const archivePath = path25.join(staging, expectedName);
5815
+ fs19.mkdirSync(path24.dirname(bin), { recursive: true });
5816
+ staging = fs19.mkdtempSync(path24.join(path24.dirname(bin), ".engram-install-"));
5817
+ const archivePath = path24.join(staging, expectedName);
5803
5818
  fs19.writeFileSync(archivePath, archive, { flag: "wx", mode: 384 });
5804
5819
  const binary = execFileSync6(resolveTarBin(), ["-xOf", archivePath, binaryName], {
5805
5820
  maxBuffer: 64 * 1024 * 1024,
@@ -5807,7 +5822,7 @@ async function installMissingEngram(options = {}) {
5807
5822
  stdio: ["ignore", "pipe", "pipe"]
5808
5823
  });
5809
5824
  if (binary.length === 0) throw new Error("El artefacto Engram no contiene un binario v\xE1lido.");
5810
- const stagedBin = path25.join(staging, binaryName);
5825
+ const stagedBin = path24.join(staging, binaryName);
5811
5826
  fs19.writeFileSync(stagedBin, binary, { flag: "wx", mode: 493 });
5812
5827
  fs19.linkSync(stagedBin, bin);
5813
5828
  outcome = { ok: true, bin };