auroq-os 2.5.11 → 2.5.12
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/synapse/engine.js +54 -11
- package/.auroq-core/core/synapse/layers/layer-processor.js +11 -2
- package/.auroq-core/core/synapse/runtime/hook-runtime.js +27 -15
- package/.auroq-core/core-config.yaml +1 -1
- package/CHANGELOG.md +8 -0
- package/README.md +5 -6
- package/bin/auroq-os.js +2 -2
- package/installer/install.ps1 +2 -2
- package/installer/install.sh +2 -2
- package/lib/runtime-integrity.json +288 -0
- package/lib/synapse-hashes.json +6 -3
- package/package.json +5 -4
- package/scripts/build-pack.mjs +43 -12
- package/scripts/pack-state.mjs +64 -0
- package/scripts/postpack-casca.mjs +3 -26
- package/scripts/prepack-casca.mjs +32 -32
- package/scripts/runtime-integrity.mjs +173 -0
|
@@ -123,9 +123,8 @@ class PipelineMetrics {
|
|
|
123
123
|
* Record that a layer encountered an error.
|
|
124
124
|
*
|
|
125
125
|
* @param {string} name - Layer name
|
|
126
|
-
* @param {Error} error - The error object
|
|
127
126
|
*/
|
|
128
|
-
errorLayer(name
|
|
127
|
+
errorLayer(name) {
|
|
129
128
|
const existing = this.layers[name] || {};
|
|
130
129
|
if (existing.start) {
|
|
131
130
|
const endTime = process.hrtime.bigint();
|
|
@@ -135,7 +134,7 @@ class PipelineMetrics {
|
|
|
135
134
|
this.layers[name] = {
|
|
136
135
|
...existing,
|
|
137
136
|
status: 'error',
|
|
138
|
-
|
|
137
|
+
errorCode: 'SYNAPSE_LAYER_FAILED',
|
|
139
138
|
};
|
|
140
139
|
}
|
|
141
140
|
|
|
@@ -170,8 +169,27 @@ class PipelineMetrics {
|
|
|
170
169
|
// SynapseEngine
|
|
171
170
|
// ---------------------------------------------------------------------------
|
|
172
171
|
|
|
173
|
-
/**
|
|
172
|
+
/** Cooperative budget between layers; synchronous work cannot be interrupted. */
|
|
174
173
|
const PIPELINE_TIMEOUT_MS = 100;
|
|
174
|
+
// Keep substantial headroom below the outer hook's 5000 ms safety timeout.
|
|
175
|
+
const MAX_PIPELINE_TIMEOUT_MS = 1000;
|
|
176
|
+
const SYNAPSE_PIPELINE_TIMEOUT_ENV = 'AUROQ_SYNAPSE_PIPELINE_TIMEOUT_MS';
|
|
177
|
+
|
|
178
|
+
/** Resolve a short pipeline budget. Invalid values preserve the safe default. */
|
|
179
|
+
function resolvePipelineTimeoutMs(config = {}) {
|
|
180
|
+
const fromEnv = process.env[SYNAPSE_PIPELINE_TIMEOUT_ENV];
|
|
181
|
+
const value = fromEnv !== undefined && fromEnv !== ''
|
|
182
|
+
? fromEnv
|
|
183
|
+
: config.synapse?.pipelineTimeoutMs;
|
|
184
|
+
if (value === undefined || value === null) return PIPELINE_TIMEOUT_MS;
|
|
185
|
+
const timeout = typeof value === 'number' || typeof value === 'string' ? Number(value) : NaN;
|
|
186
|
+
if (!Number.isInteger(timeout) || timeout <= 0 || timeout > MAX_PIPELINE_TIMEOUT_MS) {
|
|
187
|
+
// Do not echo invalid values: environment/config may contain private text.
|
|
188
|
+
console.warn('[synapse:engine] SYNAPSE_INVALID_PIPELINE_TIMEOUT');
|
|
189
|
+
return PIPELINE_TIMEOUT_MS;
|
|
190
|
+
}
|
|
191
|
+
return timeout;
|
|
192
|
+
}
|
|
175
193
|
|
|
176
194
|
/**
|
|
177
195
|
* NOG-18: Default active layers (L0-L2 only).
|
|
@@ -250,8 +268,13 @@ class SynapseEngine {
|
|
|
250
268
|
async process(prompt, session, processConfig) {
|
|
251
269
|
const safeProcessConfig = (processConfig && typeof processConfig === 'object') ? processConfig : {};
|
|
252
270
|
const mergedConfig = { ...this.config, ...safeProcessConfig };
|
|
271
|
+
mergedConfig.synapse = { ...(this.config.synapse || {}), ...(safeProcessConfig.synapse || {}) };
|
|
272
|
+
const pipelineTimeoutMs = resolvePipelineTimeoutMs(mergedConfig);
|
|
273
|
+
const pipelineNow = typeof safeProcessConfig.nowNs === 'function'
|
|
274
|
+
? safeProcessConfig.nowNs
|
|
275
|
+
: process.hrtime.bigint;
|
|
253
276
|
const metrics = new PipelineMetrics();
|
|
254
|
-
metrics.totalStart =
|
|
277
|
+
metrics.totalStart = pipelineNow();
|
|
255
278
|
|
|
256
279
|
// 1. Calculate bracket (or use fixed layers in non-legacy mode)
|
|
257
280
|
const promptCount = (session && session.prompt_count) || 0;
|
|
@@ -266,7 +289,7 @@ class SynapseEngine {
|
|
|
266
289
|
|
|
267
290
|
// Guard: no layer config (invalid bracket — should not happen)
|
|
268
291
|
if (!layerConfig) {
|
|
269
|
-
metrics.totalEnd =
|
|
292
|
+
metrics.totalEnd = pipelineNow();
|
|
270
293
|
return { xml: '', metrics: metrics.getSummary() };
|
|
271
294
|
}
|
|
272
295
|
activeLayers = layerConfig.layers;
|
|
@@ -291,8 +314,8 @@ class SynapseEngine {
|
|
|
291
314
|
continue;
|
|
292
315
|
}
|
|
293
316
|
|
|
294
|
-
//
|
|
295
|
-
if (Number(
|
|
317
|
+
// Cooperative check between layers; the host owns interruption of a stuck process.
|
|
318
|
+
if (Number(pipelineNow() - metrics.totalStart) / 1e6 >= pipelineTimeoutMs) {
|
|
296
319
|
// Log remaining layers as skipped
|
|
297
320
|
const remaining = this.layers.slice(this.layers.indexOf(layer));
|
|
298
321
|
for (const r of remaining) {
|
|
@@ -314,14 +337,28 @@ class SynapseEngine {
|
|
|
314
337
|
previousLayers,
|
|
315
338
|
});
|
|
316
339
|
|
|
317
|
-
|
|
340
|
+
let result;
|
|
341
|
+
try {
|
|
342
|
+
result = layer._safeProcess(context);
|
|
343
|
+
} catch (_error) {
|
|
344
|
+
metrics.errorLayer(layer.name);
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
318
347
|
|
|
319
348
|
if (result && Array.isArray(result.rules)) {
|
|
320
349
|
metrics.endLayer(layer.name, result.rules.length);
|
|
321
350
|
results.push(result);
|
|
322
351
|
previousLayers.push(result);
|
|
323
352
|
} else if (result === null || result === undefined) {
|
|
324
|
-
|
|
353
|
+
try {
|
|
354
|
+
if (typeof layer.getLastError === 'function' && layer.getLastError()) {
|
|
355
|
+
metrics.errorLayer(layer.name);
|
|
356
|
+
} else {
|
|
357
|
+
metrics.skipLayer(layer.name, 'Returned null');
|
|
358
|
+
}
|
|
359
|
+
} catch (_error) {
|
|
360
|
+
metrics.errorLayer(layer.name);
|
|
361
|
+
}
|
|
325
362
|
} else {
|
|
326
363
|
metrics.skipLayer(layer.name, 'Invalid result format');
|
|
327
364
|
}
|
|
@@ -341,8 +378,9 @@ class SynapseEngine {
|
|
|
341
378
|
}
|
|
342
379
|
}
|
|
343
380
|
|
|
344
|
-
metrics.totalEnd =
|
|
381
|
+
metrics.totalEnd = pipelineNow();
|
|
345
382
|
const summary = metrics.getSummary();
|
|
383
|
+
summary.pipeline_timeout_ms = pipelineTimeoutMs;
|
|
346
384
|
|
|
347
385
|
// Persist hook metrics (fire-and-forget)
|
|
348
386
|
this._persistHookMetrics(summary, bracket, mergedConfig);
|
|
@@ -382,6 +420,7 @@ class SynapseEngine {
|
|
|
382
420
|
const hookBootMs = hookBootTime ? Number(process.hrtime.bigint() - hookBootTime) / 1e6 : 0;
|
|
383
421
|
const data = {
|
|
384
422
|
totalDuration: summary.total_ms,
|
|
423
|
+
pipelineTimeoutMs: summary.pipeline_timeout_ms,
|
|
385
424
|
hookBootMs,
|
|
386
425
|
bracket,
|
|
387
426
|
layersLoaded: summary.layers_loaded,
|
|
@@ -397,6 +436,7 @@ class SynapseEngine {
|
|
|
397
436
|
duration: info.duration || 0,
|
|
398
437
|
status: info.status || 'unknown',
|
|
399
438
|
rules: info.rules || 0,
|
|
439
|
+
...(info.errorCode ? { errorCode: info.errorCode } : {}),
|
|
400
440
|
};
|
|
401
441
|
}
|
|
402
442
|
fs.writeFileSync(
|
|
@@ -413,4 +453,7 @@ module.exports = {
|
|
|
413
453
|
SynapseEngine,
|
|
414
454
|
PipelineMetrics,
|
|
415
455
|
PIPELINE_TIMEOUT_MS,
|
|
456
|
+
MAX_PIPELINE_TIMEOUT_MS,
|
|
457
|
+
SYNAPSE_PIPELINE_TIMEOUT_ENV,
|
|
458
|
+
resolvePipelineTimeoutMs,
|
|
416
459
|
};
|
|
@@ -34,6 +34,7 @@ class LayerProcessor {
|
|
|
34
34
|
this.name = name;
|
|
35
35
|
this.layer = layer;
|
|
36
36
|
this.timeout = timeout;
|
|
37
|
+
this._lastError = null;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
/**
|
|
@@ -65,6 +66,7 @@ class LayerProcessor {
|
|
|
65
66
|
*/
|
|
66
67
|
_safeProcess(context) {
|
|
67
68
|
const start = Date.now();
|
|
69
|
+
this._lastError = null;
|
|
68
70
|
try {
|
|
69
71
|
const result = this.process(context);
|
|
70
72
|
const elapsed = Date.now() - start;
|
|
@@ -72,11 +74,18 @@ class LayerProcessor {
|
|
|
72
74
|
console.warn(`[synapse:${this.name}] Warning: Layer exceeded timeout (${elapsed}ms > ${this.timeout}ms)`);
|
|
73
75
|
}
|
|
74
76
|
return result;
|
|
75
|
-
} catch (
|
|
76
|
-
|
|
77
|
+
} catch (_error) {
|
|
78
|
+
// Raw error messages/stacks can contain prompt or domain content.
|
|
79
|
+
this._lastError = new Error('SYNAPSE_LAYER_FAILED');
|
|
80
|
+
console.warn(`[synapse:${this.name}] SYNAPSE_LAYER_FAILED`);
|
|
77
81
|
return null;
|
|
78
82
|
}
|
|
79
83
|
}
|
|
84
|
+
|
|
85
|
+
/** Return a content-free failure marker for the engine's metrics. */
|
|
86
|
+
getLastError() {
|
|
87
|
+
return this._lastError;
|
|
88
|
+
}
|
|
80
89
|
}
|
|
81
90
|
|
|
82
91
|
module.exports = LayerProcessor;
|
|
@@ -6,25 +6,29 @@ const fs = require('fs');
|
|
|
6
6
|
const DEFAULT_STALE_TTL_HOURS = 168; // 7 days
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Read
|
|
10
|
-
* Falls back to DEFAULT_STALE_TTL_HOURS (168h = 7 days).
|
|
9
|
+
* Read optional project configuration without disclosing parse failures.
|
|
11
10
|
*
|
|
12
11
|
* @param {string} cwd - Working directory
|
|
13
|
-
* @returns {
|
|
12
|
+
* @returns {object} Configuration or an empty object
|
|
14
13
|
*/
|
|
15
|
-
function
|
|
14
|
+
function loadCoreConfig(cwd) {
|
|
16
15
|
try {
|
|
17
|
-
const yaml = require('js-yaml');
|
|
18
16
|
const configPath = path.join(cwd, '.auroq-core', 'core-config.yaml');
|
|
19
|
-
if (!fs.existsSync(configPath)) return
|
|
17
|
+
if (!fs.existsSync(configPath)) return {};
|
|
18
|
+
const yaml = require('js-yaml');
|
|
20
19
|
const config = yaml.load(fs.readFileSync(configPath, 'utf8'));
|
|
21
|
-
|
|
22
|
-
return typeof ttl === 'number' && ttl > 0 ? ttl : DEFAULT_STALE_TTL_HOURS;
|
|
20
|
+
return config && typeof config === 'object' ? config : {};
|
|
23
21
|
} catch (_err) {
|
|
24
|
-
|
|
22
|
+
// YAML errors can contain configuration values; never log their text.
|
|
23
|
+
return {};
|
|
25
24
|
}
|
|
26
25
|
}
|
|
27
26
|
|
|
27
|
+
function getStaleSessionTTL(config) {
|
|
28
|
+
const ttl = config && config.synapse && config.synapse.session && config.synapse.session.staleTTLHours;
|
|
29
|
+
return typeof ttl === 'number' && ttl > 0 ? ttl : DEFAULT_STALE_TTL_HOURS;
|
|
30
|
+
}
|
|
31
|
+
|
|
28
32
|
/**
|
|
29
33
|
* Resolve runtime dependencies for Synapse hook execution.
|
|
30
34
|
*
|
|
@@ -46,7 +50,7 @@ function resolveHookRuntime(input) {
|
|
|
46
50
|
if (!fs.existsSync(synapsePath)) return null;
|
|
47
51
|
|
|
48
52
|
try {
|
|
49
|
-
const { loadSession, cleanStaleSessions } = require(
|
|
53
|
+
const { loadSession, createSession, cleanStaleSessions } = require(
|
|
50
54
|
path.join(cwd, '.auroq-core', 'core', 'synapse', 'session', 'session-manager.js'),
|
|
51
55
|
);
|
|
52
56
|
const { SynapseEngine } = require(
|
|
@@ -54,13 +58,21 @@ function resolveHookRuntime(input) {
|
|
|
54
58
|
);
|
|
55
59
|
|
|
56
60
|
const sessionsDir = path.join(synapsePath, 'sessions');
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
let session = sessionId ? loadSession(sessionId, sessionsDir) : null;
|
|
62
|
+
// loadSession validates the ID before we use it as a filename. Create only
|
|
63
|
+
// a missing session: an unreadable/corrupt existing file is kept intact.
|
|
64
|
+
if (!session && sessionId && !fs.existsSync(path.join(sessionsDir, `${sessionId}.json`))) {
|
|
65
|
+
session = createSession(sessionId, cwd, sessionsDir);
|
|
66
|
+
}
|
|
67
|
+
const shouldCleanStaleSessions = session?.prompt_count === 0;
|
|
68
|
+
session = session || { prompt_count: 0 };
|
|
69
|
+
const coreConfig = loadCoreConfig(cwd);
|
|
70
|
+
const engine = new SynapseEngine(synapsePath, { synapse: coreConfig.synapse || {} });
|
|
59
71
|
|
|
60
72
|
// AC3: Run cleanup on first prompt only (fire-and-forget)
|
|
61
|
-
if (
|
|
73
|
+
if (shouldCleanStaleSessions) {
|
|
62
74
|
try {
|
|
63
|
-
const ttlHours = getStaleSessionTTL(
|
|
75
|
+
const ttlHours = getStaleSessionTTL(coreConfig);
|
|
64
76
|
const removed = cleanStaleSessions(sessionsDir, ttlHours);
|
|
65
77
|
if (removed > 0 && process.env.DEBUG === '1') {
|
|
66
78
|
console.error(`[hook-runtime] Cleaned ${removed} stale session(s) (TTL: ${ttlHours}h)`);
|
|
@@ -73,7 +85,7 @@ function resolveHookRuntime(input) {
|
|
|
73
85
|
return { engine, session, sessionId, sessionsDir, cwd };
|
|
74
86
|
} catch (error) {
|
|
75
87
|
if (process.env.DEBUG === '1') {
|
|
76
|
-
console.error(
|
|
88
|
+
console.error('[hook-runtime] SYNAPSE_RUNTIME_FAILED');
|
|
77
89
|
}
|
|
78
90
|
return null;
|
|
79
91
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## 2.5.12 — 2026-09-21
|
|
2
|
+
|
|
3
|
+
- SYNAPSE persiste a sessao desde o primeiro prompt, limita o orcamento total entre camadas e distingue falhas sem expor mensagens/conteudo privado. Mantem manifest, eventos dos hosts e camadas opcionais desligadas.
|
|
4
|
+
- Pacote real passa por inventario SHA-256 apos a casca, arquivos obrigatorios/proibidos e referencias locais do runtime. O empacotamento restaura o checkout, inclusive em falhas. Integridade de conteudo nao equivale a assinatura de autoria.
|
|
5
|
+
- Atualiza js-yaml para 4.3.2, corrigindo avisos de consumo excessivo de CPU no parser usado pelo motor.
|
|
6
|
+
- Manutencao reconhece as versoes oficiais anteriores do SYNAPSE e preserva arquivos personalizados e dados do negocio. Mantem arcane-mcp@0.6.1.
|
|
7
|
+
- Instaladores preparados para esta versao; copias publicas so sao promovidas depois dos gates nativos macOS/Windows Node 22/24 e da verificacao no npm. Maquinas existentes atualizam pelo fluxo de manutencao.
|
|
8
|
+
|
|
1
9
|
## 2.5.11 — 2026-09-21
|
|
2
10
|
|
|
3
11
|
### O diagnostico passa a dizer o que achou (EMB-050)
|
package/README.md
CHANGED
|
@@ -228,14 +228,14 @@ agents/ → Seu exercito (companion, workers, minds, squads)
|
|
|
228
228
|
*Auroq OS — by Euriler Jube / Arka*
|
|
229
229
|
|
|
230
230
|
|
|
231
|
-
## Observabilidade do motor
|
|
231
|
+
## Observabilidade e integridade do motor
|
|
232
232
|
|
|
233
|
-
|
|
234
|
-
manutencao/diagnostico. `npx -y auroq-os@2.5.
|
|
233
|
+
`npx -y auroq-os@2.5.12 doctor` mostra a fila local segura e os comandos pinados de
|
|
234
|
+
manutencao/diagnostico. `npx -y auroq-os@2.5.12 manutencao` preserva o caminho existente
|
|
235
235
|
de consentimento legado, studentFiles, customizacoes e dados do negocio. Nao ha
|
|
236
236
|
migracao forcada. O registro MCP aponta para `arcane-mcp@0.6.1`, publicado no npm em
|
|
237
237
|
21/09/2026; `npm run release:verify` recusa publicar com um pin que o npm nao resolva.
|
|
238
|
-
|
|
238
|
+
A versao 2.5.12 so deve chegar aos instaladores publicos apos os gates nativos e a verificacao do tarball publicado. O pacote inclui `lib/runtime-integrity.json`: inventario SHA-256 gerado depois da montagem da casca, verificavel com `npm run integrity:verify` dentro do pacote extraido. Ele comprova consistencia do conteudo; nao e uma assinatura de autoria.
|
|
239
239
|
|
|
240
240
|
O CLI inicia captura antes das dependencias pesadas e registra resultado ao sair.
|
|
241
241
|
Eventos com identidade ja existente podem seguir pela rota autenticada na proxima
|
|
@@ -254,8 +254,7 @@ instalacao/manutencao/doctor/login/register-mcp. Bootstrap conversacional e o tr
|
|
|
254
254
|
final do squad nao sao inferidos como sucesso por sair do CLI ou preparar arquivos.
|
|
255
255
|
Antes de o script chegar ou em computador que nunca executa nosso codigo, nao ha sinal.
|
|
256
256
|
A rota events continua autenticada, limitada e idempotente. A plataforma deve receber
|
|
257
|
-
a whitelist antes de distribuir/promover os clientes;
|
|
258
|
-
mantem o pin 2.5.1 publicado ate a promocao npm ser possivel. Nao precisa migration adicional.
|
|
257
|
+
a whitelist antes de distribuir/promover os clientes; a promocao dos instaladores sincronizados depende da publicacao e verificacao da versao fixada. Nao precisa migration adicional.
|
|
259
258
|
|
|
260
259
|
O canal de adocao e o instalador oficial, o README/changelog, o doctor e o aviso de
|
|
261
260
|
comando aposentado quando a versao nova e executada. Isso nao atualiza silenciosamente
|
package/bin/auroq-os.js
CHANGED
|
@@ -31,7 +31,7 @@ async function observedMain() {
|
|
|
31
31
|
telemetry.runtimeReady=()=>{importing=false;};
|
|
32
32
|
runRuntime(telemetry);
|
|
33
33
|
} catch {
|
|
34
|
-
console.error('[auroq-os] '+(importing?'BOOTSTRAP_IMPORT':'RUNTIME_FAILURE')+'. Rode: npx -y auroq-os@2.5.
|
|
34
|
+
console.error('[auroq-os] '+(importing?'BOOTSTRAP_IMPORT':'RUNTIME_FAILURE')+'. Rode: npx -y auroq-os@2.5.12 doctor');
|
|
35
35
|
process.exitCode=1;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -1848,7 +1848,7 @@ if (['init', 'install', 'update'].includes(command)) {
|
|
|
1848
1848
|
error('Comando aposentado. Nada foi instalado ou alterado.');
|
|
1849
1849
|
error('Primeira instalacao: https://arcane.arka.education/auroq');
|
|
1850
1850
|
error('No negocio existente, peca ao Ops: manutencao do motor. Conteudo chega pelo MCP.');
|
|
1851
|
-
error('Diagnostico: npx -y auroq-os@2.5.
|
|
1851
|
+
error('Diagnostico: npx -y auroq-os@2.5.12 doctor. Manutencao: npx -y auroq-os@2.5.12 manutencao.');
|
|
1852
1852
|
process.exitCode = 1;
|
|
1853
1853
|
} else if (command === 'instalar' || command === 'manutencao') {
|
|
1854
1854
|
// `--pasta <nome>`: o instalador manda o CLI criar e entrar na pasta do negocio,
|
package/installer/install.ps1
CHANGED
|
@@ -589,7 +589,7 @@ function Invoke-AuroqLogin {
|
|
|
589
589
|
# sucesso. Usado como pergunta de sim/nao, ele dizia "voce ja estava logado"
|
|
590
590
|
# pra quem nunca logou, pulava o portao e deixava a conta sem acesso chegar ate
|
|
591
591
|
# a criacao da pasta.
|
|
592
|
-
& (Get-AuroqNpx) -y auroq-os@2.5.
|
|
592
|
+
& (Get-AuroqNpx) -y auroq-os@2.5.12 check-access
|
|
593
593
|
if ($LASTEXITCODE -ne 0) {
|
|
594
594
|
Write-AuroqLog 'login' 'recusado'
|
|
595
595
|
Write-Host ''
|
|
@@ -677,7 +677,7 @@ function Invoke-AuroqInit {
|
|
|
677
677
|
if ($env:AUROQ_INSTALL_DRY_RUN) { Write-AuroqOk 'Sistema - seria montado aqui'; return }
|
|
678
678
|
|
|
679
679
|
Set-Location $script:AuroqPastaAlvo
|
|
680
|
-
& (Get-AuroqNpx) -y auroq-os@2.5.
|
|
680
|
+
& (Get-AuroqNpx) -y auroq-os@2.5.12 instalar
|
|
681
681
|
if ($LASTEXITCODE -ne 0) {
|
|
682
682
|
Write-AuroqLog 'init' 'falhou'
|
|
683
683
|
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
|
@@ -219,9 +219,9 @@ auroq_tem_terminal() {
|
|
|
219
219
|
# recebem pedaco do script no lugar da resposta dele.
|
|
220
220
|
auroq_npx_aluno() {
|
|
221
221
|
if [ -t 0 ]; then
|
|
222
|
-
npx -y auroq-os@2.5.
|
|
222
|
+
npx -y auroq-os@2.5.12 "$@"
|
|
223
223
|
else
|
|
224
|
-
npx -y auroq-os@2.5.
|
|
224
|
+
npx -y auroq-os@2.5.12 "$@" < /dev/tty
|
|
225
225
|
fi
|
|
226
226
|
}
|
|
227
227
|
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": 1,
|
|
3
|
+
"algorithm": "sha256",
|
|
4
|
+
"scope": "packaged-runtime-and-cascas",
|
|
5
|
+
"version": "2.5.12",
|
|
6
|
+
"files": [
|
|
7
|
+
{
|
|
8
|
+
"path": ".auroq-core/constitution.md",
|
|
9
|
+
"sha256": "8b6df553e2708e3d9eff3f12627808ca953a4272cfbd2f94cb9ae3d4c70a73de"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"path": ".auroq-core/core-config.yaml",
|
|
13
|
+
"sha256": "bb98d40d411423cfd4e92100a003a029309d5db1a5514b1a7fed880b96fc1f56"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"path": ".auroq-core/core/synapse/context/context-builder.js",
|
|
17
|
+
"sha256": "121cd0a1df8a44098831cd4335536e8facf4e65b8aec48f4ce9c2d432dc6252a"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"path": ".auroq-core/core/synapse/context/context-tracker.js",
|
|
21
|
+
"sha256": "48e94db7b1778dedecc8eae829139579ad7778ff47668597ebe766610696553f"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"path": ".auroq-core/core/synapse/diagnostics/collectors/consistency-collector.js",
|
|
25
|
+
"sha256": "65f4255f87c9900400649dc8b9aedaac4851b5939d93e127778bd93cee99db12"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"path": ".auroq-core/core/synapse/diagnostics/collectors/hook-collector.js",
|
|
29
|
+
"sha256": "c2cfa1b760bcb05decf5ad05f9159140cbe0cdc6b0f91581790e44d83dc6b660"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"path": ".auroq-core/core/synapse/diagnostics/collectors/manifest-collector.js",
|
|
33
|
+
"sha256": "3dc895eb94485320ecbaca3a1d29e3776cfb691dd7dcc71cf44b34af30e8ebb6"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"path": ".auroq-core/core/synapse/diagnostics/collectors/output-analyzer.js",
|
|
37
|
+
"sha256": "e6846b1aba0a6cba17c297a871861d4f8199d7500220bff296a6a3291e32493e"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"path": ".auroq-core/core/synapse/diagnostics/collectors/pipeline-collector.js",
|
|
41
|
+
"sha256": "8655b6240e2f54b70def1a8c2fae00d40e2615cb95fd7ca0d64c2e0a6dfe3b73"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"path": ".auroq-core/core/synapse/diagnostics/collectors/quality-collector.js",
|
|
45
|
+
"sha256": "30ae299eab6d569d09afe3530a5b2f1ff35ef75366a1ab56a9e2a57d39d3611c"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"path": ".auroq-core/core/synapse/diagnostics/collectors/relevance-matrix.js",
|
|
49
|
+
"sha256": "f92c4f7061dc82eed4310a27b69eade33d3015f9beb1bed688601a2dccbad22e"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"path": ".auroq-core/core/synapse/diagnostics/collectors/safe-read-json.js",
|
|
53
|
+
"sha256": "dc7bcd13779207ad67b1c3929b7e1e0ccfa3563f3458c20cad28cb1922e9a74c"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"path": ".auroq-core/core/synapse/diagnostics/collectors/session-collector.js",
|
|
57
|
+
"sha256": "a116d884d6947ddc8e5f3def012d93696576c584c4fde1639b8d895924fc09ea"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"path": ".auroq-core/core/synapse/diagnostics/collectors/timing-collector.js",
|
|
61
|
+
"sha256": "2523ce93f863a28f798d992c4f2fab041c91a09413b3186fd290e6035b391587"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"path": ".auroq-core/core/synapse/diagnostics/collectors/uap-collector.js",
|
|
65
|
+
"sha256": "dd025894f8f0d3bd22a147dbc0debef8b83e96f3c59483653404b3cd5a01d5aa"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"path": ".auroq-core/core/synapse/diagnostics/report-formatter.js",
|
|
69
|
+
"sha256": "1aa2853928df194b669ce32c3b050a90de1311739045074f699d10210ed8d381"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"path": ".auroq-core/core/synapse/diagnostics/synapse-diagnostics.js",
|
|
73
|
+
"sha256": "de9dffce0e380637027cbd64b062d3eeffc37e42a84a337e5758fbef39fe3a00"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"path": ".auroq-core/core/synapse/domain/domain-loader.js",
|
|
77
|
+
"sha256": "af788f9da956b89eef1e5eb4ef4efdf05ca758c8969a2c375f568119495ebc05"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"path": ".auroq-core/core/synapse/engine.js",
|
|
81
|
+
"sha256": "775d232f67c92596f4a4a4302d5f4c69b6473680badead6ff4772f46e157381c"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"path": ".auroq-core/core/synapse/layers/l0-constitution.js",
|
|
85
|
+
"sha256": "2123a6a44915aaac2a6bbd26c67c285c9d1e12b50fe42a8ada668306b07d1c4a"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"path": ".auroq-core/core/synapse/layers/l1-global.js",
|
|
89
|
+
"sha256": "21f6969e6d64e9a85c876be6799db4ca7d090f0009057f4a06ead8da12392d45"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"path": ".auroq-core/core/synapse/layers/l2-agent.js",
|
|
93
|
+
"sha256": "a8677dc58ae7927c5292a4b52883bbc905c8112573b8b8631f0b8bc01ea2b6e6"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"path": ".auroq-core/core/synapse/layers/l3-workflow.js",
|
|
97
|
+
"sha256": "496cbd71d7dac9c1daa534ffac45c622d0c032f334fedf493e9322a565b2b181"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"path": ".auroq-core/core/synapse/layers/l4-task.js",
|
|
101
|
+
"sha256": "30df70c04b16e3aff95899211ef6ae3d9f0a8097ebdc7de92599fc6cb792e5f0"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"path": ".auroq-core/core/synapse/layers/l5-squad.js",
|
|
105
|
+
"sha256": "d6d35cbf966deb5a7d2df2b09f5abe8da8c6d4e346b385418f8dc1fae3ddf830"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"path": ".auroq-core/core/synapse/layers/l6-keyword.js",
|
|
109
|
+
"sha256": "8e5405999a2ce2f3ca4e62e863cf702ba27448914241f5eb8f02760bc7477523"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"path": ".auroq-core/core/synapse/layers/l7-star-command.js",
|
|
113
|
+
"sha256": "3b8372ac1c51830c1ef560b1012b112a3559651b0750e42f2037f7fe9e6787d6"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"path": ".auroq-core/core/synapse/layers/layer-processor.js",
|
|
117
|
+
"sha256": "46a7d08e088017a61fa6033ce4d9b3b8caba622e2c732fe158e0f531690fa3d9"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"path": ".auroq-core/core/synapse/memory/memory-bridge.js",
|
|
121
|
+
"sha256": "820875f97ceea80fc6402c0dab1706cfe58de527897b22dea68db40b0d6ec368"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"path": ".auroq-core/core/synapse/memory/synapse-memory-provider.js",
|
|
125
|
+
"sha256": "5d613d1fac7ee82c49a3f03b38735fd3cabfe87dd868494672ddfef300ea3145"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"path": ".auroq-core/core/synapse/output/formatter.js",
|
|
129
|
+
"sha256": "3e722c4736642ef96ec73a54cd2011eed7bd1074394a38eac66cb6f0af2c855b"
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"path": ".auroq-core/core/synapse/runtime/hook-runtime.js",
|
|
133
|
+
"sha256": "77a88b9324940b4feb14de6fe4de51c0fd82e2062ef4470b93de2e57bd02c88a"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"path": ".auroq-core/core/synapse/scripts/generate-constitution.js",
|
|
137
|
+
"sha256": "e2f645d5de44e6b3721a5de9b19982bc7b8cf7eed3ca4d62bc53221649c59af1"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"path": ".auroq-core/core/synapse/session/session-manager.js",
|
|
141
|
+
"sha256": "98e8c8fa15b074b6102bcd51c6f91f101743338e8cde6de9c31d6b6eea5d6580"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"path": ".auroq-core/core/synapse/utils/atomic-write.js",
|
|
145
|
+
"sha256": "efeef0fbcebb184df5b79f4ba4b4b7fe274c3ba7d1c705ce1af92628e920bd8b"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"path": ".auroq-core/core/synapse/utils/paths.js",
|
|
149
|
+
"sha256": "bf8cf93c1a16295e7de055bee292e2778a152b6e7d6c648dbc054a4b04dffc10"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"path": ".auroq-core/core/synapse/utils/tokens.js",
|
|
153
|
+
"sha256": "3b927daec51d0a791f3fe4ef9aafc362773450e7cf50eb4b6d8ae9011d70df9a"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"path": ".auroq-core/dna-operacional.md",
|
|
157
|
+
"sha256": "36d3118831d1d406a1e5eef2394fef6628396712534c59888a5968f9ffdba796"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"path": ".claude/commands/AuroqOS/agents/ops.md",
|
|
161
|
+
"sha256": "6f0df7c0dfbe28f4efa4d49d010f5a2520293c972623eb5c7dc25aa62ba7fc37"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"path": ".claude/commands/auroq-companion.md",
|
|
165
|
+
"sha256": "789bb61f076847f5695be0ea1133cfe026024c3e7a77a48f142297cc30e02196"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"path": ".claude/hooks/ahi-capture.cjs",
|
|
169
|
+
"sha256": "d99564a5bebc23281da5dbba2e82ef099c390768bed2b63f70be17c75ab8fd57"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"path": ".claude/hooks/ahi/auth-config.cjs",
|
|
173
|
+
"sha256": "bbe1f01165f0cf4562b8685a59bd2aac94758dbd0b072d287c09db10d9c6e0eb"
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"path": ".claude/hooks/ahi/runtime.cjs",
|
|
177
|
+
"sha256": "82c0b93351f25959e5cbe0a9a57b7ae29a3b497298ab351bddd7361a2ef6ce1a"
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"path": ".claude/hooks/ahi/security.cjs",
|
|
181
|
+
"sha256": "dc27db1392acd0abd8102490860bfad6a94276bbc92f63e086dc997dbe6b208c"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"path": ".claude/hooks/ahi/worker.cjs",
|
|
185
|
+
"sha256": "3eabd293f3c9c6887f6850ca4be9ad7021d6659967f2f5eecadefb2bb78e9b85"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"path": ".claude/hooks/auroq-sync.cjs",
|
|
189
|
+
"sha256": "2655dbd0a6f73ae83d0fabfb9567fc7dbf79708adcf9bfa455ea6da6fc183b9f"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"path": ".claude/hooks/precompact-session-digest.cjs",
|
|
193
|
+
"sha256": "cca89df5591fd52581d62bd35cc097d7e3d2622bd2227e7e53b425d5a6d8bdb2"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"path": ".claude/hooks/synapse-engine.cjs",
|
|
197
|
+
"sha256": "4d01f376993b570b9ca995b839d292ce9b73c597a0a1ebc8cb1ffbd214093bfe"
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"path": ".claude/settings.json",
|
|
201
|
+
"sha256": "3d0a9836997e7524d1538e96799bd5ea06575620c97a2eb03d3410b6df5d0e5a"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"path": ".claude/settings.local.json",
|
|
205
|
+
"sha256": "cb81d47fef6536bd472841811bb85f36a8219994d55399eac85732f920c566c6"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"path": "bin/auroq-os.js",
|
|
209
|
+
"sha256": "b043982de702e524799b51968b29578c04e8a6ed5f66c318d661bf776f0ef838"
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"path": "lib/ahi/client.mjs",
|
|
213
|
+
"sha256": "ded0ba89b58193e59b4ced26321965f85b8b19abc498ed8b079cab956806d789"
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"path": "lib/ahi/historico.mjs",
|
|
217
|
+
"sha256": "cb85e53dae59e793bdb83f59c3f8d14342912953b43dd9408d757a7b7182733a"
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"path": "lib/ahi/install.cjs",
|
|
221
|
+
"sha256": "f3a9fec92e64b8624fb45e062b51777788831337dec6a89ce8222d7813baca9d"
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"path": "lib/auth.js",
|
|
225
|
+
"sha256": "e775938f20b86c305e44c2b5834eeb886fec0316dccc0f3565536689b7bfb46a"
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"path": "lib/credentials.js",
|
|
229
|
+
"sha256": "92ecfba2b7ded12de5b236d64b24781ffdf05c1e770614a8d02bf05ab78d59e0"
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"path": "lib/diagnostico.js",
|
|
233
|
+
"sha256": "a7c15e8aa9dd3a7ceca3784ce7207f9593baaabedc87e88d0a674096b20c6835"
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
"path": "lib/legacy-shims.json",
|
|
237
|
+
"sha256": "1ea331604dfcadc579a7a27d53bfb2c1d1a2263e1d2ca83ed780c5ce5d2fe877"
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"path": "lib/onepassword.js",
|
|
241
|
+
"sha256": "a65d425182e0698d3f80b8d81bb088b13c5e5b60ae1aa92b095ab38d60e22ea9"
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"path": "lib/supabase.js",
|
|
245
|
+
"sha256": "a922dee14500e95b4b1f7a8d2a67baedee71c547f863e69e63f25830f9786f28"
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"path": "lib/synapse-hashes.json",
|
|
249
|
+
"sha256": "061dfe2e2c7e2a75472ae133e3465931c1267cc18e0740e7c1515404095b47e6"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"path": "lib/telemetry.mjs",
|
|
253
|
+
"sha256": "13643a1f8c33d7063a07b37190ba157755f8e26aadd4059e1afdc25fada0cf38"
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
"path": "package.json",
|
|
257
|
+
"sha256": "17d5e5a26ffd8044fd8b98260ca7961b37a326acbe8b63dd3a65af73edff1317"
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"path": "scripts/build-pack.mjs",
|
|
261
|
+
"sha256": "c4f7bbc40320dcf848307ab9d7d7c84c864ddc70a0e4db933a35406f55dcf881"
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"path": "scripts/pack-state.mjs",
|
|
265
|
+
"sha256": "7399b388eab97dd35da49055b126aba39a0c95d82cf422c62b603e9bf5de7f36"
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"path": "scripts/postpack-casca.mjs",
|
|
269
|
+
"sha256": "e361ed44a688d0cd6804bdbf3e240649b69171c2396433f0fdb55cb0f739d993"
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"path": "scripts/prepack-casca.mjs",
|
|
273
|
+
"sha256": "ecd4381a411d275af339e0bdc3acc5a0ea33ad65c1eaafad6ff3d6c79b415aff"
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"path": "scripts/runtime-integrity.mjs",
|
|
277
|
+
"sha256": "af0cb75622dcf4c049da3fc053817087648a86fc31df3be4762e974279eb87a3"
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"path": "scripts/sync-codex-skills.mjs",
|
|
281
|
+
"sha256": "36e703e8d298a5fc4cff3a85828b93a5123ab9563eeb2808c30f23f3eefd58f8"
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"path": "scripts/validate-hybrid.mjs",
|
|
285
|
+
"sha256": "d70636ad4fd6a7975df552de5cc4a88d535f0ec8596b7cf74c20e9ff73f02505"
|
|
286
|
+
}
|
|
287
|
+
]
|
|
288
|
+
}
|
package/lib/synapse-hashes.json
CHANGED
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
],
|
|
50
50
|
"engine.js": [
|
|
51
51
|
"47bab93a2144edce875ee68cc2717fee1bd824c9affdd5964454f5141310b8e0",
|
|
52
|
-
"c061df38ec24956da9a752f13f9455c7cd69546adb330c7587b9d456e79b4aa1"
|
|
52
|
+
"c061df38ec24956da9a752f13f9455c7cd69546adb330c7587b9d456e79b4aa1",
|
|
53
|
+
"775d232f67c92596f4a4a4302d5f4c69b6473680badead6ff4772f46e157381c"
|
|
53
54
|
],
|
|
54
55
|
"layers/l0-constitution.js": [
|
|
55
56
|
"2123a6a44915aaac2a6bbd26c67c285c9d1e12b50fe42a8ada668306b07d1c4a"
|
|
@@ -76,7 +77,8 @@
|
|
|
76
77
|
"3b8372ac1c51830c1ef560b1012b112a3559651b0750e42f2037f7fe9e6787d6"
|
|
77
78
|
],
|
|
78
79
|
"layers/layer-processor.js": [
|
|
79
|
-
"73cb0e5b4bada80d8e256009004679e483792077fac4358c6466cd77136f79fa"
|
|
80
|
+
"73cb0e5b4bada80d8e256009004679e483792077fac4358c6466cd77136f79fa",
|
|
81
|
+
"46a7d08e088017a61fa6033ce4d9b3b8caba622e2c732fe158e0f531690fa3d9"
|
|
80
82
|
],
|
|
81
83
|
"memory/memory-bridge.js": [
|
|
82
84
|
"820875f97ceea80fc6402c0dab1706cfe58de527897b22dea68db40b0d6ec368"
|
|
@@ -90,7 +92,8 @@
|
|
|
90
92
|
],
|
|
91
93
|
"runtime/hook-runtime.js": [
|
|
92
94
|
"5518692eeee7dcb570507c4bb96ef68a1ef51d6ad6c417e9d1f649cd8b21b199",
|
|
93
|
-
"7c34b84c5693045a007356081959c335493bbd3afc69822fb6661e19cc10d56c"
|
|
95
|
+
"7c34b84c5693045a007356081959c335493bbd3afc69822fb6661e19cc10d56c",
|
|
96
|
+
"77a88b9324940b4feb14de6fe4de51c0fd82e2062ef4470b93de2e57bd02c88a"
|
|
94
97
|
],
|
|
95
98
|
"scripts/generate-constitution.js": [
|
|
96
99
|
"e2f645d5de44e6b3721a5de9b19982bc7b8cf7eed3ca4d62bc53221649c59af1"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "auroq-os",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.12",
|
|
4
4
|
"description": "Auroq OS — Sistema Operacional de IA para Experts",
|
|
5
5
|
"bin": {
|
|
6
6
|
"auroq-os": "bin/auroq-os.js"
|
|
@@ -18,14 +18,15 @@
|
|
|
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 && node --check scripts/assert-mcp-pin.mjs && node --check lib/telemetry.mjs && node --check scripts/synapse-hashes.mjs && node --check lib/ahi/historico.mjs && node --check .claude/hooks/ahi-capture.cjs && node --check .claude/hooks/ahi/security.cjs && node --check .claude/hooks/ahi/runtime.cjs && node --check .claude/hooks/ahi/worker.cjs && node --check lib/ahi/install.cjs && node --check .claude/hooks/ahi/auth-config.cjs && node --check lib/ahi/client.mjs && node --check scripts/build-pack.mjs && node --check scripts/assert-native-release.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/assert-mcp-pin.mjs && node --check lib/telemetry.mjs && node --check scripts/synapse-hashes.mjs && node --check lib/ahi/historico.mjs && node --check .claude/hooks/ahi-capture.cjs && node --check .claude/hooks/ahi/security.cjs && node --check .claude/hooks/ahi/runtime.cjs && node --check .claude/hooks/ahi/worker.cjs && node --check lib/ahi/install.cjs && node --check .claude/hooks/ahi/auth-config.cjs && node --check lib/ahi/client.mjs && node --check scripts/build-pack.mjs && node --check scripts/assert-native-release.mjs && node --check scripts/runtime-integrity.mjs && node --check scripts/pack-state.mjs",
|
|
22
22
|
"typecheck": "npm run validate:hybrid",
|
|
23
23
|
"test": "node --test tests/*.test.mjs",
|
|
24
24
|
"release:verify": "node scripts/assert-mcp-pin.mjs && node scripts/assert-native-release.mjs",
|
|
25
25
|
"prepublishOnly": "npm run release:verify",
|
|
26
26
|
"prepack": "node scripts/prepack-casca.mjs",
|
|
27
27
|
"postpack": "node scripts/postpack-casca.mjs",
|
|
28
|
-
"build": "node scripts/build-pack.mjs"
|
|
28
|
+
"build": "node scripts/build-pack.mjs",
|
|
29
|
+
"integrity:verify": "node scripts/runtime-integrity.mjs --verify"
|
|
29
30
|
},
|
|
30
31
|
"files": [
|
|
31
32
|
"bin/",
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
"dependencies": {
|
|
57
58
|
"@supabase/supabase-js": "^2.103.0",
|
|
58
59
|
"fs-extra": "^11.3.0",
|
|
59
|
-
"js-yaml": "^4.
|
|
60
|
+
"js-yaml": "^4.3.2",
|
|
60
61
|
"prompts": "^2.4.2"
|
|
61
62
|
},
|
|
62
63
|
"author": "Euriler Jube / Arka",
|
package/scripts/build-pack.mjs
CHANGED
|
@@ -1,13 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
//
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
// Validate actual tarball bytes AFTER the casca overlay; never pack this checkout.
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { execFileSync } from 'node:child_process';
|
|
8
|
+
import { verifyRuntimeInventory } from './runtime-integrity.mjs';
|
|
9
|
+
|
|
10
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
11
|
+
const temporary = fs.mkdtempSync(path.join(os.tmpdir(), 'auroq-build-pack-'));
|
|
12
|
+
try {
|
|
13
|
+
const copy = path.join(temporary, 'source');
|
|
14
|
+
const excluded = new Set(['.git', 'node_modules', '.pack-casca-backup']);
|
|
15
|
+
if (fs.existsSync(path.join(root, '.pack-casca-backup'))) throw new Error('Pending casca backup: restore the checkout before building.');
|
|
16
|
+
fs.cpSync(root, copy, { recursive: true, filter: source => !path.relative(root, source).split(path.sep).some(part => excluded.has(part) || part.endsWith('.tgz')) });
|
|
17
|
+
const cli = process.env.npm_execpath || (process.platform === 'win32'
|
|
18
|
+
? path.join(path.dirname(process.execPath), 'node_modules', 'npm', 'bin', 'npm-cli.js') : null);
|
|
19
|
+
const args = ['pack', '--json', '--pack-destination', temporary];
|
|
20
|
+
const output = execFileSync(cli ? process.execPath : 'npm', cli ? [cli, ...args] : args,
|
|
21
|
+
{ cwd: copy, encoding: 'utf8', maxBuffer: 8 * 1024 * 1024, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
22
|
+
const match = output.match(/(\[\s*\{[\s\S]*\}\s*\])/);
|
|
23
|
+
if (!match) throw new Error('Package manifest unavailable');
|
|
24
|
+
const packages = JSON.parse(match[1]);
|
|
25
|
+
if (packages.length !== 1 || !packages[0].filename || path.basename(packages[0].filename) !== packages[0].filename) throw new Error('Invalid package result');
|
|
26
|
+
const artifact = path.join(temporary, packages[0].filename);
|
|
27
|
+
const listing = execFileSync('tar', ['-tzf', artifact], { encoding: 'utf8', maxBuffer: 8 * 1024 * 1024 });
|
|
28
|
+
const packedPaths = listing.split(/\r?\n/).filter(Boolean).map(file => {
|
|
29
|
+
if (!file.startsWith('package/') || file.endsWith('/') || file.includes('..') || file.includes('\\')) throw new Error('Invalid tarball path');
|
|
30
|
+
return file.slice('package/'.length);
|
|
31
|
+
});
|
|
32
|
+
const extracted = path.join(temporary, 'extracted');
|
|
33
|
+
fs.mkdirSync(extracted);
|
|
34
|
+
execFileSync('tar', ['-xzf', artifact, '-C', extracted], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
35
|
+
const result = verifyRuntimeInventory(path.join(extracted, 'package'), packedPaths);
|
|
36
|
+
if (fs.existsSync(path.join(copy, '.pack-casca-backup'))) throw new Error('Pack did not restore its casca overlay');
|
|
37
|
+
process.stdout.write(`Package validated: ${result.files} protected files, SHA256 and local runtime references.\n`);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
// Do not print npm lifecycle output: it may include environment-specific data.
|
|
40
|
+
console.error(`Package validation failed: ${error.status !== undefined ? 'pack/extraction command failed' : error.message}`);
|
|
41
|
+
process.exitCode = 1;
|
|
42
|
+
} finally {
|
|
43
|
+
fs.rmSync(temporary, { recursive: true, force: true });
|
|
44
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** Journal the temporary casca overlay, including files absent before packing. */
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
|
|
5
|
+
const BACKUP = '.pack-casca-backup';
|
|
6
|
+
const JOURNAL = 'overlay-state.json';
|
|
7
|
+
|
|
8
|
+
function assertPath(relative) {
|
|
9
|
+
if (!relative || path.isAbsolute(relative) || /^[A-Za-z]:/.test(relative) || relative.includes('\\') || relative.split('/').some(p => !p || p === '.' || p === '..')) {
|
|
10
|
+
throw new Error('Invalid overlay path');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function assertNoSymlink(root, relative) {
|
|
15
|
+
let current = root;
|
|
16
|
+
for (const segment of relative.split('/')) {
|
|
17
|
+
current = path.join(current, segment);
|
|
18
|
+
let stat;
|
|
19
|
+
try { stat = fs.lstatSync(current); } catch (error) { if (error.code !== 'ENOENT') throw error; }
|
|
20
|
+
if (stat?.isSymbolicLink()) throw new Error(`Symlink in overlay path: ${relative}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function beginOverlay(root) {
|
|
25
|
+
const backup = path.join(root, BACKUP);
|
|
26
|
+
if (fs.existsSync(backup)) throw new Error('Pending casca backup: restore with node scripts/postpack-casca.mjs before packing again.');
|
|
27
|
+
fs.mkdirSync(backup);
|
|
28
|
+
fs.writeFileSync(path.join(backup, JOURNAL), '[]\n');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function preserveOverlayFile(root, relative) {
|
|
32
|
+
assertPath(relative);
|
|
33
|
+
assertNoSymlink(root, relative);
|
|
34
|
+
const backup = path.join(root, BACKUP);
|
|
35
|
+
const journalFile = path.join(backup, JOURNAL);
|
|
36
|
+
const journal = JSON.parse(fs.readFileSync(journalFile, 'utf8'));
|
|
37
|
+
if (journal.some(entry => entry.path === relative)) return;
|
|
38
|
+
const source = path.join(root, relative);
|
|
39
|
+
const existed = fs.existsSync(source);
|
|
40
|
+
if (existed) {
|
|
41
|
+
if (!fs.lstatSync(source).isFile()) throw new Error(`Overlay target is not a regular file: ${relative}`);
|
|
42
|
+
const target = path.join(backup, 'files', relative);
|
|
43
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
44
|
+
fs.copyFileSync(source, target);
|
|
45
|
+
}
|
|
46
|
+
journal.push({ path: relative, existed });
|
|
47
|
+
fs.writeFileSync(journalFile, `${JSON.stringify(journal)}\n`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function restoreOverlay(root) {
|
|
51
|
+
const backup = path.join(root, BACKUP);
|
|
52
|
+
if (!fs.existsSync(backup)) return;
|
|
53
|
+
const journal = JSON.parse(fs.readFileSync(path.join(backup, JOURNAL), 'utf8'));
|
|
54
|
+
for (const entry of journal.reverse()) {
|
|
55
|
+
assertPath(entry.path);
|
|
56
|
+
assertNoSymlink(root, entry.path);
|
|
57
|
+
const target = path.join(root, entry.path);
|
|
58
|
+
if (entry.existed) {
|
|
59
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
60
|
+
fs.copyFileSync(path.join(backup, 'files', entry.path), target);
|
|
61
|
+
} else fs.rmSync(target, { force: true });
|
|
62
|
+
}
|
|
63
|
+
fs.rmSync(backup, { recursive: true });
|
|
64
|
+
}
|
|
@@ -1,32 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/** Restaura o miolo depois do npm pack/publish. */
|
|
3
|
-
import fs from 'node:fs';
|
|
4
3
|
import path from 'node:path';
|
|
5
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { restoreOverlay } from './pack-state.mjs';
|
|
6
6
|
|
|
7
|
-
const root =
|
|
8
|
-
|
|
9
|
-
const backupRoot = path.join(root, '.pack-casca-backup');
|
|
10
|
-
|
|
11
|
-
function walk(dir) {
|
|
12
|
-
const out = [];
|
|
13
|
-
if (!fs.existsSync(dir)) return out;
|
|
14
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
15
|
-
const full = path.join(dir, entry.name);
|
|
16
|
-
if (entry.isDirectory()) out.push(...walk(full));
|
|
17
|
-
else out.push(full);
|
|
18
|
-
}
|
|
19
|
-
return out;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (!fs.existsSync(backupRoot)) process.exit(0);
|
|
23
|
-
|
|
24
|
-
for (const bak of walk(backupRoot)) {
|
|
25
|
-
const rel = path.relative(backupRoot, bak);
|
|
26
|
-
const dest = path.join(root, rel);
|
|
27
|
-
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
28
|
-
fs.copyFileSync(bak, dest);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
fs.rmSync(backupRoot, { recursive: true, force: true });
|
|
7
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
8
|
+
restoreOverlay(root);
|
|
32
9
|
console.log('postpack-casca: working tree restaurado');
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
import fs from 'node:fs';
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import { beginOverlay, preserveOverlayFile, restoreOverlay } from './pack-state.mjs';
|
|
10
|
+
import { INVENTORY_PATH, writeRuntimeInventory, verifyRuntimeInventory } from './runtime-integrity.mjs';
|
|
9
11
|
|
|
10
12
|
const root = fs.realpathSync(path.join(path.dirname(fileURLToPath(import.meta.url)), '..'));
|
|
11
13
|
const cascaRoot = path.join(root, 'casca');
|
|
12
|
-
const backupRoot = path.join(root, '.pack-casca-backup');
|
|
13
14
|
|
|
14
15
|
function walk(dir) {
|
|
15
16
|
const out = [];
|
|
@@ -22,45 +23,44 @@ function walk(dir) {
|
|
|
22
23
|
return out;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
if (fs.existsSync(backupRoot)) {
|
|
26
|
-
fs.rmSync(backupRoot, { recursive: true, force: true });
|
|
27
|
-
}
|
|
28
|
-
|
|
29
26
|
const files = walk(cascaRoot);
|
|
30
27
|
if (!files.length) {
|
|
31
28
|
console.error('casca/ vazia — recusando pack');
|
|
32
29
|
process.exit(1);
|
|
33
30
|
}
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
// A missing validator fails at import time, before touching the checkout.
|
|
33
|
+
beginOverlay(root);
|
|
34
|
+
try {
|
|
35
|
+
for (const src of files) {
|
|
36
|
+
const rel = path.relative(cascaRoot, src).split(path.sep).join('/');
|
|
37
|
+
const dest = path.join(root, rel);
|
|
38
|
+
preserveOverlayFile(root, rel);
|
|
39
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
40
|
+
fs.copyFileSync(src, dest);
|
|
42
41
|
}
|
|
43
|
-
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
44
|
-
fs.copyFileSync(src, dest);
|
|
45
|
-
}
|
|
46
42
|
|
|
47
|
-
// O hook auroq-sync compara a versao lida de .auroq-core/core-config.yaml com a
|
|
48
|
-
// do npm para avisar de update. Se o core-config ficar para tras, TODO aluno ja
|
|
49
|
-
// atualizado ve "saiu versao nova" para sempre. Sincroniza no pack.
|
|
50
|
-
const pkgVersion = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8')).version;
|
|
51
|
-
const cfgPath = path.join(root, '.auroq-core', 'core-config.yaml');
|
|
52
|
-
if (fs.existsSync(cfgPath)) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
fs.copyFileSync(cfgPath, bak);
|
|
43
|
+
// O hook auroq-sync compara a versao lida de .auroq-core/core-config.yaml com a
|
|
44
|
+
// do npm para avisar de update. Se o core-config ficar para tras, TODO aluno ja
|
|
45
|
+
// atualizado ve "saiu versao nova" para sempre. Sincroniza no pack.
|
|
46
|
+
const pkgVersion = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8')).version;
|
|
47
|
+
const cfgPath = path.join(root, '.auroq-core', 'core-config.yaml');
|
|
48
|
+
if (fs.existsSync(cfgPath)) {
|
|
49
|
+
const cfg = fs.readFileSync(cfgPath, 'utf8');
|
|
50
|
+
const synced = cfg.replace(/^(\s*version:\s*)["']?\d+\.\d+\.\d+["']?/m, `$1${pkgVersion}`);
|
|
51
|
+
if (synced !== cfg) {
|
|
52
|
+
preserveOverlayFile(root, '.auroq-core/core-config.yaml');
|
|
53
|
+
fs.writeFileSync(cfgPath, synced);
|
|
54
|
+
console.log(`prepack-casca: core-config.yaml sincronizado para ${pkgVersion}`);
|
|
60
55
|
}
|
|
61
|
-
fs.writeFileSync(cfgPath, synced);
|
|
62
|
-
console.log(`prepack-casca: core-config.yaml sincronizado para ${pkgVersion}`);
|
|
63
56
|
}
|
|
64
|
-
}
|
|
65
57
|
|
|
66
|
-
|
|
58
|
+
preserveOverlayFile(root, INVENTORY_PATH);
|
|
59
|
+
writeRuntimeInventory(root);
|
|
60
|
+
const verified = verifyRuntimeInventory(root);
|
|
61
|
+
console.log(`prepack-casca: ${files.length} arquivos sobrepostos`);
|
|
62
|
+
console.log(`prepack-casca: inventario SHA256 de ${verified.files} arquivos (nao e assinatura)`);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
restoreOverlay(root);
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/** Package completeness and accidental-change checks; SHA256 is not a signature.
|
|
3
|
+
* Scope: shipped engine/cascas only. Business files and optional legacy modules
|
|
4
|
+
* are not a source of dependencies. Generate AFTER the casca overlay.
|
|
5
|
+
*/
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import crypto from 'node:crypto';
|
|
9
|
+
import { fileURLToPath } from 'node:url';
|
|
10
|
+
|
|
11
|
+
export const INVENTORY_PATH = 'lib/runtime-integrity.json';
|
|
12
|
+
const SYNAPSE_ROOT = '.auroq-core/core/synapse/';
|
|
13
|
+
const SYNAPSE_LAYERS = ['l0-constitution', 'l1-global', 'l2-agent', 'l3-workflow', 'l4-task', 'l5-squad', 'l6-keyword', 'l7-star-command'];
|
|
14
|
+
export const REQUIRED_FILES = [
|
|
15
|
+
'package.json', 'bin/auroq-os.js',
|
|
16
|
+
'lib/auth.js', 'lib/credentials.js', 'lib/diagnostico.js', 'lib/supabase.js',
|
|
17
|
+
'lib/onepassword.js', 'lib/telemetry.mjs', 'lib/synapse-hashes.json', 'lib/legacy-shims.json',
|
|
18
|
+
'lib/ahi/install.cjs', 'lib/ahi/client.mjs', 'lib/ahi/historico.mjs',
|
|
19
|
+
'scripts/runtime-integrity.mjs', 'scripts/pack-state.mjs',
|
|
20
|
+
'scripts/prepack-casca.mjs', 'scripts/postpack-casca.mjs', 'scripts/build-pack.mjs',
|
|
21
|
+
'scripts/sync-codex-skills.mjs', 'scripts/validate-hybrid.mjs',
|
|
22
|
+
'.auroq-core/core-config.yaml', '.auroq-core/constitution.md', '.auroq-core/dna-operacional.md',
|
|
23
|
+
'.auroq-core/core/synapse/engine.js', '.auroq-core/core/synapse/runtime/hook-runtime.js',
|
|
24
|
+
'.auroq-core/core/synapse/session/session-manager.js', '.auroq-core/core/synapse/domain/domain-loader.js',
|
|
25
|
+
...SYNAPSE_LAYERS.map(layer => `${SYNAPSE_ROOT}layers/${layer}.js`),
|
|
26
|
+
'.claude/settings.json', '.claude/settings.local.json',
|
|
27
|
+
'.claude/commands/AuroqOS/agents/ops.md', '.claude/commands/auroq-companion.md',
|
|
28
|
+
'.claude/hooks/synapse-engine.cjs', '.claude/hooks/auroq-sync.cjs',
|
|
29
|
+
'.claude/hooks/ahi-capture.cjs', '.claude/hooks/ahi/runtime.cjs',
|
|
30
|
+
'.claude/hooks/ahi/security.cjs', '.claude/hooks/ahi/worker.cjs', '.claude/hooks/ahi/auth-config.cjs',
|
|
31
|
+
];
|
|
32
|
+
const PROTECTED_TREES = ['lib/', '.auroq-core/core/synapse/', '.claude/hooks/'];
|
|
33
|
+
const FORBIDDEN_PREFIXES = ['business/', 'docs/knowledge/', 'casca/', '.git/', '.pack-casca-backup/'];
|
|
34
|
+
|
|
35
|
+
function safeRelative(relative) {
|
|
36
|
+
if (typeof relative !== 'string' || !relative || relative.includes('\\') || relative.startsWith('/')
|
|
37
|
+
|| relative.split('/').some(part => !part || part === '.' || part === '..') || /^[A-Za-z]:/.test(relative)) {
|
|
38
|
+
throw new Error('Invalid package path');
|
|
39
|
+
}
|
|
40
|
+
return relative;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function checkedFile(root, relative) {
|
|
44
|
+
safeRelative(relative);
|
|
45
|
+
let current = root;
|
|
46
|
+
for (const segment of relative.split('/')) {
|
|
47
|
+
current = path.join(current, segment);
|
|
48
|
+
if (fs.lstatSync(current).isSymbolicLink()) throw new Error(`Symlink in protected path: ${relative}`);
|
|
49
|
+
}
|
|
50
|
+
if (!fs.statSync(current).isFile()) throw new Error(`Not a regular file: ${relative}`);
|
|
51
|
+
return current;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function walk(root, relative) {
|
|
55
|
+
const out = [];
|
|
56
|
+
const dir = path.join(root, relative);
|
|
57
|
+
if (!fs.existsSync(dir)) throw new Error(`Missing protected directory: ${relative}`);
|
|
58
|
+
if (fs.lstatSync(dir).isSymbolicLink()) throw new Error(`Symlink in protected directory: ${relative}`);
|
|
59
|
+
for (const item of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
60
|
+
const rel = `${relative}${item.name}`;
|
|
61
|
+
if (item.isSymbolicLink()) throw new Error(`Symlink in protected path: ${rel}`);
|
|
62
|
+
if (item.isDirectory()) out.push(...walk(root, `${rel}/`));
|
|
63
|
+
else if (item.isFile() && rel !== INVENTORY_PATH) out.push(rel);
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function inventoryPaths(root) {
|
|
69
|
+
return [...new Set([...REQUIRED_FILES, ...PROTECTED_TREES.flatMap(dir => walk(root, dir))])].sort();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function digest(root, relative) {
|
|
73
|
+
return crypto.createHash('sha256').update(fs.readFileSync(checkedFile(root, relative))).digest('hex');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function resolveLocal(root, source, reference) {
|
|
77
|
+
const relative = path.posix.normalize(path.posix.join(path.posix.dirname(source), reference));
|
|
78
|
+
safeRelative(relative);
|
|
79
|
+
const candidates = path.posix.extname(relative) ? [relative] : [relative, `${relative}.js`, `${relative}.json`, `${relative}/index.js`];
|
|
80
|
+
const found = candidates.find(candidate => fs.existsSync(path.join(root, candidate)) && fs.statSync(path.join(root, candidate)).isFile());
|
|
81
|
+
if (!found) throw new Error(`Broken required local reference: ${source} -> ${reference}`);
|
|
82
|
+
checkedFile(root, found);
|
|
83
|
+
return found;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Literal imports/requires in active CLI/lib/AHI/SYNAPSE code.
|
|
87
|
+
* Dynamic SYNAPSE layers/entry targets are explicitly required above. Diagnostic
|
|
88
|
+
* tooling is outside this runtime scope; only the precise optional Pro edge is exempt.
|
|
89
|
+
*/
|
|
90
|
+
function verifyReferences(root, paths) {
|
|
91
|
+
const sources = paths.filter(p => p === 'bin/auroq-os.js'
|
|
92
|
+
|| (/\.(?:js|mjs|cjs)$/.test(p) && (p.startsWith('lib/') || p.startsWith('.claude/hooks/ahi/')))
|
|
93
|
+
|| p === `${SYNAPSE_ROOT}engine.js`
|
|
94
|
+
|| /^\.auroq-core\/core\/synapse\/(?:context|domain|layers|output|session|runtime|memory|utils)\/.*\.js$/.test(p)
|
|
95
|
+
|| p === '.claude/hooks/ahi-capture.cjs');
|
|
96
|
+
const protectedSet = new Set(paths);
|
|
97
|
+
for (const source of sources) {
|
|
98
|
+
const content = fs.readFileSync(checkedFile(root, source), 'utf8')
|
|
99
|
+
.replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, '');
|
|
100
|
+
const references = /(?:\brequire\s*\(\s*|\bimport\s*\(\s*|\bfrom\s+|\bimport\s+)['"](\.[^'"\r\n]+)['"]/g;
|
|
101
|
+
for (const match of content.matchAll(references)) {
|
|
102
|
+
if (source === `${SYNAPSE_ROOT}memory/synapse-memory-provider.js`
|
|
103
|
+
&& match[1] === '../../../../pro/memory/memory-loader') continue;
|
|
104
|
+
const target = resolveLocal(root, source, match[1]);
|
|
105
|
+
if (!protectedSet.has(target)) throw new Error(`Required reference outside protected inventory: ${source} -> ${match[1]}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
for (const source of ['.claude/settings.json', '.claude/settings.local.json']) {
|
|
109
|
+
const settings = JSON.parse(fs.readFileSync(checkedFile(root, source), 'utf8'));
|
|
110
|
+
for (const groups of Object.values(settings.hooks || {})) {
|
|
111
|
+
for (const group of groups) for (const hook of group.hooks || []) {
|
|
112
|
+
const match = typeof hook.command === 'string' && hook.command.match(/^node\s+(\.claude\/hooks\/[^\s]+)(?:\s|$)/);
|
|
113
|
+
if (match) checkedFile(root, match[1]);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function writeRuntimeInventory(root) {
|
|
120
|
+
const paths = inventoryPaths(root);
|
|
121
|
+
verifyReferences(root, paths);
|
|
122
|
+
const version = JSON.parse(fs.readFileSync(checkedFile(root, 'package.json'), 'utf8')).version;
|
|
123
|
+
const inventory = { schema: 1, algorithm: 'sha256', scope: 'packaged-runtime-and-cascas', version,
|
|
124
|
+
files: paths.map(file => ({ path: file, sha256: digest(root, file) })) };
|
|
125
|
+
fs.writeFileSync(path.join(root, INVENTORY_PATH), `${JSON.stringify(inventory, null, 2)}\n`);
|
|
126
|
+
return inventory;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function verifyRuntimeInventory(root, packedPaths) {
|
|
130
|
+
const inventory = JSON.parse(fs.readFileSync(checkedFile(root, INVENTORY_PATH), 'utf8'));
|
|
131
|
+
const version = JSON.parse(fs.readFileSync(checkedFile(root, 'package.json'), 'utf8')).version;
|
|
132
|
+
if (inventory.schema !== 1 || inventory.algorithm !== 'sha256' || inventory.scope !== 'packaged-runtime-and-cascas'
|
|
133
|
+
|| inventory.version !== version || !Array.isArray(inventory.files)) throw new Error('Invalid runtime inventory');
|
|
134
|
+
const expected = inventoryPaths(root);
|
|
135
|
+
const entries = new Map();
|
|
136
|
+
for (const entry of inventory.files) {
|
|
137
|
+
safeRelative(entry.path);
|
|
138
|
+
if (entries.has(entry.path) || !/^[a-f0-9]{64}$/.test(entry.sha256)) throw new Error('Invalid or duplicate inventory entry');
|
|
139
|
+
entries.set(entry.path, entry.sha256);
|
|
140
|
+
}
|
|
141
|
+
if (entries.size !== expected.length || expected.some(file => !entries.has(file))) throw new Error('Protected inventory is incomplete or changed');
|
|
142
|
+
for (const file of expected) {
|
|
143
|
+
if (digest(root, file) !== entries.get(file)) throw new Error(`Runtime hash mismatch: ${file}`);
|
|
144
|
+
}
|
|
145
|
+
verifyReferences(root, expected);
|
|
146
|
+
if (packedPaths) {
|
|
147
|
+
const included = new Set(packedPaths.map(safeRelative));
|
|
148
|
+
for (const file of [...expected, INVENTORY_PATH]) {
|
|
149
|
+
if (!included.has(file)) throw new Error(`Protected file missing from package: ${file}`);
|
|
150
|
+
}
|
|
151
|
+
for (const file of included) {
|
|
152
|
+
const parts = file.split('/');
|
|
153
|
+
if (FORBIDDEN_PREFIXES.some(prefix => file.startsWith(prefix))
|
|
154
|
+
|| (file.startsWith('agents/') && !file.startsWith('agents/organizer/'))
|
|
155
|
+
|| parts.some(part => part === '.npmrc' || part === '.env' || (part.startsWith('.env.') && part !== '.env.example'))
|
|
156
|
+
|| file.includes('arcane-method') || file.includes('consultor/knowledge')) throw new Error(`Forbidden package file: ${file}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return { version, files: expected.length };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (process.argv[1] && fs.existsSync(process.argv[1])
|
|
163
|
+
&& fs.realpathSync(process.argv[1]) === fs.realpathSync(fileURLToPath(import.meta.url))) {
|
|
164
|
+
try {
|
|
165
|
+
const args = process.argv.slice(2).filter(arg => arg !== '--verify');
|
|
166
|
+
if (args.length > 1 || args.some(arg => arg.startsWith('--'))) throw new Error('Usage: runtime-integrity.mjs [--verify] [package-root]');
|
|
167
|
+
const result = verifyRuntimeInventory(path.resolve(args[0] || '.'));
|
|
168
|
+
console.log(`Runtime inventory verified: ${result.files} files (SHA256; not a signature).`);
|
|
169
|
+
} catch (error) {
|
|
170
|
+
console.error(`Runtime inventory failed: ${error.message}`);
|
|
171
|
+
process.exitCode = 1;
|
|
172
|
+
}
|
|
173
|
+
}
|