/*
 * atualizar-manual-gc - recria a arvore operador-manual-gc em sisc/arvores/
 * Uso: pp --atualizar-manual-gc
 *
 * Este comando sempre usa pp --sa para materializar a arvore. A saida canonica
 * e sisc/arvores/operador-manual-gc.json, independentemente do diretorio onde
 * o comando foi chamado.
 */
#define _DEFAULT_SOURCE
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include "manual-dinamico.h"

#ifndef PATH_MAX
#define PATH_MAX 4096
#endif

typedef struct {
    const char *pai;
    const char *texto;
} ItemArvore;

static void uso(void)
{
    fputs(
        "Uso:\n"
        "  pp --atualizar-manual-gc\n"
        "  pp --atualizar-manual-gc --ajuda:<grupo>\n"
        "\n"
        "Descrição:\n"
        "  Recria, do zero, a árvore sisc/arvores/operador-manual-gc.json com o\n"
        "  fluxograma manual para conduzir atualizações organizadas e seguras usando\n"
        "  pp --sa com --gc, --mm, --itens e --prompt.\n"
        "  O comando sempre chama pp --sa para montar a árvore.\n"
        "\n"
        "Grupos de ajuda: uso, comportamento, varredura, arquivos, exemplos.\n"
        "\n"
        "1) Uso e ajuda [uso ajuda]\n"
        "  --ajuda, --help, -h            Exibe esta ajuda\n"
        "  --ajuda:<grupo>                Filtra um grupo. Ex: pp --atualizar-manual-gc --ajuda:arquivos\n"
        "\n"
        "2) Comportamento [comportamento]\n"
        "  Remove a árvore operador-manual-gc.json existente e recria o fluxograma\n"
        "  usando chamadas a pp --sa=operador-manual-gc --ag=... [--em=...].\n"
        "  A geração é direcionada para sisc/arvores, mesmo que o comando seja chamado\n"
        "  de outro diretório. Não executa prompts, não chama LLM e não altera árvores de produto.\n"
        "\n"
        "3) Varredura automática [varredura comandos]\n"
        "  Ao final da árvore, registra assinaturas de comandos e arquivos ligados\n"
        "  a pp --sa, GC, prompt, reversão e agente-at para evidenciar mudanças.\n"
        "  Lei fonte-código: usa como fonte apenas código/contratos/configs operacionais;\n"
        "  não usa árvores/mapas/manuais JSON gerados como fonte de pesquisa.\n"
        "\n"
        "4) Arquivos [arquivos saida]\n"
        "  Saída: sisc/arvores/operador-manual-gc.json\n"
        "\n"
        "5) Exemplos [exemplos]\n"
        "  pp --atualizar-manual-gc\n"
        "  pp --sa=arvores/operador-manual-gc\n",
        stdout);
}

static int mkdir_p(const char *path)
{
    if (!path || !*path) return -1;
    char tmp[PATH_MAX * 2];
    snprintf(tmp, sizeof(tmp), "%s", path);
    size_t len = strlen(tmp);
    while (len > 1 && tmp[len - 1] == '/') tmp[--len] = '\0';
    for (char *p = tmp + 1; *p; p++) {
        if (*p == '/') {
            *p = '\0';
            if (mkdir(tmp, 0775) != 0 && errno != EEXIST) return -1;
            *p = '/';
        }
    }
    if (mkdir(tmp, 0775) != 0 && errno != EEXIST) return -1;
    chmod(tmp, 0775);
    return 0;
}

static int localizar_raiz_sisc(char *out, size_t tam)
{
    char exe[PATH_MAX];
    ssize_t n = readlink("/proc/self/exe", exe, sizeof(exe) - 1);
    if (n <= 0) return -1;
    exe[n] = '\0';

    /* .../sisc/core/comandos/atualizar-manual-gc -> .../sisc */
    char *slash = strrchr(exe, '/'); if (!slash) return -1; *slash = '\0';
    slash = strrchr(exe, '/'); if (!slash) return -1; *slash = '\0';
    slash = strrchr(exe, '/'); if (!slash) return -1; *slash = '\0';

    snprintf(out, tam, "%s", exe);
    return 0;
}

