auroq-os 2.5.1 → 2.5.2
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/.auroq-core/core-config.yaml +1 -1
- package/.claude/settings.local.json +3 -0
- package/CHANGELOG.md +7 -0
- package/bin/auroq-os.js +217 -21
- package/installer/install.ps1 +2 -2
- package/installer/install.sh +2 -2
- package/lib/synapse-hashes.json +110 -0
- package/package.json +2 -2
- package/scripts/synapse-hashes.mjs +60 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## 2.5.2 — 2026-09-11
|
|
2
|
+
|
|
3
|
+
- **"UserPromptSubmit hook error ... hookEventName" a cada mensagem (EMB-040).** Quem instalou ate a 2.4.9 ficou com o Synapse antigo para sempre: a pasta era copiada sem sobrescrever e a correcao da 2.4.10 nunca chegava — o Claude Code recusava o pacote de regras em toda mensagem, enquanto a manutencao carimbava a versao nova. A manutencao agora troca todo arquivo do Synapse que seja uma versao oficial antiga (hashes das 90 versoes publicadas em `lib/synapse-hashes.json`) e guarda em `.auroq-core/preservado/synapse/` qualquer arquivo diferente de todas elas antes da troca. Integridade e `doctor` apontam o Synapse antigo em vez de dizer que esta tudo em dia.
|
|
4
|
+
- **MCP arcane com CONNECT_TIMEOUT no Claude Code (EMB-041).** O Claude Code desiste do conteudo ao vivo aos 30s; o npx a frio no Windows leva 44-77s. Instalar, manutencao, register-mcp e clone gravam `env.MCP_TIMEOUT = 120000` em `.claude/settings.local.json` (o Codex ja tinha 120s); o `doctor` cobra esse tempo.
|
|
5
|
+
- `.claude/settings.local.json` ilegivel deixa de virar `{}` (o aluno perdia os hooks): o original fica guardado ao lado e o arquivo volta a partir do modelo.
|
|
6
|
+
- Instaladores fixam 2.5.2. Correcao feita a partir da 2.5.1 publicada; o candidato de telemetria segue separado.
|
|
7
|
+
|
|
1
8
|
## 2.5.1 — 2026-09-04
|
|
2
9
|
|
|
3
10
|
- Motor registra arcane-mcp 0.5.0: diagnostico de tentativas, erros, ambiente e reenvio apos falha de rede. Conteudo de conversas e arquivos nao e coletado. Instaladores fixam esta versao validada.
|
package/bin/auroq-os.js
CHANGED
|
@@ -246,6 +246,11 @@ async function runHealthChecks(targetDir) {
|
|
|
246
246
|
missing.push(`${label} (${file})`);
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
|
+
if (await synapseDesatualizado(targetDir)) {
|
|
250
|
+
// Aviso, nao trava: um clone de negocio antigo traz o arquivo velho pelo git e so a
|
|
251
|
+
// manutencao nesta maquina (ou na outra, depois entregue) troca.
|
|
252
|
+
warn('Synapse antigo nesta pasta (erro "hookEventName" a cada mensagem). Peca ao Ops: manutencao do motor.');
|
|
253
|
+
}
|
|
249
254
|
if (passed === HEALTH_CHECKS.length) {
|
|
250
255
|
success(`${passed}/${HEALTH_CHECKS.length} verificacoes OK`);
|
|
251
256
|
} else {
|
|
@@ -280,6 +285,14 @@ async function runDoctor(targetDir) {
|
|
|
280
285
|
error(`Arquivos do sistema: faltam ${faltando}`);
|
|
281
286
|
problemas.push('Peca manutencao do motor ao Ops dentro do Claude Code pra repor o que falta.');
|
|
282
287
|
}
|
|
288
|
+
if (!(await synapseRegistrado(targetDir))) {
|
|
289
|
+
error('O hook do Synapse nao esta registrado: as regras do sistema nao chegam ao modelo');
|
|
290
|
+
problemas.push('Rode: npx auroq-os@latest register-mcp na pasta (repoe o registro sem tirar nada seu). Depois feche e abra o Claude Code.');
|
|
291
|
+
}
|
|
292
|
+
if (await synapseDesatualizado(targetDir)) {
|
|
293
|
+
error('Synapse antigo: o Claude Code recusa as regras a cada mensagem ("hookEventName")');
|
|
294
|
+
problemas.push('Peca manutencao do motor ao Ops dentro do Claude Code (ou rode npx auroq-os@latest manutencao na pasta) pra trocar o Synapse antigo.');
|
|
295
|
+
}
|
|
283
296
|
|
|
284
297
|
// 2. O motor — e, principalmente, se quem abre pelo icone vai enxergar ele.
|
|
285
298
|
// Esta e a falha silenciosa do §5.4: no terminal funciona, no app nao, e
|
|
@@ -327,6 +340,15 @@ async function runDoctor(targetDir) {
|
|
|
327
340
|
}
|
|
328
341
|
if (pin) {
|
|
329
342
|
success(`MCP arcane registrado no Claude Code (${pin})`);
|
|
343
|
+
let espera = NaN;
|
|
344
|
+
try {
|
|
345
|
+
const local = JSON.parse((await fs.readFile(path.join(targetDir, '.claude', 'settings.local.json'), 'utf8')).replace(/^\uFEFF/, ''));
|
|
346
|
+
espera = Number(local?.env?.MCP_TIMEOUT);
|
|
347
|
+
} catch { /* sem arquivo ou ilegivel = sem tempo de espera */ }
|
|
348
|
+
if (!(espera >= CLAUDE_MCP_TIMEOUT_MS)) {
|
|
349
|
+
error('O Claude Code esta com a espera padrao de 30s pelo conteudo ao vivo — no Windows a abertura pode cair (CONNECT_TIMEOUT)');
|
|
350
|
+
problemas.push('Rode: npx auroq-os@latest register-mcp (da ao Claude Code 2 minutos de espera). Depois feche e abra o Claude Code.');
|
|
351
|
+
}
|
|
330
352
|
} else {
|
|
331
353
|
error('MCP arcane nao registrado em .mcp.json');
|
|
332
354
|
problemas.push('Rode: npx auroq-os register-mcp (reescreve o registro). Depois feche e abra o Claude Code.');
|
|
@@ -461,6 +483,10 @@ async function runDoctor(targetDir) {
|
|
|
461
483
|
// pacote, (3) o doctor mede o arranque de verdade em vez de so olhar o registro.
|
|
462
484
|
const ARCANE_MCP_PIN = 'arcane-mcp@0.5.0';
|
|
463
485
|
const CODEX_MCP_STARTUP_SEC = 120;
|
|
486
|
+
// O Claude Code tambem desistia aos 30s (MCP_TIMEOUT) e o aluno via CONNECT_TIMEOUT com o
|
|
487
|
+
// servidor no ar e nenhum pedido chegando nele (11/09, EMB-041). Ele le o tempo do `env` das
|
|
488
|
+
// configuracoes da pasta: provado no 2.1.267, servidor de 40s cai aos 30s sem isto e conecta com isto.
|
|
489
|
+
const CLAUDE_MCP_TIMEOUT_MS = 120000;
|
|
464
490
|
const CODEX_ENV_MINIMO = ['PATH', 'PATHEXT', 'USERNAME', 'USERDOMAIN', 'USERPROFILE', 'TEMP', 'TMP',
|
|
465
491
|
'HOME', 'LOGNAME', 'SHELL', 'TERM', 'USER'];
|
|
466
492
|
|
|
@@ -768,6 +794,16 @@ function rodarNoCodex(pasta) {
|
|
|
768
794
|
}
|
|
769
795
|
|
|
770
796
|
async function writeArcaneMcpConfig(targetDir) {
|
|
797
|
+
// Todo caminho que registra o MCP (instalar, manutencao, register-mcp, clone) passa aqui,
|
|
798
|
+
// entao e aqui que o Claude Code ganha o tempo de espera. Falhar em gravar isso (arquivo
|
|
799
|
+
// somente leitura, dono root) nao pode derrubar o registro nem o resto da manutencao.
|
|
800
|
+
let esperaOk = false;
|
|
801
|
+
try {
|
|
802
|
+
await patchEnableAllProjectMcpServers(targetDir);
|
|
803
|
+
esperaOk = true;
|
|
804
|
+
} catch (e) {
|
|
805
|
+
warn(`Nao consegui gravar .claude/settings.local.json (${e.code || e.message}): o Claude Code segue esperando so 30s pelo conteudo ao vivo. Confira a permissao desse arquivo e rode register-mcp de novo.`);
|
|
806
|
+
}
|
|
771
807
|
const pin = ARCANE_MCP_PIN;
|
|
772
808
|
const mcpPath = path.join(targetDir, '.mcp.json');
|
|
773
809
|
let json = { mcpServers: {} };
|
|
@@ -791,22 +827,181 @@ async function writeArcaneMcpConfig(targetDir) {
|
|
|
791
827
|
const next = (toml.trimEnd() ? `${toml.trimEnd()}\n\n` : '') + block;
|
|
792
828
|
await fs.writeFile(tomlPath, next);
|
|
793
829
|
}
|
|
830
|
+
return { esperaOk };
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
async function modeloSettingsLocal() {
|
|
834
|
+
try {
|
|
835
|
+
return await fs.readJSON(path.resolve(__dirname, '..', '.claude', 'settings.local.json'));
|
|
836
|
+
} catch {
|
|
837
|
+
return {};
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
// Copia dos bytes do aluno antes de reescrever o arquivo dele. Vai pra `.auroq/` (fora do
|
|
842
|
+
// git): um settings.local.json pode ter token no `env` e nao pode subir pro GitHub.
|
|
843
|
+
async function guardarSettingsLocal(targetDir, bruto, motivo) {
|
|
844
|
+
const quando = new Date().toISOString().slice(0, 19).replace(/[:T]/g, '-');
|
|
845
|
+
const guarda = path.join(targetDir, '.auroq', 'preservado', `settings.local.json.${motivo}-${quando}`);
|
|
846
|
+
await fs.ensureDir(path.dirname(guarda));
|
|
847
|
+
await fs.writeFile(guarda, bruto);
|
|
848
|
+
const giPath = path.join(targetDir, '.gitignore');
|
|
849
|
+
const gi = (await fs.pathExists(giPath)) ? await fs.readFile(giPath, 'utf8') : '';
|
|
850
|
+
if (!gi.split('\n').map(l => l.trim()).includes('.auroq/')) {
|
|
851
|
+
await fs.writeFile(giPath, `${gi.replace(/\s*$/, gi.trim() ? '\n' : '')}.auroq/\n`);
|
|
852
|
+
}
|
|
853
|
+
return path.relative(targetDir, guarda).split(path.sep).join('/');
|
|
794
854
|
}
|
|
795
855
|
|
|
856
|
+
const ehObjeto = v => Boolean(v) && typeof v === 'object' && !Array.isArray(v);
|
|
857
|
+
|
|
858
|
+
// `.claude/settings.local.json` e do aluno: so acrescenta o que falta, nunca tira nada.
|
|
859
|
+
// E o unico lugar que registra os hooks do Synapse e do PreCompact; se o arquivo nasce
|
|
860
|
+
// sem eles (clone numa maquina nova, ou criado pelo proprio Claude Code), as regras
|
|
861
|
+
// deixam de chegar ao modelo em silencio. Por isso os hooks do modelo que faltarem entram.
|
|
796
862
|
async function patchEnableAllProjectMcpServers(targetDir) {
|
|
797
863
|
const settingsPath = path.join(targetDir, '.claude', 'settings.local.json');
|
|
798
|
-
|
|
864
|
+
const modelo = await modeloSettingsLocal();
|
|
865
|
+
let json;
|
|
866
|
+
let mudou = false;
|
|
799
867
|
if (await fs.pathExists(settingsPath)) {
|
|
868
|
+
const bruto = await fs.readFile(settingsPath);
|
|
800
869
|
try {
|
|
801
|
-
json =
|
|
870
|
+
json = JSON.parse(bruto.toString('utf8').replace(/^\uFEFF/, ''));
|
|
871
|
+
if (!ehObjeto(json)) throw new Error('nao e um objeto');
|
|
802
872
|
} catch {
|
|
803
|
-
|
|
873
|
+
// Antes virava {} e o aluno perdia os hooks e o que mais tivesse ali.
|
|
874
|
+
const guarda = await guardarSettingsLocal(targetDir, bruto, 'ilegivel');
|
|
875
|
+
warn(`.claude/settings.local.json estava ilegivel: guardei o original em ${guarda} e refiz a partir do modelo`);
|
|
876
|
+
json = JSON.parse(JSON.stringify(modelo));
|
|
877
|
+
mudou = true;
|
|
878
|
+
}
|
|
879
|
+
if (json.env !== undefined && !ehObjeto(json.env)) {
|
|
880
|
+
const guarda = await guardarSettingsLocal(targetDir, bruto, 'env-invalido');
|
|
881
|
+
warn(`O "env" de .claude/settings.local.json nao era uma lista de variaveis: guardei o original em ${guarda}`);
|
|
882
|
+
delete json.env;
|
|
883
|
+
mudou = true;
|
|
804
884
|
}
|
|
885
|
+
} else {
|
|
886
|
+
json = JSON.parse(JSON.stringify(modelo));
|
|
887
|
+
mudou = true;
|
|
888
|
+
}
|
|
889
|
+
if (ehObjeto(modelo.hooks)) {
|
|
890
|
+
// Hook ja registrado (aqui ou no settings.json, com qualquer forma de caminho) nao
|
|
891
|
+
// entra de novo: rodar o Synapse duas vezes duplicaria as regras.
|
|
892
|
+
let doProjeto = {};
|
|
893
|
+
try {
|
|
894
|
+
doProjeto = JSON.parse((await fs.readFile(path.join(targetDir, '.claude', 'settings.json'), 'utf8')).replace(/^/, ''));
|
|
895
|
+
} catch { /* sem settings.json legivel */ }
|
|
896
|
+
const scripts = (grupos) => (Array.isArray(grupos) ? grupos : [])
|
|
897
|
+
.flatMap(g => (Array.isArray(g?.hooks) ? g.hooks : []))
|
|
898
|
+
.map(h => (String(h?.command || '').match(/[\w.-]+\.c?js\b/) || [''])[0]);
|
|
899
|
+
if (!ehObjeto(json.hooks)) json.hooks = {};
|
|
900
|
+
for (const [evento, grupos] of Object.entries(modelo.hooks)) {
|
|
901
|
+
const atuais = Array.isArray(json.hooks[evento]) ? json.hooks[evento] : [];
|
|
902
|
+
const presentes = new Set([...scripts(atuais), ...scripts(doProjeto?.hooks?.[evento])].filter(Boolean));
|
|
903
|
+
const faltando = (grupos || []).filter(g => scripts([g]).some(s => s && !presentes.has(s)));
|
|
904
|
+
if (faltando.length) {
|
|
905
|
+
json.hooks[evento] = [...atuais, ...faltando];
|
|
906
|
+
mudou = true;
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
if (json.enableAllProjectMcpServers !== true) {
|
|
911
|
+
json.enableAllProjectMcpServers = true;
|
|
912
|
+
mudou = true;
|
|
805
913
|
}
|
|
806
|
-
|
|
807
|
-
|
|
914
|
+
const env = ehObjeto(json.env) ? json.env : {};
|
|
915
|
+
const atual = Number(env.MCP_TIMEOUT);
|
|
916
|
+
if (!(Number.isFinite(atual) && atual >= CLAUDE_MCP_TIMEOUT_MS)) {
|
|
917
|
+
json.env = { ...env, MCP_TIMEOUT: String(CLAUDE_MCP_TIMEOUT_MS) };
|
|
918
|
+
mudou = true;
|
|
919
|
+
}
|
|
920
|
+
if (!mudou) return false;
|
|
808
921
|
await fs.ensureDir(path.dirname(settingsPath));
|
|
809
922
|
await fs.writeJSON(settingsPath, json, { spaces: 2 });
|
|
923
|
+
return true;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
// ─── Synapse: o motor que reforca as regras do sistema a cada mensagem ───
|
|
927
|
+
// Ate a 2.5.1 esta pasta era copiada com overwrite:false. Quem instalou ate a 2.4.9 ficou
|
|
928
|
+
// para sempre com o hook-runtime.js sem `hookEventName`: o Claude Code recusava o pacote
|
|
929
|
+
// inteiro ("UserPromptSubmit hook error" a cada mensagem) e nenhuma regra chegava ao modelo,
|
|
930
|
+
// enquanto a manutencao carimbava a versao nova (EMB-040). Agora: arquivo identico a uma
|
|
931
|
+
// versao que publicamos e trocado; arquivo que ninguem publicou (mexido a mao) e guardado
|
|
932
|
+
// em .auroq-core/preservado/synapse/ antes da troca.
|
|
933
|
+
function hashNormalizado(buf) {
|
|
934
|
+
return require('crypto').createHash('sha256').update(buf.toString('utf8').replace(/\r\n/g, '\n')).digest('hex');
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
async function listarArquivos(dir, base = dir) {
|
|
938
|
+
const saida = [];
|
|
939
|
+
for (const nome of await fs.readdir(dir)) {
|
|
940
|
+
const abs = path.join(dir, nome);
|
|
941
|
+
const st = await fs.lstat(abs);
|
|
942
|
+
if (st.isDirectory()) saida.push(...(await listarArquivos(abs, base)));
|
|
943
|
+
else if (st.isFile()) saida.push(path.relative(base, abs).split(path.sep).join('/'));
|
|
944
|
+
}
|
|
945
|
+
return saida;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
async function atualizarSynapse(sourceDir, targetDir) {
|
|
949
|
+
const origem = path.join(sourceDir, '.auroq-core', 'core', 'synapse');
|
|
950
|
+
const destino = path.join(targetDir, '.auroq-core', 'core', 'synapse');
|
|
951
|
+
if (!(await fs.pathExists(origem))) return null;
|
|
952
|
+
const oficiais = require('../lib/synapse-hashes.json');
|
|
953
|
+
const r = { novos: 0, atualizados: 0, iguais: 0, preservados: [], falhas: [] };
|
|
954
|
+
for (const rel of await listarArquivos(origem)) {
|
|
955
|
+
const src = path.join(origem, ...rel.split('/'));
|
|
956
|
+
const dst = path.join(destino, ...rel.split('/'));
|
|
957
|
+
try {
|
|
958
|
+
if (!(await fs.pathExists(dst))) {
|
|
959
|
+
await fs.copy(src, dst);
|
|
960
|
+
r.novos++;
|
|
961
|
+
continue;
|
|
962
|
+
}
|
|
963
|
+
const atual = await fs.readFile(dst);
|
|
964
|
+
const hAtual = hashNormalizado(atual);
|
|
965
|
+
if (hAtual === hashNormalizado(await fs.readFile(src))) {
|
|
966
|
+
r.iguais++;
|
|
967
|
+
continue;
|
|
968
|
+
}
|
|
969
|
+
if (!(oficiais[rel] || []).includes(hAtual)) {
|
|
970
|
+
const guarda = path.join(targetDir, '.auroq-core', 'preservado', 'synapse', `${rel}.${hAtual.slice(0, 12)}`);
|
|
971
|
+
if (!(await fs.pathExists(guarda))) {
|
|
972
|
+
await fs.ensureDir(path.dirname(guarda));
|
|
973
|
+
await fs.writeFile(guarda, atual);
|
|
974
|
+
}
|
|
975
|
+
r.preservados.push(rel);
|
|
976
|
+
}
|
|
977
|
+
await fs.copy(src, dst, { overwrite: true });
|
|
978
|
+
r.atualizados++;
|
|
979
|
+
} catch (e) {
|
|
980
|
+
r.falhas.push(`${rel} (${e.code || e.message})`);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
return r;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
async function synapseRegistrado(targetDir) {
|
|
987
|
+
for (const nome of ['settings.local.json', 'settings.json']) {
|
|
988
|
+
try {
|
|
989
|
+
const json = JSON.parse((await fs.readFile(path.join(targetDir, '.claude', nome), 'utf8')).replace(/^/, ''));
|
|
990
|
+
const grupos = Array.isArray(json?.hooks?.UserPromptSubmit) ? json.hooks.UserPromptSubmit : [];
|
|
991
|
+
if (grupos.some(g => (g?.hooks || []).some(h => String(h?.command || '').includes('synapse-engine.cjs')))) return true;
|
|
992
|
+
} catch { /* arquivo ausente ou ilegivel */ }
|
|
993
|
+
}
|
|
994
|
+
return false;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
// O hook-runtime sem `hookEventName` e a assinatura do Synapse antigo (EMB-040).
|
|
998
|
+
async function synapseDesatualizado(targetDir) {
|
|
999
|
+
const arq = path.join(targetDir, '.auroq-core', 'core', 'synapse', 'runtime', 'hook-runtime.js');
|
|
1000
|
+
try {
|
|
1001
|
+
return !(await fs.readFile(arq, 'utf8')).includes('hookEventName');
|
|
1002
|
+
} catch {
|
|
1003
|
+
return false;
|
|
1004
|
+
}
|
|
810
1005
|
}
|
|
811
1006
|
|
|
812
1007
|
// ─── INSTALACAO ──────────────────────────────────────────
|
|
@@ -1196,25 +1391,26 @@ async function init({ pasta = null, maintenance = false } = {}) {
|
|
|
1196
1391
|
await fs.copy(seedRoot, targetDir, { overwrite: false });
|
|
1197
1392
|
success('Semente do aluno instalada (memoria, docs, cockpit — nunca sobrescreve)');
|
|
1198
1393
|
}
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
step('Preparando o conteudo ao vivo (baixa uma vez; no Windows prepara tambem pro Codex; pode levar 1-3 min)...');
|
|
1202
|
-
if (aquecerArcaneMcp()) success('Conteudo ao vivo pronto pra abrir rapido');
|
|
1203
|
-
else warn('Nao consegui baixar o conteudo ao vivo agora — a primeira abertura vai demorar mais');
|
|
1204
|
-
|
|
1205
|
-
// ─── Fase 4: Copiar Synapse Engine
|
|
1394
|
+
// ─── Fase 4: Synapse Engine (troca versao oficial antiga; guarda o que foi mexido a mao).
|
|
1395
|
+
// Antes do registro do MCP: se algo ali falhar, a correcao do hook (EMB-040) ja entrou.
|
|
1206
1396
|
step('Instalando Synapse Engine...');
|
|
1207
1397
|
|
|
1208
|
-
const
|
|
1209
|
-
|
|
1210
|
-
if (await fs.pathExists(synapseSrc)) {
|
|
1211
|
-
await fs.copy(synapseSrc, synapseDst, { overwrite: false });
|
|
1212
|
-
const synapseFiles = await fs.readdir(synapseSrc, { recursive: true });
|
|
1213
|
-
success(`Synapse Engine instalado (${synapseFiles.length} arquivos)`);
|
|
1214
|
-
} else {
|
|
1398
|
+
const sinapse = await atualizarSynapse(sourceDir, targetDir);
|
|
1399
|
+
if (!sinapse) {
|
|
1215
1400
|
warn('Synapse Engine nao encontrado na fonte — pulando');
|
|
1401
|
+
} else {
|
|
1402
|
+
success(`Synapse Engine em dia (${sinapse.novos} novo(s), ${sinapse.atualizados} atualizado(s))`);
|
|
1403
|
+
if (sinapse.preservados.length) {
|
|
1404
|
+
warn(`Arquivo(s) do Synapse diferente(s) de qualquer versao oficial guardado(s) em .auroq-core/preservado/synapse antes da troca: ${sinapse.preservados.join(', ')}`);
|
|
1405
|
+
}
|
|
1406
|
+
if (sinapse.falhas.length) warn(`Nao consegui atualizar: ${sinapse.falhas.join(', ')}`);
|
|
1216
1407
|
}
|
|
1217
1408
|
|
|
1409
|
+
await writeArcaneMcpConfig(targetDir);
|
|
1410
|
+
step('Preparando o conteudo ao vivo (baixa uma vez; no Windows prepara tambem pro Codex; pode levar 1-3 min)...');
|
|
1411
|
+
if (aquecerArcaneMcp()) success('Conteudo ao vivo pronto pra abrir rapido');
|
|
1412
|
+
else warn('Nao consegui baixar o conteudo ao vivo agora — a primeira abertura vai demorar mais');
|
|
1413
|
+
|
|
1218
1414
|
// ─── Fase 4b: Copiar Meta Squads e scripts (diretorios inteiros)
|
|
1219
1415
|
step('Instalando Meta Squads e scripts...');
|
|
1220
1416
|
|
|
@@ -1591,9 +1787,9 @@ if (['init', 'install', 'update'].includes(command)) {
|
|
|
1591
1787
|
error('Rode este comando na raiz do seu negocio.');
|
|
1592
1788
|
process.exit(1);
|
|
1593
1789
|
}
|
|
1594
|
-
await
|
|
1595
|
-
await writeArcaneMcpConfig(targetDir);
|
|
1790
|
+
const { esperaOk } = await writeArcaneMcpConfig(targetDir);
|
|
1596
1791
|
success('Conteudo ao vivo registrado (.mcp.json e .codex/config.toml).');
|
|
1792
|
+
if (esperaOk) success(`Claude Code espera o conteudo ao vivo por ate ${CLAUDE_MCP_TIMEOUT_MS / 1000}s (.claude/settings.local.json)`);
|
|
1597
1793
|
log(`${DIM}Baixando o conteudo ao vivo uma vez (pode levar 1-2 min)...${RESET}`);
|
|
1598
1794
|
if (aquecerArcaneMcp()) success('Conteudo ao vivo pronto pra abrir rapido');
|
|
1599
1795
|
else warn('Nao consegui baixar o conteudo ao vivo agora — a primeira abertura vai demorar mais');
|
package/installer/install.ps1
CHANGED
|
@@ -486,7 +486,7 @@ function Invoke-AuroqLogin {
|
|
|
486
486
|
# sucesso. Usado como pergunta de sim/nao, ele dizia "voce ja estava logado"
|
|
487
487
|
# pra quem nunca logou, pulava o portao e deixava a conta sem acesso chegar ate
|
|
488
488
|
# a criacao da pasta.
|
|
489
|
-
& (Get-AuroqNpx) -y auroq-os@2.5.
|
|
489
|
+
& (Get-AuroqNpx) -y auroq-os@2.5.2 check-access
|
|
490
490
|
if ($LASTEXITCODE -ne 0) {
|
|
491
491
|
Write-AuroqLog 'login' 'recusado'
|
|
492
492
|
Write-Host ''
|
|
@@ -574,7 +574,7 @@ function Invoke-AuroqInit {
|
|
|
574
574
|
if ($env:AUROQ_INSTALL_DRY_RUN) { Write-AuroqOk 'Sistema - seria montado aqui'; return }
|
|
575
575
|
|
|
576
576
|
Set-Location $script:AuroqPastaAlvo
|
|
577
|
-
& (Get-AuroqNpx) -y auroq-os@2.5.
|
|
577
|
+
& (Get-AuroqNpx) -y auroq-os@2.5.2 instalar
|
|
578
578
|
if ($LASTEXITCODE -ne 0) {
|
|
579
579
|
Write-AuroqLog 'init' 'falhou'
|
|
580
580
|
Write-AuroqErro 'A montagem do sistema parou no meio.' 'Rode o mesmo comando de novo. Se repetir, mande pro suporte o arquivo install.log da pasta .auroq.'
|
package/installer/install.sh
CHANGED
|
@@ -151,9 +151,9 @@ auroq_tem_terminal() {
|
|
|
151
151
|
# recebem pedaco do script no lugar da resposta dele.
|
|
152
152
|
auroq_npx_aluno() {
|
|
153
153
|
if [ -t 0 ]; then
|
|
154
|
-
npx -y auroq-os@2.5.
|
|
154
|
+
npx -y auroq-os@2.5.2 "$@"
|
|
155
155
|
else
|
|
156
|
-
npx -y auroq-os@2.5.
|
|
156
|
+
npx -y auroq-os@2.5.2 "$@" < /dev/tty
|
|
157
157
|
fi
|
|
158
158
|
}
|
|
159
159
|
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"context/context-builder.js": [
|
|
3
|
+
"121cd0a1df8a44098831cd4335536e8facf4e65b8aec48f4ce9c2d432dc6252a"
|
|
4
|
+
],
|
|
5
|
+
"context/context-tracker.js": [
|
|
6
|
+
"48e94db7b1778dedecc8eae829139579ad7778ff47668597ebe766610696553f"
|
|
7
|
+
],
|
|
8
|
+
"diagnostics/collectors/consistency-collector.js": [
|
|
9
|
+
"65f4255f87c9900400649dc8b9aedaac4851b5939d93e127778bd93cee99db12"
|
|
10
|
+
],
|
|
11
|
+
"diagnostics/collectors/hook-collector.js": [
|
|
12
|
+
"c2cfa1b760bcb05decf5ad05f9159140cbe0cdc6b0f91581790e44d83dc6b660"
|
|
13
|
+
],
|
|
14
|
+
"diagnostics/collectors/manifest-collector.js": [
|
|
15
|
+
"3dc895eb94485320ecbaca3a1d29e3776cfb691dd7dcc71cf44b34af30e8ebb6"
|
|
16
|
+
],
|
|
17
|
+
"diagnostics/collectors/output-analyzer.js": [
|
|
18
|
+
"e6846b1aba0a6cba17c297a871861d4f8199d7500220bff296a6a3291e32493e"
|
|
19
|
+
],
|
|
20
|
+
"diagnostics/collectors/pipeline-collector.js": [
|
|
21
|
+
"8655b6240e2f54b70def1a8c2fae00d40e2615cb95fd7ca0d64c2e0a6dfe3b73"
|
|
22
|
+
],
|
|
23
|
+
"diagnostics/collectors/quality-collector.js": [
|
|
24
|
+
"30ae299eab6d569d09afe3530a5b2f1ff35ef75366a1ab56a9e2a57d39d3611c"
|
|
25
|
+
],
|
|
26
|
+
"diagnostics/collectors/relevance-matrix.js": [
|
|
27
|
+
"f92c4f7061dc82eed4310a27b69eade33d3015f9beb1bed688601a2dccbad22e"
|
|
28
|
+
],
|
|
29
|
+
"diagnostics/collectors/safe-read-json.js": [
|
|
30
|
+
"dc7bcd13779207ad67b1c3929b7e1e0ccfa3563f3458c20cad28cb1922e9a74c"
|
|
31
|
+
],
|
|
32
|
+
"diagnostics/collectors/session-collector.js": [
|
|
33
|
+
"a116d884d6947ddc8e5f3def012d93696576c584c4fde1639b8d895924fc09ea"
|
|
34
|
+
],
|
|
35
|
+
"diagnostics/collectors/timing-collector.js": [
|
|
36
|
+
"2523ce93f863a28f798d992c4f2fab041c91a09413b3186fd290e6035b391587"
|
|
37
|
+
],
|
|
38
|
+
"diagnostics/collectors/uap-collector.js": [
|
|
39
|
+
"dd025894f8f0d3bd22a147dbc0debef8b83e96f3c59483653404b3cd5a01d5aa"
|
|
40
|
+
],
|
|
41
|
+
"diagnostics/report-formatter.js": [
|
|
42
|
+
"1aa2853928df194b669ce32c3b050a90de1311739045074f699d10210ed8d381"
|
|
43
|
+
],
|
|
44
|
+
"diagnostics/synapse-diagnostics.js": [
|
|
45
|
+
"de9dffce0e380637027cbd64b062d3eeffc37e42a84a337e5758fbef39fe3a00"
|
|
46
|
+
],
|
|
47
|
+
"domain/domain-loader.js": [
|
|
48
|
+
"af788f9da956b89eef1e5eb4ef4efdf05ca758c8969a2c375f568119495ebc05"
|
|
49
|
+
],
|
|
50
|
+
"engine.js": [
|
|
51
|
+
"47bab93a2144edce875ee68cc2717fee1bd824c9affdd5964454f5141310b8e0",
|
|
52
|
+
"c061df38ec24956da9a752f13f9455c7cd69546adb330c7587b9d456e79b4aa1"
|
|
53
|
+
],
|
|
54
|
+
"layers/l0-constitution.js": [
|
|
55
|
+
"2123a6a44915aaac2a6bbd26c67c285c9d1e12b50fe42a8ada668306b07d1c4a"
|
|
56
|
+
],
|
|
57
|
+
"layers/l1-global.js": [
|
|
58
|
+
"21f6969e6d64e9a85c876be6799db4ca7d090f0009057f4a06ead8da12392d45"
|
|
59
|
+
],
|
|
60
|
+
"layers/l2-agent.js": [
|
|
61
|
+
"a8677dc58ae7927c5292a4b52883bbc905c8112573b8b8631f0b8bc01ea2b6e6"
|
|
62
|
+
],
|
|
63
|
+
"layers/l3-workflow.js": [
|
|
64
|
+
"496cbd71d7dac9c1daa534ffac45c622d0c032f334fedf493e9322a565b2b181"
|
|
65
|
+
],
|
|
66
|
+
"layers/l4-task.js": [
|
|
67
|
+
"30df70c04b16e3aff95899211ef6ae3d9f0a8097ebdc7de92599fc6cb792e5f0"
|
|
68
|
+
],
|
|
69
|
+
"layers/l5-squad.js": [
|
|
70
|
+
"d6d35cbf966deb5a7d2df2b09f5abe8da8c6d4e346b385418f8dc1fae3ddf830"
|
|
71
|
+
],
|
|
72
|
+
"layers/l6-keyword.js": [
|
|
73
|
+
"8e5405999a2ce2f3ca4e62e863cf702ba27448914241f5eb8f02760bc7477523"
|
|
74
|
+
],
|
|
75
|
+
"layers/l7-star-command.js": [
|
|
76
|
+
"3b8372ac1c51830c1ef560b1012b112a3559651b0750e42f2037f7fe9e6787d6"
|
|
77
|
+
],
|
|
78
|
+
"layers/layer-processor.js": [
|
|
79
|
+
"73cb0e5b4bada80d8e256009004679e483792077fac4358c6466cd77136f79fa"
|
|
80
|
+
],
|
|
81
|
+
"memory/memory-bridge.js": [
|
|
82
|
+
"820875f97ceea80fc6402c0dab1706cfe58de527897b22dea68db40b0d6ec368"
|
|
83
|
+
],
|
|
84
|
+
"memory/synapse-memory-provider.js": [
|
|
85
|
+
"5d613d1fac7ee82c49a3f03b38735fd3cabfe87dd868494672ddfef300ea3145"
|
|
86
|
+
],
|
|
87
|
+
"output/formatter.js": [
|
|
88
|
+
"fe4f6c2f6091defb6af66dad71db0640f919b983111087f8cc5821e3d44ca864",
|
|
89
|
+
"3e722c4736642ef96ec73a54cd2011eed7bd1074394a38eac66cb6f0af2c855b"
|
|
90
|
+
],
|
|
91
|
+
"runtime/hook-runtime.js": [
|
|
92
|
+
"5518692eeee7dcb570507c4bb96ef68a1ef51d6ad6c417e9d1f649cd8b21b199",
|
|
93
|
+
"7c34b84c5693045a007356081959c335493bbd3afc69822fb6661e19cc10d56c"
|
|
94
|
+
],
|
|
95
|
+
"scripts/generate-constitution.js": [
|
|
96
|
+
"e2f645d5de44e6b3721a5de9b19982bc7b8cf7eed3ca4d62bc53221649c59af1"
|
|
97
|
+
],
|
|
98
|
+
"session/session-manager.js": [
|
|
99
|
+
"98e8c8fa15b074b6102bcd51c6f91f101743338e8cde6de9c31d6b6eea5d6580"
|
|
100
|
+
],
|
|
101
|
+
"utils/atomic-write.js": [
|
|
102
|
+
"efeef0fbcebb184df5b79f4ba4b4b7fe274c3ba7d1c705ce1af92628e920bd8b"
|
|
103
|
+
],
|
|
104
|
+
"utils/paths.js": [
|
|
105
|
+
"bf8cf93c1a16295e7de055bee292e2778a152b6e7d6c648dbc054a4b04dffc10"
|
|
106
|
+
],
|
|
107
|
+
"utils/tokens.js": [
|
|
108
|
+
"3b927daec51d0a791f3fe4ef9aafc362773450e7cf50eb4b6d8ae9011d70df9a"
|
|
109
|
+
]
|
|
110
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auroq-os",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.2",
|
|
4
4
|
"description": "Auroq OS \u2014 Sistema Operacional de IA para Experts",
|
|
5
5
|
"bin": {
|
|
6
6
|
"auroq-os": "bin/auroq-os.js"
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"auroq:sync:codex:check": "npm run sync:codex:check",
|
|
19
19
|
"auroq:validate": "npm run validate:hybrid",
|
|
20
20
|
"validate:hybrid": "node scripts/validate-hybrid.mjs",
|
|
21
|
-
"lint": "node --check bin/auroq-os.js && node --check lib/auth.js && node --check lib/diagnostico.js && node --check lib/credentials.js && node --check lib/onepassword.js && node --check lib/supabase.js && node --check scripts/sync-codex-skills.mjs && node --check scripts/validate-hybrid.mjs && node --check scripts/prepack-casca.mjs && node --check scripts/postpack-casca.mjs",
|
|
21
|
+
"lint": "node --check bin/auroq-os.js && node --check lib/auth.js && node --check lib/diagnostico.js && node --check lib/credentials.js && node --check lib/onepassword.js && node --check lib/supabase.js && node --check scripts/sync-codex-skills.mjs && node --check scripts/validate-hybrid.mjs && node --check scripts/prepack-casca.mjs && node --check scripts/postpack-casca.mjs && node --check scripts/synapse-hashes.mjs",
|
|
22
22
|
"typecheck": "npm run validate:hybrid",
|
|
23
23
|
"test": "node --test tests/*.test.mjs",
|
|
24
24
|
"prepack": "node scripts/prepack-casca.mjs",
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Lista de versoes OFICIAIS de cada arquivo do Synapse (`.auroq-core/core/synapse`).
|
|
4
|
+
*
|
|
5
|
+
* A manutencao so troca sem cerimonia um arquivo do aluno se ele for identico a
|
|
6
|
+
* alguma versao que nos publicamos; o que ninguem publicou (mexido a mao) e
|
|
7
|
+
* guardado antes da troca. Por isso esta lista so cresce: toda versao nova do
|
|
8
|
+
* Synapse precisa entrar aqui ANTES de publicar (o teste cobra).
|
|
9
|
+
*
|
|
10
|
+
* node scripts/synapse-hashes.mjs # acrescenta os arquivos atuais
|
|
11
|
+
* node scripts/synapse-hashes.mjs <pasta>... # acrescenta de pacotes extraidos (package/)
|
|
12
|
+
*
|
|
13
|
+
* Hash sobre o texto com CRLF normalizado para LF: a mesma versao vinda de um
|
|
14
|
+
* clone no Windows (autocrlf) continua reconhecida como oficial.
|
|
15
|
+
*/
|
|
16
|
+
import crypto from 'node:crypto';
|
|
17
|
+
import fs from 'node:fs';
|
|
18
|
+
import path from 'node:path';
|
|
19
|
+
import { fileURLToPath } from 'node:url';
|
|
20
|
+
|
|
21
|
+
const raiz = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
22
|
+
const destino = path.join(raiz, 'lib', 'synapse-hashes.json');
|
|
23
|
+
const REL = path.join('.auroq-core', 'core', 'synapse');
|
|
24
|
+
|
|
25
|
+
export function hashNormalizado(buf) {
|
|
26
|
+
return crypto.createHash('sha256').update(buf.toString('utf8').replace(/\r\n/g, '\n')).digest('hex');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function listar(dir, base = dir) {
|
|
30
|
+
const saida = [];
|
|
31
|
+
for (const nome of fs.readdirSync(dir)) {
|
|
32
|
+
const abs = path.join(dir, nome);
|
|
33
|
+
const st = fs.lstatSync(abs);
|
|
34
|
+
if (st.isDirectory()) saida.push(...listar(abs, base));
|
|
35
|
+
else if (st.isFile()) saida.push(path.relative(base, abs).split(path.sep).join('/'));
|
|
36
|
+
}
|
|
37
|
+
return saida;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function acrescentar(mapa, pacoteRaiz) {
|
|
41
|
+
const dir = path.join(pacoteRaiz, REL);
|
|
42
|
+
if (!fs.existsSync(dir)) return 0;
|
|
43
|
+
let novos = 0;
|
|
44
|
+
for (const rel of listar(dir)) {
|
|
45
|
+
const h = hashNormalizado(fs.readFileSync(path.join(dir, rel)));
|
|
46
|
+
mapa[rel] = mapa[rel] || [];
|
|
47
|
+
if (!mapa[rel].includes(h)) { mapa[rel].push(h); novos++; }
|
|
48
|
+
}
|
|
49
|
+
return novos;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
53
|
+
const mapa = fs.existsSync(destino) ? JSON.parse(fs.readFileSync(destino, 'utf8')) : {};
|
|
54
|
+
const fontes = process.argv.slice(2);
|
|
55
|
+
let novos = 0;
|
|
56
|
+
for (const fonte of fontes.length ? fontes : [raiz]) novos += acrescentar(mapa, fonte);
|
|
57
|
+
const ordenado = Object.fromEntries(Object.keys(mapa).sort().map(k => [k, mapa[k]]));
|
|
58
|
+
fs.writeFileSync(destino, `${JSON.stringify(ordenado, null, 2)}\n`);
|
|
59
|
+
console.log(`synapse-hashes: ${novos} hash(es) novo(s), ${Object.keys(ordenado).length} arquivo(s)`);
|
|
60
|
+
}
|