ozali 0.4.0 → 0.4.1

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
@@ -2,6 +2,8 @@
2
2
 
3
3
  # ozali
4
4
 
5
+ [![npm version](https://img.shields.io/npm/v/ozali.svg)](https://www.npmjs.com/package/ozali)
6
+
5
7
  **Bootstrap de IA por equipo — calibra tus proyectos, genera una skill de ejecución con TDD/SDD, y mantiene memoria de equipo (Engram) con histórico aislado.**
6
8
 
7
9
  </div>
@@ -59,7 +61,7 @@ git clone <repo> && node ozali/cli/bin/ozali.mjs init
59
61
  ```bash
60
62
  ozali init # detecta agente, instala la skill, aísla el histórico, instala+configura Engram
61
63
  ozali doctor # health-check read-only (fuente de verdad, Engram, Cloud, Strict TDD, runner…)
62
- ozali update # actualiza la skill instalada a la versión del paquete
64
+ ozali update # actualiza la instalación (skill ozali + ozali-jarvis + permisos) al paquete
63
65
  ozali sync # lleva el histórico (docs + Engram) al repo de conocimiento de equipo
64
66
  ozali audit # navega/audita la memoria de Engram del proyecto (o general)
65
67
  ```
@@ -69,6 +71,18 @@ ozali audit # navega/audita la memoria de Engram del proyecto (o general)
69
71
  `--tui` para el navegador interactivo, `--search "<texto>"` para buscar y `--general` para forzar el
70
72
  alcance. Sin Engram, audita el histórico local de `.ozali/docs/`.
71
73
 
74
+ ### Actualizar a una versión nueva
75
+
76
+ ```bash
77
+ pnpm add -g ozali@<versión> # actualiza el CLI global (pinea la versión por el cooldown de pnpm)
78
+ ozali update # en cada repo: refresca skill ozali + ozali-jarvis + permisos
79
+ ```
80
+
81
+ `ozali update` también **crea ozali-jarvis** en repos inicializados con versiones anteriores. La skill
82
+ `cdk` la **regenera tu agente** (no el CLI): tras `ozali update`, abre el agente y vuelve a correr la
83
+ skill `ozali` para regenerar `cdk` con el contrato nuevo — tus docs por hito y el plan congelado se
84
+ conservan.
85
+
72
86
  `init` también escribe un **perfil base de permisos** (`.claude/settings.json` para Claude Code,
73
87
  `opencode.json` para opencode) para reducir confirmaciones: deja libres comandos seguros y bloquea
74
88
  los destructivos. Es un template — tus reglas se conservan al re-correr `init`. Como Claude Code
package/cli/bin/ozali.mjs CHANGED
@@ -15,7 +15,7 @@ ${c.bold("Comandos:")}
15
15
  init Detecta el agente (Claude Code/opencode), instala la skill ozali,
16
16
  aísla el histórico, configura Engram y el repo de conocimiento.
17
17
  doctor Health-check read-only del proyecto (fuente de verdad, Engram, TDD…).
18
- update Actualiza la skill ozali instalada a la versión de este paquete.
18
+ update Actualiza la instalación (skill ozali + ozali-jarvis + permisos) al paquete.
19
19
  sync Sincroniza el histórico (docs + Engram) con el repo de conocimiento.
20
20
  audit Navega/audita la memoria de Engram del proyecto (o general).
21
21
 
@@ -27,7 +27,7 @@ ${c.bold("Opciones comunes:")}
27
27
  --knowledge-repo <p> (init) Ruta del repo de conocimiento.
28
28
  --no-engram (init) No usar Engram; arranca en modo docs.
29
29
  --no-trust (init) No marcar el workspace como confiable en Claude Code.
30
- --no-jarvis (init) No crear el orquestador ozali-jarvis.
30
+ --no-jarvis (init/update) No crear/refrescar el orquestador ozali-jarvis.
31
31
  --import (sync) Importa del repo de conocimiento a local.
32
32
  --push (sync) Hace push al remoto del repo de conocimiento.
33
33
  --cloud (sync) Replica también a Engram Cloud (si está habilitado).
@@ -75,10 +75,12 @@ async function main() {
75
75
  if (!cmd || opts.help || cmd === "help") { console.log(HELP); return 0; }
76
76
 
77
77
  const cwd = process.cwd();
78
+ // Banner de versión: confirma qué versión de ozali está corriendo en cada comando.
79
+ console.log(`${c.bold("ozali")} ${c.dim("v" + pkgVersion())}`);
78
80
  switch (cmd) {
79
81
  case "init": return await init(cwd, opts);
80
82
  case "doctor": return doctor(cwd);
81
- case "update": return update(cwd);
83
+ case "update": return update(cwd, opts);
82
84
  case "sync": return sync(cwd, opts);
83
85
  case "audit": return await audit(cwd, opts);
84
86
  default:
@@ -528,20 +528,72 @@ function readStrictTdd(cwd, sot) {
528
528
  }
529
529
 
530
530
  // =========================================================== update ==========
531
- export function update(cwd) {
532
- step("ozali update actualizar skill instalada");
531
+ // Lleva una instalación existente al paquete actual: refresca la skill ozali (con sus
532
+ // references), los perfiles de permisos y **crea/refresca ozali-jarvis** (clave para repos
533
+ // inicializados antes de 0.4.0). La skill `cdk` la regenera el AGENTE (no el CLI): se detecta
534
+ // y se guía la regeneración.
535
+ export function update(cwd, opts = {}) {
536
+ step("ozali update — actualizar la instalación al paquete actual");
533
537
  const env = detectAll(cwd);
534
- if (!env.skill.installed) { warn("No hay skill ozali instalada. Corre " + c.bold("ozali init") + " primero."); return 1; }
535
- for (const p of env.skill.paths) {
536
- copyDir(SKILL_SRC, p);
537
- ok(`Actualizada: ${path.relative(cwd, p) || p} → v${pkgVersion()}`);
538
- }
539
538
  const cfgPath = CONFIG_PATH(cwd);
540
539
  const cfg = readJSON(cfgPath);
540
+ if (!env.skill.installed && !cfg) {
541
+ warn("No hay instalación de ozali en esta ruta. Corre " + c.bold("ozali init") + " primero.");
542
+ return 1;
543
+ }
544
+
545
+ // 1) Skill ozali (incluye las references: la base desde la que el agente regenera cdk)
546
+ if (env.skill.installed) {
547
+ for (const p of env.skill.paths) {
548
+ copyDir(SKILL_SRC, p);
549
+ ok(`Skill ozali actualizada: ${path.relative(cwd, p) || p} → v${pkgVersion()}`);
550
+ }
551
+ } else {
552
+ warn("Skill ozali no instalada en esta ruta (corre " + c.bold("ozali init") + " para instalarla).");
553
+ }
554
+
555
+ // Agente/scope: del config; si falta, infiere del entorno.
556
+ const agent = (cfg && cfg.agent) || (env.agents.opencode.present && !env.agents.claudeCode.present ? "opencode"
557
+ : env.agents.claudeCode.present && env.agents.opencode.present ? "both" : "claude-code");
558
+ const scope = (cfg && cfg.scope) || "project";
559
+
560
+ // 2) Perfiles base de permisos (idempotente: recoge defaults nuevos del paquete)
561
+ if (agent === "claude-code" || agent === "both") ensureClaudeCodeProfile(cwd, scope);
562
+ if (agent === "opencode" || agent === "both") ensureOpencodeProfile(cwd);
563
+
564
+ // 3) ozali-jarvis: crea el orquestador en repos previos a 0.4.0 y refresca el resto.
565
+ if (!opts.noJarvis) {
566
+ const proj = projectName(cwd);
567
+ const engPath = path.join(cwd, ".engram", "config.json");
568
+ if (!exists(engPath)) { writeJSON(engPath, { project_name: proj }); ok(`Proyecto de memoria fijado en ${c.bold(".engram/config.json")} (${proj}).`); }
569
+ if (agent === "claude-code" || agent === "both") ensureJarvisClaudeCode(cwd);
570
+ if (agent === "opencode" || agent === "both") ensureJarvisOpencode(cwd);
571
+ }
572
+
573
+ // 4) Skill cdk: la genera el AGENTE (Fase 6), el CLI no la regenera.
574
+ const cdk = detectCdk(cwd);
575
+ if (cdk.installed) {
576
+ step("Skill cdk (generada por el agente)");
577
+ warn("cdk no se actualiza desde el CLI: la regenera tu agente con el contrato nuevo.");
578
+ info("Abre tu agente y vuelve a correr la skill " + c.bold("ozali") + " para regenerar cdk (ozali-jarvis, recall-first §7, telemetría).");
579
+ info("Tus docs por hito (" + c.bold(".ozali/docs/cdk/") + ") y el plan congelado se conservan.");
580
+ }
581
+
582
+ // 5) versión del config
541
583
  if (cfg) { cfg.version = pkgVersion(); cfg.updatedAt = new Date().toISOString(); writeJSON(cfgPath, cfg); }
584
+ ok(`Instalación al día con ozali v${pkgVersion()}.`);
542
585
  return 0;
543
586
  }
544
587
 
588
+ /** ¿Existe la skill cdk (generada por el agente)? */
589
+ function detectCdk(cwd) {
590
+ const paths = [
591
+ path.join(cwd, ".claude", "skills", "cdk", "SKILL.md"),
592
+ path.join(HOME, ".claude", "skills", "cdk", "SKILL.md"),
593
+ ].filter(exists);
594
+ return { installed: paths.length > 0, paths };
595
+ }
596
+
545
597
  // ============================================================= sync ===========
546
598
  export function sync(cwd, opts) {
547
599
  step(`ozali sync${opts.import ? " --import" : ""} — histórico ↔ repo de conocimiento`);
@@ -118,6 +118,20 @@ test("init opencode crea jarvis (AGENTS.md + agente + plugin)", () => {
118
118
  }
119
119
  });
120
120
 
121
+ test("update agrega ozali-jarvis en un repo que no lo tenía", () => {
122
+ const dir = tmpProject();
123
+ try {
124
+ run(["init", "--yes", "--no-engram", "--no-trust", "--no-jarvis", "--agent", "claude-code", "--scope", "project", "--knowledge-repo", path.join(dir, ".k")], dir);
125
+ assert.ok(!fs.existsSync(path.join(dir, ".claude", "agents", "ozali-jarvis.md")), "precondición: sin jarvis");
126
+ run(["update"], dir);
127
+ assert.ok(fs.existsSync(path.join(dir, ".claude", "agents", "ozali-jarvis.md")), "update crea subagente jarvis");
128
+ assert.match(fs.readFileSync(path.join(dir, "CLAUDE.md"), "utf8"), /ozali-jarvis:start/, "update crea bloque jarvis");
129
+ assert.ok(fs.existsSync(path.join(dir, ".engram", "config.json")), "update fija .engram/config.json");
130
+ } finally {
131
+ fs.rmSync(dir, { recursive: true, force: true });
132
+ }
133
+ });
134
+
121
135
  test("init --dry-run no escribe nada", () => {
122
136
  const dir = tmpProject();
123
137
  try {
@@ -82,7 +82,7 @@ Lleva el histórico y la memoria al repo de conocimiento del equipo. Tus compañ
82
82
  |---|---|
83
83
  | `ozali init` | Prepara el proyecto (lo corres una vez por repo). |
84
84
  | `ozali doctor` | Revisa que todo esté bien. Es solo lectura, no cambia nada. |
85
- | `ozali update` | Actualiza la skill a la última versión. |
85
+ | `ozali update` | Actualiza skill ozali + ozali-jarvis + permisos (y guía cómo regenerar cdk). |
86
86
  | `ozali sync` | Sube el histórico/memoria al repo de equipo. |
87
87
  | `ozali sync --import` | Baja lo que el equipo ya guardó. |
88
88
  | `ozali audit` | Navega/audita la memoria de Engram (qué se ha hecho). |
@@ -190,6 +190,11 @@ Es el aviso de seguridad de Claude Code: ignora los permisos del proyecto hasta
190
190
  Deja que `init` lo marque como confiable, o abre Claude Code en la carpeta y acepta el diálogo una
191
191
  vez. Tras eso, el aviso desaparece y los permisos surten efecto.
192
192
 
193
+ **Actualicé ozali pero no veo ozali-jarvis (o cdk quedó viejo).**
194
+ Corre `ozali update` en el repo: refresca la skill ozali, los permisos y **crea/actualiza
195
+ ozali-jarvis**. La skill `cdk` la regenera tu agente: tras `ozali update`, abre el agente y vuelve a
196
+ correr la skill `ozali` para regenerar `cdk` con lo nuevo (tus docs por hito y el plan se conservan).
197
+
193
198
  **¿Funciona en Windows?**
194
199
  Sí. Los permisos base incluyen variantes PowerShell, y Engram se instala con `go install` o un
195
200
  binario descargable.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ozali",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Bootstrap interactivo de IA por equipo: calibra el proyecto, genera la skill de ejecución (cdk) con TDD/SDD, y mantiene memoria de equipo (Engram) con histórico aislado.",
5
5
  "type": "module",
6
6
  "bin": {