static int executar_sa(const char *pp_path, const char *diretorio_trabalho, const char *pai, const char *texto, int silenciar_stderr)
{
    int in_pipe[2] = {-1, -1};
    if (pipe(in_pipe) != 0) {
        perror("atualizar-manual-gc: pipe");
        return 1;
    }
    const char *confirmacao = "s\n";
    (void)write(in_pipe[1], confirmacao, strlen(confirmacao));
    close(in_pipe[1]);
    in_pipe[1] = -1;

    pid_t pid = fork();
    if (pid < 0) {
        perror("atualizar-manual-gc: fork");
        close(in_pipe[0]);
        return 1;
    }
    if (pid == 0) {
        dup2(in_pipe[0], STDIN_FILENO);
        close(in_pipe[0]);
        if (chdir(diretorio_trabalho) != 0) {
            perror("atualizar-manual-gc: chdir diretorio de arvores");
            _exit(126);
        }
        int null_fd = open("/dev/null", O_WRONLY);
        if (null_fd >= 0) {
            dup2(null_fd, STDOUT_FILENO);
            if (silenciar_stderr) dup2(null_fd, STDERR_FILENO);
            close(null_fd);
        }
        char ag_arg[PATH_MAX * 2];
        char em_arg[64];
        snprintf(ag_arg, sizeof(ag_arg), "--ag=%s", texto ? texto : "");
        char *args_com_pai[] = { (char *)pp_path, "--sa=operador-manual-gc", ag_arg, em_arg, NULL };
        char *args_sem_pai[] = { (char *)pp_path, "--sa=operador-manual-gc", ag_arg, NULL };
        if (pai && *pai) {
            snprintf(em_arg, sizeof(em_arg), "--em=%s", pai);
            execv(pp_path, args_com_pai);
        } else {
            execv(pp_path, args_sem_pai);
        }
        perror("atualizar-manual-gc: execv pp --sa");
        _exit(127);
    }

    close(in_pipe[0]);

    int st = 0;
    if (waitpid(pid, &st, 0) != pid) {
        perror("atualizar-manual-gc: waitpid");
        return 1;
    }
    if (WIFEXITED(st)) return WEXITSTATUS(st);
    if (WIFSIGNALED(st)) return 128 + WTERMSIG(st);
    return 1;
}


typedef struct {
    const char *nome;
    const char *papel;
    const char *flags;
} ComandoRelacionado;

static const ComandoRelacionado COMANDOS_RELACIONADOS[] = {
    {"atualizar-manual-gc", "gera esta árvore manual e deve refletir mudanças do roteiro", "--atualizar-manual-gc"},
    {"sa", "base operacional de árvores, GCs, mensagens, prompts e reversão", "--sa=<arvore> --gc= --mm= --itens= --prompt= --reverter="},
    {"sa-mapa", "apoia visualização/mapeamento de árvores", "--sa-mapa"},
    {"parallm", "executa chamada LLM usada pelo prompt do GC", "--parallm"},
    {"agente", "roteia agente-at após prompt GC", "--agente=agente-at"},
    {"agente-at", "executa manutenção/correção disparada pelo GC", "--ler-mensagem"},
    {"push-github", "cria checkpoint remoto antes de alterações amplas", "--push-github"},
    {"listar-commits", "consulta histórico/checkpoints para auditoria", "--listar-commits"},
    {"atualizar-ajuda-comandos", "sincroniza ajuda JSON quando comandos mudam", "--atualizar-ajuda-comandos=<comando>"}
};

static const char *ARQUIVOS_RELACIONADOS[] = {
    "pp.c",
    "core/comandos/sa.c",
    "core/comandos/sa-mapa.c",
    "core/comandos/parallm.c",
    "core/biblioteca-agentes-fixos/agente-at.json",
    "ajuda/sa.json",
    "ajuda/agente-at.json",
    "core/config/mapa-comandos.json"
};

