auroq-os 2.0.4 → 2.1.1

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.
@@ -2,24 +2,25 @@
2
2
 
3
3
  > Principios inegociaveis do framework. Governam o comportamento de todos os agentes, squads, workers e minds dentro do Auroq OS.
4
4
 
5
- **Version:** 1.0.0
5
+ **Version:** 2.0.0
6
6
  **Status:** Active
7
- **Effective Date:** 2026-03-16
7
+ **Effective Date:** 2026-06-09
8
8
 
9
9
  ---
10
10
 
11
- ## Artigo I — Claude Code e o Centro de Comando
11
+ ## Artigo I — O Terminal e o Centro de Comando
12
12
 
13
13
  **Severity:** NON-NEGOTIABLE
14
14
  **Gate:** WARN
15
15
 
16
- Toda operacao do negocio passa pelo Claude Code no terminal. Claude Code e o centro de comando o SO de IA materializado. Ferramentas externas (ManyChat, Hotmart, Meta Ads, N8N, etc.) sao **bracos e pernas**, nao centros alternativos.
16
+ Toda operacao do negocio passa pelo Auroq OS no terminal. Claude Code e Codex CLI sao runtimes oficiais e equivalentes para acessar o sistema. O centro de comando e o projeto Auroq seus documentos, agentes, regras e memoria — nao um fornecedor especifico. Ferramentas externas (ManyChat, Hotmart, Meta Ads, N8N, etc.) sao **bracos e pernas**, nao centros alternativos.
17
17
 
18
18
  **Implicacoes:**
19
- - Decisoes estrategicas: dentro do Claude Code com o Companion
20
- - Planejamento: dentro do Claude Code com documentos .md
21
- - Execucao operacional: Claude Code coordena, ferramentas executam
19
+ - Decisoes estrategicas: dentro do Auroq OS com o Companion, via Claude Code ou Codex
20
+ - Planejamento: dentro do projeto com documentos .md
21
+ - Execucao operacional: o runtime escolhido coordena, ferramentas executam
22
22
  - Memoria e contexto: persistem no Exocortex (pastas e documentos locais)
23
+ - Uma sessao usa um runtime por vez; a troca de runtime nao muda as fontes de verdade
23
24
 
24
25
  **Violacao:** Operar o negocio exclusivamente em ferramentas externas sem documentar no sistema.
25
26
 
@@ -1,14 +1,16 @@
1
1
  project:
2
2
  name: "Auroq OS"
3
3
  type: greenfield
4
- version: 1.0.0
4
+ version: 2.1.1
5
5
  installedAt: '2026-03-16'
6
6
 
7
7
  ide:
8
8
  selected:
9
9
  - claude-code
10
+ - codex
10
11
  configs:
11
12
  claude-code: true
13
+ codex: true
12
14
 
13
15
  mcp:
14
16
  enabled: false
package/.claude/CLAUDE.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Auroq OS — Sistema Operacional de IA para Experts
2
2
 
3
- Voce esta trabalhando com o Auroq OS, um framework que transforma o Claude Code num centro de comando inteligente para operar um negocio digital. Sempre reconheca e trabalhe dentro desta arquitetura.
3
+ Voce esta trabalhando com o Auroq OS, um framework que transforma Claude Code ou Codex CLI num centro de comando inteligente para operar um negocio digital. Sempre reconheca e trabalhe dentro desta arquitetura.
4
4
 
5
5
  ## Filosofia
6
6
 
7
- O Auroq OS materializa 3 capacidades no Claude Code:
7
+ O Auroq OS materializa 3 capacidades no runtime de terminal escolhido:
8
8
  - **Pensar com IA** — decisoes, planos, estrategias, raciocinio. IA como parceira cognitiva 24h
9
9
  - **Fazer com IA** — execucao colaborativa. Expert direciona, IA executa, expert julga
10
10
  - **Lembrar com IA** — todo aprendizado consolida no sistema. Persiste, acumula, integra
@@ -21,7 +21,7 @@ O Auroq OS possui uma Constitution formal com principios inegociaveis.
21
21
 
22
22
  | Artigo | Principio | Severidade |
23
23
  |--------|-----------|------------|
24
- | I | Claude Code e o Centro de Comando | NON-NEGOTIABLE |
24
+ | I | O Terminal e o Centro de Comando | NON-NEGOTIABLE |
25
25
  | II | Cada um faz o seu | NON-NEGOTIABLE |
26
26
  | III | Documentar = Investir | MUST |
27
27
  | IV | Nao inventar | MUST |
@@ -181,7 +181,7 @@ npx auroq-os check-access # no projeto do aluno (baixa o pacote com as deps)
181
181
  A validacao e ONLINE e obrigatoria, sem fallback offline — e a mesma trava do Pack Arcane: quem saiu da mentoria nao atualiza. **Nunca pular este passo.**
182
182
 
183
183
  **Passo 1 — Verificar versao atual vs disponivel**
184
- 1. Ler versao local: `cat package.json | grep version`
184
+ 1. Ler versao local do framework em `.auroq-core/core-config.yaml` (`project.version`)
185
185
  2. Verificar versao mais recente no npm: `npm view auroq-os version`
186
186
  3. SE versao local == versao npm: "Voce ja ta na versao mais recente ({versao}). Nada pra atualizar."
187
187
  4. SE versao npm > versao local: "Tem atualizacao disponivel: {versao atual} → {versao nova}. Vou aplicar."
@@ -206,6 +206,8 @@ A validacao e ONLINE e obrigatoria, sem fallback offline — e a mesma trava do
206
206
  - `.claude/rules/` — todas as rules
207
207
  - `.claude/hooks/` — synapse-engine.cjs, precompact
208
208
  - `.claude/settings.local.json` — hooks registrados
209
+ - `AGENTS.md` — regras e contexto do Codex
210
+ - `scripts/sync-codex-skills.mjs` e `scripts/validate-hybrid.mjs` — ponte Codex
209
211
  - `.synapse/` — manifest, constitution, global, context
210
212
  - `bin/` — installer
211
213
  - `package.json` — dependencias
@@ -239,11 +241,12 @@ Para cada arquivo da versao nova:
239
241
 
240
242
  **Passo 5 — Pos-atualizacao**
241
243
  1. `npm install` — atualizar dependencias
242
- 2. Atualizar versao no package.json local
243
- 3. Limpar temp: `rm -rf /tmp/auroq-update/`
244
- 4. Commitar: "setup: Auroq OS atualizado pra v{versao nova}"
245
- 5. Rodar health check rapido
246
- 6. Informar: "Auroq OS atualizado de v{antiga} pra v{nova}. Seus dados estao intactos."
244
+ 2. Confirmar que `.auroq-core/core-config.yaml` recebeu a nova `project.version` (nao alterar a versao do app do expert)
245
+ 3. Rodar `node scripts/sync-codex-skills.mjs --clean` e depois `--check`
246
+ 4. Limpar temp: `rm -rf /tmp/auroq-update/`
247
+ 5. Commitar: "setup: Auroq OS atualizado pra v{versao nova}"
248
+ 6. Rodar health check rapido
249
+ 7. Informar: "Auroq OS atualizado de v{antiga} pra v{nova}. Seus dados e skills locais estao intactos."
247
250
 
248
251
  **Protecoes:**
249
252
  - SEMPRE commitar antes de atualizar (protege trabalho do expert)
@@ -267,7 +270,9 @@ npx arcane-pack update
267
270
  O CLI faz tudo: autentica (mesma credencial do Auroq em `~/.arcane/credentials.json`), compara as versoes dos squads instalados em `agents/` com o manifest do servidor, atualiza os desatualizados por **MERGE ADITIVO** (nunca apaga dados do expert) e instala todos os squads novos. **Um comando so traz tudo** — sem distincao de core/extras.
268
271
 
269
272
  **Passo 2 — Reportar**
270
- Mostrar o resultado do CLI pro expert: squads atualizados, instalados e preservados.
273
+ 1. Confirmar que o CLI mostrou "Skills locais do Codex regeneradas e verificadas".
274
+ 2. Se a ponte Codex estiver ausente, atualizar primeiro o Auroq OS para v2.1.1+ e repetir o Pack.
275
+ 3. Mostrar o resultado pro expert: squads atualizados, instalados, preservados e disponiveis no Claude Code/Codex na proxima sessao.
271
276
 
