jorgex-stack 1.0.7 → 1.0.9

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # JorgeX Stack
2
2
 
3
- Portable multi-agent harness: one configuration source — 15 agents, 18 skills, hooks, persistent memory ([Engram](https://github.com/Gentleman-Programming/engram)), MCPs, and system prompt — installable with one command in **Claude Code**, **Codex CLI**, and **OpenCode**.
3
+ Portable multi-agent harness: one configuration source — 15 agents, 17 skills, hooks, persistent memory ([Engram](https://github.com/Gentleman-Programming/engram)), MCPs, and system prompt — installable with one command in **Claude Code**, **Codex CLI**, and **OpenCode**.
4
4
 
5
5
  > Inspired by [gentle-ai](https://github.com/Gentleman-Programming/gentle-ai), rebuilt for the JorgeX stack.
6
6
 
@@ -13,7 +13,7 @@ pnpm dlx jorgex-stack install # interactive: choose runtimes and confirm
13
13
  pnpm dlx jorgex-stack models # model picker by runtime and tier (strong/standard/cheap)
14
14
  pnpm dlx jorgex-stack sync # reapplies config (idempotent; removes orphans)
15
15
  pnpm dlx jorgex-stack doctor # checks that everything is healthy (Engram, drift, hooks, keys)
16
- pnpm dlx jorgex-stack update # interactive: scans stack/Engram/skills, multiselect, diff/confirm
16
+ pnpm dlx jorgex-stack update # interactive: scans stack + Engram, multiselect, diff/confirm
17
17
  # With --check: report only, no changes
18
18
  # With --yes: batch mode (report only)
19
19
  pnpm dlx jorgex-stack restore # restores a backup
@@ -26,11 +26,11 @@ Every command supports `--dry-run`, `--yes`, and `--target-dir <dir>` for testin
26
26
 
27
27
  ### Update: Interactive Flow
28
28
 
29
- `update` manages three sources:
29
+ `update` manages two sources for the end user, plus a maintainer-only one:
30
30
 
31
31
  1. **Stack** (jorgex-stack): detects whether it is a git clone or a global install, then offers an update with confirmation.
32
32
  2. **Engram** (binary): detects the installed version and offers an update through the **native channel** (brew -> `go install` -> release URL). Nothing needs to be stopped: as in upstream macOS/Linux, live processes keep using the old version until clients restart; on Windows, the in-use `.exe` is rotated by rename before installation. **Automatic DB backup before updating**. The database and memories are never touched.
33
- 3. **Vendored skills**: detects changes in upstreams registered in `upstreams.json`, downloads the upstream to a temp directory, **shows a mandatory diff**, and asks for confirmation. Skills with local changes (`modified: true`) warn and require double confirmation.
33
+ 3. **Vendored skills** (maintainer only): third-party skills ship **pinned** with the stack version, so the installed package never reaches out to their upstreams. Only when running from a git clone (`pnpm cli update`) does `update` scan the upstreams in `upstreams.json`, download to a temp directory, **show a mandatory diff**, and ask for confirmation — so the review and re-pin persist in the repo and get published. Skills with local changes (`modified: true`) warn and require double confirmation.
34
34
 
35
35
  Usage:
36
36
  - `update --check`: scans versions without applying changes.
package/dist/cli.js CHANGED
@@ -1947,6 +1947,9 @@ function loadUpstreams() {
1947
1947
  const file = path22.join(path22.dirname(stackRoot()), "upstreams.json");
1948
1948
  return JSON.parse(fs16.readFileSync(file, "utf8"));
1949
1949
  }
1950
+ function skillsToScan(maintainer, upstreams) {
1951
+ return maintainer ? Object.keys(upstreams.skills) : [];
1952
+ }
1950
1953
  async function latestNpmVersion(pkg) {
1951
1954
  try {
1952
1955
  const res = await fetch(`https://registry.npmjs.org/${pkg}/latest`, {
@@ -1985,37 +1988,45 @@ async function runUpdateCheck(localVersion) {
1985
1988
  `engram: ${local} local, ${latest} disponible. Tu instalaci\xF3n NO se toca (D7) \u2014 actualiza t\xFA: github.com/${engramRepo}/releases`
1986
1989
  );
1987
1990
  }
1988
- const byRepo = /* @__PURE__ */ new Map();
1989
- for (const [name, info] of Object.entries(upstreams.skills)) {
1990
- const repo = info.source.replace(/^github:/, "");
1991
- const entry = byRepo.get(repo) ?? { skills: [], pinned: info.commit };
1992
- entry.skills.push(info.modified ? `${name} (modificada localmente)` : name);
1993
- byRepo.set(repo, entry);
1994
- }
1995
- const heads = await Promise.all(
1996
- [...byRepo.keys()].map(async (repo) => [repo, await latestGithubCommit(repo)])
1997
- );
1998
- let moved = 0;
1999
- for (const [repo, head] of heads) {
2000
- const { skills, pinned } = byRepo.get(repo);
2001
- if (!pinned)
2002
- p4.log.warn(
2003
- `${repo}: sin pin en upstreams.json \u2014 a\xF1ade el commit revisado. Skills: ${skills.join(", ")}`
2004
- );
2005
- else if (head === null)
2006
- p4.log.info(`${repo}: pin ${pinned.slice(0, 7)} (no se pudo consultar el upstream).`);
2007
- else if (head === pinned)
2008
- p4.log.success(`${repo}: al d\xEDa con el pin ${pinned.slice(0, 7)} (${skills.join(", ")}).`);
2009
- else {
2010
- moved++;
2011
- p4.log.warn(
2012
- `${repo}: el upstream se movi\xF3 (pin ${pinned.slice(0, 7)} \u2192 ${head.slice(0, 7)}). Skills: ${skills.join(", ")}.
1991
+ const checkSkillNames = skillsToScan(isGitClone(), upstreams);
1992
+ if (checkSkillNames.length === 0) {
1993
+ p4.log.info(
1994
+ "Skills de terceros: pineadas con la versi\xF3n del stack (su revisi\xF3n upstream se hace desde el clon del repo)."
1995
+ );
1996
+ } else {
1997
+ const byRepo = /* @__PURE__ */ new Map();
1998
+ for (const name of checkSkillNames) {
1999
+ const info = upstreams.skills[name];
2000
+ const repo = info.source.replace(/^github:/, "");
2001
+ const entry = byRepo.get(repo) ?? { skills: [], pinned: info.commit };
2002
+ entry.skills.push(info.modified ? `${name} (modificada localmente)` : name);
2003
+ byRepo.set(repo, entry);
2004
+ }
2005
+ const heads = await Promise.all(
2006
+ [...byRepo.keys()].map(async (repo) => [repo, await latestGithubCommit(repo)])
2007
+ );
2008
+ let moved = 0;
2009
+ for (const [repo, head] of heads) {
2010
+ const { skills, pinned } = byRepo.get(repo);
2011
+ if (!pinned)
2012
+ p4.log.warn(
2013
+ `${repo}: sin pin en upstreams.json \u2014 a\xF1ade el commit revisado. Skills: ${skills.join(", ")}`
2014
+ );
2015
+ else if (head === null)
2016
+ p4.log.info(`${repo}: pin ${pinned.slice(0, 7)} (no se pudo consultar el upstream).`);
2017
+ else if (head === pinned)
2018
+ p4.log.success(`${repo}: al d\xEDa con el pin ${pinned.slice(0, 7)} (${skills.join(", ")}).`);
2019
+ else {
2020
+ moved++;
2021
+ p4.log.warn(
2022
+ `${repo}: el upstream se movi\xF3 (pin ${pinned.slice(0, 7)} \u2192 ${head.slice(0, 7)}). Skills: ${skills.join(", ")}.
2013
2023
  Revisa el diff y, si lo aceptas, actualiza la copia vendorizada y el pin: github.com/${repo}/compare/${pinned.slice(0, 7)}...${head.slice(0, 7)}`
2014
- );
2024
+ );
2025
+ }
2026
+ }
2027
+ if (moved === 0 && heads.every(([, head]) => head !== null)) {
2028
+ p4.log.info("Skills de terceros: ning\xFAn upstream se ha movido respecto a su pin.");
2015
2029
  }
2016
- }
2017
- if (moved === 0 && heads.every(([, head]) => head !== null)) {
2018
- p4.log.info("Skills de terceros: ning\xFAn upstream se ha movido respecto a su pin.");
2019
2030
  }
2020
2031
  if (githubRateLimited()) {
2021
2032
  p4.log.warn(rateLimitHint("GitHub limit\xF3 algunas consultas (rate limit sin token)."));
@@ -2046,8 +2057,7 @@ function isEngramRunning() {
2046
2057
  return null;
2047
2058
  }
2048
2059
  }
2049
- function isGitClone() {
2050
- const projectRoot = path22.dirname(stackRoot());
2060
+ function isGitClone(projectRoot = path22.dirname(stackRoot())) {
2051
2061
  return fs16.existsSync(path22.join(projectRoot, ".git"));
2052
2062
  }
2053
2063
  var STACK_METHOD_CLONE = "git pull + pnpm install + pnpm build";
@@ -2325,8 +2335,10 @@ async function runInteractiveUpdate(localVersion, yes, dryRun = false) {
2325
2335
  const upstreams = loadUpstreams();
2326
2336
  let exitCode = 0;
2327
2337
  let appliedUpdates = false;
2338
+ const maintainer = isGitClone();
2328
2339
  const spin = p4.spinner();
2329
2340
  spin.start("Consultando versiones upstream\u2026");
2341
+ const skillNames = skillsToScan(maintainer, upstreams);
2330
2342
  const [npmLatest, engramLatestRaw, ...skillHeads] = await Promise.all([
2331
2343
  latestNpmVersion("jorgex-stack"),
2332
2344
  (async () => {
@@ -2334,7 +2346,7 @@ async function runInteractiveUpdate(localVersion, yes, dryRun = false) {
2334
2346
  if (!repo) return null;
2335
2347
  return { repo, version: await latestGithubRelease(repo) };
2336
2348
  })(),
2337
- ...Object.keys(upstreams.skills).map(async (name) => {
2349
+ ...skillNames.map(async (name) => {
2338
2350
  const info = upstreams.skills[name];
2339
2351
  const repo = info.source.replace(/^github:/, "");
2340
2352
  const head = await latestGithubCommit(repo);
@@ -2354,7 +2366,7 @@ async function runInteractiveUpdate(localVersion, yes, dryRun = false) {
2354
2366
  p4.log.success(`jorgex-stack: v${localVersion} \u2014 al d\xEDa.`);
2355
2367
  } else {
2356
2368
  stackNeedsUpdate = true;
2357
- const mode = isGitClone() ? STACK_METHOD_CLONE : `pnpm add -g jorgex-stack@${npmLatest}`;
2369
+ const mode = maintainer ? STACK_METHOD_CLONE : `pnpm add -g jorgex-stack@${npmLatest}`;
2358
2370
  updateItems.push({
2359
2371
  value: "stack",
2360
2372
  label: `jorgex-stack: v${localVersion} \u2192 v${npmLatest}`,
@@ -2406,6 +2418,11 @@ async function runInteractiveUpdate(localVersion, yes, dryRun = false) {
2406
2418
  p4.log.success(`${repo}: al d\xEDa (pin ${pinned.slice(0, 7)}). Skills: ${names.join(", ")}`);
2407
2419
  }
2408
2420
  }
2421
+ if (!maintainer) {
2422
+ p4.log.info(
2423
+ "Skills de terceros: pineadas con esta versi\xF3n del stack \u2014 su revisi\xF3n upstream se hace desde el clon del repo."
2424
+ );
2425
+ }
2409
2426
  const skillUpdates = buildEligibleSkillUpdates(typedSkillHeads);
2410
2427
  for (const skillInfo of skillUpdates) {
2411
2428
  const modifiedWarning = skillInfo.modified ? " \u26A0 modificada localmente" : "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jorgex-stack",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
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",
package/upstreams.json CHANGED
@@ -23,20 +23,15 @@
23
23
  },
24
24
  "diagnose": {
25
25
  "source": "github:mattpocock/skills",
26
- "path": "skills/engineering/diagnose",
27
- "commit": "694fa30311e02c2639942308513555e61ee84a6f"
26
+ "path": "skills/engineering/diagnosing-bugs",
27
+ "commit": "694fa30311e02c2639942308513555e61ee84a6f",
28
+ "note": "upstream renombró la carpeta diagnose → diagnosing-bugs; mantenemos el nombre local 'diagnose'. El pin sigue en la última revisión aceptada hasta hacer diff y re-pin deliberado del contenido nuevo."
28
29
  },
29
30
  "find-skills": {
30
31
  "source": "github:vercel-labs/skills",
31
32
  "path": "skills/find-skills",
32
33
  "commit": "be0dd25b4a8665894a56f45ef582cc02ca802c39"
33
34
  },
34
- "graphify": {
35
- "source": "github:safishamsi/graphify",
36
- "kind": "release",
37
- "version": "0.7.16",
38
- "commit": "cce26730212baab6d92ce5f390ef5aae56268f31"
39
- },
40
35
  "mcp-builder": {
41
36
  "source": "github:anthropics/skills",
42
37
  "path": "skills/mcp-builder",
@@ -1 +0,0 @@
1
- 0.7.16