static uint64_t fnv1a_arquivo(const char *path, int *ok, off_t *size_out, time_t *mtime_out)
{
    *ok = 0;
    if (size_out) *size_out = 0;
    if (mtime_out) *mtime_out = 0;
    struct stat st;
    if (stat(path, &st) != 0 || !S_ISREG(st.st_mode)) return 0;
    if (size_out) *size_out = st.st_size;
    if (mtime_out) *mtime_out = st.st_mtime;
    FILE *f = fopen(path, "rb");
    if (!f) return 0;
    uint64_t h = 1469598103934665603ULL;
    unsigned char buf[8192];
    size_t n;
    while ((n = fread(buf, 1, sizeof(buf), f)) > 0) {
        for (size_t i = 0; i < n; i++) {
            h ^= (uint64_t)buf[i];
            h *= 1099511628211ULL;
        }
    }
    int erro = ferror(f);
    fclose(f);
    if (erro) return 0;
    *ok = 1;
    return h;
}

static void iso_mtime(time_t t, char out[32])
{
    if (!t) { snprintf(out, 32, "ausente"); return; }
    struct tm tmv;
    gmtime_r(&t, &tmv);
    strftime(out, 32, "%Y-%m-%dT%H:%M:%SZ", &tmv);
}

static void assinatura_path(const char *path, char *out, size_t outsz)
{
    int ok = 0;
    off_t sz = 0;
    time_t mt = 0;
    uint64_t h = fnv1a_arquivo(path, &ok, &sz, &mt);
    if (!ok) {
        snprintf(out, outsz, "ausente");
        return;
    }
    char mtiso[32];
    iso_mtime(mt, mtiso);
    snprintf(out, outsz, "ok size=%lld mtime=%s fnv=%016llx", (long long)sz, mtiso, (unsigned long long)h);
}

static int adicionar_varredura_manual(const char *pp_path, const char *arvores_dir, const char *raiz_sisc, size_t root_id)
{
    char pai[32];
    snprintf(pai, sizeof(pai), "%zu", root_id);

    int rc = executar_sa(pp_path, arvores_dir, NULL, "VARREDURA AUTOMÁTICA — assinaturas de comandos e arquivos relacionados a este manual", 0);
    if (rc != 0) return rc;
    rc = executar_sa(pp_path, arvores_dir, pai, "Regra: esta seção é recriada a cada execução; se assinatura/alerta mudar, revisar o ramo correspondente antes de operar", 0);
    if (rc != 0) return rc;
    rc = executar_sa(pp_path, arvores_dir, pai, "Critério: fonte .c mais nova que executável indica recompilação pendente; executável/fonte mais novo que ajuda indica ajuda possivelmente desatualizada", 0);
    if (rc != 0) return rc;

    for (size_t i = 0; i < sizeof(COMANDOS_RELACIONADOS) / sizeof(COMANDOS_RELACIONADOS[0]); i++) {
        const ComandoRelacionado *c = &COMANDOS_RELACIONADOS[i];
        char src[PATH_MAX * 2], exe[PATH_MAX * 2], ajuda[PATH_MAX * 2];
        char sig_src[160], sig_exe[160], sig_ajuda[160];
        snprintf(src, sizeof(src), "%s/core/comandos/%s.c", raiz_sisc, c->nome);
        snprintf(exe, sizeof(exe), "%s/core/comandos/%s", raiz_sisc, c->nome);
        snprintf(ajuda, sizeof(ajuda), "%s/ajuda/%s.json", raiz_sisc, c->nome);
        assinatura_path(src, sig_src, sizeof(sig_src));
        assinatura_path(exe, sig_exe, sizeof(sig_exe));
        assinatura_path(ajuda, sig_ajuda, sizeof(sig_ajuda));
        char alerta[220] = "";
        struct stat st_src, st_exe, st_ajuda;
        int tem_src = stat(src, &st_src) == 0 && S_ISREG(st_src.st_mode);
        int tem_exe = stat(exe, &st_exe) == 0 && S_ISREG(st_exe.st_mode);
        int tem_ajuda = stat(ajuda, &st_ajuda) == 0 && S_ISREG(st_ajuda.st_mode);
        if (tem_src && (!tem_exe || st_src.st_mtime > st_exe.st_mtime)) {
            snprintf(alerta, sizeof(alerta), "; ATENÇÃO: fonte mais nova que executável/script, recompilar antes de operar");
        } else if ((tem_src || tem_exe) && tem_ajuda && ((tem_src ? st_src.st_mtime : st_exe.st_mtime) > st_ajuda.st_mtime)) {
            snprintf(alerta, sizeof(alerta), "; atenção: ajuda possivelmente desatualizada, rode pp --atualizar-ajuda-comandos=%s", c->nome);
        }
        char texto[1600];
        snprintf(texto, sizeof(texto), "%s — %s; flags-chave: %s; fonte: %s; executável/script: %s; ajuda: %s%s", c->nome, c->papel, c->flags, sig_src, sig_exe, sig_ajuda, alerta);
        rc = executar_sa(pp_path, arvores_dir, pai, texto, 0);
        if (rc != 0) return rc;
    }

    for (size_t i = 0; i < sizeof(ARQUIVOS_RELACIONADOS) / sizeof(ARQUIVOS_RELACIONADOS[0]); i++) {
        char path[PATH_MAX * 2], sig[180], texto[1600];
        snprintf(path, sizeof(path), "%s/%s", raiz_sisc, ARQUIVOS_RELACIONADOS[i]);
        assinatura_path(path, sig, sizeof(sig));
        snprintf(texto, sizeof(texto), "Arquivo relacionado: %s — %s", ARQUIVOS_RELACIONADOS[i], sig);
        rc = executar_sa(pp_path, arvores_dir, pai, texto, 0);
        if (rc != 0) return rc;
    }
    return 0;
}

