feat(v1.5.2): Execute database migrations and complete setup

- Execute all 6 migrations on Desk CRM production database
- Create missing tables: cr_lsps, cr_agent_lsps, cr_lsp_usage
- Create archive tables: cr_*_usage_archive (4 tables)
- Create system tables: cr_migrations, cr_maintenance_log
- Make all scripts executable (chmod +x)
- Total cr_* tables: 38

Migration files:
- 001_initial_schema.sql
- 002_add_lsps.sql
- 003_add_relationships.sql
- 004_add_telemetry.sql
- 005_add_archive_tables.sql
- 006_add_maintenance_log.sql

Scripts:
- session-init.sh, session-end.sh
- inject-context.sh, inject-agent-context.sh
- record-usage.sh, db-backup.sh, sync-to-mysql.sh

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-04 16:18:02 +00:00
commit 692475a315
55 changed files with 11950 additions and 0 deletions

89
scripts/db-backup.sh Executable file
View File

@@ -0,0 +1,89 @@
#!/bin/bash
# db-backup.sh - Backup selectivo das tabelas cr_*
# Author: Descomplicar®
#
# Uso: ./db-backup.sh [--compress] [--tables=X,Y]
set -e
# Directório de backups (regra CLAUDE.md)
BACKUP_BASE="/media/ealmeida/Dados/Backups"
BACKUP_DIR="$BACKUP_BASE/claude-infrastructure/cr_backup_$(date +%Y%m%d_%H%M%S)"
COMPRESS=0
TABLES=""
# Parse argumentos
while [[ $# -gt 0 ]]; do
case $1 in
--compress)
COMPRESS=1
shift
;;
--tables=*)
TABLES="${1#*=}"
shift
;;
*)
shift
;;
esac
done
# Criar directório de backup
mkdir -p "$BACKUP_DIR/schema"
mkdir -p "$BACKUP_DIR/data"
# Lista de tabelas cr_* (se não especificadas)
if [[ -z "$TABLES" ]]; then
TABLES="cr_agents,cr_skills,cr_mcps,cr_lsps,cr_sdks,cr_mcp_tools,cr_plugins,cr_hooks"
TABLES="$TABLES,cr_agent_mcps,cr_agent_lsps,cr_agent_skills,cr_skill_mcps"
TABLES="$TABLES,cr_sdk_agents,cr_sdk_skills,cr_sdk_mcps,cr_agent_collaborations"
TABLES="$TABLES,cr_agent_usage,cr_skill_usage,cr_mcp_tool_usage,cr_lsp_usage"
TABLES="$TABLES,cr_decision_trees,cr_recommendations,cr_component_issues,cr_reflections"
TABLES="$TABLES,cr_migrations,cr_maintenance_log"
fi
# Criar manifest.json
cat > "$BACKUP_DIR/manifest.json" << EOF
{
"backup_id": "$(basename $BACKUP_DIR)",
"created_at": "$(date -Iseconds)",
"created_by": "descomplicar-meta-plugin",
"version": "1.5.1",
"tables": "$(echo $TABLES | tr ',' '\n' | wc -l)",
"compressed": $COMPRESS
}
EOF
echo "╔══════════════════════════════════════════════════════════════════════╗"
echo "║ DB BACKUP ║"
echo "╠══════════════════════════════════════════════════════════════════════╣"
echo "║ Backup ID: $(basename $BACKUP_DIR)"
echo "║ Output: $BACKUP_DIR/"
echo "╠══════════════════════════════════════════════════════════════════════╣"
echo "║ NOTA: Este script gera estrutura de backup. ║"
echo "║ Para dump real, usar desk-crm-v3 MCP ou mysqldump. ║"
echo "╠══════════════════════════════════════════════════════════════════════╣"
# Gerar SQL para cada tabela (esqueleto - dump real via MCP)
IFS=',' read -ra TABLE_ARRAY <<< "$TABLES"
for table in "${TABLE_ARRAY[@]}"; do
echo "-- Backup: $table" > "$BACKUP_DIR/schema/$table.sql"
echo "-- Dump via: mysqldump perfex_crm $table > $BACKUP_DIR/data/$table.sql" >> "$BACKUP_DIR/schema/$table.sql"
echo "$table"
done
if [[ $COMPRESS -eq 1 ]]; then
echo "╠══════════════════════════════════════════════════════════════════════╣"
echo "║ Compressing..."
cd "$BACKUP_BASE/claude-infrastructure"
tar -czf "$(basename $BACKUP_DIR).tar.gz" "$(basename $BACKUP_DIR)"
rm -rf "$BACKUP_DIR"
echo "║ Compressed: $(basename $BACKUP_DIR).tar.gz"
fi
echo "╠══════════════════════════════════════════════════════════════════════╣"
echo "║ Status: ✓ SUCCESS ║"
echo "╚══════════════════════════════════════════════════════════════════════╝"
exit 0

