auroq-os 2.6.3 → 2.6.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/.auroq-core/core-config.yaml +1 -1
- package/.claude/CLAUDE.md +1 -1
- package/CHANGELOG.md +36 -0
- package/README.md +8 -3
- package/bin/auroq-os.js +61 -4
- package/installer/install.ps1 +2 -2
- package/installer/install.sh +30 -4
- package/lib/onepassword.js +17 -0
- package/lib/runtime-integrity.json +6 -6
- package/package.json +1 -1
- package/scripts/sync-codex-skills.mjs +67 -6
package/.claude/CLAUDE.md
CHANGED
|
@@ -4,6 +4,6 @@ Sistema operacional de IA para o negócio. Você manda e julga; a IA executa.
|
|
|
4
4
|
|
|
5
5
|
Ative um agente pelo comando (`/companion`, `$companion`, `@companion`). Todo conteúdo Arcane (Companion interno, Consultor, forjas, Pack) vem pelo MCP `arcane` — nunca procurar em `agents/`.
|
|
6
6
|
|
|
7
|
-
Sua memória
|
|
7
|
+
Sua memória e seus documentos ficam na sua máquina e no seu GitHub privado (senhas e `business/vault/` ficam fora). O histórico das sessões com os squads só vai para a Arka se você autorizar na plataforma, e você pode retirar a autorização quando quiser. Além disso, a Arka registra qual conteúdo licenciado foi entregue, quando e pra qual conta — igual a uma nota de entrega.
|
|
8
8
|
|
|
9
9
|
Rules em `.claude/rules/`. Constitution em `.auroq-core/constitution.md`.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
## 2.6.5 — 2026-10-02
|
|
2
|
+
|
|
3
|
+
### Pasta do negocio nunca vai inteira pro ar na Vercel
|
|
4
|
+
|
|
5
|
+
- O Bootstrap 1 ligava a publicacao automatica da Vercel (`vercel link` + `vercel git connect`) na raiz da pasta do negocio. Sem site, a Vercel publica a pasta inteira: memoria, `business/`, `docs/`, `.claude/`, `.synapse/` num endereco aberto (conferido com `vercel build` num projeto de teste).
|
|
6
|
+
- Ops (auroq-core 2.3.21): a FASE 6 so faz login e confere a trava. A publicacao automatica liga no primeiro site, com `--root-directory` na pasta do site e conferencia em `vercel project inspect` antes do `git connect`. Pasta ja ligada na raiz: o Ops aponta a raiz pro site ou desliga o git (sem apagar nada no ar).
|
|
7
|
+
- `instalar`, `manutencao`, `clone` e `fix-gitignore` gravam um `.vercelignore` que nega memoria, negocio, documentos e configuracao. Linhas proprias do aluno ficam; rodar de novo nao duplica.
|
|
8
|
+
|
|
9
|
+
### Supabase sem segredo na conversa
|
|
10
|
+
|
|
11
|
+
- Ops FASE 7: o login do Supabase vai numa janela separada do Terminal/PowerShell aberta pelo aluno na pasta do negocio. Acabou o roteiro "gera token com validade Nunca e cola aqui no terminal" (o terminal, ali, era a conversa). Token, codigo e senha do banco colados por engano: o Ops avisa, nao repete e manda revogar.
|
|
12
|
+
- Windows: Supabase pelo instalador oficial (Scoop ou o `.exe` da pagina de releases), nunca `npm install -g`.
|
|
13
|
+
- Antes do `supabase link`, o Ops mostra os projetos da conta e o aluno confirma qual e deste negocio; projeto de outro produto ou de producao nao e usado.
|
|
14
|
+
|
|
15
|
+
### Instalador do Mac nao tira mais o `claude` do caminho
|
|
16
|
+
|
|
17
|
+
- `auroq_aplicar_path` reescrevia o bloco do perfil so com a pasta da vez: no Mac sem Node, a pasta do motor (segunda chamada) apagava `~/.local/bin` e o aluno ficava com `claude: command not found`. O bloco agora guarda as duas pastas (motor na frente), sem duplicar ao reinstalar, descarta pasta que nao existe mais e aceita caminho com espaco. Testes com shell limpo (bash e zsh).
|
|
18
|
+
|
|
19
|
+
### Texto de privacidade verdadeiro
|
|
20
|
+
|
|
21
|
+
- `casca/.claude/CLAUDE.md` dizia que memoria, documentos e conversas "nunca saem da sua maquina". Agora: ficam na maquina e no GitHub privado do aluno; o historico das sessoes com squads so vai para a Arka se ele autorizar na plataforma, e a autorizacao pode ser retirada.
|
|
22
|
+
- Mantem `arcane-mcp@0.7.0`. Instaladores do repositorio preparados para 2.6.5.
|
|
23
|
+
|
|
24
|
+
## 2.6.4 — 2026-09-29
|
|
25
|
+
|
|
26
|
+
### Companion com o nome do aluno nao trava mais a atualizacao
|
|
27
|
+
|
|
28
|
+
- Quem deu nome ao Companion no Bootstrap (ex.: "Atlas" → `/atlas-companion`) podia ficar preso em "Sync de skills do Codex falhou" → "arquivo faltando: Codex Companion (.agents/skills/companion/SKILL.md)" → `AUROQ_RESULTADO status=erro`. Tres alunos em 29/09.
|
|
29
|
+
- Causa: o sync do Codex morria inteiro na primeira pasta de skill que nao reconhecia — pasta do negocio movida, copiada ou vinda de outra maquina (marcador com outro caminho), `companion.md` antigo colidindo com `auroq-companion.md`, ou skill feita a mao pelo agente. Como o `--clean` ja tinha apagado a skill `companion` quando o comando base sumiu, ela nunca voltava e a verificacao final derrubava a atualizacao.
|
|
30
|
+
- O sync nao para mais por isso: pasta de skill com o nosso marcador dentro do proprio negocio e reconhecida mesmo depois de mover a pasta; colisao de nome usa o comando oficial e segue; skill sem marcador feita pelo aluno fica como esta, com aviso. A pasta global `~/.agents/skills` continua recusando o que e de outro projeto.
|
|
31
|
+
- `$companion` sempre existe no Codex: sem o comando base, vira atalho do comando com o nome do aluno. `$atlas-companion` continua.
|
|
32
|
+
- A verificacao de integridade aceita o comando com o nome do aluno como o Companion (so ele; os outros arquivos seguem exigidos pelo caminho exato). Quando o sync falha, a manutencao mostra o motivo.
|
|
33
|
+
- Ops (auroq-core 2.3.20): a FASE 10 cria o comando com o nome e deixa `/auroq-companion` no lugar (antes mandava apagar um `companion.md` que nao existe mais).
|
|
34
|
+
- Quem esta travado: "atualiza o sistema" termina `status=ok` e mantem o nome, o comando e o conteudo do Companion.
|
|
35
|
+
- Mantem `arcane-mcp@0.7.0`. Instaladores do repositorio preparados para 2.6.4.
|
|
36
|
+
|
|
1
37
|
## 2.6.3 — 2026-09-29
|
|
2
38
|
|
|
3
39
|
### Codex no Windows volta a ler e gravar na pasta (EMB-063)
|
package/README.md
CHANGED
|
@@ -55,6 +55,11 @@ O caminho manual antigo foi aposentado. Use a instalacao guiada acima. Em negoci
|
|
|
55
55
|
| `auroq-os sync-codex` | Regenera e verifica as skills locais do Codex |
|
|
56
56
|
| `auroq-os conectar-1password` | Conecta o 1Password CLI — le o token de Service Account direto do Ctrl+C (nunca digitado nem exposto), instala o `op` se faltar, valida online e salva permanente (Mac/Windows) |
|
|
57
57
|
|
|
58
|
+
> **Seguranca do token 1Password:** o token fica salvo no computador e qualquer programa seu consegue usa-lo.
|
|
59
|
+
> Crie a Service Account com acesso a **um cofre so**, dedicado ao Auroq (o cofre `Claude`), sem senhas
|
|
60
|
+
> pessoais, de banco ou da empresa. Permissao **so leitura**; libere escrita apenas nesse cofre se quiser
|
|
61
|
+
> que o Auroq guarde ali as credenciais novas que voce conectar.
|
|
62
|
+
|
|
58
63
|
Dentro do projeto instalado, os mesmos checks ficam disponiveis como
|
|
59
64
|
`npm run auroq:sync:codex`, `npm run auroq:sync:codex:check` e
|
|
60
65
|
`npm run auroq:validate`. O instalador adiciona esses scripts sem sobrescrever
|
|
@@ -241,13 +246,13 @@ agents/ → Seu exercito (companion, workers, minds, squads)
|
|
|
241
246
|
|
|
242
247
|
## Observabilidade e integridade do motor
|
|
243
248
|
|
|
244
|
-
Apos publicacao, `npx -y auroq-os@2.6.
|
|
245
|
-
manutencao/diagnostico. `npx -y auroq-os@2.6.
|
|
249
|
+
Apos publicacao, `npx -y auroq-os@2.6.5 doctor` mostra a fila local segura e os comandos pinados de
|
|
250
|
+
manutencao/diagnostico. `npx -y auroq-os@2.6.5 manutencao` preserva o caminho existente
|
|
246
251
|
de consentimento legado, studentFiles, customizacoes e dados do negocio. Nao ha
|
|
247
252
|
migracao forcada. O registro MCP aponta para `arcane-mcp@0.7.0` — o pin mora no campo
|
|
248
253
|
`arcaneMcpPin` do package.json (fonte unica; o servidor le o mesmo campo no npm).
|
|
249
254
|
`npm run release:verify` recusa publicar com um pin que o npm nao resolva.
|
|
250
|
-
Os instaladores do repositorio ficam preparados para 2.6.
|
|
255
|
+
Os instaladores do repositorio ficam preparados para 2.6.5; as copias publicas so recebem
|
|
251
256
|
a versao apos os gates nativos e a verificacao do tarball publicado.
|
|
252
257
|
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.
|
|
253
258
|
|
package/bin/auroq-os.js
CHANGED
|
@@ -353,6 +353,30 @@ async function untrackSecrets(targetDir) {
|
|
|
353
353
|
return tracked;
|
|
354
354
|
}
|
|
355
355
|
|
|
356
|
+
// ─── TRAVA DA VERCEL (.vercelignore canonico) ────────────
|
|
357
|
+
// A pasta do negocio nao e um site. Se alguem ligar a Vercel na raiz do repositorio
|
|
358
|
+
// (Bootstrap antigo: `vercel link` + `vercel git connect` sem site), sem esta trava a
|
|
359
|
+
// Vercel publica memoria, documentos e configuracao num endereco aberto. Com a raiz
|
|
360
|
+
// na pasta do site (o certo), este arquivo nem e lido. Linhas proprias do expert ficam.
|
|
361
|
+
const VERCELIGNORE_HEADER = '# ── Trava do Auroq OS: a pasta do negocio nao vai ao ar (adicionada automaticamente) ──';
|
|
362
|
+
const VERCELIGNORE_PROTECTIONS = [
|
|
363
|
+
'.claude/', '.codex/', '.agents/', '.synapse/', '.auroq-core/', '.auroq/', '.git/',
|
|
364
|
+
'agents/', 'business/', 'docs/', 'memoria/', 'memory/', 'squads/',
|
|
365
|
+
'AGENTS.md', 'CLAUDE.md', '*.md', '.env', '.env.*', '*.key', '*.pem', '.npmrc',
|
|
366
|
+
];
|
|
367
|
+
|
|
368
|
+
async function ensureVercelignore(targetDir) {
|
|
369
|
+
const viPath = path.join(targetDir, '.vercelignore');
|
|
370
|
+
const existing = (await fs.pathExists(viPath)) ? await fs.readFile(viPath, 'utf8') : '';
|
|
371
|
+
const have = new Set(existing.split('\n').map(l => l.trim()).filter(Boolean));
|
|
372
|
+
const missing = VERCELIGNORE_PROTECTIONS.filter(l => !have.has(l));
|
|
373
|
+
if (!missing.length) return [];
|
|
374
|
+
const base = existing.trim().length ? existing.replace(/\s*$/, '\n\n') : '';
|
|
375
|
+
const header = have.has(VERCELIGNORE_HEADER) ? '' : `${VERCELIGNORE_HEADER}\n`;
|
|
376
|
+
await fs.writeFile(viPath, base + header + missing.join('\n') + '\n');
|
|
377
|
+
return missing;
|
|
378
|
+
}
|
|
379
|
+
|
|
356
380
|
async function applySecretProtections(targetDir) {
|
|
357
381
|
const added = await ensureGitignore(targetDir);
|
|
358
382
|
if (added.length) {
|
|
@@ -360,6 +384,10 @@ async function applySecretProtections(targetDir) {
|
|
|
360
384
|
} else {
|
|
361
385
|
success('.gitignore ja protege segredos e runtime');
|
|
362
386
|
}
|
|
387
|
+
const travaVercel = await ensureVercelignore(targetDir);
|
|
388
|
+
if (travaVercel.length) {
|
|
389
|
+
success('Trava da Vercel no lugar: memoria, documentos e configuracao do negocio nunca vao ao ar');
|
|
390
|
+
}
|
|
363
391
|
const untracked = await untrackSecrets(targetDir);
|
|
364
392
|
if (untracked.length) {
|
|
365
393
|
warn(`${untracked.length} arquivo(s) sensivel(is) removido(s) do controle de versao (continuam no seu disco):`);
|
|
@@ -398,6 +426,32 @@ const HEALTH_CHECKS = [
|
|
|
398
426
|
['scripts/validate-hybrid.mjs', 'Validador hibrido'],
|
|
399
427
|
];
|
|
400
428
|
|
|
429
|
+
/**
|
|
430
|
+
* O aluno da um nome ao Companion no bootstrap (FASE 10 do Ops): `/atlas-companion`. Um
|
|
431
|
+
* comando com esse nome que ainda aponta pro Companion (recurso `companion` do MCP ou a
|
|
432
|
+
* pasta agents/companion/) vale como a casca dele — um clone do negocio que so tem o
|
|
433
|
+
* comando com o nome do aluno nao pode ser acusado de "arquivo faltando". So o Companion
|
|
434
|
+
* tem essa folga: os outros arquivos continuam exigidos pelo caminho exato.
|
|
435
|
+
*/
|
|
436
|
+
async function companionComNomeDoAluno(targetDir) {
|
|
437
|
+
const dir = path.join(targetDir, '.claude', 'commands');
|
|
438
|
+
let nomes = [];
|
|
439
|
+
try { nomes = await fs.readdir(dir); } catch { return null; }
|
|
440
|
+
for (const nome of nomes.filter(n => /^[a-z0-9-]+-companion\.md$/.test(n)).sort()) {
|
|
441
|
+
try {
|
|
442
|
+
const texto = await fs.readFile(path.join(dir, nome), 'utf8');
|
|
443
|
+
if (/recurso_id\s*`?companion`?/.test(texto) || /agents\/companion\//.test(texto)) return `.claude/commands/${nome}`;
|
|
444
|
+
} catch { /* ilegivel: nao conta */ }
|
|
445
|
+
}
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
async function checagemPresente(targetDir, file) {
|
|
450
|
+
if (await fs.pathExists(path.join(targetDir, file))) return true;
|
|
451
|
+
if (file === '.claude/commands/auroq-companion.md') return Boolean(await companionComNomeDoAluno(targetDir));
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
|
|
401
455
|
/**
|
|
402
456
|
* Registro pro suporte (PRD "Embarque em 2 passos" §5.7).
|
|
403
457
|
*
|
|
@@ -494,7 +548,7 @@ async function runHealthChecks(targetDir) {
|
|
|
494
548
|
let passed = 0;
|
|
495
549
|
const missing = [];
|
|
496
550
|
for (const [file, label] of HEALTH_CHECKS) {
|
|
497
|
-
if (await
|
|
551
|
+
if (await checagemPresente(targetDir, file)) {
|
|
498
552
|
passed++;
|
|
499
553
|
} else {
|
|
500
554
|
missing.push(`${label} (${file})`);
|
|
@@ -531,7 +585,7 @@ async function runDoctor(targetDir) {
|
|
|
531
585
|
// 1. arquivos de autoload
|
|
532
586
|
let faltando = 0;
|
|
533
587
|
for (const [file] of HEALTH_CHECKS) {
|
|
534
|
-
if (!(await
|
|
588
|
+
if (!(await checagemPresente(targetDir, file))) faltando++;
|
|
535
589
|
}
|
|
536
590
|
if (faltando === 0) {
|
|
537
591
|
success(`Arquivos do sistema: ${HEALTH_CHECKS.length}/${HEALTH_CHECKS.length} no lugar`);
|
|
@@ -1968,8 +2022,11 @@ async function init({ pasta = null, maintenance = false, modoAgente = false, mig
|
|
|
1968
2022
|
execSync('node scripts/sync-codex-skills.mjs --clean', { cwd: targetDir, stdio: 'pipe' });
|
|
1969
2023
|
execSync('node scripts/sync-codex-skills.mjs --check', { cwd: targetDir, stdio: 'pipe' });
|
|
1970
2024
|
success('Codex CLI pronto — skills locais verificadas ($companion, $ops, etc.)');
|
|
1971
|
-
} catch {
|
|
2025
|
+
} catch (e) {
|
|
1972
2026
|
warn('Sync de skills do Codex falhou — rode "npx auroq-os sync-codex" para diagnosticar');
|
|
2027
|
+
// Sem o motivo, o suporte so via o efeito ("Codex Companion faltando") e nunca a causa.
|
|
2028
|
+
const motivo = String(e && (e.stderr || e.message) || '').split(/\r?\n/).find(l => /Error:|Skill |Drift|Ownership|Recusando/.test(l));
|
|
2029
|
+
if (motivo) warn(` ${motivo.trim().slice(0, 300)}`);
|
|
1973
2030
|
}
|
|
1974
2031
|
|
|
1975
2032
|
// ─── Fase 5: npm install
|
|
@@ -2401,6 +2458,6 @@ if (['init', 'install', 'update'].includes(command)) {
|
|
|
2401
2458
|
log('');
|
|
2402
2459
|
}
|
|
2403
2460
|
|
|
2404
|
-
if (process.env.AUROQ_EXPORTA_INTERNOS === '1') module.exports = { blocoCodexArcane, envCodexArcane, lerBlocoArcane, lerEnvDoBloco, limparArcaneDoGlobal, envComoCodex, argumentosCodexSmoke, avaliarEventosCodex, rotulo, ARCANE_MCP_PIN };
|
|
2461
|
+
if (process.env.AUROQ_EXPORTA_INTERNOS === '1') module.exports = { blocoCodexArcane, envCodexArcane, lerBlocoArcane, lerEnvDoBloco, limparArcaneDoGlobal, envComoCodex, argumentosCodexSmoke, avaliarEventosCodex, rotulo, ARCANE_MCP_PIN, ensureVercelignore, VERCELIGNORE_PROTECTIONS };
|
|
2405
2462
|
|
|
2406
2463
|
}
|
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.6.
|
|
592
|
+
& (Get-AuroqNpx) -y auroq-os@2.6.5 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.6.
|
|
680
|
+
& (Get-AuroqNpx) -y auroq-os@2.6.5 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.6.
|
|
222
|
+
npx -y auroq-os@2.6.5 "$@"
|
|
223
223
|
else
|
|
224
|
-
npx -y auroq-os@2.6.
|
|
224
|
+
npx -y auroq-os@2.6.5 "$@" < /dev/tty
|
|
225
225
|
fi
|
|
226
226
|
}
|
|
227
227
|
|
|
@@ -245,6 +245,32 @@ auroq_aplicar_path() {
|
|
|
245
245
|
local bin="${2:-}"
|
|
246
246
|
local tmp="${arquivo}.auroq-tmp.$$"
|
|
247
247
|
[ -f "$arquivo" ] || : > "$arquivo"
|
|
248
|
+
# O instalador publica DUAS pastas, em chamadas separadas: a da ferramenta
|
|
249
|
+
# (~/.local/bin, onde mora o `claude`) e a do motor. Reescrever o bloco so com
|
|
250
|
+
# a pasta da vez apagava a outra: Mac sem Node terminava com `claude: command
|
|
251
|
+
# not found`. Agora o bloco guarda todas as pastas do Auroq que ainda existem,
|
|
252
|
+
# a da vez na frente (o motor entra por ultimo e fica na frente do Node velho).
|
|
253
|
+
local pastas="$bin"
|
|
254
|
+
local antiga
|
|
255
|
+
while IFS= read -r antiga; do
|
|
256
|
+
[ -n "$antiga" ] || continue
|
|
257
|
+
[ "$antiga" = "$bin" ] && continue
|
|
258
|
+
[ -d "$antiga" ] || continue
|
|
259
|
+
case ":${pastas}:" in *":${antiga}:"*) continue ;; esac
|
|
260
|
+
pastas="${pastas}:${antiga}"
|
|
261
|
+
done <<EOF
|
|
262
|
+
$(awk '
|
|
263
|
+
/^# >>> auroq >>>$/ { dentro=1; next }
|
|
264
|
+
/^# <<< auroq <<<$/ { dentro=0; next }
|
|
265
|
+
dentro == 1 && /^export PATH="/ {
|
|
266
|
+
linha=$0
|
|
267
|
+
sub(/^export PATH="/, "", linha)
|
|
268
|
+
sub(/:\$PATH"$/, "", linha)
|
|
269
|
+
n=split(linha, partes, ":")
|
|
270
|
+
for (i=1; i<=n; i++) if (partes[i] != "") print partes[i]
|
|
271
|
+
}
|
|
272
|
+
' "$arquivo" 2>/dev/null)
|
|
273
|
+
EOF
|
|
248
274
|
# tira o bloco antigo (se houver) e escreve o novo — nunca empilha
|
|
249
275
|
awk '
|
|
250
276
|
/^# >>> auroq >>>$/ { pulando=1; next }
|
|
@@ -253,8 +279,8 @@ auroq_aplicar_path() {
|
|
|
253
279
|
' "$arquivo" > "$tmp" 2>/dev/null || cp "$arquivo" "$tmp"
|
|
254
280
|
{
|
|
255
281
|
printf '# >>> auroq >>>\n'
|
|
256
|
-
printf '# Motor do Auroq OS. Bloco gerado pelo instalador — pode apagar se desinstalar.\n'
|
|
257
|
-
printf 'export PATH="%s:$PATH"\n' "$
|
|
282
|
+
printf '# Motor e ferramentas do Auroq OS. Bloco gerado pelo instalador — pode apagar se desinstalar.\n'
|
|
283
|
+
printf 'export PATH="%s:$PATH"\n' "$pastas"
|
|
258
284
|
printf '# <<< auroq <<<\n'
|
|
259
285
|
} >> "$tmp"
|
|
260
286
|
mv "$tmp" "$arquivo"
|
package/lib/onepassword.js
CHANGED
|
@@ -191,6 +191,19 @@ function persistToken(token) {
|
|
|
191
191
|
|
|
192
192
|
// ─── Comando principal ───────────────────────────────────
|
|
193
193
|
|
|
194
|
+
// Orientacao de escopo: o token fica salvo no computador e qualquer programa do
|
|
195
|
+
// aluno consegue usa-lo, entao a Service Account deve alcancar so um cofre
|
|
196
|
+
// dedicado. "Claude" e o cofre que os agentes do Auroq usam (ops.md).
|
|
197
|
+
function accessTips() {
|
|
198
|
+
log(`${BOLD}Seguranca do token (recomendado):${RESET}`);
|
|
199
|
+
log(' - Crie a Service Account com acesso a UM cofre so, dedicado ao Auroq');
|
|
200
|
+
log(` (o cofre ${CYAN}"Claude"${RESET}), sem suas senhas pessoais, de banco ou da empresa.`);
|
|
201
|
+
log(' - Permissao: so leitura. Se quiser que o Auroq guarde credenciais novas');
|
|
202
|
+
log(' pra voce nesse cofre, libere tambem escrita — mas so nesse cofre.');
|
|
203
|
+
log(` ${DIM}- O token fica salvo neste computador e qualquer programa seu consegue usa-lo:${RESET}`);
|
|
204
|
+
log(` ${DIM} com o cofre dedicado, um vazamento so alcanca o que esta nele.${RESET}`);
|
|
205
|
+
}
|
|
206
|
+
|
|
194
207
|
async function connect() {
|
|
195
208
|
console.log(`\n${PURPLE}${BOLD} Conectar 1Password — Auroq OS${RESET}`);
|
|
196
209
|
|
|
@@ -223,6 +236,8 @@ async function connect() {
|
|
|
223
236
|
log(`${BOLD}Como resolver:${RESET}`);
|
|
224
237
|
log(` 1. Abra o 1Password e copie o seu token de Service Account (${CYAN}Ctrl/Cmd + C${RESET})`);
|
|
225
238
|
log(` 2. ${BOLD}Sem copiar mais nada${RESET}, rode este comando de novo`);
|
|
239
|
+
log('');
|
|
240
|
+
accessTips();
|
|
226
241
|
process.exit(1);
|
|
227
242
|
}
|
|
228
243
|
ok('Token encontrado (formato valido)');
|
|
@@ -258,6 +273,8 @@ ${GREEN}${BOLD} ✅ 1Password conectado com sucesso.${RESET}
|
|
|
258
273
|
${DIM} A conexao e permanente — voce nao precisa repetir este processo.${RESET}
|
|
259
274
|
${restartHint}
|
|
260
275
|
`);
|
|
276
|
+
accessTips();
|
|
277
|
+
log('');
|
|
261
278
|
}
|
|
262
279
|
|
|
263
280
|
module.exports = {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schema": 1,
|
|
3
3
|
"algorithm": "sha256",
|
|
4
4
|
"scope": "packaged-runtime-and-cascas",
|
|
5
|
-
"version": "2.6.
|
|
5
|
+
"version": "2.6.5",
|
|
6
6
|
"files": [
|
|
7
7
|
{
|
|
8
8
|
"path": ".auroq-core/constitution.md",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
"path": ".auroq-core/core-config.yaml",
|
|
13
|
-
"sha256": "
|
|
13
|
+
"sha256": "8134b48404278f57dd5fa423638a486ffc0b9d6fd8e0c8207ee0332e6ffc3456"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"path": ".auroq-core/core/synapse/context/context-builder.js",
|
|
@@ -206,7 +206,7 @@
|
|
|
206
206
|
},
|
|
207
207
|
{
|
|
208
208
|
"path": "bin/auroq-os.js",
|
|
209
|
-
"sha256": "
|
|
209
|
+
"sha256": "f0cfd3e5434118c618a1a48b93902ff38eb70b340c44a5af13bcc7130b45c853"
|
|
210
210
|
},
|
|
211
211
|
{
|
|
212
212
|
"path": "lib/ahi/client.mjs",
|
|
@@ -242,7 +242,7 @@
|
|
|
242
242
|
},
|
|
243
243
|
{
|
|
244
244
|
"path": "lib/onepassword.js",
|
|
245
|
-
"sha256": "
|
|
245
|
+
"sha256": "e14a7b5347e46f48d7f319c010e019f503f206d6dee8a37455ae71c77bed2635"
|
|
246
246
|
},
|
|
247
247
|
{
|
|
248
248
|
"path": "lib/supabase.js",
|
|
@@ -258,7 +258,7 @@
|
|
|
258
258
|
},
|
|
259
259
|
{
|
|
260
260
|
"path": "package.json",
|
|
261
|
-
"sha256": "
|
|
261
|
+
"sha256": "687f311ba5fadb11f900e924d16ac3ec683f6459d3164907a008229621889444"
|
|
262
262
|
},
|
|
263
263
|
{
|
|
264
264
|
"path": "scripts/build-pack.mjs",
|
|
@@ -282,7 +282,7 @@
|
|
|
282
282
|
},
|
|
283
283
|
{
|
|
284
284
|
"path": "scripts/sync-codex-skills.mjs",
|
|
285
|
-
"sha256": "
|
|
285
|
+
"sha256": "889394bcbf80aefeba49adf2f19202b47382324f3b1357063ca04b87ce46ddb2"
|
|
286
286
|
},
|
|
287
287
|
{
|
|
288
288
|
"path": "scripts/validate-hybrid.mjs",
|
package/package.json
CHANGED
|
@@ -61,12 +61,48 @@ function summaryFromMarkdown(file) {
|
|
|
61
61
|
return output.join(' ').replace(/\s+/g, ' ').replaceAll('"', "'") || 'Agente do Auroq OS.';
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
const avisos = [];
|
|
65
|
+
|
|
66
|
+
// Comando oficial = `auroq-<nome>.md` ou o Ops. Numa colisao de nome ele vence; o
|
|
67
|
+
// outro comando continua valendo no Claude/Grok e so fica sem skill no Codex.
|
|
68
|
+
const oficial = (file) => /^auroq-/.test(path.basename(file)) || relative(file).startsWith('.claude/commands/AuroqOS/');
|
|
69
|
+
|
|
64
70
|
function registerSkill(name, commandFile) {
|
|
65
|
-
if (!/^[a-z0-9-]+$/.test(name))
|
|
66
|
-
|
|
71
|
+
if (!/^[a-z0-9-]+$/.test(name)) {
|
|
72
|
+
avisos.push(`Comando ${relative(commandFile)} ignorado no Codex: nome de skill invalido '${name}'.`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (skills.has(name)) {
|
|
76
|
+
// Uma colisao (ex: companion.md de antes do prefixo auroq- ao lado de auroq-companion.md)
|
|
77
|
+
// derrubava o sync inteiro — e junto a skill $companion, que a manutencao exige.
|
|
78
|
+
const atual = skills.get(name);
|
|
79
|
+
const [fica, sai] = oficial(commandFile) && !oficial(atual) ? [commandFile, atual] : [atual, commandFile];
|
|
80
|
+
skills.set(name, fica);
|
|
81
|
+
avisos.push(`Colisao de nome '${name}': usando ${relative(fica)}; ${relative(sai)} continua valendo no Claude, sem skill propria no Codex.`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
67
84
|
skills.set(name, commandFile);
|
|
68
85
|
}
|
|
69
86
|
|
|
87
|
+
// O aluno da um nome ao Companion no bootstrap (FASE 10 do Ops: /atlas-companion).
|
|
88
|
+
// Se o comando base sumiu, $companion continua existindo, apontando pro comando dele.
|
|
89
|
+
function comandoDoCompanion(file) {
|
|
90
|
+
try {
|
|
91
|
+
const texto = fs.readFileSync(file, 'utf8');
|
|
92
|
+
return /recurso_id\s*`?companion`?/.test(texto) || /agents\/companion\//.test(texto);
|
|
93
|
+
} catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function garantirAliasCompanion() {
|
|
99
|
+
if (skills.has('companion')) return;
|
|
100
|
+
const candidatos = [...skills.entries()]
|
|
101
|
+
.filter(([name, file]) => name.endsWith('-companion') && comandoDoCompanion(file))
|
|
102
|
+
.sort(([a], [b]) => a.localeCompare(b));
|
|
103
|
+
if (candidatos.length) skills.set('companion', candidatos[0][1]);
|
|
104
|
+
}
|
|
105
|
+
|
|
70
106
|
function collectSkills() {
|
|
71
107
|
const commandRoot = path.join(root, '.claude', 'commands');
|
|
72
108
|
if (!fs.existsSync(commandRoot)) return;
|
|
@@ -88,6 +124,7 @@ function collectSkills() {
|
|
|
88
124
|
registerSkill(kebab(file.replace(/\.md$/, '')), path.join(coreAgents, file));
|
|
89
125
|
}
|
|
90
126
|
}
|
|
127
|
+
garantirAliasCompanion();
|
|
91
128
|
}
|
|
92
129
|
|
|
93
130
|
function skillContent(name, commandFile, outRoot) {
|
|
@@ -139,13 +176,20 @@ function readOwner(dir) {
|
|
|
139
176
|
// Mesma pasta de projeto = mesmo dono, mesmo que o name do package tenha
|
|
140
177
|
// mudado depois (ex: marcador gerado antes do package.json existir).
|
|
141
178
|
if (data.sourceRoot && path.resolve(data.sourceRoot) === root) return { kind: 'owned', data };
|
|
179
|
+
// .agents/skills mora DENTRO do projeto: marcador do nosso gerador com outro caminho
|
|
180
|
+
// e a mesma pasta de negocio movida, copiada ou vinda de outra maquina. Tratar como
|
|
181
|
+
// estranho travava o sync inteiro (e com ele a skill $companion) pra sempre.
|
|
182
|
+
if (path.dirname(dir) === localOut && data.schema === 2 && data.projectId) return { kind: 'owned', data, movido: true };
|
|
142
183
|
return { kind: 'foreign', data };
|
|
143
184
|
} catch {
|
|
144
185
|
return { kind: 'foreign', data: { invalidMarker: true } };
|
|
145
186
|
}
|
|
146
187
|
}
|
|
147
188
|
|
|
148
|
-
|
|
189
|
+
// Local: pasta de skill sem o nosso marcador e do aluno — fica como esta, com aviso,
|
|
190
|
+
// e o resto do sync segue. Global (~/.agents/skills, dividido entre projetos): recusa tudo.
|
|
191
|
+
function collisions(outRoot) {
|
|
192
|
+
const preservadas = new Set();
|
|
149
193
|
for (const [name, commandFile] of skills) {
|
|
150
194
|
const dir = path.join(outRoot, name);
|
|
151
195
|
if (!fs.existsSync(dir)) continue;
|
|
@@ -155,8 +199,15 @@ function assertNoCollisions(outRoot) {
|
|
|
155
199
|
if (adoptLegacy && owner.kind === 'foreign' && owner.data?.projectName === projectName) continue;
|
|
156
200
|
const existing = path.join(dir, 'SKILL.md');
|
|
157
201
|
if (owner.kind === 'legacy' && fs.existsSync(existing) && fs.readFileSync(existing, 'utf8') === skillContent(name, commandFile, outRoot)) continue;
|
|
202
|
+
if (outRoot === localOut && owner.kind === 'legacy') continue;
|
|
203
|
+
if (outRoot === localOut) {
|
|
204
|
+
preservadas.add(name);
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
158
207
|
throw new Error(`Recusando sobrescrever ${dir}; ownership: ${owner.kind}.`);
|
|
159
208
|
}
|
|
209
|
+
for (const name of preservadas) avisos.push(`Skill ${name} em ${relative(path.join(outRoot, name))} nao foi gerada por este sync: mantida como esta.`);
|
|
210
|
+
return preservadas;
|
|
160
211
|
}
|
|
161
212
|
|
|
162
213
|
function inspect(outRoot) {
|
|
@@ -168,7 +219,9 @@ function inspect(outRoot) {
|
|
|
168
219
|
issues.push(`Skill ausente: ${name}`);
|
|
169
220
|
continue;
|
|
170
221
|
}
|
|
171
|
-
|
|
222
|
+
const owner = readOwner(dir);
|
|
223
|
+
if (outRoot === localOut && owner.kind === 'unmanaged') continue; // skill do aluno, preservada
|
|
224
|
+
if (owner.kind !== 'owned' || owner.movido) issues.push(`Ownership invalido: ${name}`);
|
|
172
225
|
const file = path.join(dir, 'SKILL.md');
|
|
173
226
|
if (!fs.existsSync(file) || fs.readFileSync(file, 'utf8') !== skillContent(name, commandFile, outRoot)) {
|
|
174
227
|
issues.push(`Drift de conteudo: ${name}`);
|
|
@@ -183,16 +236,18 @@ function inspect(outRoot) {
|
|
|
183
236
|
|
|
184
237
|
function sync(outRoot) {
|
|
185
238
|
ensureDir(outRoot);
|
|
186
|
-
|
|
239
|
+
const preservadas = collisions(outRoot);
|
|
187
240
|
const stage = fs.mkdtempSync(path.join(outRoot, '.auroq-stage-'));
|
|
188
241
|
try {
|
|
189
242
|
for (const [name, commandFile] of skills) {
|
|
243
|
+
if (preservadas.has(name)) continue;
|
|
190
244
|
const dir = path.join(stage, name);
|
|
191
245
|
ensureDir(dir);
|
|
192
246
|
fs.writeFileSync(path.join(dir, markerFile), marker, 'utf8');
|
|
193
247
|
fs.writeFileSync(path.join(dir, 'SKILL.md'), skillContent(name, commandFile, outRoot), 'utf8');
|
|
194
248
|
}
|
|
195
249
|
for (const name of skills.keys()) {
|
|
250
|
+
if (preservadas.has(name)) continue;
|
|
196
251
|
const target = path.join(outRoot, name);
|
|
197
252
|
fs.rmSync(target, { recursive: true, force: true });
|
|
198
253
|
fs.renameSync(path.join(stage, name), target);
|
|
@@ -237,6 +292,11 @@ Padrao gera skills locais em .agents/skills (recomendado)
|
|
|
237
292
|
collectSkills();
|
|
238
293
|
if (targets.includes(localOut)) cleanLegacyLocalLocation();
|
|
239
294
|
|
|
295
|
+
const mostrarAvisos = () => {
|
|
296
|
+
for (const aviso of new Set(avisos)) console.error(`Aviso: ${aviso}`);
|
|
297
|
+
avisos.length = 0;
|
|
298
|
+
};
|
|
299
|
+
|
|
240
300
|
for (const target of targets) {
|
|
241
301
|
if (check) {
|
|
242
302
|
const issues = inspect(target);
|
|
@@ -247,10 +307,11 @@ for (const target of targets) {
|
|
|
247
307
|
console.log(`Auroq: ${skills.size} skills verificadas em ${target}`);
|
|
248
308
|
}
|
|
249
309
|
} else if (dryRun) {
|
|
250
|
-
if (fs.existsSync(target))
|
|
310
|
+
if (fs.existsSync(target)) collisions(target);
|
|
251
311
|
console.log(`Auroq: ${skills.size} skills validadas para ${target}`);
|
|
252
312
|
} else {
|
|
253
313
|
sync(target);
|
|
254
314
|
console.log(`Auroq: ${skills.size} skills sincronizadas em ${target}`);
|
|
255
315
|
}
|
|
316
|
+
mostrarAvisos();
|
|
256
317
|
}
|