engine-kit 0.2.3 → 0.2.5

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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Allan Santos
3
+ Copyright (c) 2026 The engine-registry maintainers
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -27,12 +27,12 @@ vive num lugar só e o consumidor apenas **declara a dependência**.
27
27
  |---|---|---|---|
28
28
  | `embed-house` | 1.0.5 | `daemon` (http) | Casa de embeddings (MiniLM-L6-v2, 384-dim): carrega o modelo uma vez e serve vetores a N consumidores. |
29
29
  | `vox-engine` | 0.28.7 | `daemon` (pipe), **self-managed** | Motor de voz (STT/TTS) compartilhado, com auto-unload quando ocioso. Traz o próprio instalador e updater. |
30
- | `mcp-gateway` | 0.16.4 | `daemon` (http) | Agregador MCP: conecta uma vez em cada servidor MCP e reexpõe tudo num endpoint único. |
30
+ | `mcp-gateway` | 0.17.2 | `daemon` (http) | Agregador MCP: conecta uma vez em cada servidor MCP e reexpõe tudo num endpoint único. |
31
31
  | `neural-link` | 0.7.15 | `cli` | Dispatcher adaptativo de hooks: recebe o evento por stdin, pontua os handlers e devolve uma decisão composta. |
32
- | `vxk` | 0.19.0 | `cli` | Explicações visuais animadas e narradas como servidor MCP (stdio): devolve UM HTML autocontido e offline, ou o vídeo MP4 (preset, aplicativo real, Motion) e o PDF. Um daemon único por máquina atende os agentes. A narração vem do `vox-engine`. |
33
- | `cerne` | 0.4.10 | `daemon`, **self-managed** | Leitura ativa de vídeo (captura, quadros, transcrição, tradução) exposta via MCP. Instalador Inno por usuário, Windows. |
34
- | `skill-engine` | 0.1.0 | `cli` | Gerencia skills de agentes fora de qualquer IDE: busca repositórios em quarentena, varre com regras determinísticas e só ativa o que sai limpo. |
35
- | `client-harness` | 0.1.1 | `cli` | Daemon local que faz o Claude Code e o Codex respeitarem os padrões de cada cliente: confere cada ação do agente contra as regras da pasta e recusa antes de gravar, com o motivo. |
32
+ | `vxk` | 0.21.0 | `cli` | Explicações visuais animadas e narradas como servidor MCP (stdio): devolve UM HTML autocontido e offline, ou o vídeo MP4 (preset, aplicativo real, Motion) e o PDF. Um daemon único por máquina atende os agentes. A narração vem do `vox-engine`. |
33
+ | `cerne` | 0.4.14 | `daemon`, **self-managed** | Leitura ativa de vídeo (captura, quadros, transcrição, tradução) exposta via MCP. Instalador Inno por usuário, Windows. |
34
+ | `skill-engine` | 0.2.1 | `cli` | Gerencia skills de agentes fora de qualquer IDE: busca repositórios em quarentena, varre com regras determinísticas e só ativa o que sai limpo. |
35
+ | `client-harness` | 0.1.5 | `cli` | Daemon local que faz o Claude Code e o Codex respeitarem os padrões de cada cliente: confere cada ação do agente contra as regras da pasta e recusa antes de gravar, com o motivo. |
36
36
 
37
37
  **Todos** são publicados aqui, assinados com Ed25519 e verificados antes de instalar.
38
38
 
@@ -59,7 +59,7 @@ Sem clonar o repositório, com Node 18 ou mais:
59
59
 
60
60
  ```sh
61
61
  npx engine-kit ensure vxk # instala ou atualiza; reusa se já estiver em dia
62
- npx engine-kit ensure vxk --version 0.19.0 # pin de versão
62
+ npx engine-kit ensure vxk --version 0.21.0 # pin de versão
63
63
  ```
64
64
 