272
277
  **Observacao:** depende do pacote `arcane-pack` (npm) e dos endpoints da plataforma estarem no ar. Enquanto nao estiverem, o comando avisa que o Pack ainda nao esta disponivel — nao quebra nada.
273
278
 
@@ -424,6 +429,7 @@ Verificar infraestrutura:
424
429
  - `.claude/settings.local.json` tem hooks registrados
425
430
  - `.gitignore` protege vault/, .env, .synapse/sessions/, node_modules/
426
431
  - `.synapse/manifest` existe com agents registrados
432
+ - `AGENTS.md` existe e `node scripts/sync-codex-skills.mjs --check` passa
427
433
  - `npm install` — instalar dependencias (js-yaml, fs-extra)
428
434
 
429
435
  Verificar agentes core:
@@ -439,6 +445,13 @@ Verificar agentes core:
439
445
 
440
446
  Instalar ferramentas que todo expert precisa. NAO inclui servicos (Supabase, Vercel) — esses tem fase propria.
441
447
 
448
+ **DETECTAR O RUNTIME ANTES DE CONFIGURAR MCP:**
449
+ - No Claude Code: usar `claude mcp add ...`, `claude mcp list` e `/mcp`.
450
+ - No Codex CLI: usar `codex mcp add ...`, `codex mcp --help` e `/mcp`. Para configuracao versionada por projeto confiavel, usar `.codex/config.toml`; configuracao pessoal fica em `~/.codex/config.toml`.
451
+ - Quando um exemplo abaixo mostrar `claude mcp add NOME -- COMANDO`, no Codex executar o equivalente `codex mcp add NOME -- COMANDO`.
452
+ - Para servidor HTTP com OAuth no Codex, registrar o servidor e usar `codex mcp login NOME` quando suportado.
453
+ - Nao configurar os dois runtimes automaticamente. Configurar apenas o runtime escolhido pelo expert para aquela instalacao; o outro pode ser conectado depois.
454
+
442
455
  **IMPORTANTE — AUTH DE MCPs:**
443
456
  Alguns MCPs precisam de autenticacao (abrir browser, logar, autorizar). Quando isso acontecer, o fluxo e:
444
457
  1. Ops registra o MCP (`claude mcp add ...`)
package/.gitignore CHANGED
@@ -12,7 +12,7 @@ business/vault/
12
12
  node_modules/
13
13
 
14
14
  # Codex CLI skills geradas (regeneradas no init / por "auroq-os sync-codex")
15
- .codex/
15
+ .agents/skills/
16
16
 
17
17
  # Screenshots de operacao
18
18
  *.png
package/AGENTS.md CHANGED
@@ -28,8 +28,11 @@ terminal, com agentes especializados pra cada coisa. Constitution formal em
28
28
 
29
29
  ## Como ativar os agentes no Codex (`$nome`)
30
30
 
31
- As skills ativaveis vivem em `.codex/skills/` (e/ou `~/.codex/skills/`), geradas
32
- por `node scripts/sync-codex-skills.mjs`. Digite `$nome` pra ativar. Depois de
31
+ As skills ativaveis vivem em `.agents/skills/`, local oficial de skills de
32
+ repositorio do Codex, e sao geradas por
33
+ `node scripts/sync-codex-skills.mjs`. O modo local e o padrao porque isola cada
34
+ negocio e evita colisao entre projetos. A instalacao global existe apenas como
35
+ opcao explicita em `~/.agents/skills/` via `npm run sync:codex:global`. Digite `$nome` pra ativar. Depois de
33
36
  criar ou atualizar um agente, rode o sync de novo pra a skill aparecer.
34
37
 
35
38
  | Agente | Ativacao | O que faz |
@@ -55,7 +58,7 @@ instrucoes do arquivo ate `*exit`.
55
58
 
56
59
  ## Constitution — principios inegociaveis (replica de `.auroq-core/constitution.md`)
57
60
 
58
- 1. **Centro de comando** — toda operacao passa pelo terminal. Ferramentas externas (Meta Ads, Hotmart, n8n) sao bracos, nao centros. *(NON-NEGOTIABLE)*
61
+ 1. **Centro de comando** — toda operacao passa pelo projeto Auroq no terminal, via Claude Code ou Codex. Ferramentas externas (Meta Ads, Hotmart, n8n) sao bracos, nao centros. *(NON-NEGOTIABLE)*
59
62
  2. **Cada um faz o seu** — `git commit/push/deploy` e o `*update` do framework sao **EXCLUSIVOS do Ops**. Outro agente delega. *(NON-NEGOTIABLE)*
60
63
  3. **Documentar = investir** — todo trabalho significativo vira `.md`. O que nao e documentado, morre. *(MUST)*
61
64
  4. **Nao inventar** — fundamenta em KB, instrucao ou plano. Nao gera dado/numero/fato sem fonte. Se precisa mudar o plano, PARA e pergunta. *(MUST)*
@@ -82,6 +85,14 @@ instrucoes do arquivo ate `*exit`.
82
85
  - MCP e infra sao responsabilidade do **Ops**.
83
86
  - Nunca use API paga no Claude/Codex onde o plano ja resolve — e dinheiro jogado fora.
84
87
  - Em respostas grandes de ferramenta, filtre ruido e preserve so o relevante.
88
+ - Use um runtime por sessao. Antes de trocar entre Claude Code e Codex, finalize ou documente o estado do trabalho.
89
+
90
+ ## Gates da camada hibrida
91
+
92
+ - `npm run auroq:sync:codex` — gera/atualiza as skills locais
93
+ - `npm run auroq:sync:codex:check` — detecta drift sem escrever
94
+ - `npm run auroq:validate` — valida estrutura e comandos
95
+ - No repo da distribuicao: `npm run lint && npm run typecheck && npm test && npm run build`
85
96
 
86
97
  ## Memoria e contexto (carregar sob demanda)
87
98
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Auroq OS — Sistema Operacional de IA para Experts
2
2
 
3
- Transforma o Claude Code num centro de comando inteligente para operar seu negocio digital.
3
+ Transforma Claude Code ou Codex CLI num centro de comando inteligente para operar seu negocio digital.
4
4
 
5
5
  **Pensar. Fazer. Lembrar.** Tudo com IA.
6
6
 
@@ -10,7 +10,7 @@ Transforma o Claude Code num centro de comando inteligente para operar seu negoc
10
10
  - Mac com Apple Silicon (recomendado)
11
11
  - Node.js 22+
12
12
  - Git
13
- - Claude Code (plano Max recomendado)
13
+ - Claude Code ou Codex CLI
14
14
 
15
15
  ### Setup
16
16
 
@@ -21,11 +21,17 @@ mkdir meu-negocio && cd meu-negocio
21
21
  # 2. Instale o Auroq OS (gate: email + senha da Mentoria Arcane)
22
22
  npx auroq-os init
23
23
 
24
- # 3. Abra o Claude Code
24
+ # 3A. Abra o Claude Code
25
25
  claude
26
26
 
27
- # 4. Ative o Companion
27
+ # 4A. Ative o Companion
28
28
  /auroq-companion
29
+
30
+ # OU 3B. Abra o Codex CLI
31
+ codex
32
+
33
+ # 4B. Ative o Companion
34
+ $companion
29
35
  ```
30
36
 
31
37
  > **Acesso exclusivo para alunos da Mentoria Arcane.** O `init` pede o mesmo email + senha
@@ -40,6 +46,12 @@ claude
40
46
  | `auroq-os login` | Forca novo login (substitui credencial atual) |
41
47
  | `auroq-os logout` | Encerra sessao local (remove `~/.arcane/credentials.json`) |
42
48
  | `auroq-os whoami` | Mostra usuario autenticado e status de acesso |
49
+ | `auroq-os sync-codex` | Regenera e verifica as skills locais do Codex |
50
+
51
+ Dentro do projeto instalado, os mesmos checks ficam disponiveis como
52
+ `npm run auroq:sync:codex`, `npm run auroq:sync:codex:check` e
53
+ `npm run auroq:validate`. O instalador adiciona esses scripts sem sobrescrever
54
+ os comandos existentes do seu negocio.
43
55
 
44
56
  ## Estrutura
45
57
 
@@ -48,6 +60,7 @@ business/ → Sua empresa (campanhas, processos, agentes)
48
60
  docs/knowledge/ → Biblioteca ETL (sua mente, seu negocio, conhecimento)
49
61
  agents/ → Seu exercito (companion, workers, minds, squads)
50
62
  .claude/ → Ponte Claude Code (agentes, rules, hooks)
63
+ .agents/skills/ → Ponte Codex local (skills geradas por projeto)
51
64
  .auroq-core/ → Framework (nao modificar)
52
65
  ```
