aios-core 4.0.2 → 4.1.0
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/.aios-core/cli/commands/migrate/analyze.js +6 -6
- package/.aios-core/cli/commands/migrate/backup.js +2 -2
- package/.aios-core/cli/commands/migrate/execute.js +4 -4
- package/.aios-core/cli/commands/migrate/index.js +5 -5
- package/.aios-core/cli/commands/migrate/rollback.js +6 -6
- package/.aios-core/cli/commands/migrate/update-imports.js +2 -2
- package/.aios-core/cli/commands/migrate/validate.js +2 -2
- package/.aios-core/cli/commands/pro/index.js +52 -0
- package/.aios-core/cli/index.js +1 -1
- package/.aios-core/core/ids/registry-updater.js +29 -3
- package/.aios-core/core/migration/migration-config.yaml +2 -2
- package/.aios-core/core/migration/module-mapping.yaml +2 -2
- package/.aios-core/core/registry/README.md +2 -2
- package/.aios-core/core/synapse/context/context-builder.js +34 -0
- package/.aios-core/core/synapse/diagnostics/collectors/consistency-collector.js +168 -0
- package/.aios-core/core/synapse/diagnostics/collectors/hook-collector.js +129 -0
- package/.aios-core/core/synapse/diagnostics/collectors/manifest-collector.js +82 -0
- package/.aios-core/core/synapse/diagnostics/collectors/output-analyzer.js +134 -0
- package/.aios-core/core/synapse/diagnostics/collectors/pipeline-collector.js +75 -0
- package/.aios-core/core/synapse/diagnostics/collectors/quality-collector.js +252 -0
- package/.aios-core/core/synapse/diagnostics/collectors/relevance-matrix.js +174 -0
- package/.aios-core/core/synapse/diagnostics/collectors/safe-read-json.js +31 -0
- package/.aios-core/core/synapse/diagnostics/collectors/session-collector.js +102 -0
- package/.aios-core/core/synapse/diagnostics/collectors/timing-collector.js +126 -0
- package/.aios-core/core/synapse/diagnostics/collectors/uap-collector.js +83 -0
- package/.aios-core/core/synapse/diagnostics/report-formatter.js +484 -0
- package/.aios-core/core/synapse/diagnostics/synapse-diagnostics.js +95 -0
- package/.aios-core/core/synapse/engine.js +73 -20
- package/.aios-core/core/synapse/runtime/hook-runtime.js +60 -0
- package/.aios-core/core-config.yaml +6 -0
- package/.aios-core/data/agent-config-requirements.yaml +2 -2
- package/.aios-core/data/aios-kb.md +4 -4
- package/.aios-core/data/entity-registry.yaml +5 -5
- package/.aios-core/development/agents/architect.md +10 -10
- package/.aios-core/development/agents/devops.md +93 -50
- package/.aios-core/development/agents/qa.md +94 -40
- package/.aios-core/development/agents/ux-design-expert.md +25 -25
- package/.aios-core/development/scripts/activation-runtime.js +63 -0
- package/.aios-core/development/scripts/generate-greeting.js +9 -8
- package/.aios-core/development/scripts/unified-activation-pipeline.js +102 -2
- package/.aios-core/development/tasks/{db-expansion-pack-integration.md → db-squad-integration.md} +5 -5
- package/.aios-core/development/tasks/{integrate-expansion-pack.md → integrate-squad.md} +2 -2
- package/.aios-core/development/tasks/next.md +3 -3
- package/.aios-core/development/tasks/pr-automation.md +2 -2
- package/.aios-core/development/tasks/publish-npm.md +257 -0
- package/.aios-core/development/tasks/release-management.md +4 -4
- package/.aios-core/development/tasks/setup-github.md +1 -1
- package/.aios-core/development/tasks/squad-creator-migrate.md +1 -1
- package/.aios-core/development/tasks/squad-creator-sync-ide-command.md +14 -14
- package/.aios-core/development/tasks/update-aios.md +1 -1
- package/.aios-core/docs/standards/AIOS-COLOR-PALETTE-QUICK-REFERENCE.md +1 -1
- package/.aios-core/docs/standards/AIOS-COLOR-PALETTE-V2.1.md +5 -5
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-COMPLETE.md +21 -21
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.2-SUMMARY.md +25 -25
- package/.aios-core/docs/standards/OPEN-SOURCE-VS-SERVICE-DIFFERENCES.md +4 -4
- package/.aios-core/docs/standards/QUALITY-GATES-SPECIFICATION.md +3 -3
- package/.aios-core/docs/standards/STANDARDS-INDEX.md +13 -13
- package/.aios-core/docs/standards/STORY-TEMPLATE-V2-SPECIFICATION.md +1 -1
- package/.aios-core/framework-config.yaml +4 -0
- package/.aios-core/infrastructure/scripts/codex-skills-sync/index.js +182 -0
- package/.aios-core/infrastructure/scripts/codex-skills-sync/validate.js +172 -0
- package/.aios-core/infrastructure/scripts/ide-sync/README.md +14 -0
- package/.aios-core/infrastructure/scripts/ide-sync/index.js +6 -0
- package/.aios-core/infrastructure/scripts/tool-resolver.js +4 -4
- package/.aios-core/infrastructure/scripts/validate-paths.js +142 -0
- package/.aios-core/infrastructure/templates/aios-sync.yaml.template +11 -11
- package/.aios-core/infrastructure/templates/github-workflows/README.md +1 -1
- package/.aios-core/install-manifest.yaml +190 -106
- package/.aios-core/local-config.yaml.template +2 -0
- package/.aios-core/product/README.md +2 -2
- package/.aios-core/product/data/integration-patterns.md +1 -1
- package/.aios-core/product/templates/ide-rules/cline-rules.md +1 -1
- package/.aios-core/product/templates/ide-rules/codex-rules.md +65 -0
- package/.aios-core/product/templates/ide-rules/copilot-rules.md +1 -1
- package/.aios-core/product/templates/ide-rules/roo-rules.md +1 -1
- package/.aios-core/user-guide.md +15 -14
- package/.aios-core/workflow-intelligence/engine/output-formatter.js +1 -1
- package/.claude/hooks/enforce-architecture-first.py +196 -0
- package/.claude/hooks/install-hooks.sh +41 -0
- package/.claude/hooks/mind-clone-governance.py +192 -0
- package/.claude/hooks/pre-commit-mmos-guard.sh +99 -0
- package/.claude/hooks/pre-commit-version-check.sh +156 -0
- package/.claude/hooks/read-protection.py +151 -0
- package/.claude/hooks/slug-validation.py +176 -0
- package/.claude/hooks/sql-governance.py +182 -0
- package/.claude/hooks/synapse-engine.js +9 -20
- package/.claude/hooks/write-path-validation.py +194 -0
- package/README.md +44 -14
- package/bin/aios-init.js +255 -184
- package/bin/aios-minimal.js +2 -2
- package/bin/aios.js +19 -19
- package/package.json +7 -4
- package/packages/aios-pro-cli/bin/aios-pro.js +75 -2
- package/packages/aios-pro-cli/package.json +5 -1
- package/packages/aios-pro-cli/src/recover.js +100 -0
- package/packages/installer/src/__tests__/performance-benchmark.js +382 -0
- package/packages/installer/src/config/ide-configs.js +12 -1
- package/packages/installer/src/config/templates/core-config-template.js +2 -2
- package/packages/installer/src/installer/aios-core-installer.js +2 -2
- package/packages/installer/src/installer/file-hasher.js +97 -0
- package/packages/installer/src/installer/post-install-validator.js +41 -1
- package/packages/installer/src/pro/pro-scaffolder.js +335 -0
- package/packages/installer/src/utils/aios-colors.js +2 -2
- package/packages/installer/src/wizard/feedback.js +1 -1
- package/packages/installer/src/wizard/ide-config-generator.js +2 -2
- package/packages/installer/src/wizard/index.js +58 -19
- package/packages/installer/src/wizard/pro-setup.js +547 -0
- package/packages/installer/src/wizard/questions.js +20 -14
- package/packages/installer/src/wizard/validators.js +1 -1
- package/scripts/package-synapse.js +323 -0
- package/scripts/validate-package-completeness.js +317 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# AGENTS.md - Synkra AIOS (Codex CLI)
|
|
2
|
+
|
|
3
|
+
Este arquivo define as instrucoes do projeto para o Codex CLI.
|
|
4
|
+
|
|
5
|
+
<!-- AIOS-MANAGED-START: core -->
|
|
6
|
+
## Core Rules
|
|
7
|
+
|
|
8
|
+
1. Siga a Constitution em `.aios-core/constitution.md`
|
|
9
|
+
2. Priorize `CLI First -> Observability Second -> UI Third`
|
|
10
|
+
3. Trabalhe por stories em `docs/stories/`
|
|
11
|
+
4. Nao invente requisitos fora dos artefatos existentes
|
|
12
|
+
<!-- AIOS-MANAGED-END: core -->
|
|
13
|
+
|
|
14
|
+
<!-- AIOS-MANAGED-START: quality -->
|
|
15
|
+
## Quality Gates
|
|
16
|
+
|
|
17
|
+
- Rode `npm run lint`
|
|
18
|
+
- Rode `npm run typecheck`
|
|
19
|
+
- Rode `npm test`
|
|
20
|
+
- Atualize checklist e file list da story antes de concluir
|
|
21
|
+
<!-- AIOS-MANAGED-END: quality -->
|
|
22
|
+
|
|
23
|
+
<!-- AIOS-MANAGED-START: codebase -->
|
|
24
|
+
## Project Map
|
|
25
|
+
|
|
26
|
+
- Core framework: `.aios-core/`
|
|
27
|
+
- CLI entrypoints: `bin/`
|
|
28
|
+
- Shared packages: `packages/`
|
|
29
|
+
- Tests: `tests/`
|
|
30
|
+
- Docs: `docs/`
|
|
31
|
+
<!-- AIOS-MANAGED-END: codebase -->
|
|
32
|
+
|
|
33
|
+
<!-- AIOS-MANAGED-START: commands -->
|
|
34
|
+
## Common Commands
|
|
35
|
+
|
|
36
|
+
- `npm run sync:ide`
|
|
37
|
+
- `npm run sync:ide:check`
|
|
38
|
+
- `npm run sync:skills:codex`
|
|
39
|
+
- `npm run sync:skills:codex:global` (opcional; neste repo o padrao e local-first)
|
|
40
|
+
- `npm run validate:structure`
|
|
41
|
+
- `npm run validate:agents`
|
|
42
|
+
<!-- AIOS-MANAGED-END: commands -->
|
|
43
|
+
|
|
44
|
+
<!-- AIOS-MANAGED-START: shortcuts -->
|
|
45
|
+
## Agent Shortcuts
|
|
46
|
+
|
|
47
|
+
Preferencia de ativacao no Codex CLI:
|
|
48
|
+
1. Use `/skills` e selecione `aios-<agent-id>` vindo de `.codex/skills` (ex.: `aios-architect`)
|
|
49
|
+
2. Se preferir, use os atalhos abaixo (`@architect`, `/architect`, etc.)
|
|
50
|
+
|
|
51
|
+
Interprete os atalhos abaixo carregando o arquivo correspondente em `.aios-core/development/agents/` (fallback: `.codex/agents/`), renderize o greeting via `generate-greeting.js` e assuma a persona ate `*exit`:
|
|
52
|
+
|
|
53
|
+
- `@architect`, `/architect`, `/architect.md` -> `.aios-core/development/agents/architect.md`
|
|
54
|
+
- `@dev`, `/dev`, `/dev.md` -> `.aios-core/development/agents/dev.md`
|
|
55
|
+
- `@qa`, `/qa`, `/qa.md` -> `.aios-core/development/agents/qa.md`
|
|
56
|
+
- `@pm`, `/pm`, `/pm.md` -> `.aios-core/development/agents/pm.md`
|
|
57
|
+
- `@po`, `/po`, `/po.md` -> `.aios-core/development/agents/po.md`
|
|
58
|
+
- `@sm`, `/sm`, `/sm.md` -> `.aios-core/development/agents/sm.md`
|
|
59
|
+
- `@analyst`, `/analyst`, `/analyst.md` -> `.aios-core/development/agents/analyst.md`
|
|
60
|
+
- `@devops`, `/devops`, `/devops.md` -> `.aios-core/development/agents/devops.md`
|
|
61
|
+
- `@data-engineer`, `/data-engineer`, `/data-engineer.md` -> `.aios-core/development/agents/data-engineer.md`
|
|
62
|
+
- `@ux-design-expert`, `/ux-design-expert`, `/ux-design-expert.md` -> `.aios-core/development/agents/ux-design-expert.md`
|
|
63
|
+
- `@squad-creator`, `/squad-creator`, `/squad-creator.md` -> `.aios-core/development/agents/squad-creator.md`
|
|
64
|
+
- `@aios-master`, `/aios-master`, `/aios-master.md` -> `.aios-core/development/agents/aios-master.md`
|
|
65
|
+
<!-- AIOS-MANAGED-END: shortcuts -->
|
package/.aios-core/user-guide.md
CHANGED
|
@@ -35,7 +35,7 @@ O AIOS-FullStack oferece instalação simplificada através de um instalador int
|
|
|
35
35
|
cd /path/to/your/project
|
|
36
36
|
|
|
37
37
|
# Execute o instalador (versão RC atual)
|
|
38
|
-
npx @synkra/aios-core@
|
|
38
|
+
npx @synkra/aios-core@latest install
|
|
39
39
|
|
|
40
40
|
# OU usando NPM direto (produção - quando disponível)
|
|
41
41
|
npx @aios/fullstack install
|
|
@@ -90,7 +90,7 @@ cd @synkra/aios-core
|
|
|
90
90
|
npm install
|
|
91
91
|
|
|
92
92
|
# Execute o instalador no modo desenvolvimento
|
|
93
|
-
npx @synkra/aios-core@
|
|
93
|
+
npx @synkra/aios-core@latest install
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
### Estrutura Pós-Instalação
|
|
@@ -133,10 +133,10 @@ Se você já tem AIOS instalado e quer fazer upgrade:
|
|
|
133
133
|
|
|
134
134
|
```bash
|
|
135
135
|
# Upgrade automático (RC.9+)
|
|
136
|
-
npx @synkra/aios-core@
|
|
136
|
+
npx @synkra/aios-core@latest install --force-upgrade
|
|
137
137
|
|
|
138
138
|
# OU interativo (todos os RCs)
|
|
139
|
-
npx @synkra/aios-core@
|
|
139
|
+
npx @synkra/aios-core@latest install
|
|
140
140
|
# → Menu aparece:
|
|
141
141
|
# 1. Keep current version (v1.0.0-rc.8)
|
|
142
142
|
# 2. Upgrade AIOS core (v1.0.0-rc.8 → v1.0.0-rc.10)
|
|
@@ -148,17 +148,18 @@ npx @synkra/aios-core@rc install
|
|
|
148
148
|
|
|
149
149
|
```bash
|
|
150
150
|
# Ver versão disponível no NPM
|
|
151
|
-
npm view @synkra/aios-core@
|
|
151
|
+
npm view @synkra/aios-core@latest version
|
|
152
152
|
# Output: 1.0.0-rc.10
|
|
153
153
|
|
|
154
|
-
# Ver
|
|
155
|
-
npx @synkra/aios-core@
|
|
154
|
+
# Ver opções de instalação e comandos disponíveis
|
|
155
|
+
npx @synkra/aios-core@latest --help
|
|
156
156
|
|
|
157
|
-
# Ver
|
|
158
|
-
|
|
157
|
+
# Ver squads instalados
|
|
158
|
+
# Use o wizard de instalação para selecionar/visualizar squads disponíveis
|
|
159
|
+
npx @synkra/aios-core@latest install
|
|
159
160
|
|
|
160
161
|
# Ajuda do instalador
|
|
161
|
-
npx @synkra/aios-core@
|
|
162
|
+
npx @synkra/aios-core@latest install --help
|
|
162
163
|
```
|
|
163
164
|
|
|
164
165
|
### 🚀 Futuro: Modo de Instalação Explícito (Story 3.14)
|
|
@@ -211,7 +212,7 @@ npx @synkra/aios-core@1.0.0-rc.10 install --force-upgrade
|
|
|
211
212
|
|
|
212
213
|
**Solução**: Usar RC.8 ou superior
|
|
213
214
|
```bash
|
|
214
|
-
npx @synkra/aios-core@
|
|
215
|
+
npx @synkra/aios-core@latest install
|
|
215
216
|
```
|
|
216
217
|
|
|
217
218
|
**Problema**: Versão GitHub (4.31.1) detectada como mais nova que RC
|
|
@@ -220,7 +221,7 @@ npx @synkra/aios-core@rc install
|
|
|
220
221
|
|
|
221
222
|
**Solução**: Escolher "Upgrade" ou usar `--force-upgrade`
|
|
222
223
|
```bash
|
|
223
|
-
npx @synkra/aios-core@
|
|
224
|
+
npx @synkra/aios-core@latest install --force-upgrade
|
|
224
225
|
# Migra de v4.31.1 para v1.0.0-rc.10 (novo scheme)
|
|
225
226
|
```
|
|
226
227
|
|
|
@@ -1293,7 +1294,7 @@ O Synkra AIOS suporta expansion packs para domínios específicos:
|
|
|
1293
1294
|
**Configurar expansion packs na instalação**:
|
|
1294
1295
|
```bash
|
|
1295
1296
|
# Durante a instalação, o wizard pergunta quais expansion packs instalar
|
|
1296
|
-
npx @synkra/aios-core@
|
|
1297
|
+
npx @synkra/aios-core@latest install
|
|
1297
1298
|
|
|
1298
1299
|
# O wizard mostra:
|
|
1299
1300
|
# 📦 Select Expansion Packs to Install:
|
|
@@ -1306,7 +1307,7 @@ npx @synkra/aios-core@rc install
|
|
|
1306
1307
|
**Adicionar expansion packs depois**:
|
|
1307
1308
|
```bash
|
|
1308
1309
|
# Re-execute o instalador
|
|
1309
|
-
npx @synkra/aios-core@
|
|
1310
|
+
npx @synkra/aios-core@latest install
|
|
1310
1311
|
|
|
1311
1312
|
# Escolha "Configure IDE settings" ou "Upgrade"
|
|
1312
1313
|
# Wizard permitirá adicionar expansion packs não instalados
|
|
@@ -211,7 +211,7 @@ function displayHelp() {
|
|
|
211
211
|
output.push(
|
|
212
212
|
` ${colorize('*next', 'green')} ${colorize('# Auto-detect context', 'dim')}`,
|
|
213
213
|
);
|
|
214
|
-
output.push(` ${colorize('*next --story docs/stories/
|
|
214
|
+
output.push(` ${colorize('*next --story docs/stories/v4.0.4/sprint-10/story-wis-3.md', 'green')}`);
|
|
215
215
|
output.push(
|
|
216
216
|
` ${colorize('*next --all', 'green')} ${colorize('# Show all suggestions', 'dim')}`,
|
|
217
217
|
);
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Hook: Enforce Architecture-First Development
|
|
4
|
+
|
|
5
|
+
REGRA: Código só pode ser criado/editado se existir documentação prévia.
|
|
6
|
+
|
|
7
|
+
Este hook intercepta Write/Edit em paths de código e verifica se existe
|
|
8
|
+
documentação aprovada antes de permitir a operação.
|
|
9
|
+
|
|
10
|
+
Exit Codes:
|
|
11
|
+
- 0: Permitido (doc existe ou path não requer doc)
|
|
12
|
+
- 2: Bloqueado (doc não existe para path protegido)
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
import sys
|
|
17
|
+
import os
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
# =============================================================================
|
|
21
|
+
# CONFIGURAÇÃO: Paths que EXIGEM documentação prévia
|
|
22
|
+
# =============================================================================
|
|
23
|
+
|
|
24
|
+
PROTECTED_PATHS = [
|
|
25
|
+
# Edge Functions - exigem docs/architecture/{function-name}.md
|
|
26
|
+
{
|
|
27
|
+
"pattern": "supabase/functions/",
|
|
28
|
+
"doc_patterns": [
|
|
29
|
+
"docs/architecture/{name}.md",
|
|
30
|
+
"docs/architecture/{name}-architecture.md",
|
|
31
|
+
"docs/approved-plans/{name}.md",
|
|
32
|
+
],
|
|
33
|
+
"extract_name": lambda p: p.split("supabase/functions/")[1].split("/")[0] if "supabase/functions/" in p else None,
|
|
34
|
+
},
|
|
35
|
+
# Migrations - exigem documentação de schema changes
|
|
36
|
+
{
|
|
37
|
+
"pattern": "supabase/migrations/",
|
|
38
|
+
"doc_patterns": [
|
|
39
|
+
"docs/approved-plans/migration-{name}.md",
|
|
40
|
+
"docs/architecture/database-changes.md",
|
|
41
|
+
],
|
|
42
|
+
"extract_name": lambda p: Path(p).stem if "supabase/migrations/" in p else None,
|
|
43
|
+
"allow_if_exists": True, # Permite editar migrations existentes
|
|
44
|
+
},
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
# Paths que são SEMPRE permitidos (não exigem doc)
|
|
48
|
+
ALWAYS_ALLOWED = [
|
|
49
|
+
".claude/",
|
|
50
|
+
"docs/",
|
|
51
|
+
"outputs/",
|
|
52
|
+
"squads/",
|
|
53
|
+
".aios-core/",
|
|
54
|
+
".aios-custom/",
|
|
55
|
+
"node_modules/",
|
|
56
|
+
".git/",
|
|
57
|
+
"package.json",
|
|
58
|
+
"package-lock.json",
|
|
59
|
+
"tsconfig.json",
|
|
60
|
+
".env",
|
|
61
|
+
"README.md",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
# =============================================================================
|
|
65
|
+
# LÓGICA DO HOOK
|
|
66
|
+
# =============================================================================
|
|
67
|
+
|
|
68
|
+
def get_project_root():
|
|
69
|
+
"""Obtém o root do projeto via variável de ambiente ou cwd."""
|
|
70
|
+
return os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
|
|
71
|
+
|
|
72
|
+
def is_always_allowed(file_path: str) -> bool:
|
|
73
|
+
"""Verifica se o path está na lista de sempre permitidos."""
|
|
74
|
+
for allowed in ALWAYS_ALLOWED:
|
|
75
|
+
if allowed in file_path:
|
|
76
|
+
return True
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
def find_matching_protection(file_path: str) -> dict | None:
|
|
80
|
+
"""Encontra a regra de proteção que corresponde ao path."""
|
|
81
|
+
for protection in PROTECTED_PATHS:
|
|
82
|
+
if protection["pattern"] in file_path:
|
|
83
|
+
return protection
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
def check_documentation_exists(file_path: str, protection: dict, project_root: str) -> tuple[bool, str]:
|
|
87
|
+
"""
|
|
88
|
+
Verifica se existe documentação para o path protegido.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
(exists: bool, doc_path: str | None)
|
|
92
|
+
"""
|
|
93
|
+
extract_fn = protection.get("extract_name")
|
|
94
|
+
if not extract_fn:
|
|
95
|
+
return True, None
|
|
96
|
+
|
|
97
|
+
name = extract_fn(file_path)
|
|
98
|
+
if not name:
|
|
99
|
+
return True, None
|
|
100
|
+
|
|
101
|
+
# Verificar cada padrão de documentação
|
|
102
|
+
for doc_pattern in protection["doc_patterns"]:
|
|
103
|
+
doc_path = doc_pattern.format(name=name)
|
|
104
|
+
full_doc_path = os.path.join(project_root, doc_path)
|
|
105
|
+
|
|
106
|
+
if os.path.exists(full_doc_path):
|
|
107
|
+
return True, doc_path
|
|
108
|
+
|
|
109
|
+
# Se allow_if_exists e o arquivo já existe, permitir edição
|
|
110
|
+
if protection.get("allow_if_exists"):
|
|
111
|
+
full_file_path = os.path.join(project_root, file_path) if not file_path.startswith("/") else file_path
|
|
112
|
+
if os.path.exists(full_file_path):
|
|
113
|
+
return True, "(arquivo existente)"
|
|
114
|
+
|
|
115
|
+
return False, None
|
|
116
|
+
|
|
117
|
+
def format_required_docs(protection: dict, name: str) -> str:
|
|
118
|
+
"""Formata a lista de documentos aceitos."""
|
|
119
|
+
docs = []
|
|
120
|
+
for pattern in protection["doc_patterns"]:
|
|
121
|
+
docs.append(f" - {pattern.format(name=name)}")
|
|
122
|
+
return "\n".join(docs)
|
|
123
|
+
|
|
124
|
+
def main():
|
|
125
|
+
# Ler input do stdin
|
|
126
|
+
try:
|
|
127
|
+
input_data = json.load(sys.stdin)
|
|
128
|
+
except json.JSONDecodeError:
|
|
129
|
+
# Se não conseguir parsear, permitir (fail-open)
|
|
130
|
+
sys.exit(0)
|
|
131
|
+
|
|
132
|
+
tool_name = input_data.get("tool_name", "")
|
|
133
|
+
tool_input = input_data.get("tool_input", {})
|
|
134
|
+
file_path = tool_input.get("file_path", "")
|
|
135
|
+
|
|
136
|
+
# Só processar Write e Edit
|
|
137
|
+
if tool_name not in ["Write", "Edit"]:
|
|
138
|
+
sys.exit(0)
|
|
139
|
+
|
|
140
|
+
# Normalizar path (remover prefixo absoluto se presente)
|
|
141
|
+
project_root = get_project_root()
|
|
142
|
+
relative_path = file_path
|
|
143
|
+
if file_path.startswith(project_root):
|
|
144
|
+
relative_path = file_path[len(project_root):].lstrip("/")
|
|
145
|
+
|
|
146
|
+
# Verificar se é sempre permitido
|
|
147
|
+
if is_always_allowed(relative_path):
|
|
148
|
+
sys.exit(0)
|
|
149
|
+
|
|
150
|
+
# Verificar se path está protegido
|
|
151
|
+
protection = find_matching_protection(relative_path)
|
|
152
|
+
if not protection:
|
|
153
|
+
# Path não protegido, permitir
|
|
154
|
+
sys.exit(0)
|
|
155
|
+
|
|
156
|
+
# Verificar se documentação existe
|
|
157
|
+
doc_exists, doc_path = check_documentation_exists(relative_path, protection, project_root)
|
|
158
|
+
|
|
159
|
+
if doc_exists:
|
|
160
|
+
# Documentação existe, permitir
|
|
161
|
+
sys.exit(0)
|
|
162
|
+
|
|
163
|
+
# BLOQUEAR: Documentação não existe
|
|
164
|
+
name = protection["extract_name"](relative_path) or "unknown"
|
|
165
|
+
required_docs = format_required_docs(protection, name)
|
|
166
|
+
|
|
167
|
+
error_message = f"""
|
|
168
|
+
╔══════════════════════════════════════════════════════════════════════════════╗
|
|
169
|
+
║ 🛑 ARCHITECTURE-FIRST: Documentação obrigatória antes de código ║
|
|
170
|
+
╠══════════════════════════════════════════════════════════════════════════════╣
|
|
171
|
+
║ ║
|
|
172
|
+
║ Arquivo bloqueado: {relative_path[:50]:<50} ║
|
|
173
|
+
║ ║
|
|
174
|
+
║ REGRA: Antes de criar/editar código em paths protegidos, você DEVE: ║
|
|
175
|
+
║ ║
|
|
176
|
+
║ 1. Documentar o plano de arquitetura ║
|
|
177
|
+
║ 2. Obter aprovação do usuário ║
|
|
178
|
+
║ 3. Criar o arquivo de documentação ║
|
|
179
|
+
║ ║
|
|
180
|
+
║ Documentos aceitos para '{name}': ║
|
|
181
|
+
{required_docs}
|
|
182
|
+
║ ║
|
|
183
|
+
║ AÇÃO: Crie um dos documentos acima com o plano aprovado, depois tente ║
|
|
184
|
+
║ novamente a operação de código. ║
|
|
185
|
+
║ ║
|
|
186
|
+
║ DICA: Use `*create-doc architecture` para criar doc de arquitetura ║
|
|
187
|
+
║ Ou crie docs/approved-plans/{name}.md com o plano resumido ║
|
|
188
|
+
║ ║
|
|
189
|
+
╚══════════════════════════════════════════════════════════════════════════════╝
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
print(error_message, file=sys.stderr)
|
|
193
|
+
sys.exit(2) # Exit code 2 = bloqueia o tool
|
|
194
|
+
|
|
195
|
+
if __name__ == "__main__":
|
|
196
|
+
main()
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Install AIOS Git Hooks
|
|
3
|
+
# Version: 1.0
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
echo "🔧 Installing AIOS Git Hooks..."
|
|
8
|
+
|
|
9
|
+
# Get script directory
|
|
10
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
12
|
+
HOOKS_DIR="$PROJECT_ROOT/.git/hooks"
|
|
13
|
+
|
|
14
|
+
# Ensure hooks directory exists
|
|
15
|
+
if [ ! -d "$HOOKS_DIR" ]; then
|
|
16
|
+
echo "❌ Error: .git/hooks directory not found"
|
|
17
|
+
echo "Are you in a git repository?"
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
# Install pre-commit hook (MMOS architecture guard)
|
|
22
|
+
echo "Installing pre-commit hook (MMOS architecture guard)..."
|
|
23
|
+
ln -sf ../../.aios-core/hooks/pre-commit-mmos-guard.sh "$HOOKS_DIR/pre-commit"
|
|
24
|
+
chmod +x "$HOOKS_DIR/pre-commit"
|
|
25
|
+
|
|
26
|
+
echo "✅ Pre-commit hook installed"
|
|
27
|
+
|
|
28
|
+
# Make all hooks executable
|
|
29
|
+
chmod +x "$SCRIPT_DIR"/*.sh
|
|
30
|
+
|
|
31
|
+
echo ""
|
|
32
|
+
echo "✅ All hooks installed successfully!"
|
|
33
|
+
echo ""
|
|
34
|
+
echo "Installed hooks:"
|
|
35
|
+
echo " - pre-commit: MMOS architecture guard"
|
|
36
|
+
echo ""
|
|
37
|
+
echo "To test:"
|
|
38
|
+
echo " .aios-core/hooks/pre-commit-mmos-guard.sh"
|
|
39
|
+
echo ""
|
|
40
|
+
echo "To uninstall:"
|
|
41
|
+
echo " rm .git/hooks/pre-commit"
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Hook: Mind Clone Governance
|
|
4
|
+
|
|
5
|
+
REGRA: Agents baseados em pessoas reais (mind clones) DEVEM passar pelo
|
|
6
|
+
pipeline de extração de DNA antes de serem criados.
|
|
7
|
+
|
|
8
|
+
Este hook intercepta Write/Edit em squads/*/agents/*.md e verifica:
|
|
9
|
+
1. Se é um mind clone (baseado em pessoa real)
|
|
10
|
+
2. Se existe DNA extraído correspondente
|
|
11
|
+
|
|
12
|
+
NÃO BLOQUEIA:
|
|
13
|
+
- Orchestrators (nome contém 'chief', 'orchestrator', 'chair')
|
|
14
|
+
- Tool agents (nome contém 'validator', 'calculator', 'generator')
|
|
15
|
+
- Process agents (nome contém 'architect', 'mapper', 'designer')
|
|
16
|
+
- Edição de arquivo existente (apenas criação é bloqueada)
|
|
17
|
+
|
|
18
|
+
Exit Codes:
|
|
19
|
+
- 0: Permitido
|
|
20
|
+
- 2: Bloqueado (mind clone sem DNA)
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import json
|
|
24
|
+
import sys
|
|
25
|
+
import os
|
|
26
|
+
import re
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
|
|
29
|
+
# =============================================================================
|
|
30
|
+
# CONFIGURAÇÃO
|
|
31
|
+
# =============================================================================
|
|
32
|
+
|
|
33
|
+
# Padrões que indicam que NÃO é um mind clone (agents funcionais)
|
|
34
|
+
FUNCTIONAL_AGENT_PATTERNS = [
|
|
35
|
+
# Orchestrators
|
|
36
|
+
r'.*-chief$',
|
|
37
|
+
r'.*-orchestrator$',
|
|
38
|
+
r'.*-chair$',
|
|
39
|
+
r'^orchestrator$',
|
|
40
|
+
|
|
41
|
+
# Tool agents
|
|
42
|
+
r'.*-validator$',
|
|
43
|
+
r'.*-calculator$',
|
|
44
|
+
r'.*-generator$',
|
|
45
|
+
r'.*-extractor$',
|
|
46
|
+
r'.*-analyzer$',
|
|
47
|
+
|
|
48
|
+
# Process agents
|
|
49
|
+
r'.*-architect$',
|
|
50
|
+
r'.*-mapper$',
|
|
51
|
+
r'.*-designer$',
|
|
52
|
+
r'.*-engineer$',
|
|
53
|
+
|
|
54
|
+
# Generic functional
|
|
55
|
+
r'^tools?-.*',
|
|
56
|
+
r'^process-.*',
|
|
57
|
+
r'^workflow-.*',
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
# Locais onde DNA pode estar
|
|
61
|
+
DNA_LOCATIONS = [
|
|
62
|
+
"squads/{pack}/data/minds/{agent_id}_dna.yaml",
|
|
63
|
+
"squads/{pack}/data/minds/{agent_id}_dna.md",
|
|
64
|
+
"squads/{pack}/data/{agent_id}-dna.yaml",
|
|
65
|
+
"outputs/minds/{agent_id}/",
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
# =============================================================================
|
|
69
|
+
# LÓGICA DO HOOK
|
|
70
|
+
# =============================================================================
|
|
71
|
+
|
|
72
|
+
def get_project_root():
|
|
73
|
+
"""Obtém o root do projeto via variável de ambiente ou cwd."""
|
|
74
|
+
return os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
|
|
75
|
+
|
|
76
|
+
def extract_agent_info(file_path: str) -> tuple:
|
|
77
|
+
"""Extrai pack_name e agent_id do path."""
|
|
78
|
+
# squads/{pack}/agents/{agent_id}.md
|
|
79
|
+
match = re.match(r'.*/squads/([^/]+)/agents/([^/]+)\.md$', file_path)
|
|
80
|
+
if match:
|
|
81
|
+
return match.group(1), match.group(2)
|
|
82
|
+
return None, None
|
|
83
|
+
|
|
84
|
+
def is_functional_agent(agent_id: str) -> bool:
|
|
85
|
+
"""Verifica se o agent é funcional (não é mind clone)."""
|
|
86
|
+
for pattern in FUNCTIONAL_AGENT_PATTERNS:
|
|
87
|
+
if re.match(pattern, agent_id, re.IGNORECASE):
|
|
88
|
+
return True
|
|
89
|
+
return False
|
|
90
|
+
|
|
91
|
+
def has_dna_extracted(project_root: str, pack_name: str, agent_id: str) -> tuple:
|
|
92
|
+
"""Verifica se existe DNA extraído para o agent."""
|
|
93
|
+
for location_template in DNA_LOCATIONS:
|
|
94
|
+
location = location_template.format(pack=pack_name, agent_id=agent_id)
|
|
95
|
+
full_path = os.path.join(project_root, location)
|
|
96
|
+
|
|
97
|
+
# Se é diretório, verificar se existe
|
|
98
|
+
if location.endswith('/'):
|
|
99
|
+
if os.path.isdir(full_path):
|
|
100
|
+
return True, full_path
|
|
101
|
+
# Se é arquivo, verificar se existe
|
|
102
|
+
elif os.path.isfile(full_path):
|
|
103
|
+
return True, full_path
|
|
104
|
+
|
|
105
|
+
return False, None
|
|
106
|
+
|
|
107
|
+
def file_already_exists(file_path: str) -> bool:
|
|
108
|
+
"""Verifica se o arquivo já existe (edit vs create)."""
|
|
109
|
+
return os.path.isfile(file_path)
|
|
110
|
+
|
|
111
|
+
def main():
|
|
112
|
+
# Ler input do stdin
|
|
113
|
+
try:
|
|
114
|
+
input_data = json.load(sys.stdin)
|
|
115
|
+
except json.JSONDecodeError:
|
|
116
|
+
# Se não conseguir parsear, permitir (fail-open)
|
|
117
|
+
sys.exit(0)
|
|
118
|
+
|
|
119
|
+
tool_name = input_data.get("tool_name", "")
|
|
120
|
+
tool_input = input_data.get("tool_input", {})
|
|
121
|
+
|
|
122
|
+
# Só processar Write e Edit
|
|
123
|
+
if tool_name not in ["Write", "Edit"]:
|
|
124
|
+
sys.exit(0)
|
|
125
|
+
|
|
126
|
+
file_path = tool_input.get("file_path", "")
|
|
127
|
+
if not file_path:
|
|
128
|
+
sys.exit(0)
|
|
129
|
+
|
|
130
|
+
# Só processar arquivos em squads/*/agents/
|
|
131
|
+
if "/squads/" not in file_path or "/agents/" not in file_path:
|
|
132
|
+
sys.exit(0)
|
|
133
|
+
|
|
134
|
+
if not file_path.endswith(".md"):
|
|
135
|
+
sys.exit(0)
|
|
136
|
+
|
|
137
|
+
project_root = get_project_root()
|
|
138
|
+
|
|
139
|
+
# Extrair informações do path
|
|
140
|
+
pack_name, agent_id = extract_agent_info(file_path)
|
|
141
|
+
if not pack_name or not agent_id:
|
|
142
|
+
sys.exit(0)
|
|
143
|
+
|
|
144
|
+
# Se é edição de arquivo existente, permitir
|
|
145
|
+
if file_already_exists(file_path):
|
|
146
|
+
sys.exit(0)
|
|
147
|
+
|
|
148
|
+
# Se é agent funcional (não mind clone), permitir
|
|
149
|
+
if is_functional_agent(agent_id):
|
|
150
|
+
sys.exit(0)
|
|
151
|
+
|
|
152
|
+
# Verificar se existe DNA extraído
|
|
153
|
+
has_dna, dna_path = has_dna_extracted(project_root, pack_name, agent_id)
|
|
154
|
+
|
|
155
|
+
if has_dna:
|
|
156
|
+
sys.exit(0)
|
|
157
|
+
|
|
158
|
+
# BLOQUEAR: Tentando criar mind clone sem DNA
|
|
159
|
+
error_message = f"""
|
|
160
|
+
╔══════════════════════════════════════════════════════════════════════════════╗
|
|
161
|
+
║ 🧬 MIND CLONE GOVERNANCE: DNA não encontrado ║
|
|
162
|
+
╠══════════════════════════════════════════════════════════════════════════════╣
|
|
163
|
+
║ ║
|
|
164
|
+
║ Agent: {agent_id:<60} ║
|
|
165
|
+
║ Pack: {pack_name:<60} ║
|
|
166
|
+
║ ║
|
|
167
|
+
║ PROBLEMA: Este parece ser um MIND CLONE (baseado em pessoa real), ║
|
|
168
|
+
║ mas não foi encontrado DNA extraído. ║
|
|
169
|
+
║ ║
|
|
170
|
+
║ Mind clones DEVEM passar pelo pipeline de extração: ║
|
|
171
|
+
║ 1. *collect-sources → Coletar fontes (livros, entrevistas, artigos) ║
|
|
172
|
+
║ 2. *extract-voice-dna → Extrair padrões linguísticos ║
|
|
173
|
+
║ 3. *extract-thinking-dna → Extrair frameworks e heurísticas ║
|
|
174
|
+
║ 4. *create-agent → Criar agent a partir do DNA ║
|
|
175
|
+
║ ║
|
|
176
|
+
║ LOCAIS VERIFICADOS: ║
|
|
177
|
+
║ • squads/{pack_name}/data/minds/{agent_id}_dna.yaml
|
|
178
|
+
║ • squads/{pack_name}/data/minds/{agent_id}_dna.md
|
|
179
|
+
║ • outputs/minds/{agent_id}/
|
|
180
|
+
║ ║
|
|
181
|
+
║ SOLUÇÕES: ║
|
|
182
|
+
║ 1. Execute o pipeline de clone: /squad-creator → *collect-sources ║
|
|
183
|
+
║ 2. OU se é agent FUNCIONAL, renomeie com sufixo: ║
|
|
184
|
+
║ -chief, -orchestrator, -validator, -architect, etc. ║
|
|
185
|
+
║ ║
|
|
186
|
+
╚══════════════════════════════════════════════════════════════════════════════╝
|
|
187
|
+
"""
|
|
188
|
+
print(error_message, file=sys.stderr)
|
|
189
|
+
sys.exit(2)
|
|
190
|
+
|
|
191
|
+
if __name__ == "__main__":
|
|
192
|
+
main()
|