aios-core 4.0.2 → 4.0.4
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/.session/current-session.json +14 -0
- package/.aios-core/core/registry/registry-schema.json +166 -166
- package/.aios-core/core/registry/service-registry.json +6585 -6585
- package/.aios-core/data/registry-update-log.jsonl +113 -0
- package/.aios-core/development/scripts/approval-workflow.js +642 -642
- package/.aios-core/development/scripts/backup-manager.js +606 -606
- package/.aios-core/development/scripts/branch-manager.js +389 -389
- package/.aios-core/development/scripts/code-quality-improver.js +1311 -1311
- package/.aios-core/development/scripts/commit-message-generator.js +849 -849
- package/.aios-core/development/scripts/conflict-resolver.js +674 -674
- package/.aios-core/development/scripts/dependency-analyzer.js +637 -637
- package/.aios-core/development/scripts/diff-generator.js +351 -351
- package/.aios-core/development/scripts/elicitation-engine.js +384 -384
- package/.aios-core/development/scripts/elicitation-session-manager.js +299 -299
- package/.aios-core/development/scripts/git-wrapper.js +461 -461
- package/.aios-core/development/scripts/manifest-preview.js +244 -244
- package/.aios-core/development/scripts/metrics-tracker.js +775 -775
- package/.aios-core/development/scripts/modification-validator.js +554 -554
- package/.aios-core/development/scripts/pattern-learner.js +1224 -1224
- package/.aios-core/development/scripts/performance-analyzer.js +757 -757
- package/.aios-core/development/scripts/refactoring-suggester.js +1138 -1138
- package/.aios-core/development/scripts/rollback-handler.js +530 -530
- package/.aios-core/development/scripts/security-checker.js +358 -358
- package/.aios-core/development/scripts/template-engine.js +239 -239
- package/.aios-core/development/scripts/template-validator.js +278 -278
- package/.aios-core/development/scripts/test-generator.js +843 -843
- package/.aios-core/development/scripts/transaction-manager.js +589 -589
- package/.aios-core/development/scripts/usage-tracker.js +673 -673
- package/.aios-core/development/scripts/validate-filenames.js +226 -226
- package/.aios-core/development/scripts/version-tracker.js +526 -526
- package/.aios-core/development/scripts/yaml-validator.js +396 -396
- package/.aios-core/development/templates/service-template/README.md.hbs +158 -158
- package/.aios-core/development/templates/service-template/__tests__/index.test.ts.hbs +237 -237
- package/.aios-core/development/templates/service-template/client.ts.hbs +403 -403
- package/.aios-core/development/templates/service-template/errors.ts.hbs +182 -182
- package/.aios-core/development/templates/service-template/index.ts.hbs +120 -120
- package/.aios-core/development/templates/service-template/package.json.hbs +87 -87
- package/.aios-core/development/templates/service-template/types.ts.hbs +145 -145
- package/.aios-core/development/templates/squad-template/LICENSE +21 -21
- package/.aios-core/docs/SHARD-TRANSLATION-GUIDE.md +335 -0
- package/.aios-core/docs/component-creation-guide.md +458 -0
- package/.aios-core/docs/session-update-pattern.md +307 -0
- package/.aios-core/docs/standards/AIOS-FRAMEWORK-MASTER.md +1963 -0
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-SUMMARY.md +1190 -0
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1.md +439 -0
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO.md +5398 -0
- package/.aios-core/docs/standards/V3-ARCHITECTURAL-DECISIONS.md +523 -0
- package/.aios-core/docs/template-syntax.md +267 -0
- package/.aios-core/docs/troubleshooting-guide.md +625 -0
- package/.aios-core/infrastructure/templates/aios-sync.yaml.template +193 -193
- package/.aios-core/infrastructure/templates/coderabbit.yaml.template +279 -279
- package/.aios-core/infrastructure/templates/github-workflows/ci.yml.template +169 -169
- package/.aios-core/infrastructure/templates/github-workflows/pr-automation.yml.template +330 -330
- package/.aios-core/infrastructure/templates/github-workflows/release.yml.template +196 -196
- package/.aios-core/infrastructure/templates/gitignore/gitignore-aios-base.tmpl +63 -63
- package/.aios-core/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +18 -18
- package/.aios-core/infrastructure/templates/gitignore/gitignore-node.tmpl +85 -85
- package/.aios-core/infrastructure/templates/gitignore/gitignore-python.tmpl +145 -145
- package/.aios-core/infrastructure/tests/utilities-audit-results.json +501 -0
- package/.aios-core/install-manifest.yaml +97 -97
- package/.aios-core/local-config.yaml.template +68 -68
- package/.aios-core/manifests/agents.csv +1 -0
- package/.aios-core/manifests/schema/manifest-schema.json +190 -190
- package/.aios-core/manifests/tasks.csv +121 -0
- package/.aios-core/manifests/workers.csv +204 -0
- package/.aios-core/monitor/hooks/lib/__init__.py +1 -1
- package/.aios-core/monitor/hooks/lib/enrich.py +58 -58
- package/.aios-core/monitor/hooks/lib/send_event.py +47 -47
- package/.aios-core/monitor/hooks/notification.py +29 -29
- package/.aios-core/monitor/hooks/post_tool_use.py +45 -45
- package/.aios-core/monitor/hooks/pre_compact.py +29 -29
- package/.aios-core/monitor/hooks/pre_tool_use.py +40 -40
- package/.aios-core/monitor/hooks/stop.py +29 -29
- package/.aios-core/monitor/hooks/subagent_stop.py +29 -29
- package/.aios-core/monitor/hooks/user_prompt_submit.py +38 -38
- package/.aios-core/product/templates/adr.hbs +125 -125
- package/.aios-core/product/templates/component-react-tmpl.tsx +98 -98
- package/.aios-core/product/templates/dbdr.hbs +241 -241
- package/.aios-core/product/templates/engine/schemas/adr.schema.json +102 -102
- package/.aios-core/product/templates/engine/schemas/dbdr.schema.json +205 -205
- package/.aios-core/product/templates/engine/schemas/epic.schema.json +175 -175
- package/.aios-core/product/templates/engine/schemas/pmdr.schema.json +175 -175
- package/.aios-core/product/templates/engine/schemas/prd-v2.schema.json +300 -300
- package/.aios-core/product/templates/engine/schemas/prd.schema.json +152 -152
- package/.aios-core/product/templates/engine/schemas/story.schema.json +222 -222
- package/.aios-core/product/templates/engine/schemas/task.schema.json +154 -154
- package/.aios-core/product/templates/epic.hbs +212 -212
- package/.aios-core/product/templates/eslintrc-security.json +32 -32
- package/.aios-core/product/templates/github-actions-cd.yml +212 -212
- package/.aios-core/product/templates/github-actions-ci.yml +172 -172
- package/.aios-core/product/templates/pmdr.hbs +186 -186
- package/.aios-core/product/templates/prd-v2.0.hbs +216 -216
- package/.aios-core/product/templates/prd.hbs +201 -201
- package/.aios-core/product/templates/shock-report-tmpl.html +502 -502
- package/.aios-core/product/templates/story.hbs +263 -263
- package/.aios-core/product/templates/task.hbs +170 -170
- package/.aios-core/product/templates/tmpl-comment-on-examples.sql +158 -158
- package/.aios-core/product/templates/tmpl-migration-script.sql +91 -91
- package/.aios-core/product/templates/tmpl-rls-granular-policies.sql +104 -104
- package/.aios-core/product/templates/tmpl-rls-kiss-policy.sql +10 -10
- package/.aios-core/product/templates/tmpl-rls-roles.sql +135 -135
- package/.aios-core/product/templates/tmpl-rls-simple.sql +77 -77
- package/.aios-core/product/templates/tmpl-rls-tenant.sql +152 -152
- package/.aios-core/product/templates/tmpl-rollback-script.sql +77 -77
- package/.aios-core/product/templates/tmpl-seed-data.sql +140 -140
- package/.aios-core/product/templates/tmpl-smoke-test.sql +16 -16
- package/.aios-core/product/templates/tmpl-staging-copy-merge.sql +139 -139
- package/.aios-core/product/templates/tmpl-stored-proc.sql +140 -140
- package/.aios-core/product/templates/tmpl-trigger.sql +152 -152
- package/.aios-core/product/templates/tmpl-view-materialized.sql +133 -133
- package/.aios-core/product/templates/tmpl-view.sql +177 -177
- package/.aios-core/product/templates/token-exports-css-tmpl.css +240 -240
- package/.aios-core/quality/schemas/quality-metrics.schema.json +233 -233
- package/.aios-core/scripts/migrate-framework-docs.sh +300 -300
- package/.aios-core/scripts/pm.sh +0 -0
- 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/write-path-validation.py +194 -0
- package/.claude/rules/agent-authority.md +105 -0
- package/.claude/rules/coderabbit-integration.md +93 -0
- package/.claude/rules/ids-principles.md +112 -0
- package/.claude/rules/story-lifecycle.md +139 -0
- package/.claude/rules/workflow-execution.md +150 -0
- package/LICENSE +48 -48
- package/README.md +30 -7
- package/bin/aios-minimal.js +0 -0
- package/bin/aios.js +15 -15
- package/package.json +2 -4
- package/packages/aios-install/bin/aios-install.js +0 -0
- package/packages/aios-install/bin/edmcp.js +0 -0
- package/packages/aios-pro-cli/bin/aios-pro.js +0 -0
- package/scripts/check-markdown-links.py +352 -352
- package/scripts/dashboard-parallel-dev.sh +0 -0
- package/scripts/dashboard-parallel-phase3.sh +0 -0
- package/scripts/dashboard-parallel-phase4.sh +0 -0
- package/scripts/glue/README.md +355 -0
- package/scripts/glue/compose-agent-prompt.cjs +362 -0
- package/scripts/install-monitor-hooks.sh +0 -0
- package/.aios-core/lib/build.json +0 -1
|
@@ -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()
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# MMOS Architecture Guard - Pre-commit Hook
|
|
3
|
+
# Version: 1.0
|
|
4
|
+
# Purpose: Prevent architectural violations in file placement
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
echo "🛡️ Running MMOS Architecture Guard..."
|
|
9
|
+
|
|
10
|
+
# Colors
|
|
11
|
+
RED='\033[0;31m'
|
|
12
|
+
GREEN='\033[0;32m'
|
|
13
|
+
YELLOW='\033[1;33m'
|
|
14
|
+
NC='\033[0m' # No Color
|
|
15
|
+
|
|
16
|
+
violations=0
|
|
17
|
+
|
|
18
|
+
# Get staged files
|
|
19
|
+
staged_files=$(git diff --cached --name-only --diff-filter=ACM)
|
|
20
|
+
|
|
21
|
+
# Rule 1: No mind-specific folders in docs/mmos/
|
|
22
|
+
echo "Checking Rule 1: No mind-specific folders in docs/mmos/..."
|
|
23
|
+
|
|
24
|
+
if echo "$staged_files" | grep -qE "docs/mmos/(validations|migrations)/[a-z_-]+"; then
|
|
25
|
+
echo -e "${RED}❌ VIOLATION: Mind-specific folders detected in docs/mmos/${NC}"
|
|
26
|
+
echo ""
|
|
27
|
+
echo "Found:"
|
|
28
|
+
echo "$staged_files" | grep -E "docs/mmos/(validations|migrations)/[a-z_-]+" | sed 's/^/ - /'
|
|
29
|
+
echo ""
|
|
30
|
+
echo -e "${YELLOW}Fix: Move to outputs/minds/{slug}/docs/ instead${NC}"
|
|
31
|
+
echo ""
|
|
32
|
+
echo "Examples:"
|
|
33
|
+
echo " ❌ docs/mmos/validations/pedro-valerio-checklist.md"
|
|
34
|
+
echo " ✅ outputs/minds/pedro_valerio/docs/validation-checklist.md"
|
|
35
|
+
echo ""
|
|
36
|
+
violations=$((violations + 1))
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# Rule 2: No output files in expansion pack
|
|
40
|
+
echo "Checking Rule 2: No output files in expansion pack..."
|
|
41
|
+
|
|
42
|
+
if echo "$staged_files" | grep -qE "expansion-packs/mmos/(benchmarks|outputs|results)/"; then
|
|
43
|
+
echo -e "${RED}❌ VIOLATION: Output files in expansion pack${NC}"
|
|
44
|
+
echo ""
|
|
45
|
+
echo "Found:"
|
|
46
|
+
echo "$staged_files" | grep -E "expansion-packs/mmos/(benchmarks|outputs|results)/" | sed 's/^/ - /'
|
|
47
|
+
echo ""
|
|
48
|
+
echo -e "${YELLOW}Fix: Move to docs/mmos/qa/benchmarks/ or appropriate output location${NC}"
|
|
49
|
+
echo ""
|
|
50
|
+
violations=$((violations + 1))
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# Rule 3: Check for common naming violations
|
|
54
|
+
echo "Checking Rule 3: Mind-specific files should be in outputs/minds/..."
|
|
55
|
+
|
|
56
|
+
# Check for files with mind names in docs/mmos/ (excluding allowed folders)
|
|
57
|
+
for mind_name in $(ls outputs/minds/ 2>/dev/null | grep -v "^README" || true); do
|
|
58
|
+
if echo "$staged_files" | grep -qE "docs/mmos/.*${mind_name}"; then
|
|
59
|
+
# Exclude allowed locations (reports can mention minds)
|
|
60
|
+
if ! echo "$staged_files" | grep -qE "docs/mmos/(reports|architecture)/"; then
|
|
61
|
+
echo -e "${YELLOW}⚠️ WARNING: File containing mind name '$mind_name' in docs/mmos/${NC}"
|
|
62
|
+
echo "$staged_files" | grep -E "docs/mmos/.*${mind_name}" | sed 's/^/ - /'
|
|
63
|
+
echo ""
|
|
64
|
+
echo "Verify this is system-level documentation, not mind-specific"
|
|
65
|
+
echo ""
|
|
66
|
+
fi
|
|
67
|
+
fi
|
|
68
|
+
done
|
|
69
|
+
|
|
70
|
+
# Rule 4: Verify outputs/minds/{slug}/ structure
|
|
71
|
+
echo "Checking Rule 4: outputs/minds/{slug}/ structure..."
|
|
72
|
+
|
|
73
|
+
if echo "$staged_files" | grep -qE "outputs/minds/[^/]+/[^/]+\.(md|yaml|json)$"; then
|
|
74
|
+
echo -e "${YELLOW}⚠️ WARNING: Files in outputs/minds/{slug}/ root detected${NC}"
|
|
75
|
+
echo ""
|
|
76
|
+
echo "Found:"
|
|
77
|
+
echo "$staged_files" | grep -E "outputs/minds/[^/]+/[^/]+\.(md|yaml|json)$" | sed 's/^/ - /'
|
|
78
|
+
echo ""
|
|
79
|
+
echo "Pipeline outputs should be in subfolders:"
|
|
80
|
+
echo " - analysis/, synthesis/, implementation/, system_prompts/, kb/"
|
|
81
|
+
echo " - Process docs should be in docs/"
|
|
82
|
+
echo " - Logs should be in logs/"
|
|
83
|
+
echo ""
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# Final verdict
|
|
87
|
+
echo ""
|
|
88
|
+
if [ $violations -gt 0 ]; then
|
|
89
|
+
echo -e "${RED}❌ COMMIT REJECTED: $violations architectural violation(s) found${NC}"
|
|
90
|
+
echo ""
|
|
91
|
+
echo "Review:"
|
|
92
|
+
echo " - docs/mmos/ARCHITECTURE_RULES.md"
|
|
93
|
+
echo " - .aios-core/checklists/mmos-architecture-guard.md"
|
|
94
|
+
echo ""
|
|
95
|
+
exit 1
|
|
96
|
+
else
|
|
97
|
+
echo -e "${GREEN}✅ Architecture guard passed${NC}"
|
|
98
|
+
exit 0
|
|
99
|
+
fi
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Pre-Commit Hook: Version Metadata Validation
|
|
4
|
+
#
|
|
5
|
+
# Ensures all tasks and agents have version metadata in frontmatter.
|
|
6
|
+
# This prevents silent version mismatches (e.g., v1.0 agent + v2.0 task).
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# Run manually: .aios-core/hooks/pre-commit-version-check.sh
|
|
10
|
+
# Install: .aios-core/hooks/install-hooks.sh
|
|
11
|
+
#
|
|
12
|
+
# Story: STORY-3.10 (Version Alignment & Compatibility Checks)
|
|
13
|
+
|
|
14
|
+
set -e
|
|
15
|
+
|
|
16
|
+
echo "🔍 Validating task and agent version metadata..."
|
|
17
|
+
|
|
18
|
+
# Colors for output
|
|
19
|
+
RED='\033[0;31m'
|
|
20
|
+
GREEN='\033[0;32m'
|
|
21
|
+
YELLOW='\033[1;33m'
|
|
22
|
+
NC='\033[0m' # No Color
|
|
23
|
+
|
|
24
|
+
# Track validation status
|
|
25
|
+
ERRORS=0
|
|
26
|
+
|
|
27
|
+
# Function to check if file has required version fields
|
|
28
|
+
check_task_version() {
|
|
29
|
+
local file="$1"
|
|
30
|
+
local missing_fields=()
|
|
31
|
+
|
|
32
|
+
if ! grep -q "^task_name:" "$file"; then
|
|
33
|
+
missing_fields+=("task_name")
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
if ! grep -q "^task_version:" "$file"; then
|
|
37
|
+
missing_fields+=("task_version")
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
if ! grep -q "^required_agent_version:" "$file"; then
|
|
41
|
+
missing_fields+=("required_agent_version")
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
if ! grep -q "^description:" "$file"; then
|
|
45
|
+
missing_fields+=("description")
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
if ! grep -q "^last_updated:" "$file"; then
|
|
49
|
+
missing_fields+=("last_updated")
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
if [ ${#missing_fields[@]} -gt 0 ]; then
|
|
53
|
+
echo -e "${RED}❌ ERROR: $file missing version metadata${NC}"
|
|
54
|
+
for field in "${missing_fields[@]}"; do
|
|
55
|
+
echo -e "${RED} - Missing field: '$field'${NC}"
|
|
56
|
+
done
|
|
57
|
+
echo ""
|
|
58
|
+
ERRORS=$((ERRORS + 1))
|
|
59
|
+
return 1
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
return 0
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
check_agent_version() {
|
|
66
|
+
local file="$1"
|
|
67
|
+
local missing_fields=()
|
|
68
|
+
|
|
69
|
+
if ! grep -q "^agent_name:" "$file"; then
|
|
70
|
+
missing_fields+=("agent_name")
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
if ! grep -q "^agent_version:" "$file"; then
|
|
74
|
+
missing_fields+=("agent_version")
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
if ! grep -q "^compatible_task_versions:" "$file"; then
|
|
78
|
+
missing_fields+=("compatible_task_versions")
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
if ! grep -q "^description:" "$file"; then
|
|
82
|
+
missing_fields+=("description")
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
if ! grep -q "^last_updated:" "$file"; then
|
|
86
|
+
missing_fields+=("last_updated")
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
if [ ${#missing_fields[@]} -gt 0 ]; then
|
|
90
|
+
echo -e "${RED}❌ ERROR: $file missing version metadata${NC}"
|
|
91
|
+
for field in "${missing_fields[@]}"; do
|
|
92
|
+
echo -e "${RED} - Missing field: '$field'${NC}"
|
|
93
|
+
done
|
|
94
|
+
echo ""
|
|
95
|
+
ERRORS=$((ERRORS + 1))
|
|
96
|
+
return 1
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
return 0
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# Check all tasks in expansion-packs/creator-os/tasks/
|
|
103
|
+
echo "Checking CreatorOS tasks..."
|
|
104
|
+
TASK_COUNT=0
|
|
105
|
+
for task in expansion-packs/creator-os/tasks/*.md; do
|
|
106
|
+
# Skip backup files
|
|
107
|
+
if [[ "$task" == *"-backup.md" ]]; then
|
|
108
|
+
echo -e "${YELLOW}⏭️ Skipping backup: $task${NC}"
|
|
109
|
+
continue
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
if [ -f "$task" ]; then
|
|
113
|
+
if check_task_version "$task"; then
|
|
114
|
+
echo -e "${GREEN}✅ $task${NC}"
|
|
115
|
+
fi
|
|
116
|
+
TASK_COUNT=$((TASK_COUNT + 1))
|
|
117
|
+
fi
|
|
118
|
+
done
|
|
119
|
+
|
|
120
|
+
# Check all agents in expansion-packs/creator-os/agents/
|
|
121
|
+
echo ""
|
|
122
|
+
echo "Checking CreatorOS agents..."
|
|
123
|
+
AGENT_COUNT=0
|
|
124
|
+
for agent in expansion-packs/creator-os/agents/*.md; do
|
|
125
|
+
if [ -f "$agent" ]; then
|
|
126
|
+
if check_agent_version "$agent"; then
|
|
127
|
+
echo -e "${GREEN}✅ $agent${NC}"
|
|
128
|
+
fi
|
|
129
|
+
AGENT_COUNT=$((AGENT_COUNT + 1))
|
|
130
|
+
fi
|
|
131
|
+
done
|
|
132
|
+
|
|
133
|
+
echo ""
|
|
134
|
+
echo "────────────────────────────────────────────────────────────"
|
|
135
|
+
echo "Summary:"
|
|
136
|
+
echo " - Tasks checked: $TASK_COUNT"
|
|
137
|
+
echo " - Agents checked: $AGENT_COUNT"
|
|
138
|
+
echo " - Errors found: $ERRORS"
|
|
139
|
+
echo "────────────────────────────────────────────────────────────"
|
|
140
|
+
|
|
141
|
+
if [ $ERRORS -gt 0 ]; then
|
|
142
|
+
echo ""
|
|
143
|
+
echo -e "${RED}❌ Version validation FAILED${NC}"
|
|
144
|
+
echo ""
|
|
145
|
+
echo "How to fix:"
|
|
146
|
+
echo "1. Add YAML frontmatter to each flagged file"
|
|
147
|
+
echo "2. Include all required fields (task_name, task_version, etc.)"
|
|
148
|
+
echo "3. See Story 3.10 for examples"
|
|
149
|
+
echo ""
|
|
150
|
+
exit 1
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
echo ""
|
|
154
|
+
echo -e "${GREEN}✅ Version validation PASSED${NC}"
|
|
155
|
+
echo ""
|
|
156
|
+
exit 0
|