53
66
 
@@ -55,9 +68,9 @@ agents/ → Seu exercito (companion, workers, minds, squads)
55
68
 
56
69
  | Agente | Comando | O que faz |
57
70
  |--------|---------|-----------|
58
- | Companion | `/auroq-companion` | Parceiro cognitivo. Situa, lembra, pensa junto |
59
- | Ops | `/AuroqOS:agents:ops` | Git, deploy, ambiente, install |
60
- | Organizer | `/auroq-organizer` | Organizacao, guarda documentos, limpeza, backup |
71
+ | Companion | `/auroq-companion` ou `$companion` | Parceiro cognitivo. Situa, lembra, pensa junto |
72
+ | Ops | `/AuroqOS:agents:ops` ou `$ops` | Git, deploy, ambiente, install |
73
+ | Organizer | `/auroq-organizer` ou `$organizer` | Organizacao, guarda documentos, limpeza, backup |
61
74
 
62
75
  ### Meta Squads (criadores de agentes)
63
76
 
@@ -71,7 +84,7 @@ agents/ → Seu exercito (companion, workers, minds, squads)
71
84
 
72
85
  ## Primeiro uso
73
86
 
74
- 1. Ative o Companion (`/auroq-companion`)
87
+ 1. Ative o Companion (`/auroq-companion` no Claude ou `$companion` no Codex)
75
88
  2. Preencha os templates em `docs/knowledge/expert-mind/` (quem voce e)
76
89
  3. Preencha `docs/knowledge/expert-business/` (o que voce faz)
77
90
  4. Pronto — o sistema ja te conhece
@@ -86,4 +99,4 @@ agents/ → Seu exercito (companion, workers, minds, squads)
86
99
 
87
100
  ---
88
101
 
89
- *Auroq OS v1.3.0 — by Euriler Jube / Arka*
102
+ *Auroq OS v2.1.0 — by Euriler Jube / Arka*
@@ -63,7 +63,7 @@ Nao. Voce me descreve o que precisa e EU te direciono pro agente certo. Se quise
63
63
 
64
64
  ## O que e o Auroq OS
65
65
 
66
- Sistema operacional de IA pro expert. Transforma o Claude Code num centro de comando inteligente pra operar um negocio digital. Nao e colecao de pastas — e sistema que gira.
66
+ Sistema operacional de IA pro expert. Transforma Claude Code ou Codex CLI num centro de comando inteligente pra operar um negocio digital. Nao e colecao de pastas — e sistema que gira.
67
67
 
68
68
  3 capacidades:
69
69
  - **Pensar com IA** — decisoes, planos, estrategias
@@ -281,7 +281,7 @@ Quando o expert tiver duvidas sobre como usar o sistema no dia-a-dia, o Companio
281
281
 
282
282
  ### Como abrir o sistema
283
283
 
284
- Sempre abrir o terminal na pasta do projeto (a mesma que escolheu na instalacao) e depois digitar `claude`. Nunca rodar `claude` de outra pasta — ele precisa estar dentro do projeto pra acessar tudo.
284
+ Sempre abrir o terminal na pasta do projeto (a mesma que escolheu na instalacao) e depois iniciar `claude` ou `codex`. Nunca iniciar o runtime fora do projeto — ele precisa estar dentro da pasta pra acessar tudo.
285
285
 
286
286
  Depois de entrar, ativar o agente que precisa: `/companion`, `/organizer`, `/squad-forge`, etc. Claude sem agente ativado = Claude generico, perde toda a especializacao.
287
287
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  ## O que é o Auroq OS
8
8
 
9
- Auroq OS é um **Sistema Operacional de IA para Experts**: engenharia de contexto permanente pro Claude Code. Na prática, são pastas estruturadas com regras, agentes, tasks e conhecimento que ensinam o Claude Code a operar como um time de especialistas dentro do negócio do expert.
9
+ Auroq OS é um **Sistema Operacional de IA para Experts**: engenharia de contexto permanente pro Claude Code e Codex CLI. Na prática, são pastas estruturadas com regras, agentes, tasks e conhecimento que ensinam o runtime escolhido a operar como um time de especialistas dentro do negócio do expert.
10
10
 
11
11
  Não é chatbot, não é automação tipo Zapier, não é ferramenta de dev. É o **centro de comando** onde o expert roda o negócio dele — com a IA como sistema operacional, não como prompt avulso.
12
12
 
@@ -103,7 +103,7 @@ Governam TODO agente, squad, worker e mind. Gates automáticos bloqueiam violaç
103
103
 
104
104
  | # | Artigo | O que significa | Severidade |
105
105
  |---|--------|-----------------|------------|
106
- | I | **Claude Code é o Centro de Comando** | Todo negócio passa pelo terminal. Ferramentas externas (Meta, Hotmart) são braços, não centros | NON-NEGOTIABLE |
106
+ | I | **O terminal é o Centro de Comando** | Todo negócio passa pelo projeto Auroq via Claude Code ou Codex. Ferramentas externas (Meta, Hotmart) são braços, não centros | NON-NEGOTIABLE |
107
107
  | II | **Cada Um Faz o Seu** | Agentes têm domínios exclusivos. Ops faz git push, Aurora governa, Companion decide com o expert | NON-NEGOTIABLE |
108
108
  | III | **Documentar = Investir** | Todo trabalho gera documento. O que não é documentado, morre | MUST (BLOCK) |
109
109
  | IV | **Não Inventar** | Agente executa o planejado, fundamenta em KB/instrução. Não viaja, não adiciona não-pedido | MUST (BLOCK) |
package/bin/auroq-os.js CHANGED
@@ -101,11 +101,16 @@ async function init() {
101
101
 
102
102
  // ─── Fase 1b: Gate de acesso (Mentoria Arcane)
103
103
  step('Verificando acesso...');
104
- try {
105
- await auth.getValidSession();
106
- } catch (e) {
107
- error(`Falha na autenticacao: ${e.message}`);
108
- process.exit(1);
104
+ const testAuthBypass = process.env.NODE_ENV === 'test' && process.env.AUROQ_SKIP_AUTH === '1';
105
+ if (testAuthBypass) {
106
+ success('Gate de acesso ignorado em ambiente de teste');
107
+ } else {
108
+ try {
109
+ await auth.getValidSession();
110
+ } catch (e) {
111
+ error(`Falha na autenticacao: ${e.message}`);
112
+ process.exit(1);
113
+ }
109
114
  }
110
115
 
111
116
  // ─── Fase 2: Copiar estrutura do framework
@@ -257,6 +262,7 @@ async function init() {
257
262
  // Codex CLI adapter
258
263
  'AGENTS.md',
259
264
  'scripts/sync-codex-skills.mjs',
265
+ 'scripts/validate-hybrid.mjs',
260
266
  ];
261
267
 
262
268
  // Arquivos do ALUNO — nunca sobrescrever se ja existem
@@ -386,13 +392,14 @@ async function init() {
386
392
  }
387
393
  success(`${dirsCopied} modulos instalados (Meta Squads + scripts)`);
388
394
 
389
- // ─── Fase 4c: Adaptador Codex CLI (gera as skills $nome)
395
+ // ─── Fase 4c: Adaptador Codex CLI (skills locais por projeto)
390
396
  step('Configurando Codex CLI...');
391
397
  try {
392
- execSync('node scripts/sync-codex-skills.mjs --all --clean', { cwd: targetDir, stdio: 'pipe' });
393
- success('Codex CLI pronto ative agentes com $companion, $ops, etc.');
398
+ execSync('node scripts/sync-codex-skills.mjs --clean', { cwd: targetDir, stdio: 'pipe' });
399
+ execSync('node scripts/sync-codex-skills.mjs --check', { cwd: targetDir, stdio: 'pipe' });
400
+ success('Codex CLI pronto — skills locais verificadas ($companion, $ops, etc.)');
394
401
  } catch {
395
- warn('Sync de skills do Codex falhou — rode "npx auroq-os sync-codex" quando quiser (so necessario se usar Codex)');
402
+ warn('Sync de skills do Codex falhou — rode "npx auroq-os sync-codex" para diagnosticar');
396
403
  }
397
404
 
398
405
  // ─── Fase 5: Package.json + npm install
@@ -411,6 +418,14 @@ async function init() {
411
418
  }, { spaces: 2 });
412
419
  }