static int adicionar_inspecao_codigo_fonte(const char *pp_path, const char *arvores_dir, const char *raiz_sisc, size_t root_id)
{
    char pai[32];
    snprintf(pai, sizeof(pai), "%zu", root_id);

    int rc = executar_sa(pp_path, arvores_dir, NULL, "CÓDIGO-FONTE LIDO NESTA GERAÇÃO — manual GC derivado do estado atual dos comandos, ajudas e arquivos", 0);
    if (rc != 0) return rc;
    rc = executar_sa(pp_path, arvores_dir, pai, "LEI FONTE-CÓDIGO: estes comandos só podem pesquisar arquivos integrantes do código de funcionamento do SISC: fontes C/H/PHP/scripts, comandos, ajudas JSON, specs JSON, agentes JSON, manifestos, formatos, catálogos, runtimes e configs operacionais. É proibido usar como fonte JSONs de contexto/entendimento/artefatos gerados, como arvores/operador-manual-*.json e arvores/reversao-gc.json.", 0);
    if (rc != 0) return rc;
    rc = executar_sa(pp_path, arvores_dir, pai, "Garantia operacional: esta seção é produzida lendo apenas arquivos classificados pela lei como código-fonte/contrato/configuração operacional no momento da invocação; não é texto fixo do roteiro", 0);
    if (rc != 0) return rc;

    for (size_t i = 0; i < sizeof(COMANDOS_RELACIONADOS) / sizeof(COMANDOS_RELACIONADOS[0]); i++) {
        char texto[3600];
        md_resumir_comando(raiz_sisc, COMANDOS_RELACIONADOS[i].nome, texto, sizeof(texto));
        rc = executar_sa(pp_path, arvores_dir, pai, texto, 0);
        if (rc != 0) return rc;
    }
    for (size_t i = 0; i < sizeof(ARQUIVOS_RELACIONADOS) / sizeof(ARQUIVOS_RELACIONADOS[0]); i++) {
        char texto[3000];
        md_resumir_arquivo_rel(raiz_sisc, ARQUIVOS_RELACIONADOS[i], texto, sizeof(texto));
        rc = executar_sa(pp_path, arvores_dir, pai, texto, 0);
        if (rc != 0) return rc;
    }
    return 0;
}

