#!/usr/bin/env bash # ============================================================================== # Script de Governança: Validar Setup Multi-Projeto (.agent) # Valida a conformidade de qualquer projeto hospedeiro com os 6 pilares DDD # e audita o agnosticismo do submódulo .agent. # ============================================================================== set -e # Cores para saída no terminal VERDE="\033[0;32m" AMARELO="\033[1;33m" VERMELHO="\033[0;31m" AZUL="\033[0;34m" NEGRITO="\033[1m" RESET="\033[0m" # Identificar a raiz do projeto pai if [ -d "memorias-ia" ] || [ -f "memorias-ia/modulo.yml" ] || [ -f "package.json" ]; then ROOT_DIR="." elif [ -d "../memorias-ia" ] || [ -f "../memorias-ia/modulo.yml" ] || [ -f "../package.json" ]; then ROOT_DIR=".." else ROOT_DIR="." fi echo -e "${AZUL}${NEGRITO}======================================================${RESET}" echo -e "${AZUL}${NEGRITO}🔍 Auditoria de Setup Multi-Projeto (.agent)${RESET}" echo -e "${AZUL}${NEGRITO}======================================================${RESET}" TOTAL_ERROS=0 TOTAL_AVISOS=0 # 0. Validar Submódulo .agent e tracking da branch master echo -e "\n${NEGRITO}[0/6] Submódulo .agent (Sincronização, Branch Master & Agnosticismo)${RESET}" if [ -f "$ROOT_DIR/.gitmodules" ]; then if grep -q '\[submodule "\.agent"\]' "$ROOT_DIR/.gitmodules"; then echo -e " ${VERDE}✓${RESET} Submódulo .agent configurado em .gitmodules." SUBMODULE_BRANCH=$(git -C "$ROOT_DIR" config -f .gitmodules submodule..agent.branch 2>/dev/null || true) if [ "$SUBMODULE_BRANCH" = "master" ]; then echo -e " ${VERDE}✓${RESET} Submódulo configurado para rastrear branch: ${NEGRITO}master${RESET}" else echo -e " ${AMARELO}⚠${RESET} Submódulo .agent não possui 'branch = master' configurado no .gitmodules." echo -e " Execute: git submodule set-branch --branch master .agent" TOTAL_AVISOS=$((TOTAL_AVISOS + 1)) fi else echo -e " ${VERMELHO}✗${RESET} Entrada do submódulo .agent não encontrada em .gitmodules." TOTAL_ERROS=$((TOTAL_ERROS + 1)) fi else echo -e " ${AMARELO}⚠${RESET} Arquivo .gitmodules não encontrado na raiz." fi # Verificar sincronismo interno das pastas espelhadas do .agent if [ -d "$ROOT_DIR/.agent/rules" ] && [ -d "$ROOT_DIR/.agent/global/rules" ]; then if diff -rq "$ROOT_DIR/.agent/rules" "$ROOT_DIR/.agent/global/rules" >/dev/null 2>&1 && \ diff -rq "$ROOT_DIR/.agent/skills" "$ROOT_DIR/.agent/global/skills" >/dev/null 2>&1; then echo -e " ${VERDE}✓${RESET} Artefatos internos do .agent (rules/ e skills/) 100% sincronizados." else echo -e " ${AMARELO}⚠${RESET} Divergência detectada entre rules/skills e global/ no .agent." TOTAL_AVISOS=$((TOTAL_AVISOS + 1)) fi fi # Verificar agnosticismo polimórfico do .agent em relação ao modulo-id hospedeiro HOST_MODULO_ID=$(grep -E "^modulo-id:" "$ROOT_DIR/memorias-ia/modulo.yml" 2>/dev/null | awk '{print $2}' || true) if [ -n "$HOST_MODULO_ID" ] && [ -d "$ROOT_DIR/.agent/rules" ]; then if grep -rnI -i "$HOST_MODULO_ID" "$ROOT_DIR/.agent/rules" "$ROOT_DIR/.agent/skills" "$ROOT_DIR/.agent/agents" >/dev/null 2>&1; then echo -e " ${VERMELHO}✗${RESET} Violação de agnosticismo: modulo-id '$HOST_MODULO_ID' encontrado hardcoded dentro de .agent/." TOTAL_ERROS=$((TOTAL_ERROS + 1)) else echo -e " ${VERDE}✓${RESET} Agnosticismo verificado: zero menções ao módulo hospedeiro (${NEGRITO}$HOST_MODULO_ID${RESET}) em .agent/." fi fi # Verificar runtime Bun e atualização diária (bun upgrade --stable) export PATH="$HOME/.bun/bin:$PATH" if command -v bun >/dev/null 2>&1; then BUN_STAMP_FILE="/tmp/.antigravity_bun_upgrade_date" TODAY=$(date +%Y-%m-%d) LAST_BUN_CHECK=$(cat "$BUN_STAMP_FILE" 2>/dev/null || true) if [ "$LAST_BUN_CHECK" != "$TODAY" ]; then if bun upgrade --stable >/dev/null 2>&1; then echo "$TODAY" > "$BUN_STAMP_FILE" 2>/dev/null || true fi fi BUN_VER=$(bun --version 2>/dev/null || true) echo -e " ${VERDE}✓${RESET} Runtime Bun verificado (${NEGRITO}v${BUN_VER}${RESET} — check diário: ${NEGRITO}bun upgrade --stable${RESET})." else echo -e " ${AMARELO}⚠${RESET} Runtime Bun não encontrado no PATH." TOTAL_AVISOS=$((TOTAL_AVISOS + 1)) fi # 1. Validar memorias-ia/modulo.yml (Pilar 6 - Identidade) MODULO_YML="$ROOT_DIR/memorias-ia/modulo.yml" echo -e "\n${NEGRITO}[1/6] Identidade do Módulo (memorias-ia/modulo.yml)${RESET}" if [ -f "$MODULO_YML" ]; then echo -e " ${VERDE}✓${RESET} Arquivo memorias-ia/modulo.yml encontrado." # Validar as 4 chaves obrigatórias MODULO_ID=$(grep -E "^modulo-id:" "$MODULO_YML" | awk '{print $2}' || true) MODULO_CAMINHO=$(grep -E "^modulo-caminho:" "$MODULO_YML" | awk '{print $2}' || true) MODULO_DESCRICAO=$(grep -E "^modulo-descricao:" "$MODULO_YML" || true) MODULO_TIPO=$(grep -E "^modulo-tipo:" "$MODULO_YML" || true) if [ -n "$MODULO_ID" ]; then echo -e " ${VERDE}✓${RESET} modulo-id: ${NEGRITO}$MODULO_ID${RESET}" else echo -e " ${VERMELHO}✗${RESET} Chave 'modulo-id' ausente ou vazia." TOTAL_ERROS=$((TOTAL_ERROS + 1)) fi if [ -n "$MODULO_CAMINHO" ]; then echo -e " ${VERDE}✓${RESET} modulo-caminho: ${NEGRITO}$MODULO_CAMINHO${RESET}" else echo -e " ${VERMELHO}✗${RESET} Chave 'modulo-caminho' ausente ou vazia." TOTAL_ERROS=$((TOTAL_ERROS + 1)) fi if [ -n "$MODULO_DESCRICAO" ]; then echo -e " ${VERDE}✓${RESET} modulo-descricao configurada." else echo -e " ${VERMELHO}✗${RESET} Chave 'modulo-descricao' ausente." TOTAL_ERROS=$((TOTAL_ERROS + 1)) fi if [ -n "$MODULO_TIPO" ]; then echo -e " ${VERDE}✓${RESET} modulo-tipo configurado." else echo -e " ${VERMELHO}✗${RESET} Chave 'modulo-tipo' ausente." TOTAL_ERROS=$((TOTAL_ERROS + 1)) fi # Validar modulo-acesso (credenciais de teste para automação e QA) if grep -q "modulo-acesso:" "$MODULO_YML"; then if grep -E -q "^\s+(interno|cliente|externo|anonimo):" "$MODULO_YML"; then echo -e " ${VERDE}✓${RESET} modulo-acesso: credenciais multi-contexto configuradas (isolamento de tokens)." else echo -e " ${VERDE}✓${RESET} modulo-acesso: credenciais de teste configuradas." fi else echo -e " ${AMARELO}⚠${RESET} modulo-acesso: credenciais de teste não configuradas em modulo.yml." fi # Resolver modulo-wiki (caminho da wiki com fallback mandatório para ../wiki) MODULO_WIKI=$(grep -E "^modulo-wiki:" "$MODULO_YML" | awk '{print $2}' || true) if [ -z "$MODULO_WIKI" ]; then MODULO_WIKI="../wiki" fi echo -e " ${VERDE}✓${RESET} modulo-wiki resolvido: ${NEGRITO}$MODULO_WIKI${RESET}" # Exibir convenção de sessão isolada para agent-browser if [ -n "$MODULO_ID" ]; then echo -e " ${AZUL}ℹ${RESET} Sessão agent-browser: agent-browser --session ${NEGRITO}${MODULO_ID}_${RESET}" echo -e " Exemplos: ${MODULO_ID}_interno | ${MODULO_ID}_cliente | ${MODULO_ID}_externo | ${MODULO_ID}_anonimo" fi # Validar memorias-ia/historico-acoes.md (Pilar 6 - Índice de Ações) HISTORICO_MD="$ROOT_DIR/memorias-ia/historico-acoes.md" if [ -f "$HISTORICO_MD" ]; then echo -e " ${VERDE}✓${RESET} Índice memorias-ia/historico-acoes.md encontrado." else echo -e " ${AMARELO}⚠${RESET} Arquivo memorias-ia/historico-acoes.md não encontrado." echo -e " Execute: cp .agent/DOCUMENTACAO/templates/historico-acoes.md.template memorias-ia/historico-acoes.md" TOTAL_AVISOS=$((TOTAL_AVISOS + 1)) fi else echo -e " ${VERMELHO}✗ CRÍTICO: Arquivo memorias-ia/modulo.yml NÃO encontrado!${RESET}" echo -e " Execute: cp .agent/DOCUMENTACAO/templates/modulo.yml.template memorias-ia/modulo.yml" TOTAL_ERROS=$((TOTAL_ERROS + 1)) fi # 2. Validar Wiki do Usuário (Pilar 3) echo -e "\n${NEGRITO}[2/6] Wiki do Usuário (Pilar 3)${RESET}" if [ -n "$MODULO_ID" ]; then WIKI_USER_DIR="$ROOT_DIR/$MODULO_WIKI/$MODULO_ID" if [ -d "$WIKI_USER_DIR" ]; then echo -e " ${VERDE}✓${RESET} Diretório encontrado em: $MODULO_WIKI/$MODULO_ID/" elif [ -d "$ROOT_DIR/$MODULO_WIKI" ]; then echo -e " ${VERDE}✓${RESET} Repositório de Wiki dedicado encontrado em: $MODULO_WIKI/" else echo -e " ${AMARELO}⚠${RESET} Diretório $MODULO_WIKI/$MODULO_ID/ não encontrado." TOTAL_AVISOS=$((TOTAL_AVISOS + 1)) fi else echo -e " ${AMARELO}⚠${RESET} Ignorado: modulo-id não definido." fi # 3. Validar Wiki de Desenvolvimento (Pilar 4) echo -e "\n${NEGRITO}[3/6] Wiki de Desenvolvimento (Pilar 4)${RESET}" if [ -n "$MODULO_ID" ]; then WIKI_DEV_DIR="$ROOT_DIR/$MODULO_WIKI/dev/$MODULO_ID" if [ -d "$WIKI_DEV_DIR" ]; then echo -e " ${VERDE}✓${RESET} Diretório encontrado em: $MODULO_WIKI/dev/$MODULO_ID/" elif [ -d "$ROOT_DIR/$MODULO_WIKI/dev" ] || [ -d "$ROOT_DIR/$MODULO_WIKI" ]; then echo -e " ${VERDE}✓${RESET} Base de Wiki disponível em: $MODULO_WIKI/ (sugerido: $MODULO_WIKI/dev/$MODULO_ID/)" else echo -e " ${AMARELO}⚠${RESET} Diretório $MODULO_WIKI/dev/$MODULO_ID/ não encontrado." TOTAL_AVISOS=$((TOTAL_AVISOS + 1)) fi else echo -e " ${AMARELO}⚠${RESET} Ignorado: modulo-id não definido." fi # 4. Validar Integração de IA (/llm.md - Pilar 5) echo -e "\n${NEGRITO}[4/6] Integração de IA /llm.md (Pilar 5)${RESET}" BACK_DIRS=$(find "$ROOT_DIR" -maxdepth 2 -iname "*-back" -type d 2>/dev/null || true) if [ -n "$BACK_DIRS" ]; then if grep -rq "llm\.md" $BACK_DIRS/src 2>/dev/null; then echo -e " ${VERDE}✓${RESET} Rota /llm.md configurada no backend." else echo -e " ${AMARELO}⚠${RESET} Rota /llm.md não detectada no código do backend." TOTAL_AVISOS=$((TOTAL_AVISOS + 1)) fi else echo -e " ${AZUL}ℹ${RESET} Nenhum pacote *-back identificado no nível raiz." fi # 5. Validar Camada de Extensão Local (.agent-local/) echo -e "\n${NEGRITO}[5/6] Extensibilidade Local (.agent-local/)${RESET}" if [ -d "$ROOT_DIR/.agent-local" ]; then echo -e " ${VERDE}✓${RESET} Camada .agent-local/ presente para regras específicas deste projeto." else echo -e " ${AZUL}ℹ${RESET} .agent-local/ ausente (usando 100% regras e skills globais)." fi # 6. Validar Limite de Linhas (Governança de Código) echo -e "\n${NEGRITO}[6/6] Governança de Código (verificar-linhas.sh)${RESET}" if [ -f "$ROOT_DIR/.agent/verificar-linhas.sh" ]; then sh "$ROOT_DIR/.agent/verificar-linhas.sh" > /dev/null 2>&1 && \ echo -e " ${VERDE}✓${RESET} 100% dos arquivos dentro do limite de 250 linhas." || \ echo -e " ${AMARELO}⚠${RESET} Há arquivos excedendo 250 linhas (execute sh .agent/verificar-linhas.sh)." fi # Resumo Final echo -e "\n${AZUL}${NEGRITO}======================================================${RESET}" if [ "$TOTAL_ERROS" -eq 0 ]; then if [ "$TOTAL_AVISOS" -eq 0 ]; then echo -e "${VERDE}${NEGRITO}🎉 SUCESSO: Projeto 100% em conformidade com o ecossistema .agent!${RESET}" else echo -e "${AMARELO}${NEGRITO}✨ PROJETO VÁLIDO: $TOTAL_AVISOS aviso(s) secundário(s) para revisar.${RESET}" fi exit 0 else echo -e "${VERMELHO}${NEGRITO}❌ CONFORMIDADE INCOMPLETA: $TOTAL_ERROS erro(s) mandatório(s) encontrado(s).${RESET}" exit 1 fi