413
420
 
421
+ // Comandos namespaced: adiciona a manutencao Auroq sem sobrescrever scripts do negocio.
422
+ const targetPackage = await fs.readJSON(pkgPath);
423
+ targetPackage.scripts = targetPackage.scripts || {};
424
+ targetPackage.scripts['auroq:sync:codex'] = 'node scripts/sync-codex-skills.mjs --clean';
425
+ targetPackage.scripts['auroq:sync:codex:check'] = 'node scripts/sync-codex-skills.mjs --check';
426
+ targetPackage.scripts['auroq:validate'] = 'node scripts/validate-hybrid.mjs';
427
+ await fs.writeJSON(pkgPath, targetPackage, { spaces: 2 });
428
+
414
429
  try {
415
430
  execSync('npm install --silent', { cwd: targetDir, stdio: 'pipe' });
416
431
  success('Dependencias instaladas');
@@ -451,6 +466,9 @@ async function init() {
451
466
  ['business/cockpit.md', 'Cockpit'],
452
467
  ['.synapse/manifest', 'Synapse Manifest'],
453
468
  ['AGENTS.md', 'Codex AGENTS.md'],
469
+ ['.agents/skills/companion/SKILL.md', 'Codex Companion'],
470
+ ['.agents/skills/ops/SKILL.md', 'Codex Ops'],
471
+ ['scripts/validate-hybrid.mjs', 'Validador hibrido'],
454
472
  ];
455
473
 
456
474
  let passed = 0;
@@ -477,8 +495,8 @@ ${GREEN}${BOLD} Auroq OS instalado com sucesso.${RESET}
477
495
  ${DIM} Proximo passo:${RESET}
478
496
 
479
497
  ${CYAN}cd ${path.basename(targetDir)}${RESET}
480
- ${CYAN}claude${RESET}
481
- ${CYAN}/companion${RESET}
498
+ ${CYAN}claude${RESET} ${DIM}ou${RESET} ${CYAN}codex${RESET}
499
+ ${CYAN}/auroq-companion${RESET} ${DIM}ou${RESET} ${CYAN}\$companion${RESET}
482
500
 
483
501
  ${DIM} O Companion vai te receber e guiar a partir daqui.${RESET}
484
502
 
@@ -494,10 +512,10 @@ ${DIM} Meta Squads (criadores de agentes):${RESET}
494
512
  ${PURPLE}/clone-forge${RESET} ${DIM}— Clona mentes reais${RESET}
495
513
  ${PURPLE}/etlmaker${RESET} ${DIM}— Extrai e estrutura conhecimento${RESET}
496
514
 
497
- ${DIM} Usa Codex CLI? Funciona igual: rode ${RESET}${CYAN}codex${RESET}${DIM} e ative com ${RESET}${PURPLE}\$companion${RESET}${DIM}, ${RESET}${PURPLE}\$ops${RESET}${DIM}, etc.${RESET}
515
+ ${DIM} Claude Code e Codex sao runtimes oficiais. Escolha um por sessao; ambos usam os mesmos agentes e arquivos.${RESET}
498
516
 
499
517
  ${PURPLE}${BOLD} ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}
500
- ${DIM} Auroq OS v1.0.0 — Sistema Operacional de IA para Experts${RESET}
518
+ ${DIM} Auroq OS v2.1.0 — Sistema Operacional de IA para Experts${RESET}
501
519
  ${DIM} "Tu aumentaste o meu poder como do boi selvagem." — Sl 92:10${RESET}
