250 lines
11 KiB
Bash
250 lines
11 KiB
Bash
#!/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}_<contexto?>${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
|