48
scripts/inject-agent-context.sh Executable file
View File

@@ -0,0 +1,48 @@
#!/bin/bash
# inject-agent-context.sh - Injecção de contexto para subagentes
# Hook: SubagentStart
# Autor: Descomplicar
# Data: 2026-02-04
# Este script é chamado quando um subagente inicia
# Recebe o tipo de agente via variável de ambiente CLAUDE_SUBAGENT_TYPE
PLUGIN_ROOT="$(dirname "$(dirname "$(readlink -f "$0")")")"
AGENT_TYPE="${CLAUDE_SUBAGENT_TYPE:-unknown}"
CONFIG_FILE="$HOME/.claude/agents/agent-knowledge-config.json"
CACHE_DIR="${PLUGIN_ROOT}/.cache"
mkdir -p "$CACHE_DIR"
# Verificar se temos configuração para este agente
if [[ ! -f "$CONFIG_FILE" ]]; then
echo "META-PLUGIN: No agent-knowledge-config.json found"
exit 0
fi
# Tentar extrair configuração do agente (usando jq se disponível)
if command -v jq &> /dev/null; then
AGENT_CONFIG=$(jq -r ".\"$AGENT_TYPE\" // empty" "$CONFIG_FILE" 2>/dev/null)
if [[ -n "$AGENT_CONFIG" && "$AGENT_CONFIG" != "null" ]]; then
# Extrair datasets
DATASETS=$(echo "$AGENT_CONFIG" | jq -r '.datasets // [] | join(", ")' 2>/dev/null)
AUTO_CONSULT=$(echo "$AGENT_CONFIG" | jq -r '.auto_consult // false' 2>/dev/null)
QUERY_TEMPLATE=$(echo "$AGENT_CONFIG" | jq -r '.query_template // ""' 2>/dev/null)
if [[ -n "$DATASETS" && "$DATASETS" != "null" ]]; then
echo "META-PLUGIN: Agent context for $AGENT_TYPE"
echo " Datasets: $DATASETS"
echo " Auto-consult: $AUTO_CONSULT"
if [[ -n "$QUERY_TEMPLATE" && "$QUERY_TEMPLATE" != "null" ]]; then
echo " Query template: $QUERY_TEMPLATE"
fi
fi
else
echo "META-PLUGIN: No specific config for agent '$AGENT_TYPE'"
fi
else
echo "META-PLUGIN: jq not installed, skipping advanced context injection"
fi
exit 0

34
scripts/inject-context.sh Executable file
View File

@@ -0,0 +1,34 @@
#!/bin/bash
# inject-context.sh - Injeta contexto específico para subagentes
# Chamado pelo hook SubagentStart
# Author: Descomplicar®
set -e
AGENT_TYPE="${1:-unknown}"
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-/home/ealmeida/mcp-servers/descomplicar-meta-plugin}"
# Output contexto relevante para o agente
cat << EOF
## Descomplicar Infrastructure Context
### Available Commands
- /descomplicar:status - Dashboard de infraestrutura
- /descomplicar:sync - Sincronização ficheiros ↔ MySQL
- /descomplicar:relationships - Gestão de relacionamentos
- /descomplicar:telemetry - Métricas de uso
### Database Tables (cr_*)
- Core: cr_agents, cr_skills, cr_mcps, cr_lsps, cr_sdks
- Relationships: cr_agent_mcps, cr_agent_skills, cr_skill_mcps
- Telemetry: cr_agent_usage, cr_skill_usage, cr_mcp_tool_usage
### MCP Available
- desk-crm-v3: Operações MySQL
- filesystem: Operações de ficheiros
- mcp-time: Data/hora actual
- gitea: Repositórios
EOF
exit 0