502
520
  `);
503
521
  }
@@ -548,8 +566,9 @@ if (command === 'init' || command === 'install') {
548
566
  } else if (command === 'sync-codex') {
549
567
  // Regenera as skills do Codex CLI a partir dos comandos atuais do projeto.
550
568
  try {
551
- execSync('node scripts/sync-codex-skills.mjs --all --clean', { cwd: process.cwd(), stdio: 'inherit' });
552
- success('Skills do Codex atualizadas. Use $companion, $ops, $consultor, ... no Codex.');
569
+ execSync('node scripts/sync-codex-skills.mjs --clean', { cwd: process.cwd(), stdio: 'inherit' });
570
+ execSync('node scripts/sync-codex-skills.mjs --check', { cwd: process.cwd(), stdio: 'inherit' });
571
+ success('Skills locais do Codex atualizadas e verificadas. Use $companion, $ops, $consultor, ...');
553
572
  } catch (err) {
554
573
  error(`Falha ao sincronizar skills do Codex: ${err.message}`);
555
574
  process.exit(1);
@@ -563,7 +582,7 @@ if (command === 'init' || command === 'install') {
563
582
  log(` ${CYAN}whoami${RESET} Mostrar usuario autenticado`);
564
583
  log(` ${CYAN}check-access${RESET} Validar acesso ativo (online; exit 0=ativo, 1=bloqueado)`);
565
584
  log(` ${CYAN}update${RESET} Atualizar (via Ops dentro do Claude Code)`);
566
- log(` ${CYAN}sync-codex${RESET} Gerar/atualizar as skills do Codex CLI ($nome)`);
585
+ log(` ${CYAN}sync-codex${RESET} Gerar e verificar as skills locais do Codex CLI ($nome)`);
567
586
  log('');
568
587
  log(`${DIM}Uso: npx auroq-os init${RESET}`);
569
588
  log('');
@@ -0,0 +1,63 @@
1
+ # AUROQ-2.1.0 — Runtime Hibrido Claude Code + Codex
2
+
3
+ **Status:** InReview
4
+ **Origem:** pedido direto do mantenedor em 2026-06-09
5
+ **Release alvo:** 2.1.0
6
+
7
+ ## Objetivo
8
+
9
+ Entregar o Auroq OS pronto para o aluno operar no Claude Code ou no Codex CLI, com as mesmas fontes de verdade, agentes, boundaries e fluxo de atualizacao.
10
+
11
+ ## Acceptance Criteria
12
+
13
+ - [x] O instalador gera skills em `.agents/skills`, local oficial do Codex, sem poluir o namespace global do aluno.
14
+ - [x] O sync possui ownership, collision guard, check real de drift e execucao fora da raiz.
15
+ - [x] Comandos e agentes criados pelo aluno entram no sync sem lista hardcoded.
16
+ - [x] O Ops atualiza e valida a camada Codex junto com o framework.
17
+ - [x] Constitution, README, AGENTS e onboarding descrevem Claude Code e Codex como runtimes equivalentes.
18
+ - [x] Quality gates e testes automatizados passam.
19
+ - [x] O pacote npm inclui todos os arquivos necessarios para instalar a camada hibrida.
20
+
21
+ ## Tasks
22
+
23
+ - [x] Reescrever o sync Codex.
24
+ - [x] Integrar sync/check ao instalador e ao Ops.
25
+ - [x] Criar validacao e testes de distribuicao.
26
+ - [x] Atualizar documentacao e versionamento.
27
+ - [x] Executar pack dry-run, smoke test do instalador e quality gates.
28
+
29
+ ## File List
30
+
31
+ - `.auroq-core/constitution.md`
32
+ - `.auroq-core/core-config.yaml`
33
+ - `.claude/CLAUDE.md`
34
+ - `.claude/commands/AuroqOS/agents/ops.md`
35
+ - `.gitignore`
36
+ - `AGENTS.md`
37
+ - `CHANGELOG.md`
38
+ - `README.md`
39
+ - `agents/companion/knowledge/system-guide.md`
40
+ - `agents/consultor/knowledge/01-arquitetura-e-engenharia.md`
41
+ - `bin/auroq-os.js`
42
+ - `docs/stories/AUROQ-2.1.0-hybrid-runtime.md`
43
+ - `package.json`
44
+ - `package-lock.json`
45
+ - `scripts/sync-codex-skills.mjs`
46
+ - `scripts/validate-hybrid.mjs`
47
+ - `tests/installer-hybrid.test.mjs`
48
+ - `tests/sync-codex-skills.test.mjs`
49
+
50
+ ## Verification
51
+
52
+ - `npm run lint` — PASS
53
+ - `npm run typecheck` — PASS
54
+ - `npm test` — PASS (3 testes, incluindo install real em temp)
55
+ - `npm run build` — PASS (npm pack dry-run)
56
+ - `npm audit --audit-level=moderate` — PASS (0 vulnerabilidades)
57
+ - Conteudo do pacote: 275 arquivos; bridge, validador, story e testes presentes
58
+
59
+ ## Log
60
+
61
+ - 2026-06-09 — Story criada e implementacao iniciada.
62
+ - 2026-06-09 — Implementacao concluida e movida para InReview.
63
+ - 2026-06-09 — Patch 2.1.1 removeu wrapper orfao do Squad Edicao e integrou o sync automatico do Pack Arcane.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auroq-os",
3
- "version": "2.0.4",
3
+ "version": "2.1.1",
4
4
  "description": "Auroq OS — Sistema Operacional de IA para Experts",
5
5
  "bin": {
6
6
  "auroq-os": "bin/auroq-os.js"
@@ -9,9 +9,19 @@
9
9
  "node": ">=18"
10
10
  },
11
11
  "scripts": {
12
- "sync:ide": "node scripts/sync-codex-skills.mjs --all --clean",
12
+ "sync:ide": "npm run sync:codex",
13
+ "sync:ide:check": "npm run sync:codex:check",
13
14
  "sync:codex": "node scripts/sync-codex-skills.mjs --clean",
14
- "sync:codex:global": "node scripts/sync-codex-skills.mjs --global --clean"
15
+ "sync:codex:check": "node scripts/sync-codex-skills.mjs --check",
16
+ "sync:codex:global": "node scripts/sync-codex-skills.mjs --global --clean",
17
+ "auroq:sync:codex": "npm run sync:codex",
18
+ "auroq:sync:codex:check": "npm run sync:codex:check",
19
+ "auroq:validate": "npm run validate:hybrid",
20
+ "validate:hybrid": "node scripts/validate-hybrid.mjs",
21
+ "lint": "node --check bin/auroq-os.js && node --check lib/auth.js && node --check lib/credentials.js && node --check lib/supabase.js && node --check scripts/sync-codex-skills.mjs && node --check scripts/validate-hybrid.mjs",
22
+ "typecheck": "npm run validate:hybrid",
23
+ "test": "node --test tests/*.test.mjs",
24
+ "build": "npm pack --dry-run --json > /dev/null"
15
25
  },
16
26
  "files": [
17
27
  "bin/",
@@ -23,6 +33,7 @@
23
33
  "agents/",
24
34
  "business/",
25
35
  "docs/",
36
+ "tests/",
26
37
  "AGENTS.md",
27
38
  "README.md",
28
39
  ".gitignore",
@@ -1,141 +1,240 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Auroq OS — Codex Skills Sync
4
- *
5
- * Gera as "skills" do Codex CLI a partir dos agentes do Auroq OS, pra que o
6
- * aluno ative cada agente com $nome no Codex (equivalente ao /comando no
7
- * Claude Code). O Codex le skills de:
8
- * - <projeto>/.codex/skills/ (local — default, fica junto do projeto)
9
- * - ~/.codex/skills/ (global — vale em qualquer projeto)
10
- *
11
- * Uso:
12
- * node scripts/sync-codex-skills.mjs -> .codex/skills (local)
13
- * node scripts/sync-codex-skills.mjs --global -> ~/.codex/skills
14
- * node scripts/sync-codex-skills.mjs --all -> os dois
15
- * --clean remove skills geradas antes (idempotente)
16
- * --help mostra esta ajuda
17
- *
18
- * Fonte de verdade de cada skill: o proprio comando em .claude/commands/.
19
- * Assim Codex e Claude Code compartilham o mesmo arquivo de ativacao.
20
- */
2
+ import crypto from 'node:crypto';
21
3
  import fs from 'node:fs';
22
- import path from 'node:path';
23
4
  import os from 'node:os';
5
+ import path from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
24
7
 
25
- const root = process.cwd();
8
+ const root = fs.realpathSync(path.join(path.dirname(fileURLToPath(import.meta.url)), '..'));
26
9
  const args = new Set(process.argv.slice(2));
27
- const MANAGED = '.auroq-codex-managed';
10
+ const localOut = path.join(root, '.agents', 'skills');
11
+ const globalOut = path.join(os.homedir(), '.agents', 'skills');
12
+ const targets = args.has('--all') ? [localOut, globalOut] : [args.has('--global') ? globalOut : localOut];
13
+ const clean = args.has('--clean');
14
+ const check = args.has('--check');
15
+ const dryRun = args.has('--dry-run');
16
+ const adoptLegacy = args.has('--adopt-legacy');
17
+ const markerFile = '.auroq-codex-managed';
18
+ const legacyMarker = 'managed by scripts/sync-codex-skills.mjs\n';
19
+ const packageFile = path.join(root, 'package.json');
20
+ const packageJson = fs.existsSync(packageFile) ? JSON.parse(fs.readFileSync(packageFile, 'utf8')) : {};
21
+ const projectName = packageJson.name || path.basename(root);
22
+ const projectId = `${projectName}:${crypto.createHash('sha256').update(root).digest('hex').slice(0, 16)}`;
23
+ const marker = `${JSON.stringify({ schema: 2, projectId, projectName, sourceRoot: root }, null, 2)}\n`;
24
+ const skills = new Map();
25
+
26
+ function ensureDir(dir) {
27
+ fs.mkdirSync(dir, { recursive: true });
28
+ }
28
29
 
29
- if (args.has('--help')) {
30
- console.log(`Uso: node scripts/sync-codex-skills.mjs [--global|--all] [--clean]
30
+ function kebab(input) {
31
+ return input
32
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
33
+ .replace(/[^a-zA-Z0-9]+/g, '-')
34
+ .replace(/^-+|-+$/g, '')
35
+ .toLowerCase();
36
+ }
31
37
 
32
- (sem flag) gera em .codex/skills (local, dentro do projeto)
33
- --global gera em ~/.codex/skills (vale em todos os projetos)
34
- --all gera nos dois
35
- --clean remove as skills geradas anteriormente antes de escrever`);
36
- process.exit(0);
38
+ function relative(file) {
39
+ return path.relative(root, file).replaceAll('\\', '/');
37
40
  }
38
41
 
39
- function ensureDir(dir) { fs.mkdirSync(dir, { recursive: true }); }
40
- function rel(file) { return path.relative(root, file); }
42
+ function sourceRef(file, outRoot) {
43
+ return (outRoot === globalOut ? fs.realpathSync(file) : relative(file)).replaceAll('\\', '/');
44
+ }
41
45
 
42
- // Extrai uma descricao curta do markdown (pula frontmatter, headings e blocos CRITICAL).
43
46
  function summaryFromMarkdown(file) {
44
- const text = fs.readFileSync(file, 'utf8');
45
- const lines = text.split(/\r?\n/);
46
- const out = [];
47
+ const lines = fs.readFileSync(file, 'utf8').split(/\r?\n/);
48
+ const output = [];
47
49
  let inFrontmatter = lines[0] === '---';
48
- for (let i = 1; i < lines.length; i += 1) {
49
- const line = lines[i].trim();
50
- if (inFrontmatter) { if (line === '---') inFrontmatter = false; continue; }
50
+ for (let index = inFrontmatter ? 1 : 0; index < lines.length; index += 1) {
51
+ const line = lines[index].trim();
52
+ if (inFrontmatter) {
53
+ if (line === '---') inFrontmatter = false;
54
+ continue;
55
+ }
51
56
  if (!line || line.startsWith('#')) continue;
52
- if (line.startsWith('CRITICAL:')) break;
53
- if (line.startsWith('ACTIVATION-NOTICE:')) break;
54
- if (line.startsWith('```')) break;
55
- out.push(line);
56
- if (out.join(' ').length > 320) break;
57
+ if (line.startsWith('CRITICAL:') || line.startsWith('ACTIVATION-NOTICE:') || line.startsWith('```')) break;
58
+ output.push(line);
59
+ if (output.join(' ').length > 420) break;
57
60
  }