static const ItemArvore ITENS[] = {
    {NULL, "INÍCIO — operador decide atualizar o sistema com GC do pp --sa"},
    {"1", "Objetivo: concentrar pedido, contexto, itens impactados e execução LLM em um Grupo de Comentário rastreável"},
    {"1", "Regra absoluta: trabalhar dentro do sistema atual: cd /var/www/html/sisc/<sistema>"},
    {"1", "Não editar JSON de árvores manualmente; toda preparação do GC deve usar pp --sa"},
    {"1", "Não usar prompt solto quando houver risco de alteração ampla; organizar pedido em --gc, --mm e --itens"},
    {"1", "Lembrar: cada árvore aceita no máximo um GC ativo; limpe ou conclua o GC anterior antes de abrir outro"},
    {"1", "Próximo: escolher árvore e escopo"},

    {NULL, "1 → ESCOLHER ÁRVORE, ESCOPO E ALVOS"},
    {"2", "Identificar a árvore de trabalho: arvores/<arvore>.json"},
    {"2", "Visualizar a árvore: pp --sa=<arvore>"},
    {"2", "Procurar itens relacionados: pp --sa=<arvore> --proc=<termo>"},
    {"2", "Listar IDs dos itens que devem receber a diretiva; anotar item principal e itens de referência"},
    {"2", "Se houver arquivos relevantes, associar ou conferir referências --ra nos itens antes de chamar o prompt"},
    {"2", "DECISÃO — existe item principal claro para receber o GC?"},
    {"2.6.1", "SIM: seguir para criação do GC no item principal"},
    {"2.6.2", "NÃO: criar um galho organizador via pp --sa=<arvore> --ag=<tema> --em=<pai> ou refinar escopo"},

    {NULL, "2 → CRIAR O GC NO ITEM PRINCIPAL"},
    {"3", "Comando base: pp --sa=<arvore> --gc=<nome-gc> --mm='<pedido objetivo>' --em=<id-principal> --itens=<ids-relacionados>"},
    {"3", "Usar nome de GC curto e sem ambiguidade, por exemplo gc-publicacao-interna ou gc-corrigir-design"},
    {"3", "A mensagem --mm deve conter objetivo, restrições, critérios de aceite e o que não deve ser alterado"},
    {"3", "Em --itens, informar IDs de referência, moldes, dependências e áreas impactadas separados por vírgula"},
    {"3", "Exemplo: pp --sa=siscore --gc=gc-public-agentes --mm='incluir public interno nos agentes 2,3,4 sem alterar pipeline central' --em=1.2 --itens=5.6,6.8"},
    {"3", "Após criar, visualizar a árvore e conferir se o GC aparece no item certo"},
    {"3", "Próximo: enriquecer contexto do GC"},

    {NULL, "3 → ENRIQUECER O GC COM MENSAGENS ADICIONAIS"},
    {"4", "Adicionar detalhes ao mesmo GC: pp --sa=<arvore> --gc=<nome-gc> --mm='<nova instrução>'"},
    {"4", "Usar mensagens separadas para: objetivo, restrições, arquivos/paths, critérios de aceite, dúvidas conhecidas"},
    {"4", "Quando o escopo envolver múltiplos itens, também é possível aplicar --mm em lista: pp --sa=<arvore> --mm='<nota>' --em=<id1,id2> --gc=<nome-gc> --itens=<ids>"},
    {"4", "Evitar mensagens vagas como 'melhore isso'; preferir comandos verificáveis"},
    {"4", "Se a diretiva depender de arquivos, garantir --ra nos itens correspondentes antes do prompt"},
    {"4", "DECISÃO — o GC está completo e auditável?"},
    {"4.6.1", "SIM: seguir para revisão pré-prompt"},
    {"4.6.2", "NÃO: continuar adicionando mensagens ou reorganizar itens da árvore"},

    {NULL, "4 → REVISÃO PRÉ-PROMPT E SEGURANÇA"},
    {"5", "Abrir a árvore completa: pp --sa=<arvore>"},
    {"5", "Conferir: item principal, nome do GC, mensagens, itens relacionados e referências de arquivo"},
    {"5", "Verificar estado Git antes da execução: git status --short"},
    {"5", "Se houver mudanças não relacionadas, commitar ou isolar antes do --prompt"},
    {"5", "Ler ajuda específica quando necessário: pp --sa --ajuda:gc"},
    {"5", "DECISÃO — ambiente está limpo e pedido está seguro?"},
    {"5.6.1", "SIM: executar --prompt"},
    {"5.6.2", "NÃO: ajustar árvore/arquivos ou cancelar com pp --sa=<arvore> --lgc=<nome-gc>"},

    {NULL, "5 → EXECUTAR O PROMPT DO GC"},
    {"6", "Comando padrão: pp --sa=<arvore> --prompt=<nome-gc>"},
    {"6", "Para comparação de contexto: pp --sa=<arvore> --prompt=<nome-gc> --rel"},
    {"6", "O --prompt faz checkpoint GitHub antes, monta prompt determinístico do GC, chama --parallm e aciona agente-at"},
    {"6", "O material de reversão fica em arvores/reversao-gc.json"},
    {"6", "O agente-at pode registrar auditoria em tarefas/agente-at/; em sucesso mantém relatório e limpa temporários"},
    {"6", "Durante a execução, não editar manualmente os mesmos arquivos"},
    {"6", "Próximo: verificar resultado"},

    {NULL, "6 → VERIFICAR RESULTADO E ARQUIVOS ALTERADOS"},
    {"7", "Conferir saída do comando e relatório: tarefas/agente-at/<execucao>/relatorio-execucao.json quando houver"},
    {"7", "Verificar Git: git status --short"},
    {"7", "Reabrir árvore alvo: pp --sa=<arvore>"},
    {"7", "Abrir árvore de reversão: pp --sa=arvores/reversao-gc"},
    {"7", "Conferir no checkpoint: arquivos commitados e arquivos alterados após o checkpoint que podem ser perdidos"},
    {"7", "Executar validações específicas: testes, pp --divergencia-sistema ou comandos pertinentes"},
    {"7", "DECISÃO — atualização ficou correta?"},
    {"7.7.1", "SIM: seguir para fechamento do GC"},
    {"7.7.2", "NÃO: decidir entre reverter ou abrir nova mensagem de correção no mesmo GC"},

    {NULL, "7 → SE PRECISAR REVERTER"},
    {"8", "Antes de reverter, revisar arvores/reversao-gc.json e confirmar arquivos que podem ser perdidos"},
    {"8", "Comando de reversão: pp --sa=<arvore> --reverter=<nome-gc>"},
    {"8", "A reversão usa o checkpoint registrado antes do --prompt"},
    {"8", "Após reverter, verificar git status --short e reabrir a árvore alvo"},
    {"8", "Se a falha foi de escopo, ajustar --mm no GC ou limpar e recriar GC menor"},
    {"8", "DECISÃO — reversão resolveu?"},
    {"8.6.1", "SIM: documentar motivo e seguir para fechamento"},
    {"8.6.2", "NÃO: investigar manualmente antes de novo --prompt"},

    {NULL, "8 → FECHAR OU CONTINUAR O GC"},
    {"9", "Se aprovado, limpar o GC da árvore: pp --sa=<arvore> --lgc=<nome-gc>"},
    {"9", "Se precisar de nova rodada, adicionar mensagem objetiva: pp --sa=<arvore> --gc=<nome-gc> --mm='<correção específica>'"},
    {"9", "Rodar novo --prompt somente após revisar escopo e git status"},
    {"9", "Registrar decisão humana em documentação do sistema ou item da árvore quando necessário"},
    {"9", "Não apagar arvores/reversao-gc.json enquanto houver possibilidade de reversão"},
    {"9", "Próximo: manutenção de histórico"},

    {NULL, "9 → MANUTENÇÃO DO HISTÓRICO DE REVERSÃO E TAREFAS"},
    {"10", "Consultar checkpoints: pp --sa=arvores/reversao-gc"},
    {"10", "Quando um checkpoint não for mais necessário, remover seu item: pp --sa=arvores/reversao-gc --dg=<id-checkpoint>"},
    {"10", "Ao remover checkpoint da árvore reversao-gc, o --sa também limpa checkpoints legados análogos em tarefas/sa-checkpoints/ quando existirem"},
    {"10", "Não apagar tarefas/agente-at/ sem política de retenção; ali ficam relatórios de auditoria de execução"},
    {"10", "Sugestão operacional: manter os últimos checkpoints relevantes e limpar material antigo já validado"},
    {"10", "FIM — atualização organizada, auditável e reversível concluída"},
};