75
scripts/record-usage.sh Executable file
View File

@@ -0,0 +1,75 @@
#!/bin/bash
# record-usage.sh - Regista uso de componentes na telemetria
# Pode ser chamado manualmente ou via hooks
# Author: Descomplicar®
#
# Uso: ./record-usage.sh <type> <component_slug> [success] [duration_ms]
# Exemplo: ./record-usage.sh agent wordpress-plugin-developer 1 5200
set -e
TYPE="${1:-agent}"
COMPONENT="${2:-unknown}"
SUCCESS="${3:-1}"
DURATION="${4:-0}"
SESSION_ID="${CLAUDE_SESSION_ID:-manual}"
# Validar argumentos
if [[ -z "$COMPONENT" || "$COMPONENT" == "unknown" ]]; then
echo "Usage: $0 <type> <component_slug> [success] [duration_ms]"
echo "Types: agent, skill, mcp_tool, lsp"
exit 1
fi
# Determinar tabela baseado no tipo
case "$TYPE" in
agent)
TABLE="cr_agent_usage"
ID_COLUMN="agent_id"
LOOKUP_TABLE="cr_agents"
;;
skill)
TABLE="cr_skill_usage"
ID_COLUMN="skill_id"
LOOKUP_TABLE="cr_skills"
;;
mcp_tool)
TABLE="cr_mcp_tool_usage"
ID_COLUMN="mcp_tool_id"
LOOKUP_TABLE="cr_mcp_tools"
;;
lsp)
TABLE="cr_lsp_usage"
ID_COLUMN="lsp_id"
LOOKUP_TABLE="cr_lsps"
;;
*)
echo "Unknown type: $TYPE"
exit 1
;;
esac
# Gerar SQL para inserção
# Nota: Este SQL seria executado via desk-crm-v3 MCP
SQL="INSERT INTO $TABLE ($ID_COLUMN, session_id, success, duration_sec, created_at)
SELECT id, '$SESSION_ID', $SUCCESS, $((DURATION / 1000)), NOW()
FROM $LOOKUP_TABLE
WHERE slug = '$COMPONENT'
LIMIT 1;"
# Output SQL para debug ou execução manual
echo "-- Record Usage: $TYPE/$COMPONENT"
echo "$SQL"
# Se EXECUTE_SQL=1, tentar executar via mysql client (se disponível)
if [[ "${EXECUTE_SQL:-0}" == "1" ]]; then
if command -v mysql &> /dev/null && [[ -n "$MYSQL_HOST" ]]; then
mysql -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASS" "$MYSQL_DB" -e "$SQL"
echo "-- Executed successfully"
else
echo "-- MySQL client not available or credentials not set"
echo "-- Set MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB to execute"
fi
fi
exit 0

46
scripts/session-end.sh Executable file
View File

@@ -0,0 +1,46 @@
#!/bin/bash
# session-end.sh - Finaliza sessão e regista métricas
# Chamado pelo hook Stop
# Author: Descomplicar®
set -e
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-/home/ealmeida/mcp-servers/descomplicar-meta-plugin}"
SESSION_FILE="$PLUGIN_ROOT/.current_session"
# Verificar se existe sessão activa
if [[ ! -f "$SESSION_FILE" ]]; then
echo "No active session found"
exit 0
fi
# Ler dados da sessão
SESSION_DATA=$(cat "$SESSION_FILE")
SESSION_ID=$(echo "$SESSION_DATA" | jq -r '.session_id // "unknown"')
STARTED_AT=$(echo "$SESSION_DATA" | jq -r '.started_at // ""')
TOOL_CALLS=$(echo "$SESSION_DATA" | jq -r '.tool_calls // 0')
# Calcular duração
if [[ -n "$STARTED_AT" ]]; then
START_EPOCH=$(date -d "$STARTED_AT" +%s 2>/dev/null || echo 0)
NOW_EPOCH=$(date +%s)
DURATION=$((NOW_EPOCH - START_EPOCH))
else
DURATION=0
fi
# Output resumo
cat << EOF
╔══════════════════════════════════════════════════════════════════════╗
║ SESSION ENDED ║
╠══════════════════════════════════════════════════════════════════════╣
║ Session ID: $SESSION_ID
║ Duration: ${DURATION}s
║ Tool Calls: $TOOL_CALLS
╚══════════════════════════════════════════════════════════════════════╝
EOF
# Limpar ficheiro de sessão
rm -f "$SESSION_FILE"
exit 0