58
- return out.join(' ').replace(/\s+/g, ' ').replace(/"/g, "'") || 'Agente do Auroq OS.';
61
+ return output.join(' ').replace(/\s+/g, ' ').replaceAll('"', "'") || 'Agente do Auroq OS.';
59
62
  }
60
63
 
61
- // Remove apenas as skills que ESTE script gerou (marcadas com .auroq-codex-managed).
62
- function cleanManaged(outRoot) {
63
- if (!fs.existsSync(outRoot)) return;
64
- for (const entry of fs.readdirSync(outRoot, { withFileTypes: true })) {
65
- if (!entry.isDirectory()) continue;
66
- if (fs.existsSync(path.join(outRoot, entry.name, MANAGED))) {
67
- fs.rmSync(path.join(outRoot, entry.name), { recursive: true, force: true });
64
+ function registerSkill(name, commandFile) {
65
+ if (!/^[a-z0-9-]+$/.test(name)) throw new Error(`Nome de skill invalido: ${name}`);
66
+ if (skills.has(name)) throw new Error(`Colisao de nome '${name}': ${relative(skills.get(name))} e ${relative(commandFile)}`);
67
+ skills.set(name, commandFile);
68
+ }
69
+
70
+ function collectSkills() {
71
+ const commandRoot = path.join(root, '.claude', 'commands');
72
+ if (!fs.existsSync(commandRoot)) return;
73
+
74
+ for (const entry of fs.readdirSync(commandRoot, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
75
+ if (!entry.isFile() || !entry.name.endsWith('.md')) continue;
76
+ const basename = entry.name.replace(/\.md$/, '');
77
+ const name = kebab(basename.replace(/^auroq-/, ''));
78
+ registerSkill(name, path.join(commandRoot, entry.name));
79
+ }
80
+
81
+ const coreAgents = path.join(commandRoot, 'AuroqOS', 'agents');
82
+ if (fs.existsSync(coreAgents)) {
83
+ for (const file of fs.readdirSync(coreAgents).filter((name) => name.endsWith('.md')).sort()) {
84
+ registerSkill(kebab(file.replace(/\.md$/, '')), path.join(coreAgents, file));
68
85
  }
69
86
  }
70
87
  }
71
88
 
72
- function writeSkill(outRoot, name, description, body, written) {
73
- if (!/^[a-z0-9-]+$/.test(name)) throw new Error(`Nome de skill invalido: ${name}`);
74
- const dir = path.join(outRoot, name);
75
- ensureDir(dir);
76
- fs.writeFileSync(path.join(dir, MANAGED), 'managed by scripts/sync-codex-skills.mjs\n', 'utf8');
77
- fs.writeFileSync(
78
- path.join(dir, 'SKILL.md'),
79
- `---\nname: ${name}\ndescription: >-\n ${description.replace(/\s+/g, ' ').trim()}\n---\n\n${body.trim()}\n`,
80
- 'utf8',
81
- );
82
- written.add(name);
83
- }
89
+ function skillContent(name, commandFile, outRoot) {
90
+ const commandRef = sourceRef(commandFile, outRoot);
91
+ const agentsRef = sourceRef(path.join(root, 'agents'), outRoot);
92
+ const agentsMdRef = sourceRef(path.join(root, 'AGENTS.md'), outRoot);
93
+ const description = `Ativa o agente Auroq '${name}' no Codex CLI. Use quando o usuario digitar $${name}, /${name}, /auroq-${name}, @${name}, pedir o agente '${name}', ou solicitar seu fluxo de trabalho. Fonte de verdade: ${commandRef}.`;
94
+ return `---
95
+ name: ${name}
96
+ description: >-
97
+ ${description}
98
+ ---
84
99
 
85
- function buildAgentSkill(outRoot, file, name, written) {
86
- const commandRel = rel(file);
87
- const description = `Ativa o agente Auroq '${name}' dentro do Codex CLI. Use quando o usuario digitar $${name}, /${name}, /auroq-${name}, @${name}, pedir o agente '${name}', ou se referir a ${commandRel}. Fonte de verdade: ${commandRel}.`;
88
- writeSkill(
89
- outRoot,
90
- name,
91
- description,
92
- `# ${name}
100
+ # ${name}
93
101
 
94
- ${summaryFromMarkdown(file)}
102
+ ${summaryFromMarkdown(commandFile)}
95
103
 
96
104
  ## Ativacao
97
105
 
98
- - Leia \`${commandRel}\` por completo.
99
- - Siga as instrucoes CRITICAL de ativacao exatamente como escritas (persona + task).
100
- - Carregue os arquivos que o comando apontar (\`agents/${name}/...\` ou o proprio comando) sob demanda nao carregue KB grande sem necessidade.
101
- - Mantenha a persona ativa ate o usuario enviar \`*exit\`.
106
+ - Leia \`${commandRef}\` por completo.
107
+ - Siga as instrucoes CRITICAL exatamente como escritas, incluindo persona, task, dependencias e exit behavior.
108
+ - Resolva referencias relativas a partir de \`${root.replaceAll('\\', '/')}\`; agentes e squads ficam em \`${agentsRef}\`.
109
+ - Carregue KBs, tasks e assets apenas quando o comando ou pedido exigir.
110
+ - Mantenha a persona ativa ate \`*exit\` ou troca explicita.
111
+
112
+ ## Compatibilidade
113
+
114
+ - Esta skill e uma ponte fina: Claude Code e Codex compartilham o mesmo comando como fonte de verdade.
115
+ - Respeite primeiro \`${agentsMdRef}\`, que replica para o Codex as regras operacionais do Auroq OS.
116
+ `;
117
+ }
118
+
119
+ function readOwner(dir) {
120
+ const file = path.join(dir, markerFile);
121
+ if (!fs.existsSync(file)) return { kind: 'unmanaged' };
122
+ const content = fs.readFileSync(file, 'utf8');
123
+ if (content === legacyMarker) return { kind: 'legacy' };
124
+ try {
125
+ const data = JSON.parse(content);
126
+ return data.projectId === projectId ? { kind: 'owned', data } : { kind: 'foreign', data };
127
+ } catch {
128
+ return { kind: 'foreign', data: { invalidMarker: true } };
129
+ }
130
+ }
102
131
 
103
- ## Compatibilidade Claude <-> Codex
132
+ function assertNoCollisions(outRoot) {
133
+ for (const [name, commandFile] of skills) {
134
+ const dir = path.join(outRoot, name);
135
+ if (!fs.existsSync(dir)) continue;
136
+ const owner = readOwner(dir);
137
+ if (owner.kind === 'owned') continue;
138
+ if (adoptLegacy && owner.kind === 'legacy') continue;
139
+ if (adoptLegacy && owner.kind === 'foreign' && owner.data?.projectName === projectName) continue;
140
+ const existing = path.join(dir, 'SKILL.md');
141
+ if (owner.kind === 'legacy' && fs.existsSync(existing) && fs.readFileSync(existing, 'utf8') === skillContent(name, commandFile, outRoot)) continue;
142
+ throw new Error(`Recusando sobrescrever ${dir}; ownership: ${owner.kind}.`);
143
+ }
144
+ }
104
145
 
105
- - Esta skill reusa no Codex o mesmo comando que o Claude Code ativa em \`.claude/commands/\`.
106
- - O Codex NAO carrega \`.claude/CLAUDE.md\`, \`.claude/rules/\` nem \`.synapse/\` automaticamente — respeite o \`AGENTS.md\` na raiz, que replica o essencial do sistema.
107
- `,
108
- written,
109
- );
146
+ function inspect(outRoot) {
147
+ const issues = [];
148
+ if (!fs.existsSync(outRoot)) return [`Diretorio ausente: ${outRoot}`];
149
+ for (const [name, commandFile] of skills) {
150
+ const dir = path.join(outRoot, name);
151
+ if (!fs.existsSync(dir)) {
152
+ issues.push(`Skill ausente: ${name}`);
153
+ continue;
154
+ }
155
+ if (readOwner(dir).kind !== 'owned') issues.push(`Ownership invalido: ${name}`);
156
+ const file = path.join(dir, 'SKILL.md');
157
+ if (!fs.existsSync(file) || fs.readFileSync(file, 'utf8') !== skillContent(name, commandFile, outRoot)) {
158
+ issues.push(`Drift de conteudo: ${name}`);
159
+ }
160
+ }
161
+ for (const entry of fs.readdirSync(outRoot, { withFileTypes: true })) {
162
+ if (!entry.isDirectory() || skills.has(entry.name)) continue;
163
+ if (readOwner(path.join(outRoot, entry.name)).kind === 'owned') issues.push(`Skill obsoleta: ${entry.name}`);
164
+ }
165
+ return issues;
110
166
  }
111
167
 
112
- function syncTo(outRoot) {
168
+ function sync(outRoot) {
113
169
  ensureDir(outRoot);
114
- if (args.has('--clean')) cleanManaged(outRoot);
115
- const written = new Set();
116
-
117
- const cmdDir = path.join(root, '.claude', 'commands');
118
- if (fs.existsSync(cmdDir)) {
119
- // 1. comandos auroq-*.md -> skill <nome sem prefixo>
120
- for (const f of fs.readdirSync(cmdDir).filter((n) => /^auroq-.+\.md$/.test(n)).sort()) {
121
- const name = f.replace(/^auroq-/, '').replace(/\.md$/, '');
122
- buildAgentSkill(outRoot, path.join(cmdDir, f), name, written);
170
+ assertNoCollisions(outRoot);
171
+ const stage = fs.mkdtempSync(path.join(outRoot, '.auroq-stage-'));
172
+ try {
173
+ for (const [name, commandFile] of skills) {
174
+ const dir = path.join(stage, name);
175
+ ensureDir(dir);
176
+ fs.writeFileSync(path.join(dir, markerFile), marker, 'utf8');
177
+ fs.writeFileSync(path.join(dir, 'SKILL.md'), skillContent(name, commandFile, outRoot), 'utf8');
178
+ }
179
+ for (const name of skills.keys()) {
180
+ const target = path.join(outRoot, name);
181
+ fs.rmSync(target, { recursive: true, force: true });
182
+ fs.renameSync(path.join(stage, name), target);
123
183
  }
124
- // 2. AuroqOS/agents/*.md -> skill <nome> (ex.: ops)
125
- const sub = path.join(cmdDir, 'AuroqOS', 'agents');
126
- if (fs.existsSync(sub)) {
127
- for (const f of fs.readdirSync(sub).filter((n) => n.endsWith('.md')).sort()) {
128
- buildAgentSkill(outRoot, path.join(sub, f), f.replace(/\.md$/, ''), written);
184
+ if (clean) {
185
+ for (const entry of fs.readdirSync(outRoot, { withFileTypes: true })) {
186
+ if (!entry.isDirectory() || skills.has(entry.name)) continue;
187
+ const dir = path.join(outRoot, entry.name);
188
+ if (readOwner(dir).kind === 'owned') fs.rmSync(dir, { recursive: true, force: true });
129
189
  }
130
190
  }
191
+ } finally {
192
+ fs.rmSync(stage, { recursive: true, force: true });
131
193
  }
132
- return written;
133
194
  }
134
195
 
135
- const localOut = path.join(root, '.codex', 'skills');
136
- const globalOut = path.join(os.homedir(), '.codex', 'skills');
137
- const targets = args.has('--all') ? [localOut, globalOut] : args.has('--global') ? [globalOut] : [localOut];
196
+ function cleanLegacyLocalLocation() {
197
+ if (!clean) return;
198
+ const legacyRoot = path.join(root, '.codex', 'skills');
199
+ if (!fs.existsSync(legacyRoot)) return;
200
+ for (const entry of fs.readdirSync(legacyRoot, { withFileTypes: true })) {
201
+ if (!entry.isDirectory()) continue;
202
+ const markerPath = path.join(legacyRoot, entry.name, markerFile);
203
+ if (fs.existsSync(markerPath)) fs.rmSync(path.join(legacyRoot, entry.name), { recursive: true, force: true });
204
+ }
205
+ if (fs.readdirSync(legacyRoot).length === 0) fs.rmSync(legacyRoot, { recursive: true, force: true });
206
+ }
207
+
208
+ if (args.has('--help')) {
209
+ console.log(`Uso: node scripts/sync-codex-skills.mjs [--global|--all] [--clean] [--check] [--dry-run] [--adopt-legacy]
210
+
211
+ Padrao gera skills locais em .agents/skills (recomendado)
212
+ --global gera em ~/.agents/skills (opcional e explicito)
213
+ --all gera local e global
214
+ --clean remove skills obsoletas pertencentes a este projeto
215
+ --check detecta drift sem escrever
216
+ --dry-run valida fontes e colisoes sem escrever
217
+ --adopt-legacy migra uma instalacao criada pelo gerador antigo`);
218
+ process.exit(0);
219
+ }
138
220
 
139
- let count = 0;
140
- for (const t of targets) count = syncTo(t).size;
141
- console.log(`Auroq: ${count} skills do Codex geradas em ${targets.map((t) => t.replace(os.homedir(), '~')).join(' + ')}`);
221
+ collectSkills();
222
+ if (targets.includes(localOut)) cleanLegacyLocalLocation();
223
+
224
+ for (const target of targets) {
225
+ if (check) {
226
+ const issues = inspect(target);
227
+ if (issues.length) {
228
+ console.error(issues.join('\n'));
229
+ process.exitCode = 1;
230
+ } else {
231
+ console.log(`Auroq: ${skills.size} skills verificadas em ${target}`);
232
+ }
233
+ } else if (dryRun) {
234
+ if (fs.existsSync(target)) assertNoCollisions(target);
235
+ console.log(`Auroq: ${skills.size} skills validadas para ${target}`);
236
+ } else {
237
+ sync(target);
238
+ console.log(`Auroq: ${skills.size} skills sincronizadas em ${target}`);
239
+ }
240
+ }
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const root = fs.realpathSync(path.join(path.dirname(fileURLToPath(import.meta.url)), '..'));
7
+ const errors = [];
8
+ const packageJson = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
9
+ const isDistributionRepo = packageJson.name === 'auroq-os';
10
+
11
+ const requiredPaths = [
12
+ 'AGENTS.md',
13
+ 'README.md',
14
+ '.auroq-core/constitution.md',
15
+ '.auroq-core/core-config.yaml',
16
+ '.claude/CLAUDE.md',
17
+ '.claude/commands',
18
+ '.claude/rules',
19
+ '.synapse/manifest',
20
+ 'agents',
21
+ 'scripts/sync-codex-skills.mjs',
22
+ ];
23
+ if (isDistributionRepo) requiredPaths.push('bin/auroq-os.js');
24
+
25
+ for (const relative of requiredPaths) {
26
+ if (!fs.existsSync(path.join(root, relative))) errors.push(`Ausente: ${relative}`);
27
+ }
28
+
29
+ const requiredScripts = isDistributionRepo
30
+ ? ['lint', 'typecheck', 'test', 'build', 'sync:codex', 'sync:codex:check']
31
+ : ['auroq:sync:codex', 'auroq:sync:codex:check', 'auroq:validate'];
32
+ for (const script of requiredScripts) {
33
+ if (!packageJson.scripts?.[script]) errors.push(`Script ausente: ${script}`);
34
+ }
35
+
36
+ const commandRoot = path.join(root, '.claude', 'commands');
37
+ let commandCount = 0;
38
+ for (const entry of fs.readdirSync(commandRoot, { withFileTypes: true })) {
39
+ if (entry.isFile() && entry.name.endsWith('.md')) commandCount += 1;
40
+ }
41
+ const coreAgents = path.join(commandRoot, 'AuroqOS', 'agents');
42
+ if (fs.existsSync(coreAgents)) commandCount += fs.readdirSync(coreAgents).filter((name) => name.endsWith('.md')).length;
43
+ if (commandCount < 9) errors.push(`Poucos comandos descobertos: ${commandCount}`);
44
+
45
+ if (errors.length) {
46
+ console.error(errors.join('\n'));
47
+ process.exit(1);
48
+ }
49
+
50
+ console.log(`Validacao hibrida passou (${commandCount} comandos descobertos)`);
@@ -0,0 +1,58 @@
1
+ import assert from 'node:assert/strict';
2
+ import { execFileSync } from 'node:child_process';
3
+ import fs from 'node:fs';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import test from 'node:test';
7
+
8
+ const root = fs.realpathSync(process.cwd());
9
+
10
+ test('installer entrega projeto hibrido funcional sem sobrescrever package scripts', () => {
11
+ const target = fs.mkdtempSync(path.join(os.tmpdir(), 'auroq-install-test-'));
12
+ const fakeHome = fs.mkdtempSync(path.join(os.tmpdir(), 'auroq-home-test-'));
13
+ try {
14
+ fs.writeFileSync(path.join(target, 'package.json'), `${JSON.stringify({
15
+ name: 'negocio-do-aluno',
16
+ private: true,
17
+ scripts: { negocio: 'echo preservado' },
18
+ }, null, 2)}\n`);
19
+
20
+ execFileSync(process.execPath, [path.join(root, 'bin', 'auroq-os.js'), 'init'], {
21
+ cwd: target,
22
+ env: { ...process.env, NODE_ENV: 'test', AUROQ_SKIP_AUTH: '1', HOME: fakeHome },
23
+ encoding: 'utf8',
24
+ stdio: 'pipe',
25
+ });
26
+
27
+ const installedPackage = JSON.parse(fs.readFileSync(path.join(target, 'package.json'), 'utf8'));
28
+ assert.equal(installedPackage.scripts.negocio, 'echo preservado');
29
+ assert.equal(installedPackage.scripts['auroq:sync:codex'], 'node scripts/sync-codex-skills.mjs --clean');
30
+ assert.ok(fs.existsSync(path.join(target, '.agents', 'skills', 'companion', 'SKILL.md')));
31
+ assert.ok(fs.existsSync(path.join(target, '.agents', 'skills', 'ops', 'SKILL.md')));
32
+ assert.equal(fs.existsSync(path.join(fakeHome, '.agents', 'skills')), false);
33
+
34
+ const check = execFileSync(process.execPath, [path.join(target, 'scripts', 'sync-codex-skills.mjs'), '--check'], {
35
+ cwd: os.tmpdir(),
36
+ encoding: 'utf8',
37
+ });
38
+ assert.match(check, /9 skills verificadas/);
39
+
40
+ const validation = execFileSync('npm', ['run', 'auroq:validate'], {
41
+ cwd: target,
42
+ encoding: 'utf8',
43
+ });
44
+ assert.match(validation, /Validacao hibrida passou \(9 comandos descobertos\)/);
45
+
46
+ fs.writeFileSync(path.join(target, '.claude', 'commands', 'squad-anuncios-arcane.md'), `# squad-anuncios-arcane
47
+
48
+ CRITICAL: Read and execute \`agents/squad-anuncios-arcane/tasks/start.md\`.
49
+ `);
50
+ fs.mkdirSync(path.join(target, 'agents', 'squad-anuncios-arcane', 'tasks'), { recursive: true });
51
+ fs.writeFileSync(path.join(target, 'agents', 'squad-anuncios-arcane', 'tasks', 'start.md'), '# Start\n');
52
+ execFileSync(process.execPath, [path.join(target, 'scripts', 'sync-codex-skills.mjs'), '--clean'], { cwd: target });
53
+ assert.ok(fs.existsSync(path.join(target, '.agents', 'skills', 'squad-anuncios-arcane', 'SKILL.md')));
54
+ } finally {
55
+ fs.rmSync(target, { recursive: true, force: true });
56
+ fs.rmSync(fakeHome, { recursive: true, force: true });
57
+ }
58
+ });
@@ -0,0 +1,67 @@
1
+ import assert from 'node:assert/strict';
2
+ import { execFileSync, spawnSync } from 'node:child_process';
3
+ import fs from 'node:fs';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import test from 'node:test';
7
+
8
+ const root = fs.realpathSync(process.cwd());
9
+ const script = path.join(root, 'scripts', 'sync-codex-skills.mjs');
10
+
11
+ function run(home, args, cwd = root) {
12
+ return execFileSync(process.execPath, [script, ...args], {
13
+ cwd,
14
+ env: { ...process.env, HOME: home },
15
+ encoding: 'utf8',
16
+ });
17
+ }
18
+
19
+ test('sync global e portavel, deterministico e preserva skills externas', () => {
20
+ const home = fs.mkdtempSync(path.join(os.tmpdir(), 'auroq-os-test-'));
21
+ const out = path.join(home, '.agents', 'skills');
22
+ try {
23
+ fs.mkdirSync(path.join(out, 'externa'), { recursive: true });
24
+ fs.writeFileSync(path.join(out, 'externa', 'SKILL.md'), 'externa\n');
25
+ const first = run(home, ['--global', '--clean'], os.tmpdir());
26
+ assert.match(first, /9 skills sincronizadas/);
27
+ assert.equal(fs.readFileSync(path.join(out, 'externa', 'SKILL.md'), 'utf8'), 'externa\n');
28
+ assert.ok(fs.existsSync(path.join(out, 'companion', 'SKILL.md')));
29
+ assert.ok(fs.existsSync(path.join(out, 'ops', 'SKILL.md')));
30
+ assert.match(fs.readFileSync(path.join(out, 'companion', 'SKILL.md'), 'utf8'), new RegExp(root.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
31
+ assert.match(run(home, ['--global', '--check']), /9 skills verificadas/);
32
+ const snapshot = fs.readFileSync(path.join(out, 'ops', 'SKILL.md'), 'utf8');
33
+ run(home, ['--global', '--clean']);
34
+ assert.equal(fs.readFileSync(path.join(out, 'ops', 'SKILL.md'), 'utf8'), snapshot);
35
+ } finally {
36
+ fs.rmSync(home, { recursive: true, force: true });
37
+ }
38
+ });
39
+
40
+ test('check detecta drift e sync bloqueia colisao externa', () => {
41
+ const home = fs.mkdtempSync(path.join(os.tmpdir(), 'auroq-os-test-'));
42
+ const out = path.join(home, '.agents', 'skills');
43
+ try {
44
+ run(home, ['--global']);
45
+ fs.appendFileSync(path.join(out, 'ops', 'SKILL.md'), '\ndrift\n');
46
+ const drift = spawnSync(process.execPath, [script, '--global', '--check'], {
47
+ cwd: root,
48
+ env: { ...process.env, HOME: home },
49
+ encoding: 'utf8',
50
+ });
51
+ assert.notEqual(drift.status, 0);
52
+ assert.match(drift.stderr, /Drift de conteudo: ops/);
53
+
54
+ fs.rmSync(path.join(out, 'ops'), { recursive: true, force: true });
55
+ fs.mkdirSync(path.join(out, 'ops'), { recursive: true });
56
+ fs.writeFileSync(path.join(out, 'ops', 'SKILL.md'), 'externa\n');
57
+ const collision = spawnSync(process.execPath, [script, '--global'], {
58
+ cwd: root,
59
+ env: { ...process.env, HOME: home },
60
+ encoding: 'utf8',
61
+ });
62
+ assert.notEqual(collision.status, 0);
63
+ assert.match(collision.stderr, /Recusando sobrescrever/);
64
+ } finally {
65
+ fs.rmSync(home, { recursive: true, force: true });
66
+ }
67
+ });