jorgex-stack 1.2.2 → 1.2.3

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 (3) hide show
  1. package/README.md +4 -2
  2. package/dist/cli.js +95 -68
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -97,7 +97,7 @@ Programmatic mode does **not** provide:
97
97
 
98
98
  ### Pi runtime
99
99
 
100
- Pi is package-managed rather than file-managed. Stack supports the exact tested pair **Pi 0.84.2 + `jorgex-pi@0.1.0`** and keeps Pi out of the adapter/component manifest and model map.
100
+ Pi is package-managed rather than file-managed. Stack supports the exact published package **`jorgex-pi@0.2.2`** and keeps Pi out of the adapter/component manifest and model map.
101
101
 
102
102
  ```bash
103
103
  pnpm dlx jorgex-stack install --agents pi
@@ -107,10 +107,12 @@ pnpm dlx jorgex-stack sync --agents pi
107
107
  pnpm dlx jorgex-stack uninstall --agents pi
108
108
  ```
109
109
 
110
- Stack downloads the frozen registry tarball, verifies its exact size plus SHA-256/SHA-512, backs up Pi's `settings.json`, and only then asks Pi to install that local file. Pi's own package-manager invocation is the narrow runtime exception to the repository's pnpm-only rule; the Stack lifecycle never launches npm directly. A scope-bound receipt under `~/.jorgex-stack/pi-receipt.json` records ownership only after the package runner reports a healthy install. Manual, duplicate, divergent, partial, corrupt, copied-to-another-scope, or unknown-history state fails closed and is never adopted or removed silently.
110
+ Stack downloads the frozen registry tarball, verifies its exact size plus SHA-256/SHA-512, backs up Pi's `settings.json`, and only then asks Pi to install that local file. Pi's own package-manager invocation is the narrow runtime exception to the repository's pnpm-only rule; the Stack lifecycle never launches npm directly. The managed Pi package entry is the exact source object `{ "source": "npm:jorgex-pi@0.2.2", "skills": [] }`: Pi discovers the canonical shared skills from `~/.agents/skills`, so the package copy is disabled and does not create duplicate skill loading. A scope-bound receipt under `~/.jorgex-stack/pi-receipt.json` records ownership only after the package runner reports a healthy install and stores the verified Engram executable as `engram.binary`, using the schema v1 consumed by `jorgex-pi@0.2.2`. Receipts created before the Engram binding existed require deliberate removal with the previous Stack release followed by reinstall; they are never adopted automatically. Manual, duplicate, divergent, partial, corrupt, copied-to-another-scope, or unknown-history state fails closed and is never adopted or removed silently.
111
111
 
112
112
  Engram remains mandatory and user-owned. An existing binary is preserved. Interactive install may offer the existing native `brew`/`go`/release channel with a default-No confirmation; `--yes` and non-TTY installs fail with a remedy when Engram is absent. No Pi lifecycle operation updates or deletes the Engram database or memories. Under `--target-dir`, Stack accepts only `<target>/bin/engram`, isolates Pi/Home/XDG/AppData/temp/npm-cache paths inside the target, and never consults the host Engram or Pi configuration.
113
113
 
114
+ The 24-hour npm maturity rule applies to the managed adoption boundary: development and PR validation may start against the exact published artifact, but merging the adoption PR, publishing that Stack adoption, and running the real managed installation wait until the package has been public for at least 24 hours unless Jorge explicitly documents an exception in the PR.
115
+
114
116
  `update --agents pi` only runs the Pi package lifecycle; it does not enter the global Stack updater. `update --check --agents pi` is a read-only Pi doctor. Uninstall runs package cleanup, backs up Pi's settings before removal, removes only the exact receipt-owned package after verifying absence, and preserves all companion/user state. Full behavior, failure states and troubleshooting are in [docs/references/pi-runtime.md](docs/references/pi-runtime.md).
115
117
 
116
118
  ### Browser automation
package/dist/cli.js CHANGED
@@ -3755,13 +3755,19 @@ function parsePackageSources(settingsJson) {
3755
3755
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return null;
3756
3756
  const packages = Reflect.get(parsed, "packages");
3757
3757
  if (!Array.isArray(packages)) return null;
3758
- const sources = packages.map(packageSource);
3759
- return sources.every((source) => source !== null) ? sources : null;
3758
+ const sources = packages.map((entry) => ({ entry, source: packageSource(entry) }));
3759
+ return sources.every((value) => value.source !== null) ? sources : null;
3760
3760
  } catch {
3761
3761
  return null;
3762
3762
  }