int main(int argc, char **argv)
{
    if (argc > 2 || (argc == 2 && strcmp(argv[1], "--ajuda") && strncmp(argv[1], "--ajuda:", 8) && strcmp(argv[1], "--help") && strcmp(argv[1], "-h"))) {
        uso();
        return 1;
    }
    if (argc == 2) {
        uso();
        return 0;
    }

    char raiz_sisc[PATH_MAX];
    if (localizar_raiz_sisc(raiz_sisc, sizeof(raiz_sisc)) != 0) {
        fprintf(stderr, "atualizar-manual-gc: nao foi possivel localizar a raiz sisc.\n");
        return 1;
    }

    char pp_path[PATH_MAX * 2], arvores_dir[PATH_MAX * 2], arvore_path[PATH_MAX * 2];
    snprintf(pp_path, sizeof(pp_path), "%s/pp", raiz_sisc);
    snprintf(arvores_dir, sizeof(arvores_dir), "%s/arvores", raiz_sisc);
    snprintf(arvore_path, sizeof(arvore_path), "%s/operador-manual-gc.json", arvores_dir);

    if (access(pp_path, X_OK) != 0) {
        fprintf(stderr, "atualizar-manual-gc: pp nao executavel em %s\n", pp_path);
        return 1;
    }
    if (mkdir_p(arvores_dir) != 0) {
        fprintf(stderr, "atualizar-manual-gc: nao foi possivel criar/acessar %s\n", arvores_dir);
        return 1;
    }

    if (unlink(arvore_path) != 0 && errno != ENOENT) {
        fprintf(stderr, "atualizar-manual-gc: nao foi possivel remover arvore antiga: %s: %s\n", arvore_path, strerror(errno));
        return 1;
    }

    size_t total = sizeof(ITENS) / sizeof(ITENS[0]);
    for (size_t i = 0; i < total; i++) {
        int rc = executar_sa(pp_path, arvores_dir, ITENS[i].pai, ITENS[i].texto, i == 0);
        if (rc != 0) {
            fprintf(stderr, "atualizar-manual-gc: falha ao criar item %zu via pp --sa (codigo %d): %s\n", i + 1, rc, ITENS[i].texto);
            return rc;
        }
    }

    size_t root_id_varredura = 1;
    for (size_t i = 0; i < total; i++) if (!ITENS[i].pai) root_id_varredura++;
    int rc_varredura = adicionar_varredura_manual(pp_path, arvores_dir, raiz_sisc, root_id_varredura);
    if (rc_varredura != 0) {
        fprintf(stderr, "atualizar-manual-gc: falha ao adicionar varredura automatica (codigo %d)\n", rc_varredura);
        return rc_varredura;
    }

    int rc_codigo = adicionar_inspecao_codigo_fonte(pp_path, arvores_dir, raiz_sisc, root_id_varredura + 1);
    if (rc_codigo != 0) {
        fprintf(stderr, "atualizar-manual-gc: falha ao adicionar inspecao dinamica de codigo (codigo %d)\n", rc_codigo);
        return rc_codigo;
    }

    printf("Árvore manual de GC atualizada via pp --sa: %s\n", arvore_path);
    printf("Itens base gravados: %zu\n", total);
    printf("Varredura automática gravada: sim\n");
    printf("Inspeção dinâmica de código gravada: sim\n");
    printf("Visualize com: pp --sa=%s\n", arvore_path);
    return 0;
}
