ostacky 0.7.2 → 0.7.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.
package/dist/cli.js CHANGED
@@ -235,6 +235,11 @@ function findOpenCodeDir(startDir = process.cwd()) {
235
235
  }
236
236
  }
237
237
  function findProjectRoot(startDir = process.cwd()) {
238
+ try {
239
+ const out = execFileSync("git", ["rev-parse", "--show-toplevel"], { encoding: "utf-8", cwd: startDir, stdio: ["pipe", "pipe", "pipe"] }).trim();
240
+ if (out && existsSync(out))
241
+ return resolve(out);
242
+ } catch {}
238
243
  let current = resolve(startDir);
239
244
  while (true) {
240
245
  if (existsSync(join(current, ".opencode")) || existsSync(join(current, ".git"))) {
@@ -546,31 +551,31 @@ var init_fs = __esm(() => {
546
551
  var manifest_default;
547
552
  var init_manifest = __esm(() => {
548
553
  manifest_default = {
549
- version: "0.7.2",
554
+ version: "0.7.3",
550
555
  repo: "JaimeHoracio/Ostacky",
551
- tag: "v0.7.2",
556
+ tag: "v0.7.3",
552
557
  agents: [
553
558
  {
554
559
  name: "ostacky",
555
560
  file: "assets/agents/ostacky.md",
556
- description: "Orquestador con recuperación automática (nunca se congela), ruteo por nivel de impacto, controller MCP con SDK oficial, edición segura con fallback inline, y delegación en OpenSpec + Superpowers. v0.7.2: prune de skills obsoletas, lastHandoff, getAvailableTransitions, consecutiveFailures real, mem_session_summary automático al cierre.",
557
- version: "0.7.2",
558
- sha256: "1b6a5cbb49f1c6e977241f8ab86d1a045fdb8a04111bbc75633429a131c71acd"
561
+ description: "Orquestador con recuperación automática (nunca se congela), ruteo por nivel de impacto, controller MCP con SDK oficial, edición segura con fallback inline, y delegación en OpenSpec + Superpowers. v0.7.3: prune de skills obsoletas, lastHandoff, getAvailableTransitions, consecutiveFailures real, mem_session_summary automático al cierre.",
562
+ version: "0.7.3",
563
+ sha256: "b6dc55a9571f9626e7912ac493cc3bfe6b0798a597f706904b2106a4a9acfcd5"
559
564
  }
560
565
  ],
561
566
  commands: [
562
567
  {
563
568
  name: "install-stack",
564
569
  file: "assets/commands/install-stack.md",
565
- description: "Instala el stack tecnológico del proyecto (CodeGraph, skills, OpenSpec, Engram, Context7, controller MCP con SDK oficial). v0.7.2: Paso 1.5 controller expandido con verificación post-instalación y troubleshooting.",
566
- version: "0.7.2",
567
- sha256: "7277d333bfe65e674b9696fa5f887854e35824eb5b88420dd0f5bbde3bca7add"
570
+ description: "Instala el stack tecnológico del proyecto (CodeGraph, skills, OpenSpec, Engram, Context7, controller MCP con SDK oficial). v0.7.3: Paso 1.5 controller expandido con verificación post-instalación y troubleshooting.",
571
+ version: "0.7.3",
572
+ sha256: "0d4bc0938110c40633b041847148d8212e34a5b5876752825cfd6e186c328b8b"
568
573
  },
569
574
  {
570
575
  name: "opsx-sync",
571
576
  file: "assets/commands/opsx-sync.md",
572
577
  description: "Sincroniza delta specs del change activo sin inicializar CodeGraph si ya existe índice",
573
- version: "0.7.2",
578
+ version: "0.7.3",
574
579
  sha256: "fe0158478f2ca63b315037a85fc1632b77868532e319af6c7384285441767d64"
575
580
  }
576
581
  ],
@@ -578,15 +583,15 @@ var init_manifest = __esm(() => {
578
583
  {
579
584
  name: "ostacky-controller",
580
585
  file: "assets/mcp/ostacky-controller/",
581
- description: "Máquina de estados persistida con @modelcontextprotocol/server SDK. v0.7.2: 22 tools (incluye set_handoff, get_handoff, clear_handoff, get_available_transitions funcional). Bugfixes: consecutiveFailures real, lastHandoff state, defaultChoice persistido. Robustez: degraded mode automático tras 3 fallos, persistence condicional para Nivel 0, prune de skills obsoletas.",
582
- version: "0.7.2",
583
- sha256: "34048819b8905dff24c731e02d813deb4fb7fbbb65e8b8df66e5c8db201492a0"
586
+ description: "Máquina de estados persistida con @modelcontextprotocol/server SDK. v0.7.3: 22 tools (incluye set_handoff, get_handoff, clear_handoff, get_available_transitions funcional). Bugfixes: consecutiveFailures real, lastHandoff state, defaultChoice persistido. Robustez: degraded mode automático tras 3 fallos, persistence condicional para Nivel 0, prune de skills obsoletas.",
587
+ version: "0.7.3",
588
+ sha256: "d723afc107c8a36721e7f04dc1c16694a617cd562492e1ece362482c9023b945"
584
589
  },
585
590
  {
586
591
  name: "openspec",
587
592
  file: "assets/mcp/openspec/",
588
593
  description: "MCP server local para OpenSpec - proposal, apply, archive, sync de cambios",
589
- version: "0.7.2",
594
+ version: "0.7.3",
590
595
  sha256: "fa4be28bfc1e75db8f1a037e2580f04a60066c80e8e5934e90e1041020d04609"
591
596
  }
592
597
  ],
@@ -595,106 +600,106 @@ var init_manifest = __esm(() => {
595
600
  name: "brainstorming",
596
601
  file: "assets/skills/brainstorming/SKILL.md",
597
602
  description: "Skill unificado de pensamiento con dos modos: creative-design (producción de diseño → transición a implementación directa o openspec-propose) y open-exploration (exploración libre)",
598
- version: "0.7.2",
603
+ version: "0.7.3",
599
604
  sha256: "333810ca63450e8ab795e8c5a58e645101e788d79210ca8ac36e10d11be39585"
600
605
  },
601
606
  {
602
607
  name: "execution-mode-evaluation",
603
608
  file: "assets/skills/execution-mode-evaluation/SKILL.md",
604
609
  description: "Skill de análisis de modo de ejecución — output reconciliado con controller snapshot contract (recommendation field)",
605
- version: "0.7.2",
606
- sha256: "edf6fca0af52cce83f8fd08e7db9b3d79cc130b53fca505e90d3fbaf4909338b"
610
+ version: "0.7.3",
611
+ sha256: "e17f1e0309572841dc1fa537b1f32c7468eb70b3acf453b9ff5cc4fa8d94fd39"
607
612
  },
608
613
  {
609
614
  name: "tdd",
610
615
  file: "assets/skills/tdd/SKILL.md",
611
616
  description: "Skill de test-driven development (Superpowers)",
612
- version: "0.7.2",
617
+ version: "0.7.3",
613
618
  sha256: "aa412298980b7826165c211145c1b8e9135f68f36247bb3cb96d0a0eae274486"
614
619
  },
615
620
  {
616
621
  name: "subagent-driven-development",
617
622
  file: "assets/skills/subagent-driven-development/SKILL.md",
618
623
  description: "Skill de ejecución con subagentes (Superpowers) — ejecuta solo después de confirmación del coordinador Ostacky",
619
- version: "0.7.2",
624
+ version: "0.7.3",
620
625
  sha256: "1a42d714a9a13faf05f0bf7b580e8d837c2e77a5633839542ccce603023419e8"
621
626
  },
622
627
  {
623
628
  name: "dispatching-parallel-agents",
624
629
  file: "assets/skills/dispatching-parallel-agents/SKILL.md",
625
630
  description: "Skill de dispatch paralelo de agentes (Superpowers)",
626
- version: "0.7.2",
631
+ version: "0.7.3",
627
632
  sha256: "3c8a66d51ae2e719e877d02c3dac32bd804722c3bb9227c258ecae78252a20ab"
628
633
  },
629
634
  {
630
635
  name: "review",
631
636
  file: "assets/skills/review/SKILL.md",
632
637
  description: "Skill de revisión de código (Superpowers)",
633
- version: "0.7.2",
638
+ version: "0.7.3",
634
639
  sha256: "b19650ed4d1d4d9857a4dd5b7e08e91328a1a1fc9c45bcc2fb600fa9d0213279"
635
640
  },
636
641
  {
637
642
  name: "receiving-code-review",
638
643
  file: "assets/skills/receiving-code-review/SKILL.md",
639
644
  description: "Skill de recibir y procesar feedback de code review",
640
- version: "0.7.2",
645
+ version: "0.7.3",
641
646
  sha256: "d761e884e71d8d3476ac734d287cae403a4024506a7d12e7361a448217c0a831"
642
647
  },
643
648
  {
644
649
  name: "openspec-propose",
645
650
  file: "assets/skills/openspec-propose/SKILL.md",
646
651
  description: "Skill de generación de proposal (OpenSpec)",
647
- version: "0.7.2",
652
+ version: "0.7.3",
648
653
  sha256: "bb59100b9fd3c9f9a1ec6509fa975ec55bf7fc737df4fe73bb3e9bbc217b83f7"
649
654
  },
650
655
  {
651
656
  name: "openspec-apply-change",
652
657
  file: "assets/skills/openspec-apply-change/SKILL.md",
653
658
  description: "Skill de aplicación de change (OpenSpec)",
654
- version: "0.7.2",
659
+ version: "0.7.3",
655
660
  sha256: "dfc823bf89fc7505e91ab6dee9c1f004be38a410bd3d88fb67b211b1b6cbb1d0"
656
661
  },
657
662
  {
658
663
  name: "openspec-archive-change",
659
664
  file: "assets/skills/openspec-archive-change/SKILL.md",
660
665
  description: "Skill de archivo de change (OpenSpec)",
661
- version: "0.7.2",
666
+ version: "0.7.3",
662
667
  sha256: "16e4b561de7747283663fed602e506abf502452c49a8d4b86d7a5539c40f0195"
663
668
  },
664
669
  {
665
670
  name: "openspec-explore",
666
671
  file: "assets/skills/openspec-explore/SKILL.md",
667
672
  description: "Modo explore para OpenSpec — thinking partner para explorar ideas, investigar problemas y clarificar requisitos antes/durante un cambio",
668
- version: "0.7.2",
673
+ version: "0.7.3",
669
674
  sha256: "37ae4aaf17ea71a395bab6dc4d9d61b9a49d7910f6692535ae8553244c46880b"
670
675
  },
671
676
  {
672
677
  name: "using-git-worktrees",
673
678
  file: "assets/skills/using-git-worktrees/SKILL.md",
674
679
  description: "Skill de uso de git worktrees para aislamiento de trabajo",
675
- version: "0.7.2",
676
- sha256: "11afa9123828fc5caa22137aff907cd99c751e99027fbd4c020751110a949281"
680
+ version: "0.7.3",
681
+ sha256: "93341bc1b7c053618a8b6dc07e3615b77990d7b549a0201f5835d95fef67ce13"
677
682
  },
678
683
  {
679
684
  name: "using-superpowers",
680
685
  file: "assets/skills/using-superpowers/SKILL.md",
681
686
  description: "Skill de orquestación de Superpowers skills",
682
- version: "0.7.2",
687
+ version: "0.7.3",
683
688
  sha256: "7e54536f96d2a379185a10bfc1e970850caa2561b6d8aca7080f0defea0381a4"
684
689
  },
685
690
  {
686
691
  name: "writing-skills",
687
692
  file: "assets/skills/writing-skills/SKILL.md",
688
693
  description: "Skill de creación y edición de skills",
689
- version: "0.7.2",
694
+ version: "0.7.3",
690
695
  sha256: "3d76b906cee518a2b809febb70db95697a35b9f368986bb504b4120c3bfb437a"
691
696
  },
692
697
  {
693
698
  name: "graceful-degradation",
694
699
  file: "assets/skills/graceful-degradation/SKILL.md",
695
700
  description: "Skill de degradación graceful cuando múltiples tools están indisponibles",
696
- version: "0.7.2",
697
- sha256: "376dc90fa27ab7e5947747f20ccf2cc76f9326c77b567fda388252a60d25c431"
701
+ version: "0.7.3",
702
+ sha256: "630b87c16d78212c865696ca5df6abb0834606095ffe0e80cff8e04350f01054"
698
703
  }
699
704
  ]
700
705
  };
@@ -1494,7 +1499,7 @@ var init_stack = __esm(() => {
1494
1499
  // package.json
1495
1500
  var package_default = {
1496
1501
  name: "ostacky",
1497
- version: "0.7.2",
1502
+ version: "0.7.3",
1498
1503
  description: "Instalador interactivo de agentes y comandos para OpenCode",
1499
1504
  type: "module",
1500
1505
  bin: {
@@ -2494,7 +2499,6 @@ import { dirname as dirname7 } from "path";
2494
2499
  init_github();
2495
2500
  init_fs();
2496
2501
  init_lockfile();
2497
- import { homedir as homedir2 } from "os";
2498
2502
 
2499
2503
  // src/installer.ts
2500
2504
  init_github();
@@ -2670,7 +2674,7 @@ async function probeMcpServer(nodeExecutable, serverPath, cwd, statePath, option
2670
2674
  params: {
2671
2675
  protocolVersion: "2025-03-26",
2672
2676
  capabilities: {},
2673
- clientInfo: { name: "ostacky-installer", version: "0.7.2" }
2677
+ clientInfo: { name: "ostacky-installer", version: "0.7.3" }
2674
2678
  }
2675
2679
  });
2676
2680
  });
@@ -3029,18 +3033,19 @@ function printPostInstallSteps() {
3029
3033
  async function resolveOpenCodePaths(scope) {
3030
3034
  if (scope === "local" || scope === "global" || scope === "auto") {
3031
3035
  const dir2 = getOpenCodeDirForScope(scope);
3036
+ const isGlobalDir = dir2.replace(/\\/g, "/") === getGlobalOpenCodeDir().replace(/\\/g, "/");
3032
3037
  try {
3033
3038
  const paths = ensureOpenCodePaths(dir2);
3034
3039
  if (scope === "global")
3035
3040
  ye(dir2, "Instalación global");
3036
3041
  else if (scope === "auto")
3037
- ye(dir2, `Scope auto → ${dir2.includes(homedir2()) && dir2.includes(".config") ? "global" : "local"}`);
3042
+ ye(dir2, `Scope auto → ${isGlobalDir ? "global" : "local"}`);
3038
3043
  else
3039
3044
  ye(dir2, "Instalación local");
3040
3045
  return paths;
3041
3046
  } catch (e2) {
3042
3047
  const msg = e2.message ?? "";
3043
- if (scope === "global" && (msg.includes("EACCES") || msg.includes("permission"))) {
3048
+ if ((scope === "global" || scope === "auto" && isGlobalDir) && (msg.includes("EACCES") || msg.toLowerCase().includes("permission"))) {
3044
3049
  v2.warn(`No se pudo escribir en global (${dir2}): ${msg}. ¿Instalar local?`);
3045
3050
  const retry = await me({ message: "¿Reintentar como instalación local?" });
3046
3051
  onCancel(retry);
@@ -3082,7 +3087,9 @@ async function resolveOpenCodePaths(scope) {
3082
3087
  }
3083
3088
  }
3084
3089
  function isGlobalScope(paths) {
3085
- return paths.root === getGlobalOpenCodeDir() || paths.root.startsWith(getGlobalOpenCodeDir() + "/");
3090
+ const globalDir = getGlobalOpenCodeDir().replace(/\\/g, "/");
3091
+ const root = paths.root.replace(/\\/g, "/");
3092
+ return root === globalDir || root.startsWith(globalDir + "/");
3086
3093
  }
3087
3094
  function getOrphanedItems(manifest, paths) {
3088
3095
  const lockfile = readLockfile(paths.root);
@@ -3200,7 +3207,7 @@ async function doInstallStack(toolsDir, projectRoot) {
3200
3207
  async function doInstallAll(manifest, paths) {
3201
3208
  const spin = L2();
3202
3209
  let errors = 0;
3203
- const isGlobal = paths.root === getGlobalOpenCodeDir() || paths.root.startsWith(getGlobalOpenCodeDir() + "/");
3210
+ const isGlobal = isGlobalScope(paths);
3204
3211
  if (!isGlobal) {
3205
3212
  ensureToolDirs(paths.tools, ["codegraph", "engram", "context7"]);
3206
3213
  } else {
@@ -3934,6 +3941,13 @@ async function runInstallStackCommand(scope) {
3934
3941
  fe("Cancelado.");
3935
3942
  return;
3936
3943
  }
3944
+ if (isGlobalScope(paths)) {
3945
+ v2.error("install-stack requiere scope local; el stack vive en <proyecto>/.opencode/tools");
3946
+ v2.info(`Scope resuelto a global (${paths.root}) — el stack debe instalarse por proyecto local.`);
3947
+ fe("Cancelado.");
3948
+ process.exitCode = 1;
3949
+ return;
3950
+ }
3937
3951
  ensureToolDirs(paths.tools, ["codegraph", "engram", "context7"]);
3938
3952
  const stackOk = await doInstallStack(paths.tools, dirname7(paths.root));
3939
3953
  if (!stackOk)
@@ -4127,6 +4141,9 @@ async function runUninstallMcpCommand(name, scope) {
4127
4141
  }
4128
4142
 
4129
4143
  // src/cli.ts
4144
+ init_fs();
4145
+ import { existsSync as existsSync8, statSync as statSync3, readFileSync as readFileSync6 } from "node:fs";
4146
+ import { join as join11, dirname as dirname8 } from "node:path";
4130
4147
  var HELP = `
4131
4148
  ostacky — Instalador de agentes, comandos, skills y MCPs para OpenCode
4132
4149
 
@@ -4139,6 +4156,8 @@ Uso:
4139
4156
  npx ostacky add mcp [--scope ...] Agregar MCP server(s)
4140
4157
  npx ostacky install-stack [--scope local|auto] Instalar solo el stack de herramientas (CodeGraph, OpenSpec, Engram, Context7) — global bloquea con error
4141
4158
  npx ostacky uninstall-stack [--scope local|global|auto] Remover la configuración del stack del proyecto
4159
+ npx ostacky doctor Diagnostica locks, tools, state health
4160
+ npx ostacky status [--json] Muestra estado del controller sin MCP
4142
4161
  npx ostacky update [--scope ...] Actualizar instalación
4143
4162
  npx ostacky uninstall [--scope ...] Desinstalar todo
4144
4163
  npx ostacky uninstall agent [--scope ...] Desinstalar agente(s)
@@ -4187,6 +4206,161 @@ function withoutScopeArgs(argv) {
4187
4206
  var scope = parseScopeArg();
4188
4207
  var argvNoScope = withoutScopeArgs(process.argv);
4189
4208
  var [, , cmd, subcmd] = argvNoScope;
4209
+ async function runDoctorCommand() {
4210
+ const cwd = process.cwd();
4211
+ const opencodeDir = findOpenCodeDir(cwd) || join11(cwd, ".opencode");
4212
+ const statePath = join11(opencodeDir, "ostacky-state.json");
4213
+ let hasError = false;
4214
+ let hasWarn = false;
4215
+ const check = (label, ok, warn = false) => {
4216
+ if (ok)
4217
+ console.log(`✅ ${label}: OK`);
4218
+ else if (warn) {
4219
+ console.log(`⚠️ ${label}`);
4220
+ hasWarn = true;
4221
+ } else {
4222
+ console.log(`❌ ${label}`);
4223
+ hasError = true;
4224
+ }
4225
+ };
4226
+ try {
4227
+ if (!existsSync8(statePath)) {
4228
+ check("controller: state file missing", false, true);
4229
+ } else {
4230
+ const stat = statSync3(statePath);
4231
+ const raw = readFileSync6(statePath, "utf-8");
4232
+ const parsed = JSON.parse(raw);
4233
+ check(`controller: OK (rev ${parsed.revision || 0} state ${parsed.state || "unknown"})`, true);
4234
+ if (parsed.degraded) {
4235
+ console.log("⚠️ degraded: true (persistido)");
4236
+ hasWarn = true;
4237
+ }
4238
+ if (parsed.degradedEditsCount > 0)
4239
+ console.log(`⚠️ degraded: confirmation not audited in controller (degradedEditsCount=${parsed.degradedEditsCount})`);
4240
+ if (parsed.codegraphBypassCount > 0)
4241
+ console.log(`⚠️ codegraphBypassCount=${parsed.codegraphBypassCount} (inefficient: codegraph bypass)`);
4242
+ if (parsed.stateOversizedCount > 0)
4243
+ console.log(`⚠️ stateOversizedCount=${parsed.stateOversizedCount} snapshots perdidos`);
4244
+ if (parsed.sensitiveAccess)
4245
+ console.log(`ℹ️ sensitiveAccess: allowed=${parsed.sensitiveAccess.allowed || 0} denied=${parsed.sensitiveAccess.denied || 0} blocked=${parsed.sensitiveAccess.blockedAttempts || 0}`);
4246
+ if (parsed.deniedFiles && Object.keys(parsed.deniedFiles).length) {
4247
+ console.log(`ℹ️ denied files: ${Object.keys(parsed.deniedFiles).join(", ")} (denied by user)`);
4248
+ }
4249
+ if (parsed.staleContentAttempts > 0)
4250
+ console.log(`⚠️ staleContentAttempts=${parsed.staleContentAttempts}`);
4251
+ if (parsed.completeWithoutValidateCount > 0)
4252
+ console.log(`⚠️ completeWithoutValidateCount=${parsed.completeWithoutValidateCount}`);
4253
+ if (stat.size > 2 * 1024 * 1024) {
4254
+ console.log("⚠️ state file >2MB (oversized)");
4255
+ hasWarn = true;
4256
+ }
4257
+ const auditSize = (parsed.audit || []).length;
4258
+ if (auditSize > 500)
4259
+ console.log(`⚠️ audit large: ${auditSize}`);
4260
+ try {
4261
+ const { statfsSync } = await import("node:fs");
4262
+ if (typeof statfsSync === "function") {
4263
+ const s = statfsSync(dirname8(statePath));
4264
+ const freeMB = Math.floor(s.bfree * s.bsize / 1048576);
4265
+ if (freeMB < 100) {
4266
+ console.log(`⚠️ Disco casi lleno: ${freeMB}MB libres`);
4267
+ hasWarn = true;
4268
+ } else
4269
+ console.log(`ℹ️ diskFreeMB: ${freeMB}`);
4270
+ }
4271
+ } catch {}
4272
+ if ((parsed.state === "EXECUTING_INLINE" || parsed.state === "EXECUTING_SUBAGENTS") && parsed.expectedTasks) {
4273
+ const pending = parsed.expectedTasks.filter((id) => !parsed.tasks?.[id] || parsed.tasks[id].status !== "COMPLETED").length;
4274
+ const lastHandoffAge = parsed.lastHandoff ? Date.now() - parsed.lastHandoff.ts : Infinity;
4275
+ if (pending === 0 && lastHandoffAge > 60000) {
4276
+ console.log("⚠️ EXECUTING_* con pending==0 y lastHandoff >60s sin progreso — sugerir implementation_complete manual");
4277
+ hasWarn = true;
4278
+ }
4279
+ }
4280
+ }
4281
+ } catch (e2) {
4282
+ check(`controller: ${e2.message}`, false);
4283
+ }
4284
+ try {
4285
+ const lockPid = join11(opencodeDir, "ostacky-state.json.lock.pid");
4286
+ const lockTs = join11(opencodeDir, "ostacky-state.json.lock.timestamp");
4287
+ if (existsSync8(lockPid) || existsSync8(lockTs)) {
4288
+ let ageStr = "";
4289
+ try {
4290
+ const ts = parseInt(readFileSync6(lockTs, "utf-8"), 10);
4291
+ const age = Date.now() - ts;
4292
+ ageStr = `${Math.floor(age / 1000)}s`;
4293
+ const pid = readFileSync6(lockPid, "utf-8").trim();
4294
+ let alive = false;
4295
+ try {
4296
+ process.kill(parseInt(pid, 10), 0);
4297
+ alive = true;
4298
+ } catch {}
4299
+ check(`lock: PID ${pid} age ${ageStr} alive=${alive}`, !alive || age > 15000, true);
4300
+ } catch {
4301
+ check("lock: exists (no timestamp)", false, true);
4302
+ }
4303
+ } else {
4304
+ check("lock: no active lock", true);
4305
+ }
4306
+ } catch {
4307
+ check("lock: check failed", false, true);
4308
+ }
4309
+ const tools = ["codegraph", "engram"];
4310
+ for (const t of tools) {
4311
+ const p2 = join11(opencodeDir, "tools", t, "bin", t);
4312
+ const pExe = p2 + ".exe";
4313
+ check(`tool ${t}: ${existsSync8(p2) || existsSync8(pExe) ? "found" : "missing"}`, existsSync8(p2) || existsSync8(pExe), true);
4314
+ }
4315
+ try {
4316
+ const manifest = JSON.parse(readFileSync6(join11(cwd, "manifest.json"), "utf-8"));
4317
+ const expected = manifest.mcpServers?.find((x2) => x2.name === "ostacky-controller")?.sha256;
4318
+ if (expected) {
4319
+ const actual = computeTreeHash(join11(cwd, "assets", "mcp", "ostacky-controller"));
4320
+ check(`manifest hash: ${expected.slice(0, 8)} vs actual ${actual.slice(0, 8)}`, expected === actual);
4321
+ if (expected !== actual)
4322
+ console.log(" Run: bun run hash:update");
4323
+ }
4324
+ } catch {
4325
+ check("manifest: not found", false, true);
4326
+ }
4327
+ if (existsSync8(statePath)) {
4328
+ try {
4329
+ const s = JSON.parse(readFileSync6(statePath, "utf-8"));
4330
+ if (s.allowedFiles || s.deniedFiles) {}
4331
+ } catch {}
4332
+ }
4333
+ if (hasError)
4334
+ process.exit(1);
4335
+ if (hasWarn)
4336
+ process.exit(0);
4337
+ }
4338
+ async function runStatusCommand(args) {
4339
+ const isJson = args.includes("--json");
4340
+ const cwd = process.cwd();
4341
+ const opencodeDir = findOpenCodeDir(cwd) || join11(cwd, ".opencode");
4342
+ const statePath = join11(opencodeDir, "ostacky-state.json");
4343
+ if (!existsSync8(statePath)) {
4344
+ console.log(isJson ? JSON.stringify({ error: "no state" }) : "No state file");
4345
+ return;
4346
+ }
4347
+ try {
4348
+ const parsed = JSON.parse(readFileSync6(statePath, "utf-8"));
4349
+ const completed = Object.values(parsed.tasks || {}).filter((t) => t.status === "COMPLETED").length;
4350
+ const expected = parsed.expectedTaskCount ?? parsed.expectedTasks?.length ?? Object.keys(parsed.tasks || {}).length;
4351
+ const degraded = parsed.degraded ? " degraded" : "";
4352
+ const lastHandoff = parsed.lastHandoff ? ` lastHandoff: ${parsed.lastHandoff.summary?.slice(0, 60)}` : "";
4353
+ if (isJson) {
4354
+ console.log(JSON.stringify({ state: parsed.state, revision: parsed.revision, degraded: !!parsed.degraded, tasks: `${completed}/${expected}`, lastHandoff: parsed.lastHandoff }, null, 2));
4355
+ } else {
4356
+ console.log(`${parsed.state} rev ${parsed.revision}${degraded} tasks ${completed}/${expected}${lastHandoff}`);
4357
+ if (parsed.lastProposal)
4358
+ console.log(`lastProposal: ${parsed.lastProposal.summary} shownToUser=${parsed.lastProposal.shownToUser}`);
4359
+ }
4360
+ } catch (e2) {
4361
+ console.log(`Error reading state: ${e2.message}`);
4362
+ }
4363
+ }
4190
4364
  async function main() {
4191
4365
  switch (cmd) {
4192
4366
  case "install":
@@ -4240,6 +4414,12 @@ async function main() {
4240
4414
  process.exit(1);
4241
4415
  }
4242
4416
  break;
4417
+ case "doctor":
4418
+ await runDoctorCommand();
4419
+ break;
4420
+ case "status":
4421
+ await runStatusCommand(argvNoScope.slice(3));
4422
+ break;
4243
4423
  case "--help":
4244
4424
  case "-h":
4245
4425
  console.log(HELP);
package/manifest.json CHANGED
@@ -1,29 +1,29 @@
1
1
  {
2
- "version": "0.7.2",
2
+ "version": "0.7.3",
3
3
  "repo": "JaimeHoracio/Ostacky",
4
- "tag": "v0.7.2",
4
+ "tag": "v0.7.3",
5
5
  "agents": [
6
6
  {
7
7
  "name": "ostacky",
8
8
  "file": "assets/agents/ostacky.md",
9
- "description": "Orquestador con recuperación automática (nunca se congela), ruteo por nivel de impacto, controller MCP con SDK oficial, edición segura con fallback inline, y delegación en OpenSpec + Superpowers. v0.7.2: prune de skills obsoletas, lastHandoff, getAvailableTransitions, consecutiveFailures real, mem_session_summary automático al cierre.",
10
- "version": "0.7.2",
11
- "sha256": "1b6a5cbb49f1c6e977241f8ab86d1a045fdb8a04111bbc75633429a131c71acd"
9
+ "description": "Orquestador con recuperación automática (nunca se congela), ruteo por nivel de impacto, controller MCP con SDK oficial, edición segura con fallback inline, y delegación en OpenSpec + Superpowers. v0.7.3: prune de skills obsoletas, lastHandoff, getAvailableTransitions, consecutiveFailures real, mem_session_summary automático al cierre.",
10
+ "version": "0.7.3",
11
+ "sha256": "b6dc55a9571f9626e7912ac493cc3bfe6b0798a597f706904b2106a4a9acfcd5"
12
12
  }
13
13
  ],
14
14
  "commands": [
15
15
  {
16
16
  "name": "install-stack",
17
17
  "file": "assets/commands/install-stack.md",
18
- "description": "Instala el stack tecnológico del proyecto (CodeGraph, skills, OpenSpec, Engram, Context7, controller MCP con SDK oficial). v0.7.2: Paso 1.5 controller expandido con verificación post-instalación y troubleshooting.",
19
- "version": "0.7.2",
20
- "sha256": "7277d333bfe65e674b9696fa5f887854e35824eb5b88420dd0f5bbde3bca7add"
18
+ "description": "Instala el stack tecnológico del proyecto (CodeGraph, skills, OpenSpec, Engram, Context7, controller MCP con SDK oficial). v0.7.3: Paso 1.5 controller expandido con verificación post-instalación y troubleshooting.",
19
+ "version": "0.7.3",
20
+ "sha256": "0d4bc0938110c40633b041847148d8212e34a5b5876752825cfd6e186c328b8b"
21
21
  },
22
22
  {
23
23
  "name": "opsx-sync",
24
24
  "file": "assets/commands/opsx-sync.md",
25
25
  "description": "Sincroniza delta specs del change activo sin inicializar CodeGraph si ya existe índice",
26
- "version": "0.7.2",
26
+ "version": "0.7.3",
27
27
  "sha256": "fe0158478f2ca63b315037a85fc1632b77868532e319af6c7384285441767d64"
28
28
  }
29
29
  ],
@@ -31,15 +31,15 @@
31
31
  {
32
32
  "name": "ostacky-controller",
33
33
  "file": "assets/mcp/ostacky-controller/",
34
- "description": "Máquina de estados persistida con @modelcontextprotocol/server SDK. v0.7.2: 22 tools (incluye set_handoff, get_handoff, clear_handoff, get_available_transitions funcional). Bugfixes: consecutiveFailures real, lastHandoff state, defaultChoice persistido. Robustez: degraded mode automático tras 3 fallos, persistence condicional para Nivel 0, prune de skills obsoletas.",
35
- "version": "0.7.2",
36
- "sha256": "34048819b8905dff24c731e02d813deb4fb7fbbb65e8b8df66e5c8db201492a0"
34
+ "description": "Máquina de estados persistida con @modelcontextprotocol/server SDK. v0.7.3: 22 tools (incluye set_handoff, get_handoff, clear_handoff, get_available_transitions funcional). Bugfixes: consecutiveFailures real, lastHandoff state, defaultChoice persistido. Robustez: degraded mode automático tras 3 fallos, persistence condicional para Nivel 0, prune de skills obsoletas.",
35
+ "version": "0.7.3",
36
+ "sha256": "d723afc107c8a36721e7f04dc1c16694a617cd562492e1ece362482c9023b945"
37
37
  },
38
38
  {
39
39
  "name": "openspec",
40
40
  "file": "assets/mcp/openspec/",
41
41
  "description": "MCP server local para OpenSpec - proposal, apply, archive, sync de cambios",
42
- "version": "0.7.2",
42
+ "version": "0.7.3",
43
43
  "sha256": "fa4be28bfc1e75db8f1a037e2580f04a60066c80e8e5934e90e1041020d04609"
44
44
  }
45
45
  ],
@@ -48,106 +48,106 @@
48
48
  "name": "brainstorming",
49
49
  "file": "assets/skills/brainstorming/SKILL.md",
50
50
  "description": "Skill unificado de pensamiento con dos modos: creative-design (producción de diseño → transición a implementación directa o openspec-propose) y open-exploration (exploración libre)",
51
- "version": "0.7.2",
51
+ "version": "0.7.3",
52
52
  "sha256": "333810ca63450e8ab795e8c5a58e645101e788d79210ca8ac36e10d11be39585"
53
53
  },
54
54
  {
55
55
  "name": "execution-mode-evaluation",
56
56
  "file": "assets/skills/execution-mode-evaluation/SKILL.md",
57
57
  "description": "Skill de análisis de modo de ejecución — output reconciliado con controller snapshot contract (recommendation field)",
58
- "version": "0.7.2",
59
- "sha256": "edf6fca0af52cce83f8fd08e7db9b3d79cc130b53fca505e90d3fbaf4909338b"
58
+ "version": "0.7.3",
59
+ "sha256": "e17f1e0309572841dc1fa537b1f32c7468eb70b3acf453b9ff5cc4fa8d94fd39"
60
60
  },
61
61
  {
62
62
  "name": "tdd",
63
63
  "file": "assets/skills/tdd/SKILL.md",
64
64
  "description": "Skill de test-driven development (Superpowers)",
65
- "version": "0.7.2",
65
+ "version": "0.7.3",
66
66
  "sha256": "aa412298980b7826165c211145c1b8e9135f68f36247bb3cb96d0a0eae274486"
67
67
  },
68
68
  {
69
69
  "name": "subagent-driven-development",
70
70
  "file": "assets/skills/subagent-driven-development/SKILL.md",
71
71
  "description": "Skill de ejecución con subagentes (Superpowers) — ejecuta solo después de confirmación del coordinador Ostacky",
72
- "version": "0.7.2",
72
+ "version": "0.7.3",
73
73
  "sha256": "1a42d714a9a13faf05f0bf7b580e8d837c2e77a5633839542ccce603023419e8"
74
74
  },
75
75
  {
76
76
  "name": "dispatching-parallel-agents",
77
77
  "file": "assets/skills/dispatching-parallel-agents/SKILL.md",
78
78
  "description": "Skill de dispatch paralelo de agentes (Superpowers)",
79
- "version": "0.7.2",
79
+ "version": "0.7.3",
80
80
  "sha256": "3c8a66d51ae2e719e877d02c3dac32bd804722c3bb9227c258ecae78252a20ab"
81
81
  },
82
82
  {
83
83
  "name": "review",
84
84
  "file": "assets/skills/review/SKILL.md",
85
85
  "description": "Skill de revisión de código (Superpowers)",
86
- "version": "0.7.2",
86
+ "version": "0.7.3",
87
87
  "sha256": "b19650ed4d1d4d9857a4dd5b7e08e91328a1a1fc9c45bcc2fb600fa9d0213279"
88
88
  },
89
89
  {
90
90
  "name": "receiving-code-review",
91
91
  "file": "assets/skills/receiving-code-review/SKILL.md",
92
92
  "description": "Skill de recibir y procesar feedback de code review",
93
- "version": "0.7.2",
93
+ "version": "0.7.3",
94
94
  "sha256": "d761e884e71d8d3476ac734d287cae403a4024506a7d12e7361a448217c0a831"
95
95
  },
96
96
  {
97
97
  "name": "openspec-propose",
98
98
  "file": "assets/skills/openspec-propose/SKILL.md",
99
99
  "description": "Skill de generación de proposal (OpenSpec)",
100
- "version": "0.7.2",
100
+ "version": "0.7.3",
101
101
  "sha256": "bb59100b9fd3c9f9a1ec6509fa975ec55bf7fc737df4fe73bb3e9bbc217b83f7"
102
102
  },
103
103
  {
104
104
  "name": "openspec-apply-change",
105
105
  "file": "assets/skills/openspec-apply-change/SKILL.md",
106
106
  "description": "Skill de aplicación de change (OpenSpec)",
107
- "version": "0.7.2",
107
+ "version": "0.7.3",
108
108
  "sha256": "dfc823bf89fc7505e91ab6dee9c1f004be38a410bd3d88fb67b211b1b6cbb1d0"
109
109
  },
110
110
  {
111
111
  "name": "openspec-archive-change",
112
112
  "file": "assets/skills/openspec-archive-change/SKILL.md",
113
113
  "description": "Skill de archivo de change (OpenSpec)",
114
- "version": "0.7.2",
114
+ "version": "0.7.3",
115
115
  "sha256": "16e4b561de7747283663fed602e506abf502452c49a8d4b86d7a5539c40f0195"
116
116
  },
117
117
  {
118
118
  "name": "openspec-explore",
119
119
  "file": "assets/skills/openspec-explore/SKILL.md",
120
120
  "description": "Modo explore para OpenSpec — thinking partner para explorar ideas, investigar problemas y clarificar requisitos antes/durante un cambio",
121
- "version": "0.7.2",
121
+ "version": "0.7.3",
122
122
  "sha256": "37ae4aaf17ea71a395bab6dc4d9d61b9a49d7910f6692535ae8553244c46880b"
123
123
  },
124
124
  {
125
125
  "name": "using-git-worktrees",
126
126
  "file": "assets/skills/using-git-worktrees/SKILL.md",
127
127
  "description": "Skill de uso de git worktrees para aislamiento de trabajo",
128
- "version": "0.7.2",
129
- "sha256": "11afa9123828fc5caa22137aff907cd99c751e99027fbd4c020751110a949281"
128
+ "version": "0.7.3",
129
+ "sha256": "93341bc1b7c053618a8b6dc07e3615b77990d7b549a0201f5835d95fef67ce13"
130
130
  },
131
131
  {
132
132
  "name": "using-superpowers",
133
133
  "file": "assets/skills/using-superpowers/SKILL.md",
134
134
  "description": "Skill de orquestación de Superpowers skills",
135
- "version": "0.7.2",
135
+ "version": "0.7.3",
136
136
  "sha256": "7e54536f96d2a379185a10bfc1e970850caa2561b6d8aca7080f0defea0381a4"
137
137
  },
138
138
  {
139
139
  "name": "writing-skills",
140
140
  "file": "assets/skills/writing-skills/SKILL.md",
141
141
  "description": "Skill de creación y edición de skills",
142
- "version": "0.7.2",
142
+ "version": "0.7.3",
143
143
  "sha256": "3d76b906cee518a2b809febb70db95697a35b9f368986bb504b4120c3bfb437a"
144
144
  },
145
145
  {
146
146
  "name": "graceful-degradation",
147
147
  "file": "assets/skills/graceful-degradation/SKILL.md",
148
148
  "description": "Skill de degradación graceful cuando múltiples tools están indisponibles",
149
- "version": "0.7.2",
150
- "sha256": "376dc90fa27ab7e5947747f20ccf2cc76f9326c77b567fda388252a60d25c431"
149
+ "version": "0.7.3",
150
+ "sha256": "630b87c16d78212c865696ca5df6abb0834606095ffe0e80cff8e04350f01054"
151
151
  }
152
152
  ]
153
153
  }