65
65
  O `npx` baixa o kit do npm e o kit baixa o motor da release, confere o **sha256**, a **assinatura Ed25519**
@@ -271,7 +271,7 @@ plataforma, e a release mora aqui, no registry público, com download **sem logi
271
271
 
272
272
  | App | Versão | Plataformas | O que faz |
273
273
  |---|---|---|---|
274
- | `agent-launcher` | 1.2.11 | `win32-x64` | Abre Claude Code, Codex e Copilot CLI nos seus projetos por qualquer host de modelos. |
274
+ | `agent-launcher` | 1.3.5 | `win32-x64` | Abre Claude Code, Codex, Copilot CLI, VS Code e o Copilot app nos seus projetos por qualquer host de modelos. Leva só o launcher; cada ferramenta se instala pelo cartão dela. |
275
275
 
276
276
  Um app só entra nesta tabela e em `manifest.apps` **depois** de a release pública existir e passar
277
277
  em `node kit/verify-release.mjs --app <nome>` (download anônimo de todos os assets, `.sha256` e
package/kit/budget.mjs CHANGED
@@ -41,9 +41,12 @@ const ROOT = resolvePath(KIT, "..");
41
41
  // e update.mjs (`npx engine-kit ensure <motor>` com autoatualização exigida pelo gate de release), +6.3 KB.
42
42
  // Escopo novo (comando de instalação), rodado pela mão de quem instala, nunca importado por consumidor:
43
43
  // o caminho do `import "engine-kit"` não mudou.
44
+ // 2026-11-09 tooling 31000 → 34000: diagnóstico de vida (pid, porta, idade do runtime) e do ponteiro
45
+ // `cli.json` no doctor (diagnose.mjs), +2.7 KB. Só leitura, rodado na mão de quem diagnostica; o caminho do
46
+ // `import "engine-kit"` não mudou.
44
47
  const BUDGETS = {
45
48
  runtime: { codeBytes: 27000, baseline: 24519, loc: 900 },
46
- tooling: { codeBytes: 31000, baseline: 16420, loc: 950 },
49
+ tooling: { codeBytes: 34000, baseline: 16420, loc: 950 },
47
50
  adapter: { codeBytes: 5000, baseline: 1859, loc: 150 },
48
51
  };
49
52
 
@@ -0,0 +1,58 @@
1
+ // engine-kit/diagnose.mjs — diagnóstico SOMENTE LEITURA de vida e de ponteiro, usado pelo doctor.
2
+ // Não sobe, não derruba e não fala com o motor: lê o runtime que o motor anuncia e o `cli.json`
3
+ // que ele publica (CONTRATO-MOTOR §4). Nunca lança.
4
+ import { existsSync, readFileSync, statSync } from "node:fs";
5
+ import { isAbsolute, join, relative } from "node:path";
6
+ import { readRuntime } from "./lifecycle.mjs";
7
+
8
+ const alive = (pid) => {
9
+ try { process.kill(pid, 0); return true; } catch (e) { return e.code === "EPERM"; }
10
+ };
11
+
12
+ /**
13
+ * Vida do motor segundo o arquivo de runtime que ele declara: pid vivo, porta e idade do heartbeat.
14
+ * Estados: SEM-DECLARAÇÃO (o registry não declara arquivo de runtime), PARADO (sem runtime),
15
+ * VIVO (pid existe), ÓRFÃO (runtime aponta para pid que não existe mais).
16
+ * @returns {{state:string, detail:string}}
17
+ */
18
+ export function lifeOf(engine, now = Date.now()) {
19
+ const rt = engine.runtime;
20
+ if (!rt?.runtimeFile) { return { state: "SEM-DECLARAÇÃO", detail: rt?.transport ? `transporte ${rt.transport}, sem arquivo de runtime` : "motor sem bloco runtime" }; }
21
+ const data = readRuntime(engine);
22
+ if (!data) { return { state: "PARADO", detail: `sem ${rt.runtimeFile}` }; }
23
+ let age = "";
24
+ try {
25
+ const ms = now - statSync(join(engine.homeDir, rt.runtimeFile)).mtimeMs;
26
+ const limit = rt.heartbeatMs ? ` (limite ${Math.round((rt.heartbeatMs * 3) / 1000)}s)` : "";
27
+ age = `, runtime atualizado há ${Math.round(ms / 1000)}s${limit}`;
28
+ } catch { /* o arquivo sumiu entre a leitura e o stat */ }
29
+ const where = `pid ${data.pid ?? "?"}${data.port ? `, porta ${data.port}` : ""}${age}`;
30
+ return data.pid && alive(data.pid)
31
+ ? { state: "VIVO", detail: where }
32
+ : { state: "ÓRFÃO", detail: `${where}; o pid não existe mais` };
33
+ }
34
+
35
+ /**
36
+ * Ponteiro `<home>/cli.json`: todo caminho absoluto que o motor publica precisa existir, e o kit
37
+ * avisa quando o ponteiro vive fora da instalação que ele provisionou.
38
+ * Estados: AUSENTE, ILEGÍVEL, QUEBRADO (algum caminho não existe), FORA-DA-INSTALAÇÃO, OK.
39
+ * @returns {{state:string, detail:string}}
40
+ */
41
+ export function pointerOf(engine) {
42
+ const file = join(engine.homeDir, "cli.json");
43
+ if (!existsSync(file)) { return { state: "AUSENTE", detail: "o motor ainda não publicou o ponteiro" }; }
44
+ let data;
45
+ try { data = JSON.parse(readFileSync(file, "utf8")); }
46
+ catch { return { state: "ILEGÍVEL", detail: `${file} não é JSON válido` }; }
47
+ const paths = Object.entries(data).filter(([, v]) => typeof v === "string" && isAbsolute(v));
48
+ const missing = paths.filter(([, v]) => !existsSync(v)).map(([k]) => k);
49
+ if (missing.length) { return { state: "QUEBRADO", detail: `aponta para caminho inexistente: ${missing.join(", ")}` }; }
50
+ const binDir = join(engine.homeDir, engine.install.extractTo ?? "bin");
51
+ const outside = paths.filter(([k, v]) => {
52
+ const rel = relative(binDir, v);
53
+ return k !== "node" && (rel.startsWith("..") || isAbsolute(rel));
54
+ });
55
+ return outside.length
56
+ ? { state: "FORA-DA-INSTALAÇÃO", detail: `${outside.map(([k]) => k).join(", ")} fora de ${binDir}` }
57
+ : { state: "OK", detail: `${paths.length} caminho(s) existem` };
58
+ }
package/kit/doctor.mjs CHANGED
@@ -17,6 +17,7 @@ import { join } from "node:path";
17
17
  import { resolve } from "./resolve.mjs";
18
18
  import { provision, satisfiesPin } from "./provision.mjs";
19
19
  import { shutdown } from "./lifecycle.mjs";
20
+ import { lifeOf, pointerOf } from "./diagnose.mjs";
20
21
 
21
22
  const args = process.argv.slice(2);
22
23
  const useLocal = args.includes("--local");
@@ -85,6 +86,11 @@ const w = Math.max(12, ...rows.map((r) => r.name.length));
85
86
  for (const r of rows) {
86
87
  const mark = (r.state === "OK" || r.state === "SELF-MANAGED") ? " OK " : r.state === "ERRO" ? " ERRO " : " !! ";
87
88
  console.log(`${mark} ${pad(r.name, w)} ${pad(r.state, 14)} ${r.detail}`);
89
+ if (r.engine && r.engine.status !== "self-managed") {
90
+ const life = lifeOf(r.engine), ptr = pointerOf(r.engine);
91
+ console.log(` ${pad("", w)} vida: ${life.state} (${life.detail})`);
92
+ console.log(` ${pad("", w)} ponteiro cli.json: ${ptr.state} (${ptr.detail})`);
93
+ }
88
94
  }
89
95
 
90
96
  const pending = rows.filter((r) => r.needsWork);
package/kit/ensure.mjs CHANGED
@@ -63,6 +63,7 @@ export async function ensureCommand(name, { version, registryUrl, bundled, manif
63
63
  const p = await provision(r.engine, {
64
64
  log,
65
65
  trustedKeys: { [name]: publicKey },
66
+ allowDowngrade: Boolean(version),
66
67
  ...(fetcher ? { fetcher } : {}),
67
68
  // Windows: arquivo em uso não se sobrescreve. Derruba o daemon pelo shutdownPath que o registry declara.
68
69
  onBeforeReplace: async () => {
package/kit/provision.mjs CHANGED
@@ -12,7 +12,7 @@ import { join, dirname } from "node:path";
12
12
  import { createHash } from "node:crypto";
13
13
  import { execFileSync } from "node:child_process";
14
14
  import { verifyBlob, DEFAULT_ALGORITHM } from "./signature.mjs";
15
- import { checkTrust, trustPath } from "./trust.mjs";
15
+ import { checkTrust, trustPath, cmpVer, rollbackReason, noteVersion } from "./trust.mjs";
16
16
 
17
17
  const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
18
18
 
@@ -77,22 +77,29 @@ function claimLock(lock) {
77
77
  }
78
78
  }
79
79
 
80
- const parseVer = (v) => String(v || "").split(".").map((n) => parseInt(n, 10) || 0);
81
-
82
80
  /** true se a versão instalada serve o pin: MESMO major e >= (protocolo é atado ao major). */
83
- export function satisfiesPin(installed, pinned) {
84
- const a = parseVer(installed), b = parseVer(pinned);
85
- if (a[0] !== b[0]) { return false; }
86
- for (let i = 0; i < 3; i++) {
87
- const x = a[i] || 0, y = b[i] || 0;
88
- if (x > y) { return true; }
89
- if (x < y) { return false; }
81
+ export const satisfiesPin = (installed, pinned) => String(installed).split(".")[0] === String(pinned).split(".")[0] && cmpVer(installed, pinned) >= 0;
82
+
83
+ /**
84
+ * Baixa o artefato e confere o sidecar SHA256 (obrigatório, fail-closed) em memória.
85
+ * @returns {Promise<{buf:Buffer} | {reason:string}>}
86
+ */
87
+ async function downloadChecked(engine, { log, fetcher, timeoutMs }) {
88
+ let expected;
89
+ try {
90
+ expected = String(await fetcher(engine.checksumUrl, 15000)).trim().split(/\s+/)[0].toLowerCase();
91
+ } catch (e) {
92
+ return { reason: `${engine.name}: sha256 sidecar inacessível (${e.status || e.message}) → ABORT (fail-closed)` };
90
93
  }
91
- return true;
92
- }
94
+ if (!/^[0-9a-f]{64}$/.test(expected)) { return { reason: `${engine.name}: sha256 sidecar malformado → ABORT` }; }
93
95
 
94
- function sha256File(p) {
95
- return createHash("sha256").update(readFileSync(p)).digest("hex").toLowerCase();
96
+ log(`[engine-kit] baixando ${engine.assetUrl} …`);
97
+ let buf;
98
+ try { buf = await fetcher(engine.assetUrl, timeoutMs); }
99
+ catch (e) { return { reason: `${engine.name}: download falhou (${e.status || e.message})` }; }
100
+
101
+ const actual = createHash("sha256").update(buf).digest("hex").toLowerCase();
102
+ return actual === expected ? { buf } : { reason: `${engine.name}: SHA256 mismatch (esperado ${expected.slice(0, 12)}…, obtido ${actual.slice(0, 12)}…) → ABORT` };
96
103
  }
97
104
 
98
105
  async function fetchBuf(url, timeoutMs) {
@@ -183,26 +190,9 @@ export async function fetchArtifact(engine, { log = () => {}, destDir, downloadT
183
190
  return { ok: false, reason: `${engine.name}: não consegui criar ${dir}: ${e?.message || e}` };
184
191
  }
185
192
 
186
- let expected;
187
- try {
188
- const buf = await fetcher(engine.checksumUrl, 15000);
189
- expected = String(buf).trim().split(/\s+/)[0].toLowerCase();
190
- } catch (e) {
191
- return { ok: false, reason: `${engine.name}: sha256 sidecar inacessível (${e.status || e.message}) → ABORT (fail-closed)` };
192
- }
193
- if (!/^[0-9a-f]{64}$/.test(expected)) {
194
- return { ok: false, reason: `${engine.name}: sha256 sidecar malformado → ABORT` };
195
- }
196
-
197
- log(`[engine-kit] baixando ${engine.assetUrl} …`);
198
- let buf;
199
- try { buf = await fetcher(engine.assetUrl, downloadTimeoutMs); }
200
- catch (e) { return { ok: false, reason: `${engine.name}: download falhou (${e.status || e.message})` }; }
201
-
202
- const actual = createHash("sha256").update(buf).digest("hex").toLowerCase();
203
- if (actual !== expected) {
204
- return { ok: false, reason: `${engine.name}: SHA256 mismatch (esperado ${expected.slice(0, 12)}…, obtido ${actual.slice(0, 12)}…) → ABORT` };
205
- }
193
+ const dl = await downloadChecked(engine, { log, fetcher, timeoutMs: downloadTimeoutMs });
194
+ if (!dl.buf) { return { ok: false, reason: dl.reason }; }
195
+ const buf = dl.buf;
206
196
 
207
197
  const auth = await verifyAuthenticity(engine, buf, { log, fetcher, trustedKeys });
208
198
  if (!auth.ok) { return { ok: false, reason: auth.reason }; }
@@ -225,7 +215,7 @@ export async function fetchArtifact(engine, { log = () => {}, destDir, downloadT
225
215
  * adivinha como derrubar um daemon: quem sabe é o descritor/consumidor).
226
216
  * @returns {Promise<{ok:true, entryPath:string, version:string, reused?:boolean, installed?:boolean} | {ok:false, reason:string}>}
227
217
  */
228
- export async function provision(engine, { log = () => {}, allowNetwork = true, onBeforeReplace, downloadTimeoutMs = 120000, fetcher = fetchBuf, trustedKeys } = {}) {
218
+ export async function provision(engine, { log = () => {}, allowNetwork = true, onBeforeReplace, downloadTimeoutMs = 120000, fetcher = fetchBuf, trustedKeys, allowDowngrade } = {}) {
229
219
  const home = engine.homeDir;
230
220
  const binDir = join(home, engine.install.extractTo ?? "bin");
231
221
  const entryPath = join(home, engine.install.entry);
@@ -239,6 +229,7 @@ export async function provision(engine, { log = () => {}, allowNetwork = true, o
239
229
  if (existsSync(entryPath)) {
240
230
  const inst = installedVersion(binDir);
241
231
  if (inst && satisfiesPin(inst, engine.version)) {
232
+ noteVersion(engine.name, inst);
242
233
  return { ok: true, entryPath, version: inst, reused: true };
243
234
  }
244
235
  if (!inst && engine.status !== "self-managed") {
@@ -266,6 +257,9 @@ export async function provision(engine, { log = () => {}, allowNetwork = true, o
266
257
  return { ok: false, reason: `${engine.name} ainda não publicou release (status: pending-release)` };
267
258
  }
268
259
 
260
+ const rb = !allowDowngrade && rollbackReason(engine.name, engine.version);
261
+ if (rb) { return { ok: false, reason: rb }; }
262
+
269
263
  mkdirSync(home, { recursive: true });
270
264
 
271
265
  // LOCK atômico: só um consumidor provisiona; os demais aguardam o resultado dele.
@@ -284,35 +278,15 @@ export async function provision(engine, { log = () => {}, allowNetwork = true, o
284
278
  }
285
279
 
286
280
  try {
287
- // 1) SHA256 sidecar OBRIGATÓRIO (fail-closed).
288
- let expected;
289
- try {
290
- const buf = await fetcher(engine.checksumUrl, 15000);
291
- expected = String(buf).trim().split(/\s+/)[0].toLowerCase();
292
- } catch (e) {
293
- return { ok: false, reason: `${engine.name}: sha256 sidecar inacessível (${e.status || e.message}) → ABORT (fail-closed)` };
294
- }
295
- if (!/^[0-9a-f]{64}$/.test(expected)) {
296
- return { ok: false, reason: `${engine.name}: sha256 sidecar malformado → ABORT` };
297
- }
298
-
299
- // 2) Download → .part → rename atômico.
300
- log(`[engine-kit] baixando ${engine.assetUrl} …`);
301
- let buf;
302
- try { buf = await fetcher(engine.assetUrl, downloadTimeoutMs); }
303
- catch (e) { return { ok: false, reason: `${engine.name}: download falhou (${e.status || e.message})` }; }
281
+ // 1-3) Sidecar SHA256 obrigatório, download e integridade: nada toca o disco antes de conferir.
282
+ const dl = await downloadChecked(engine, { log, fetcher, timeoutMs: downloadTimeoutMs });
283
+ if (!dl.buf) { return { ok: false, reason: dl.reason }; }
284
+ const buf = dl.buf;
304
285
  const part = join(home, `${engine.assetName}.part`);
305
286
  const tgz = join(home, engine.assetName);
306
287
  writeFileSync(part, buf);
307
288
  renameSync(part, tgz);
308
289
 
309
- // 3) Integridade (mismatch = apaga + ABORT).
310
- const actual = sha256File(tgz);
311
- if (actual !== expected) {
312
- dropFile(tgz);
313
- return { ok: false, reason: `${engine.name}: SHA256 mismatch (esperado ${expected.slice(0, 12)}…, obtido ${actual.slice(0, 12)}…) → ABORT` };
314
- }
315
-
316
290
  // 3.5) AUTENTICIDADE — antes de extrair. Um artefato não confiável não chega a tocar o disco
317
291
  // final: se a assinatura não confere, o .tgz é apagado e nada é instalado.
318
292
  const auth = await verifyAuthenticity(engine, buf, { log, fetcher, trustedKeys });
@@ -373,6 +347,7 @@ export async function provision(engine, { log = () => {}, allowNetwork = true, o
373
347
  if (!existsSync(entryPath)) {
374
348
  return { ok: false, reason: `${engine.name}: artefato extraído incompleto (sem ${engine.install.entry})` };
375
349
  }
350
+ noteVersion(engine.name, engine.version);
376
351
  log(`[engine-kit] ${engine.name} instalado em ${binDir} (v${engine.version})`);
377
352
  return { ok: true, entryPath, version: engine.version, installed: true, signed: auth.signed };
378
353
  } catch (e) {
package/kit/trust.mjs CHANGED
@@ -70,3 +70,22 @@ export function checkTrust(engineName, publicKey, { trustedKeys } = {}) {
70
70
  }
71
71
 
72
72
  export const trustPath = () => trustFile();
73
+
74
+ /** Compara versões `x.y.z` numericamente: negativo, zero ou positivo. */
75
+ export const cmpVer = (a, b) => String(a).localeCompare(String(b), "en", { numeric: true });
76
+
77
+ /** Motivo do ABORT se `version` é menor que a maior já instalada do motor (anti-rollback); falsy se pode seguir. */
78
+ export function rollbackReason(name, version) {
79
+ const max = readTrust()[name]?.maxVersion;
80
+ return max && cmpVer(version, max) < 0 && `${name}: v${version} < v${max} já instalada → ABORT (rollback; downgrade só com --version)`;
81
+ }
82
+
83
+ /** Grava `version` como a maior vista do motor, se superar a registrada. */
84
+ export function noteVersion(name, version) {
85
+ const store = readTrust(), max = store[name]?.maxVersion;
86
+ if (max && cmpVer(version, max) <= 0) return;
87
+ try {
88
+ mkdirSync(trustDir(), { recursive: true });
89
+ writeFileSync(trustFile(), JSON.stringify({ ...store, [name]: { ...store[name], maxVersion: version } }, null, 2));
90
+ } catch { /* sem gravar, a proteção vale a partir da próxima instalação */ }
91
+ }
package/manifest.json CHANGED
@@ -3,15 +3,15 @@
3
3
  "registry": "engine-registry",
4
4
  "version": 1,
5
5
  "owner": {
6
- "name": "Allan Santos",
6
+ "name": "The engine-registry maintainers",
7
7
  "url": "https://github.com/AllanSantos-DV"
8
8
  },
9
9
  "description": "Catálogo público de motores compartilhados e aplicativos distribuídos. engine-kit consome apenas engines; apps declara versões e downloads sem instalar aplicativos automaticamente.",
10
10
  "apps": [
11
11
  {
12
12
  "name": "agent-launcher",
13
- "version": "1.2.11",
14
- "summary": "Abre Claude Code, Codex e Copilot CLI nos seus projetos por qualquer host de modelos. Windows.",
13
+ "version": "1.3.5",
14
+ "summary": "Abre Claude Code, Codex, Copilot CLI, VS Code e o Copilot app nos seus projetos por qualquer host de modelos. Leva só o launcher; cada ferramenta se instala pelo cartão dela. Windows.",
15
15
  "homepage": "https://allansantos-dv.github.io/agent-launcher/",
16
16
  "license": "MIT",
17
17
  "platforms": [
@@ -106,7 +106,7 @@
106
106
  },
107
107
  {
108
108
  "name": "mcp-gateway",
109
- "version": "0.16.4",
109
+ "version": "0.17.2",
110
110
  "kind": "daemon",
111
111
  "summary": "Agregador MCP: conecta UMA vez em cada servidor MCP e reexpõe todas as tools num endpoint Streamable HTTP único, com auth bearer, namespacing condicional, resiliência e auditoria. Mata a multiplicação de processos por sessão.",
112
112
  "pagesPendente": "sem página de produto com vídeo; ela nasce do repositório do próprio motor e este registro só aponta para ela",
@@ -163,7 +163,7 @@
163
163
  },
164
164
  {
165
165
  "name": "vxk",
166
- "version": "0.19.0",
166
+ "version": "0.21.0",
167
167
  "kind": "cli",
168
168
  "summary": "VXK — explicações visuais animadas e narradas como servidor MCP (stdio): qualquer cliente MCP (Claude Code, Codex, Copilot) compõe a biblioteca de componentes, ícones e o controle único de reprodução e recebe UM HTML autocontido e offline, ou o vídeo MP4 da mesma explicação (por preset, do aplicativo real ou em Motion) e o PDF. A narração é assada pelo motor vox-engine.",
169
169
  "pagesUrl": "https://allansantos-dv.github.io/visual-explainer/",
@@ -197,7 +197,7 @@
197
197
  },
198
198
  {
199
199
  "name": "cerne",
200
- "version": "0.4.10",
200
+ "version": "0.4.14",
201
201
  "kind": "daemon",
202
202
  "status": "self-managed",
203
203
  "summary": "Leitura ativa de vídeo por link ou arquivo: captura, seleção de quadros, transcrição, tradução e consolidação em memória, exposta via servidor MCP por um único daemon local (CerneEngine) compartilhado entre os consumidores.",
@@ -223,7 +223,7 @@
223
223
  },
224
224
  {
225
225
  "name": "skill-engine",
226
- "version": "0.1.0",
226
+ "version": "0.2.1",
227
227
  "kind": "cli",
228
228
  "summary": "Skill Manager v2: motor portátil que gerencia skills de agentes fora de qualquer IDE — busca repositórios de skills em quarentena, varre com regras determinísticas e só ativa o que sai limpo, nas pastas que Claude Code, Codex, Copilot e OpenCode leem. CLI `skill-engine`, não é daemon.",
229
229
  "pagesPendente": "sem página de produto com vídeo; ela nasce do repositório do próprio motor e este registro só aponta para ela (a sessão do skill-manager a constrói)",
@@ -247,7 +247,7 @@
247
247
  },
248
248
  {
249
249
  "name": "client-harness",
250
- "version": "0.1.1",
250
+ "version": "0.1.5",
251
251
  "kind": "cli",
252
252
  "summary": "Daemon local que faz o Claude Code e o Codex respeitarem os padrões de cada cliente: confere cada ação do agente (hooks) contra as regras do cliente da pasta e recusa antes de gravar, em cerca de 1 ms, com o motivo e o que usar no lugar.",
253
253
  "pagesUrl": "https://allansantos-dv.github.io/harness-padroes-cliente/",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "engine-kit",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Cliente das dependências compartilhadas (motores) do engine-registry: resolve, provisiona com SHA256 e assinatura Ed25519 fail-closed, e mantém o motor vivo — uma instalação por máquina, N consumidores.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -24,7 +24,7 @@
24
24
  "node": ">=18"
25
25
  },
26
26
  "scripts": {
27
- "test": "node kit/budget.mjs && node tests/test-silencio.mjs && node tests/smoke.mjs && node tests/test-edge.mjs && node tests/test-signature.mjs && node tests/test-ensure.mjs && node tests/test-ensure-daemon.mjs && node tests/test-update.mjs && node tests/test-trust.mjs && node tests/test-tar.mjs && node tests/test-apps.mjs && node tests/test-resolve-cache.mjs && node tests/test-doctor-exit.mjs && node tests/test-mcp-gateway-token.mjs && node tests/test-gateway-provision.mjs && node tests/test-neural-link-alignment.mjs && node tests/test-site.mjs && node tests/test-pages-branch.mjs && node tests/test-readme-versions.mjs && node tests/test-pages-gate.mjs",
27
+ "test": "node kit/budget.mjs && node tests/test-silencio.mjs && node tests/smoke.mjs && node tests/test-edge.mjs && node tests/test-signature.mjs && node tests/test-ensure.mjs && node tests/test-ensure-daemon.mjs && node tests/test-update.mjs && node tests/test-trust.mjs && node tests/test-rollback.mjs && node tests/test-diagnose.mjs && node tests/test-tar.mjs && node tests/test-apps.mjs && node tests/test-resolve-cache.mjs && node tests/test-doctor-exit.mjs && node tests/test-mcp-gateway-token.mjs && node tests/test-gateway-provision.mjs && node tests/test-neural-link-alignment.mjs && node tests/test-site.mjs && node tests/test-pages-branch.mjs && node tests/test-readme-versions.mjs && node tests/test-pages-gate.mjs && node tests/test-regras-escopo.mjs",
28
28
  "test:pages-live": "node tests/test-pages-gate.mjs --live",
29
29
  "test:network": "node tests/smoke.mjs --network && node tests/test-signature.mjs --network",
30
30
  "test:e2e": "node tests/e2e-install.mjs",
@@ -41,7 +41,7 @@
41
41
  "shared-infra"
42
42
  ],
43
43
  "author": {
44
- "name": "Allan Santos",
44
+ "name": "The engine-registry maintainers",
45
45
  "url": "https://github.com/AllanSantos-DV"
46
46
  },
47
47
  "repository": {