3763
3763
  }
3764
- function expectedReceipt(candidate, state, scope) {
3764
+ function isExactManagedPackage(entry, source) {
3765
+ if (entry === null || typeof entry !== "object" || Array.isArray(entry)) return false;
3766
+ const keys = Object.keys(entry);
3767
+ const skills = Reflect.get(entry, "skills");
3768
+ return keys.length === 2 && keys.includes("source") && keys.includes("skills") && Reflect.get(entry, "source") === source && Array.isArray(skills) && skills.length === 0;
3769
+ }
3770
+ function expectedReceipt(candidate, state, scope, engramBin) {
3765
3771
  return {
3766
3772
  schemaVersion: 1,
3767
3773
  state,
@@ -3770,21 +3776,52 @@ function expectedReceipt(candidate, state, scope) {
3770
3776
  tarball: candidate.tarball,
3771
3777
  provenance: candidate.provenance
3772
3778
  },
3773
- scope
3779
+ scope,
3780
+ engram: { binary: engramBin }
3774
3781
  };
3775
3782
  }
3776
- function parseReceipt(receiptJson, candidate, scope) {
3783
+ function parseReceiptShape(receiptJson) {
3777
3784
  try {
3778
3785
  const parsed = JSON.parse(receiptJson);
3779
3786
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return null;
3787
+ const schemaVersion = Reflect.get(parsed, "schemaVersion");
3788
+ if (schemaVersion !== 1) return null;
3780
3789
  const state = Reflect.get(parsed, "state");
3781
- if (state !== "installing" && state !== "installed") return null;
3782
- const expected = expectedReceipt(candidate, state, scope);
3783
- return sameRecord(parsed, expected) ? expected : null;
3790
+ const candidate = Reflect.get(parsed, "candidate");
3791
+ if (state !== "installing" && state !== "installed" || candidate === null || typeof candidate !== "object" || Array.isArray(candidate)) {
3792
+ return null;
3793
+ }
3794
+ const packageValue = Reflect.get(candidate, "package");
3795
+ const tarball = Reflect.get(candidate, "tarball");
3796
+ const provenance = Reflect.get(candidate, "provenance");
3797
+ const scope = Reflect.get(parsed, "scope");
3798
+ const engram = Reflect.get(parsed, "engram");
3799
+ if (packageValue === null || typeof packageValue !== "object" || tarball === null || typeof tarball !== "object" || provenance === null || typeof provenance !== "object" || scope === null || typeof scope !== "object" || Array.isArray(scope)) {
3800
+ return null;
3801
+ }
3802
+ const source = Reflect.get(packageValue, "source");
3803
+ const name = Reflect.get(packageValue, "name");
3804
+ const version = Reflect.get(packageValue, "version");
3805
+ const scopeKind = Reflect.get(scope, "kind");
3806
+ const codingAgentDir = Reflect.get(scope, "codingAgentDir");
3807
+ if (name !== "jorgex-pi" || typeof version !== "string" || typeof source !== "string" || source !== `npm:jorgex-pi@${version}` || scopeKind !== "real" && scopeKind !== "target-dir" || typeof codingAgentDir !== "string") {
3808
+ return null;
3809
+ }
3810
+ if (engram === void 0) return "upgrade-required";
3811
+ if (engram === null || typeof engram !== "object" || Array.isArray(engram) || typeof Reflect.get(engram, "binary") !== "string" || !path29.isAbsolute(Reflect.get(engram, "binary"))) {
3812
+ return null;
3813
+ }
3814
+ return parsed;
3784
3815
  } catch {
3785
3816
  return null;
3786
3817
  }
3787
3818
  }
3819
+ function parseReceipt(receiptJson, candidate, scope, engramBin) {
3820
+ const parsed = parseReceiptShape(receiptJson);
3821
+ if (parsed === null || parsed === "upgrade-required") return parsed;
3822
+ const expected = expectedReceipt(candidate, parsed.state, scope, engramBin);
3823
+ return sameRecord(parsed, expected) ? expected : null;
3824
+ }
3788
3825
  function candidateIsValid(candidate, observed) {
3789
3826
  return candidate.package.name === "jorgex-pi" && candidate.package.source === `npm:${candidate.package.name}@${candidate.package.version}` && candidate.contract.schemaVersion === 1 && candidate.contract.runner.schemaVersion === 1 && candidate.contract.runner.bin === "jorgex-pi" && candidate.contract.runner.maxStdoutBytes === 65536 && candidate.contract.managedExternalWrites.length === 0 && [...REQUIRED_CAPABILITIES].every((capability) => candidate.contract.capabilities.includes(capability)) && sameRecord(candidate.tarball, observed);
3790
3827
  }
@@ -3798,21 +3835,26 @@ function planPiPackageLifecycle(input) {
3798
3835
  if (input.engramBin === null) return blocked(input, "engram-missing");
3799
3836
  const sources = parsePackageSources(input.pi.settingsJson);
3800
3837
  if (sources === null) return blocked(input, "settings-corrupt");
3801
- const matchingSources = sources.filter(isJorgeXPiSource);
3802
- const exactSources = matchingSources.filter((source) => source === input.candidate.package.source);
3838
+ const matchingSources = sources.filter(({ source }) => isJorgeXPiSource(source));
3839
+ const exactSources = matchingSources.filter(({ source }) => source === input.candidate.package.source);
3803
3840
  if (exactSources.length > 1) return blocked(input, "duplicate-package");
3804
- if (matchingSources.some((source) => source !== input.candidate.package.source)) {
3841
+ if (matchingSources.some(({ source }) => source !== input.candidate.package.source)) {
3805
3842
  return blocked(input, "source-divergent");
3806
3843
  }
3807
3844
  let receipt = null;
3808
3845
  if (input.receiptJson !== null) {
3809
- receipt = parseReceipt(input.receiptJson, input.candidate, {
3846
+ const parsedReceipt = parseReceipt(input.receiptJson, input.candidate, {
3810
3847
  kind: input.scope.kind,
3811
3848
  codingAgentDir: path29.resolve(input.scope.codingAgentDir)
3812
- });
3813
- if (receipt === null) return blocked(input, "receipt-corrupt");
3849
+ }, input.engramBin);
3850
+ if (parsedReceipt === "upgrade-required") return blocked(input, "receipt-upgrade-required");
3851
+ if (parsedReceipt === null) return blocked(input, "receipt-corrupt");
3852
+ receipt = parsedReceipt;
3814
3853
  if (receipt.state === "installing") return blocked(input, "partial-state");
3815
- if (exactSources.length !== 1) return blocked(input, "partial-state");
3854
+ const exactSource = exactSources[0];
3855
+ if (exactSources.length !== 1 || exactSource === void 0 || !isExactManagedPackage(exactSource.entry, input.candidate.package.source)) {
3856
+ return blocked(input, "source-divergent");
3857
+ }
3816
3858
  }
3817
3859
  if (exactSources.length === 1 && receipt === null) {
3818
3860
  return {
@@ -3839,7 +3881,7 @@ function planPiPackageLifecycle(input) {
3839
3881
  receipt: expectedReceipt(input.candidate, "installing", {
3840
3882
  kind: input.scope.kind,
3841
3883
  codingAgentDir: path29.resolve(input.scope.codingAgentDir)
3842
- }),
3884
+ }, input.engramBin),
3843
3885
  ownership: ownership(true)
3844
3886
  };
3845
3887
  }
@@ -3910,47 +3952,25 @@ function executePiPackageLifecycle(input, deps) {
3910
3952
  }
3911
3953
  return { kind: "models", models: { mode: "inherit-session", tiers: ["strong", "standard", "cheap"] } };
3912
3954
  }
3913
- function readReceiptCandidate(receiptJson) {
3914
- try {
3915
- const parsed = JSON.parse(receiptJson);
3916
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return null;
3917
- const schemaVersion = Reflect.get(parsed, "schemaVersion");
3918
- const state = Reflect.get(parsed, "state");
3919
- const candidate = Reflect.get(parsed, "candidate");
3920
- if (schemaVersion !== 1 || state !== "installing" && state !== "installed" || candidate === null || typeof candidate !== "object" || Array.isArray(candidate)) {
3921
- return null;
3922
- }
3923
- const packageValue = Reflect.get(candidate, "package");
3924
- const tarball = Reflect.get(candidate, "tarball");
3925
- const provenance = Reflect.get(candidate, "provenance");
3926
- const scope = Reflect.get(parsed, "scope");
3927
- if (packageValue === null || typeof packageValue !== "object" || tarball === null || typeof tarball !== "object" || provenance === null || typeof provenance !== "object" || scope === null || typeof scope !== "object" || Array.isArray(scope)) {
3928
- return null;
3929
- }
3930
- const source = Reflect.get(packageValue, "source");
3931
- const name = Reflect.get(packageValue, "name");
3932
- const version = Reflect.get(packageValue, "version");
3933
- if (name !== "jorgex-pi" || typeof version !== "string" || typeof source !== "string" || source !== `npm:jorgex-pi@${version}`) {
3934
- return null;
3935
- }
3936
- const scopeKind = Reflect.get(scope, "kind");
3937
- const codingAgentDir = Reflect.get(scope, "codingAgentDir");
3938
- if (scopeKind !== "real" && scopeKind !== "target-dir" || typeof codingAgentDir !== "string") return null;
3939
- return parsed;
3940
- } catch {
3941
- return null;
3942
- }
3955
+ function receiptUpgradeRequired() {
3956
+ return {
3957
+ kind: "blocked",
3958
+ reason: "receipt-upgrade-required",
3959
+ remedy: "El receipt no enlaza Engram; usa la versi\xF3n anterior de Stack para desinstalarlo y luego reinstala."
3960
+ };
3943
3961
  }
3944
3962
  function validateOwnedOperationState(input) {
3945
3963
  const sources = parsePackageSources(input.detected.settingsJson);
3946
3964
  if (sources === null) return { kind: "blocked", reason: "settings-corrupt" };
3947
- const matchingSources = sources.filter(isJorgeXPiSource);
3965
+ const matchingSources = sources.filter(({ source: source2 }) => isJorgeXPiSource(source2));
3948
3966
  if (matchingSources.length > 1) return { kind: "blocked", reason: "duplicate-package" };
3949
3967
  if (input.receiptJson === null) {
3950
3968
  return { kind: "blocked", reason: matchingSources.length === 1 ? "manual-existing" : "source-divergent" };
3951
3969
  }
3952
- const receipt = readReceiptCandidate(input.receiptJson);
3953
- if (receipt === null) return { kind: "blocked", reason: "receipt-corrupt" };
3970
+ const parsedReceipt = parseReceiptShape(input.receiptJson);
3971
+ if (parsedReceipt === "upgrade-required") return receiptUpgradeRequired();
3972
+ if (parsedReceipt === null) return { kind: "blocked", reason: "receipt-corrupt" };
3973
+ const receipt = parsedReceipt;
3954
3974
  if (receipt.state !== "installed") return { kind: "blocked", reason: "partial-state" };
3955
3975
  const accepted = input.registry.acceptedCandidates ?? [input.registry.candidate];
3956
3976
  if (!accepted.some((candidate) => sameRecord(receipt.candidate, {
@@ -3963,8 +3983,12 @@ function validateOwnedOperationState(input) {
3963
3983
  if (receipt.scope.kind !== (input.paths.targetDir ? "target-dir" : "real") || path29.resolve(receipt.scope.codingAgentDir) !== path29.resolve(input.paths.codingAgentDir)) {
3964
3984
  return { kind: "blocked", reason: "source-divergent" };
3965
3985
  }
3986
+ if (input.engramBin !== null && path29.resolve(receipt.engram.binary) !== path29.resolve(input.engramBin)) {
3987
+ return { kind: "blocked", reason: "receipt-corrupt" };
3988
+ }
3966
3989
  const source = receipt.candidate.package.source;
3967
- if (matchingSources.length !== 1 || matchingSources[0] !== source) {
3990
+ const matchingSource = matchingSources[0];
3991
+ if (matchingSources.length !== 1 || matchingSource === void 0 || matchingSource.source !== source || !isExactManagedPackage(matchingSource.entry, source)) {
3968
3992
  return { kind: "blocked", reason: "source-divergent" };
3969
3993
  }
3970
3994
  return { receipt, source };
@@ -4048,16 +4072,16 @@ function runPiPackageManagedOperation(input, deps) {
4048
4072
  var PI_RUNTIME_CANDIDATE = {
4049
4073
  package: {
4050
4074
  name: "jorgex-pi",
4051
- version: "0.1.0",
4052
- source: "npm:jorgex-pi@0.1.0"
4075
+ version: "0.2.2",
4076
+ source: "npm:jorgex-pi@0.2.2"
4053
4077
  },
4054
4078
  provenance: {
4055
- commit: "791db79e33efd6661899995b5491e4dff5caa363"
4079
+ commit: "99631aa3712f51a625d196e949e48e27f55031a2"
4056
4080
  },
4057
4081
  tarball: {
4058
- bytes: 89066153,
4059
- sha256: "6243bf8e3a8dbe7be9103d7ca9b03e196c41ac9eef6578f47ea6d03655366feb",
4060
- sha512: "07590abec9e9594b001e28d75eb810259c4088f9f2f6d1d5b9fe456bb2d15a7259ff31ee225d5f1f59b27a1c337a1f1f8e3e57089656bf7bbad966e653110ddd"
4082
+ bytes: 89101513,
4083
+ sha256: "e1c6b63719995cf7ba2c96c3b753f19d8f2f0be74f2af9bc319576b7383913f4",
4084
+ sha512: "7b81dc1eb6030d562c70857dcf739798df94c88bddd240b2752c558fc1d21403faa411aa88e182a01664a17e06e2caeef35f1507eff45c97f4acc521469c45a1"
4061
4085
  },
4062
4086
  pi: {
4063
4087
  testedVersions: ["0.84.2"]
@@ -4074,7 +4098,8 @@ var PI_RUNTIME_CANDIDATE = {
4074
4098
  "goal-continuation-v1",
4075
4099
  "mcp-adapter-v1",
4076
4100
  "engram-runtime-tools-v1",
4077
- "runner-json-v1"
4101
+ "runner-json-v1",
4102
+ "tui-branding-v1"
4078
4103
  ],
4079
4104
  runner: {
4080
4105
  bin: "jorgex-pi",
@@ -4134,11 +4159,11 @@ async function resolvePiEngramRequirement(input, deps) {
4134
4159
  remedy: "La instalaci\xF3n termin\xF3, pero Engram no qued\xF3 detectable; configura ENGRAM_BIN."
4135
4160
  } : { kind: "existing", bin: detected, scope: "host" };
4136
4161
  }
4137
- function flatCandidateReceipt(candidate, scope, state) {
4162
+ function flatCandidateReceipt(candidate, scope, state, engramBin) {
4138
4163
  const match = /^npm:jorgex-pi@([^\s]+)$/.exec(candidate.source);
4139
4164
  const packageValue = candidate.package ?? {
4140
4165
  name: "jorgex-pi",
4141
- version: match?.[1] ?? "0.1.0",
4166
+ version: match?.[1] ?? PI_RUNTIME_CANDIDATE.package.version,
4142
4167
  source: candidate.source
4143
4168
  };
4144
4169
  return {
@@ -4149,7 +4174,8 @@ function flatCandidateReceipt(candidate, scope, state) {
4149
4174
  tarball: { bytes: candidate.bytes, sha256: candidate.sha256, sha512: candidate.sha512 },
4150
4175
  provenance: candidate.provenance ?? { commit: PI_RUNTIME_CANDIDATE.provenance.commit }
4151
4176
  },
4152
- scope
4177
+ scope,
4178
+ engram: { binary: engramBin }
4153
4179
  };
4154
4180
  }
4155
4181
  function normalizeInstalledSource(settingsJson, alias, canonical) {
@@ -4158,8 +4184,9 @@ function normalizeInstalledSource(settingsJson, alias, canonical) {
4158
4184
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return null;
4159
4185
  const packages = Reflect.get(parsed, "packages");
4160
4186
  if (!Array.isArray(packages)) return null;
4161
- if (packages.filter((entry) => entry === alias).length !== 1 || packages.includes(canonical)) return null;
4162
- Reflect.set(parsed, "packages", packages.map((entry) => entry === alias ? canonical : entry));
4187
+ const hasCanonical = packages.some((entry) => entry === canonical || entry !== null && typeof entry === "object" && !Array.isArray(entry) && Reflect.get(entry, "source") === canonical);
4188
+ if (packages.filter((entry) => entry === alias).length !== 1 || hasCanonical) return null;
4189
+ Reflect.set(parsed, "packages", packages.map((entry) => entry === alias ? { source: canonical, skills: [] } : entry));
4163
4190
  return JSON.stringify(parsed);
4164
4191
  } catch {
4165
4192
  return null;
@@ -4179,7 +4206,7 @@ function healthyDoctor(stdout, stderr, packageRunner, candidate) {
4179
4206
  }
4180
4207
  function installPiFromVerifiedTarball(input, deps) {
4181
4208
  const paths = input.targetDir === void 0 ? userPaths(input.engramBin, input.piExecutable) : targetPaths(input.targetDir, input.engramBin, input.piExecutable);
4182
- const destination = input.targetDir === void 0 ? path30.join(dataDir(), "packages", "jorgex-pi-0.1.0.tgz") : path30.join(path30.resolve(input.targetDir), "downloads", "jorgex-pi-0.1.0.tgz");
4209
+ const destination = input.targetDir === void 0 ? path30.join(dataDir(), "packages", `jorgex-pi-${PI_RUNTIME_CANDIDATE.package.version}.tgz`) : path30.join(path30.resolve(input.targetDir), "downloads", `jorgex-pi-${PI_RUNTIME_CANDIDATE.package.version}.tgz`);
4183
4210
  const artifact = deps.download(destination);
4184
4211
  if (artifact.bytes !== input.candidate.bytes || artifact.sha256 !== input.candidate.sha256 || artifact.sha512 !== input.candidate.sha512) {
4185
4212
  return { kind: "blocked", reason: "tarball-integrity" };
@@ -4189,7 +4216,7 @@ function installPiFromVerifiedTarball(input, deps) {
4189
4216
  kind: input.targetDir === void 0 ? "real" : "target-dir",
4190
4217
  codingAgentDir: path30.resolve(paths.codingAgentDir)
4191
4218
  };
4192
- const installing = flatCandidateReceipt(input.candidate, scope, "installing");
4219
+ const installing = flatCandidateReceipt(input.candidate, scope, "installing", input.engramBin);
4193
4220
  deps.writeReceiptAtomic(`${JSON.stringify(installing)}
4194
4221
  `);
4195
4222
  const alias = `npm:jorgex-pi@file:${artifact.path}`;
@@ -4210,7 +4237,7 @@ function installPiFromVerifiedTarball(input, deps) {
4210
4237
  if (doctor.exitCode !== 0 || !healthyDoctor(doctor.stdout, doctor.stderr, paths.packageRunner, input.candidate)) {
4211
4238
  return { kind: "blocked", reason: "runner-unhealthy" };
4212
4239
  }
4213
- const receipt = flatCandidateReceipt(input.candidate, scope, "installed");
4240
+ const receipt = flatCandidateReceipt(input.candidate, scope, "installed", input.engramBin);
4214
4241
  deps.writeReceiptAtomic(`${JSON.stringify(receipt)}
4215
4242
  `);
4216
4243
  return { kind: "installed", receipt };
@@ -4430,11 +4457,11 @@ async function acquirePiTarball(destination) {
4430
4457
  }
4431
4458
  fs22.mkdirSync(path30.dirname(destination), { recursive: true });
4432
4459
  const partial = `${destination}.partial-${process.pid}`;
4433
- const response = await fetch("https://registry.npmjs.org/jorgex-pi/-/jorgex-pi-0.1.0.tgz", {
4460
+ const response = await fetch(`https://registry.npmjs.org/jorgex-pi/-/jorgex-pi-${PI_RUNTIME_CANDIDATE.package.version}.tgz`, {
4434
4461
  redirect: "error",
4435
4462
  headers: { accept: "application/octet-stream" }
4436
4463
  });
4437
- if (!response.ok || response.body === null) throw new Error(`No se pudo descargar jorgex-pi@0.1.0 (${response.status}).`);
4464
+ if (!response.ok || response.body === null) throw new Error(`No se pudo descargar jorgex-pi@${PI_RUNTIME_CANDIDATE.package.version} (${response.status}).`);
4438
4465
  const descriptor = fs22.openSync(partial, "wx", 384);
4439
4466
  let bytes = 0;
4440
4467
  try {
@@ -4501,7 +4528,7 @@ async function runPiRuntimeSystem(input) {
4501
4528
  remedy: "Instala Engram o configura un ENGRAM_BIN absoluto antes de reintentar."
4502
4529
  };
4503
4530
  }
4504
- const destination = input.targetDir === void 0 ? path30.join(dataDir(), "packages", "jorgex-pi-0.1.0.tgz") : path30.join(path30.resolve(input.targetDir), "downloads", "jorgex-pi-0.1.0.tgz");
4531
+ const destination = input.targetDir === void 0 ? path30.join(dataDir(), "packages", `jorgex-pi-${PI_RUNTIME_CANDIDATE.package.version}.tgz`) : path30.join(path30.resolve(input.targetDir), "downloads", `jorgex-pi-${PI_RUNTIME_CANDIDATE.package.version}.tgz`);
4505
4532
  let artifact;
4506
4533
  try {
4507
4534
  artifact = await acquirePiTarball(destination);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jorgex-stack",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "Harness multi-agente portable: instala la config JorgeX (agentes, skills, hooks, Engram, MCPs) en Claude Code, Codex CLI y OpenCode",
5
5
  "type": "module",
6
6
  "license": "MIT",