29
scripts/session-init.sh Executable file
View File

@@ -0,0 +1,29 @@
#!/bin/bash
# session-init.sh - Inicializa sessão e mostra status da infraestrutura
# Chamado pelo hook SessionStart
# Author: Descomplicar®
set -e
# Gerar session ID único
SESSION_ID="${CLAUDE_SESSION_ID:-$(date +%s)-$$}"
export SESSION_ID
# Ficheiro de sessão para tracking
SESSION_FILE="${CLAUDE_PLUGIN_ROOT:-/home/ealmeida/mcp-servers/descomplicar-meta-plugin}/.current_session"
# Registar início de sessão
echo "{\"session_id\": \"$SESSION_ID\", \"started_at\": \"$(date -Iseconds)\", \"tool_calls\": 0}" > "$SESSION_FILE"
# Output status (será capturado pelo Claude)
cat << 'EOF'
╔══════════════════════════════════════════════════════════════════════╗
║ DESCOMPLICAR INFRASTRUCTURE - Session Started ║
╠══════════════════════════════════════════════════════════════════════╣
║ Meta-Plugin v1.5.1 loaded ║
║ Commands: /descomplicar:status, :sync, :create, :validate, :release ║
║ DB Maintenance: :db-cleanup, :db-migrate, :db-backup, :db-archive ║
╚══════════════════════════════════════════════════════════════════════╝
EOF
exit 0

76
scripts/sync-to-mysql.sh Executable file
View File

@@ -0,0 +1,76 @@
#!/bin/bash
# sync-to-mysql.sh - Sincronização ficheiros → MySQL
# Autor: Descomplicar
# Data: 2026-02-04
# Este script é chamado manualmente ou via /descomplicar:sync
# Requer: mysql client, jq
PLUGIN_ROOT="$(dirname "$(dirname "$(readlink -f "$0")")")"
LOG_FILE="${PLUGIN_ROOT}/logs/sync.log"
# Configuração BD (usar variáveis de ambiente ou .env)
DB_HOST="${DESK_DB_HOST:-localhost}"
DB_USER="${DESK_DB_USER:-ealmeida_desk}"
DB_PASS="${DESK_DB_PASS:-}"
DB_NAME="${DESK_DB_NAME:-ealmeida_desk24}"
# Ficheiros fonte
AGENTS_FILE="$HOME/.claude/sdks/_resources/agents.json"
SKILLS_FILE="$HOME/.claude/sdks/_resources/skills.json"
MCPS_FILE="$HOME/.claude/sdks/_resources/mcps.json"
REGISTRY_FILE="$HOME/.claude/sdks/_registry.json"
# Timestamp
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
log() {
echo "[$TIMESTAMP] $1" >> "$LOG_FILE"
echo "$1"
}
# Verificar dependências
check_deps() {
if ! command -v jq &> /dev/null; then
log "ERROR: jq is required but not installed"
exit 1
fi
if ! command -v mysql &> /dev/null; then
log "ERROR: mysql client is required but not installed"
exit 1
fi
}
# Contar items em JSON
count_json() {
local file="$1"
local key="$2"
if [[ -f "$file" ]]; then
jq -r ".$key | length" "$file" 2>/dev/null || echo "0"
else
echo "0"
fi
}
# Main
main() {
log "Starting sync..."
check_deps
# Contar items locais
AGENTS_LOCAL=$(count_json "$AGENTS_FILE" "agents")
SKILLS_LOCAL=$(count_json "$SKILLS_FILE" "skills")
MCPS_LOCAL=$(count_json "$MCPS_FILE" "mcps")
SDKS_LOCAL=$(jq -r '.sdks | length' "$REGISTRY_FILE" 2>/dev/null || echo "0")
log "Local counts: Agents=$AGENTS_LOCAL, Skills=$SKILLS_LOCAL, MCPs=$MCPS_LOCAL, SDKs=$SDKS_LOCAL"
# Nota: A sincronização real com MySQL seria feita via MCP desk-crm-v3
# Este script serve como documentação e pode ser expandido
log "Sync completed (dry-run mode)"
log "Use /descomplicar:sync for full sync via MCP"
}
main "$@"