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/README.md +13 -9
- package/assets/agents/ostacky.md +26 -3
- package/assets/commands/install-stack.md +2 -2
- package/assets/mcp/ostacky-controller/index.js +847 -67
- package/assets/mcp/ostacky-controller/package.json +1 -1
- package/assets/plugins/engram.ts +41 -5
- package/assets/plugins/ostacky-guard.ts +131 -0
- package/assets/skills/execution-mode-evaluation/SKILL.md +9 -1
- package/assets/skills/graceful-degradation/SKILL.md +9 -0
- package/assets/skills/using-git-worktrees/SKILL.md +8 -0
- package/dist/cli.js +218 -38
- package/manifest.json +31 -31
- package/package.json +1 -1
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.
|
|
554
|
+
version: "0.7.3",
|
|
550
555
|
repo: "JaimeHoracio/Ostacky",
|
|
551
|
-
tag: "v0.7.
|
|
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.
|
|
557
|
-
version: "0.7.
|
|
558
|
-
sha256: "
|
|
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.
|
|
566
|
-
version: "0.7.
|
|
567
|
-
sha256: "
|
|
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.
|
|
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.
|
|
582
|
-
version: "0.7.
|
|
583
|
-
sha256: "
|
|
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.
|
|
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.
|
|
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.
|
|
606
|
-
sha256: "
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
676
|
-
sha256: "
|
|
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.
|
|
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.
|
|
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.
|
|
697
|
-
sha256: "
|
|
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.
|
|
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.
|
|
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 → ${
|
|
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
|
-
|
|
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 =
|
|
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
|
+
"version": "0.7.3",
|
|
3
3
|
"repo": "JaimeHoracio/Ostacky",
|
|
4
|
-
"tag": "v0.7.
|
|
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.
|
|
10
|
-
"version": "0.7.
|
|
11
|
-
"sha256": "
|
|
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.
|
|
19
|
-
"version": "0.7.
|
|
20
|
-
"sha256": "
|
|
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.
|
|
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.
|
|
35
|
-
"version": "0.7.
|
|
36
|
-
"sha256": "
|
|
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.
|
|
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.
|
|
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.
|
|
59
|
-
"sha256": "
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
129
|
-
"sha256": "
|
|
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.
|
|
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.
|
|
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.
|
|
150
|
-
"sha256": "
|
|
149
|
+
"version": "0.7.3",
|
|
150
|
+
"sha256": "630b87c16d78212c865696ca5df6abb0834606095ffe0e80cff8e04350f01054"
|
|
151
151
|
}
|
|
152
152
|
]
|
|
153
153
|
}
|