{
  "schemaVersion": 1,
  "produto": "SIGCOT",
  "tipo": "Caso técnico com extratos sanitizados",
  "verificado_em": "2026-10-30",
  "autor": "Jeremias Cardoso",
  "relacao_comercial": "Sistema interno desenvolvido pelo autor do Fluxonar para o centro de operação em que trabalha; não é oferecido à venda.",
  "revisao_codigo": "746c808d02229f18bd5c25446db4474279036d45",
  "metodo": "Leitura do código e da documentação do repositório (somente leitura). Nenhum banco operacional foi consultado; os números de banco, frota e testes vêm dos registros do próprio repositório. Os trechos abaixo são literais, exceto as substituições entre colchetes.",
  "contagem_linhas": {
    "regra": "Arquivos versionados (git ls-files) no commit acima. Linha de código: linha não branca que não é só comentário (// e /* */ em Java e CSS; <!-- --> em FXML; -- em SQL). aplicacao_java = src/main/java; testes_java = src/test/java; telas_fxml e estilos_css = src/main; scripts_migracao_sql = docs/migracao-sqlserver.",
    "categorias": {
      "aplicacao_java": {
        "arquivos": 822,
        "linhas_fisicas": 257195,
        "linhas_nao_brancas": 233783,
        "linhas_de_codigo": 180494
      },
      "telas_fxml": {
        "arquivos": 80,
        "linhas_fisicas": 17243,
        "linhas_nao_brancas": 15826,
        "linhas_de_codigo": 14380
      },
      "estilos_css": {
        "arquivos": 30,
        "linhas_fisicas": 14558,
        "linhas_nao_brancas": 12831,
        "linhas_de_codigo": 9921
      },
      "testes_java": {
        "arquivos": 872,
        "linhas_fisicas": 163531,
        "linhas_nao_brancas": 143475,
        "linhas_de_codigo": 126793
      },
      "scripts_migracao_sql": {
        "arquivos": 98,
        "linhas_fisicas": 17411,
        "linhas_nao_brancas": 16513,
        "linhas_de_codigo": 11137
      }
    },
    "maior_arquivo_java": {
      "arquivo": "src/main/java/com/sigo/controller/PreOperacaoController.java",
      "linhas_fisicas": 7910
    },
    "versoes_no_historico": 174,
    "classes_de_teste_de_contrato": 100
  },
  "substituicoes": [
    "[conta de serviço]",
    "[banco corporativo]",
    "[arquivo .accdb]",
    "[banco de ensaio]",
    "[nome da estação]",
    "[nome de instalação com til]",
    "[pasta local]"
  ],
  "limites": [
    "Não é laudo independente de segurança, desempenho ou conformidade regulatória.",
    "Não há medida de tempo economizado, SIs por dia ou ganho de produtividade no repositório; o texto não afirma ganho.",
    "O clone usado tem um commit só; a evolução no tempo vem das datas escritas nos documentos, não do histórico do git.",
    "Não se publicam nomes da empresa, de pessoas, de instalações, de servidores, de bancos, de estações, contas, caminhos de rede nem detalhes de segurança da infraestrutura."
  ],
  "alegacoes": [
    {
      "id": "versao-atual",
      "alegacao": "Versão atual 2.13.1.",
      "arquivo": "src/main/java/com/sigo/util/VersaoSigo.java",
      "linhas": [
        20,
        20
      ],
      "trecho": "    public static final String VERSAO_ATUAL = \"2.13.1\";"
    },
    {
      "id": "versao-base",
      "alegacao": "O histórico de versões começa na 2.0.05.",
      "arquivo": "src/main/java/com/sigo/util/VersaoSigo.java",
      "linhas": [
        1491,
        1492
      ],
      "trecho": "        new Item(\"2.0.05\",\n            \"Versão base — ponto de partida do controle de versão do SIGCOT.\")"
    },
    {
      "id": "testes-5580",
      "alegacao": "5.580 testes, nenhuma falha, em 27/10/2026.",
      "arquivo": "estado/artefatos/t41-fechamento-2026-10-27.md",
      "linhas": [
        40,
        40
      ],
      "trecho": "Suíte completa com `clean` no commit `54fb5155f41ff8d4710362cf45dbd36c15ef0bc2`: 5580 testes, 0 falhas,"
    },
    {
      "id": "testes-980",
      "alegacao": "980 testes em 22/07/2026.",
      "arquivo": "estado/estado.json",
      "linhas": [
        1128,
        1128
      ],
      "trecho": "…ste' mesmo quando a falha real era lock de rede. VALIDACAO: 980 testes verdes; boot contra copia do banco de producao…"
    },
    {
      "id": "testes-1863",
      "alegacao": "1.863 testes em 17/08/2026, cerca de 9 minutos.",
      "arquivo": "README.md",
      "linhas": [
        56,
        56
      ],
      "trecho": "Em 17/08/2026: **1.863 testes, 0 falhas, 44 skips** — cerca de 9 minutos."
    },
    {
      "id": "testes-2817-data",
      "alegacao": "Roteiro da 2.0.146 gerado em 10/09/2026.",
      "arquivo": "LEIA-ME-TESTE-2.0.146.txt",
      "linhas": [
        2,
        3
      ],
      "trecho": " SIGCOT 2.0.146 - ROTEIRO DE TESTE\n Gerado em 10/09/2026"
    },
    {
      "id": "testes-2817",
      "alegacao": "2.817 testes na 2.0.146.",
      "arquivo": "LEIA-ME-TESTE-2.0.146.txt",
      "linhas": [
        22,
        22
      ],
      "trecho": "  Suite     : 2817 testes, 0 falhas, 0 erros, 44 pulados"
    },
    {
      "id": "testes-4380",
      "alegacao": "4.380 testes na 2.9.0.",
      "arquivo": "LEIA-ME-TESTE-2.9.0.txt",
      "linhas": [
        14,
        14
      ],
      "trecho": "  Suite     : 4380 testes, 0 falhas, 0 erros, 42 pulados (allowlist);"
    },
    {
      "id": "frota",
      "alegacao": "61 estações na frota (47 + 14) e 11 sessões ativas em 26/10/2026.",
      "arquivo": "estado/artefatos/leituras-liberacao-2131-2026-10-26.md",
      "linhas": [
        17,
        18
      ],
      "trecho": "- Grade 2: 11 sessoes ativas.\n- Grade 3b (frota): 47 estacoes na 2.12.1 e 14 na 2.11.2. Nenhuma na 2.13.0 nem na 2.13.1."
    },
    {
      "id": "banco-tamanho",
      "alegacao": "Backup de 25/10/2026: 142 tabelas, 297.323 linhas, 5.460.520 bytes.",
      "arquivo": "estado/artefatos/leituras-liberacao-2131-2026-10-26.md",
      "linhas": [
        27,
        27
      ],
      "trecho": "- Grade 11: backup de 25/10/2026 23:00 OK (estacao [nome da estação]; 142 tabelas, 297323 linhas, 5460520 bytes)."
    },
    {
      "id": "arquivo-19mb-vpn",
      "alegacao": "Antes da virada, o sistema abria um arquivo de 19 MB pela VPN.",
      "arquivo": "docs/migracao-sqlserver/PIT-STOP-2026-09-11-COMUNICADO.txt",
      "linhas": [
        5,
        9
      ],
      "trecho": "Neste fim de semana o SIGCOT passa a usar o banco de dados corporativo (SQL Server), no\nlugar do arquivo Access que ficava na pasta de rede. Na prática, isso resolve o problema\nde quem acessa de fora do escritório: o sistema deixa de abrir um arquivo de 19 MB pela\nVPN e passa a conversar com o servidor — o acesso fica leve e estável, inclusive de outros\nestados."
    },
    {
      "id": "limite-15",
      "alegacao": "Limite duro de 15 clientes simultâneos no arquivo compartilhado; concorrência entre processos.",
      "arquivo": "README.md",
      "linhas": [
        12,
        13
      ],
      "trecho": "> ⚠️ O banco é um `.accdb` compartilhado em rede, com **limite duro de 15 clientes simultâneos**.\n> Concorrência aqui é entre processos, não entre threads — teste numa JVM só não cobre o caso real."
    },
    {
      "id": "teste-estacoes-concorrentes",
      "alegacao": "Quatro estações cadastrando a mesma ocorrência: uma trava do banco deixa passar só uma.",
      "arquivo": "estado/estado.json",
      "linhas": [
        5995,
        5995
      ],
      "trecho": "…com estacoes de verdade (salvar o PM que tira o passo enquanto outra executa; reprovar na conferencia e cancelar a SI no mesmo instante, so um vence; quatro estacoes cadastrando a mesma ocorrencia, o sp_getapplock deixa uma so). Nenhum defeito achado. Ficam de fora …"
    },
    {
      "id": "ponteiro-banco",
      "alegacao": "Estações abriam bancos diferentes; endereço passou a vir de ponteiro central, cópia de reserva e cache local.",
      "arquivo": "src/main/java/com/sigo/util/BancoLocator.java",
      "linhas": [
        19,
        31
      ],
      "trecho": " * Fonte da verdade do CAMINHO do banco (.accdb), independente do\n * {@code config.properties} de cada estação.\n *\n * <p><b>Por que existe:</b> o {@code config-prod.properties} era distribuído por\n * estação/versão e saiu de sincronia (uma estação abria {@code [arquivo .accdb]},\n * outra {@code [arquivo .accdb]} → parecia \"sumiço de dados\"). Aqui o caminho fica num\n * <b>ÚNICO arquivo central na rede</b> que todas as estações leem; o admin define\n * pela tela (sem editar arquivo, sem recompilar). Um <b>cache local</b> serve de\n * reserva se a rede cair no boot. Solução-ponte até a migração para SQL.\n *\n * <p>Resolução: <b>ponteiro central</b> (rede) → <b>cópia do SharePoint</b> → <b>cache local</b>.\n * Quando lê o central com sucesso, atualiza o cache local (mantém a reserva fresca) e apaga a cópia\n * do SharePoint."
    },
    {
      "id": "fx-thread-297",
      "alegacao": "297 pontos síncronos na thread da tela em 22/06/2026.",
      "arquivo": "docs/avaliacao/INVENTARIO-FXTHREAD-2026-06-22.md",
      "linhas": [
        7,
        8
      ],
      "trecho": "## Contagens\n- **Sincronos confirmados: 297** | Ja async: 140 | **~32% async (~68% da divida ainda na FX-thread)**"
    },
    {
      "id": "vigia-200ms",
      "alegacao": "Vigia da thread da tela com limiar padrão de 200 ms.",
      "arquivo": "src/main/java/com/sigo/util/VigiaFxThread.java",
      "linhas": [
        63,
        63
      ],
      "trecho": "    public static final long LIMIAR_PADRAO_MS = 200L;"
    },
    {
      "id": "mvc-erodido",
      "alegacao": "Avaliação de código: MVC erodido.",
      "arquivo": "docs/avaliacao/AVALIACAO-CODIGO-SIGCOT.md",
      "linhas": [
        9,
        9
      ],
      "trecho": "**Estilo declarado:** MVC em camadas (`controller` / `dao` / `model` / `service` / `util` / `erro` / `migracoes`). **Estilo real:** MVC erodido para *Smart-UI / Transaction Script* — a regra de negocio vazou para os controllers."
    },
    {
      "id": "premissa-27-08",
      "alegacao": "Em 27/08/2026 a premissa do plano de 18/08 caiu em quatro pontos.",
      "arquivo": "docs/migracao-sqlserver/PLANO-DE-MIGRACAO.md",
      "linhas": [
        8,
        17
      ],
      "trecho": ">\n> Em **27/08/2026** a TI enviou os manuais de conexão e a infraestrutura real apareceu. Ela não é\n> a que este documento assumiu:\n>\n> | | assumido aqui (18/08) | o que é (27/08) |\n> |---|---|---|\n> | banco | dedicado ao SIGCOT | **[banco corporativo], compartilhado** com outros projetos |\n> | fronteira | o banco | **o schema `[sigcot]`** |\n> | collation | pediríamos na criação | o [banco corporativo] já existe; não é nosso para pedir |\n> | versão | pergunta em aberto | **SQL Server 2019** |"
    },
    {
      "id": "collation",
      "alegacao": "Sem collation declarada, a mesma busca devolveu 0 linhas num banco e 1 no outro.",
      "arquivo": "docs/migracao-sqlserver/PLANO-DE-TRANSICAO.md",
      "linhas": [
        82,
        87
      ],
      "trecho": "**1. Coluna sem `COLLATE` herda o collation do banco.** O mesmo `CREATE TABLE` do `SIGCOT-01`,\nrodado em dois bancos idênticos exceto pelo collation, produziu colunas `CI_AS` num e `CI_AI` no\noutro. Com o dado gravado byte a byte igual (codepoint 227 para o `ã`), buscar `[nome de instalação com til]`\nsem o til devolveu **0 linhas no `CI_AS` e 1 no `CI_AI`**. Os quatro scripts têm **zero** cláusulas\n`COLLATE`, e as **723 colunas de texto** vão herdar o que o [banco corporativo] tiver. O remédio, também provado:\n`COLLATE` explícito na coluna vence o padrão do banco."
    },
    {
      "id": "ativo-menos-um",
      "alegacao": "Comparar campo lógico com -1 não acha nada no SQL Server; a PV sairia R$ 0,00; corrigido em 04/09.",
      "arquivo": "docs/migracao-sqlserver/PLANO-DE-TRANSICAO.md",
      "linhas": [
        473,
        481
      ],
      "trecho": "> 2. **Dois defeitos esperam a carga para mentir** (tarefa 107): `ativo = -1` em\n>    `CalculadoraPvDAO:45` e `GeroDAO:74` nunca casa com `BIT` — o tradutor converte as palavras\n>    `true`/`false`, não o `-1`; a frase compila e devolve zero, e a PV sai **R$ 0,00**. E o\n>    `DEFAULT` de `ativo` está **invertido** em 10 colunas (Access `TRUE`, `SIGCOT-01` `0`): carga\n>    que omita `ativo` cria linha inativa, a contagem por linha **bate**, e usuário assim não entra.\n>    Regra: a carga **sempre** escreve `ativo`; a conferência **sempre** conta por `ativo = 1`.\n>    **Feito em 04/09 (tarefa 107):** os dois `-1` viraram `true`, com teste que varre `src/main`\n>    inteiro. E o `DEFAULT 0` **fica**: a Lição #57 (`AtivoRapDAO:76`) já media que o Access\n>    *não aplica* o `DEFAULT TRUE` que declara, e todos os 14 `INSERT` do app escrevem `ativo` —"
    },
    {
      "id": "tradutor-central",
      "alegacao": "Tradutor central na conexão em vez de reescrever 98 arquivos.",
      "arquivo": "docs/migracao-sqlserver/PLANO-DE-TRANSICAO.md",
      "linhas": [
        236,
        239
      ],
      "trecho": "> 1. **Tradutor central na conexão**, não reescrita dos 98 arquivos. `TradutorSql` traduz a frase\n>    final na fronteira (`sigcot.` nas tabelas, `true/false` → `1/0`, `Now()` → `GETDATE()`,\n>    `UCase` → `UPPER`), fora de literais e comentários, idempotente; `ConexaoTraduzida` é o proxy\n>    que o `ConexaoDB.conectar` devolve para toda URL `jdbc:sqlserver:`."
    },
    {
      "id": "corpus-727",
      "alegacao": "727 frases SQL: 716 compilam, 3 falhas reais (nenhuma do tradutor), 8 inconclusivas.",
      "arquivo": "docs/migracao-sqlserver/PLANO-DE-TRANSICAO.md",
      "linhas": [
        246,
        250
      ],
      "trecho": "> **Fatia 1 entregue em 03/09.** A prova é mecânica: `CorpusSql` extrai cada frase do próprio Java\n> (constantes resolvidas, ternários expandidos) e `ProvarCorpusSql` a compila **sem executar** no\n> SQL Server 2019 local com as 99 tabelas. Resultado: **727 frases, 716 compilam, 3 falhas reais\n> e 8 inconclusivas** — e nenhuma das 3 é do tradutor: duas são as tabelas do Escala (decisão da\n> TI) e uma é código morto (`tb_regras_ui`). Evidência em"
    },
    {
      "id": "pit-stop",
      "alegacao": "Rejeição de dois bancos vivos sincronizados; ensaio sobre cópia; virada com todos fora e conferência por contagem.",
      "arquivo": "docs/migracao-sqlserver/PLANO-DE-TRANSICAO.md",
      "linhas": [
        438,
        456
      ],
      "trecho": "> ### A virada é um **pit stop**, não uma troca de pneu com o carro andando\n>\n> A distinção foi acertada com o Jeremias em 04/09 e é a que separa as duas formas de fazer isto:\n>\n> **O antipadrão, que é justamente o tentador:** manter os dois bancos vivos ao mesmo tempo, com\n> gente trabalhando no `.accdb` enquanto o [banco corporativo] é sincronizado por baixo. Alguém salva uma SI\n> depois da extração, a virada acontece, e aquela SI deixa de existir — **sem erro, sem log e sem\n> ninguém perceber** até a pessoa procurar. É a mesma família do incidente de 03/08/2026: o sistema\n> segue achando que está certo.\n>\n> **O que se faz em vez disso:**\n>\n> - **O ensaio roda com o carro andando, e sem risco:** extrai-se uma cópia do `.accdb`, carrega-se\n>   no [banco corporativo] e testa-se o sistema inteiro com dado real, enquanto a produção segue no Access,\n>   intocada. Se der errado, ninguém sente.\n> - **A virada é o pit stop:** todos fora do sistema, retrato final, recarga, conferência por\n>   contagem, estações apontadas, liberado. Curto **porque o trabalho já está feito** — schema de\n>   pé e conferido, conexão provada, tradutor funcionando. No dia da virada não sobra nada para\n>   descobrir: só copiar dado e conferir número."
    },
    {
      "id": "cura-real",
      "alegacao": "Em julho de 2026 o projeto já registrava a decisão fechada de trocar o banco.",
      "arquivo": "docs/leva-campo-2026-07/PLANO.md",
      "linhas": [
        45,
        45
      ],
      "trecho": "conversa com a decisão fechada \"cura real = trocar o banco\""
    },
    {
      "id": "ensaio-47619",
      "alegacao": "Carga de ensaio: 47.619 linhas em 87 tabelas.",
      "arquivo": "estado/artefatos/t104-ensaio-na-estacao-2026-09-06.md",
      "linhas": [
        48,
        48
      ],
      "trecho": "Segunda geração, 22:45, **código 0**: 47.619 linhas em 87 tabelas, 633 lotes, aprovado pela guarda"
    },
    {
      "id": "virada-11-09",
      "alegacao": "Virada na noite de 11/09/2026; operação na 2.0.146; campo a partir de 14/09.",
      "arquivo": "docs/migracao-sqlserver/0-ESTADO-DOS-PEDIDOS.txt",
      "linhas": [
        20,
        25
      ],
      "trecho": "*** FATO DE 11/09/2026 (noite) - PIT STOP EXECUTADO ***\n  A virada do Access para o [banco corporativo] aconteceu: Gerar-Carga --recarga, Aplicar\n  --carga e Conferir-Carga com codigo 0 nos tres (relato do Jeremias; os\n  relatorios chegam em 14/09). O COT ja opera na 2.0.146 sobre o [banco corporativo]; o\n  campo entra a partir de 14/09 pelo Instalar-SIGCOT.cmd da pasta de rede.\n  O [arquivo .accdb] ficou CONGELADO (renomeado) como artefato de rollback."
    },
    {
      "id": "aposentadoria-16-09",
      "alegacao": "Access aposentado em 16/09/2026: novas versões em Access não voltam; o arquivo congelado vira histórico.",
      "arquivo": "docs/migracao-sqlserver/PLANO-APOSENTADORIA-ACCESS-E-DATAS-TIPADAS.md",
      "linhas": [
        3,
        5
      ],
      "trecho": "Escrito em 16/09/2026 a partir da decisão do Jeremias, alinhada internamente: **\"novas versões em\n> Access não voltam mais\"**. O `[arquivo .accdb]` congelado no pit stop de 11/09 deixa de ser alvo de\n> rollback e vira arquivo histórico."
    },
    {
      "id": "escala-21989",
      "alegacao": "Carga da escala: 21.989 linhas numa transação, conferida origem contra destino.",
      "arquivo": "docs/migracao-sqlserver/0-ESTADO-DOS-PEDIDOS.txt",
      "linhas": [
        4,
        4
      ],
      "trecho": "…CARGA DA ESCALA FEITA (18:27, +21989 linhas em 5 tabelas, uma transacao) e CONFERIDA (18:28, origem = destino nas seis…"
    },
    {
      "id": "instalacao-local",
      "alegacao": "Instalação local em cada estação e atualização avisada pelo sistema (decisão de 07/09/2026).",
      "arquivo": "docs/migracao-sqlserver/PLANO-DE-TRANSICAO.md",
      "linhas": [
        615,
        620
      ],
      "trecho": "> ### ⭐ Decidido em 07/09/2026 — a Etapa 4 entra na 2.0.143 (tarefas 109, 110 e 111)\n>\n> **O que o Jeremias decidiu.** O app passa a ser **instalado em `[pasta local]` em cada estação**;\n> o pacote publicado fica numa pasta compartilhada; o sistema avisa quando há versão nova e, ao\n> clicar, fecha e um `.cmd` faz a troca; o runtime Java continua embutido no app-image, porque nem\n> toda máquina tem Java. Anexos ficam **fora** do banco (decisão dele; pasta no OneDrive para"
    },
    {
      "id": "rito-script",
      "alegacao": "Toda mudança de estrutura é script numerado, idempotente, validado num SQL Server 2019 local, aplicado pela ferramenta e conferido depois.",
      "arquivo": "docs/migracao-sqlserver/ROTEIRO-PEDIDOS-DE-SCHEMA.md",
      "linhas": [
        9,
        12
      ],
      "trecho": "> schema, `ALTER ANY SCHEMA` concedidas). O que era **pedido à TI** passa a ser **script que a\n> própria equipe aplica**, pelo `Aplicar.cmd` do pacote do conferente, na estação do COT. Tudo o\n> mais neste roteiro continua valendo: script numerado, idempotente, validado no SQL Server 2019\n> local, conferido pelo catálogo depois."
    },
    {
      "id": "sem-ddl",
      "alegacao": "A aplicação não emite DDL; uma pessoa aplica com confirmação digitada.",
      "arquivo": "docs/migracao-sqlserver/ROTEIRO-PEDIDOS-DE-SCHEMA.md",
      "linhas": [
        16,
        17
      ],
      "trecho": "> - **A aplicação continua sem emitir DDL** (ADR-009). Quem aplica é uma pessoa, por ferramenta,\n>   com confirmação digitada. Nunca o SIGO no boot."
    },
    {
      "id": "guarda-escopo",
      "alegacao": "A ferramenta recusa comando fora da área do sistema antes de conectar.",
      "arquivo": "docs/migracao-sqlserver/ROTEIRO-PEDIDOS-DE-SCHEMA.md",
      "linhas": [
        18,
        19
      ],
      "trecho": "O `Aplicar.cmd` recusa qualquer comando\n>   fora do schema `[sigcot]` antes de conectar."
    },
    {
      "id": "adr009",
      "alegacao": "ADR-009: em modo servidor a aplicação não emite DDL.",
      "arquivo": "docs/adr/ADR-009-migrador-sem-ddl.md",
      "linhas": [
        77,
        77
      ],
      "trecho": "**Em modo servidor, a aplicação não emite DDL — por nenhum dos quatro caminhos.** Só isso."
    },
    {
      "id": "adr009-reprovado",
      "alegacao": "A primeira versão do ADR-009 foi reprovada com notas de 7,5 a 8,7 contra corte de 9,5.",
      "arquivo": "docs/adr/ADR-009-migrador-sem-ddl.md",
      "linhas": [
        17,
        18
      ],
      "trecho": "> contrato. Foi a comitê de quatro lentes e **reprovou** — arquiteto-software 7,5 · arquiteto-dados\n> 7,5 · qa-usabilidade 7,5 · dev-senior 8,7, contra nota de corte 9,5 —, com um achado fatal e"
    },
    {
      "id": "largura-31-07",
      "alegacao": "Largura se decide na criação; VARCHAR(100) parou a SI em 31/07/2026; texto livre vai como NVARCHAR(MAX).",
      "arquivo": "docs/migracao-sqlserver/ROTEIRO-PEDIDOS-DE-SCHEMA.md",
      "linhas": [
        105,
        109
      ],
      "trecho": "Alargar campo depois é um chamado; nascer largo é grátis. Este projeto já pagou por isso: em\n31/07/2026 a SI parou de salvar em produção porque `equipamento_nome` era `VARCHAR(100)`.\n\n- Texto que o usuário digita livremente (local, instalação, equipamento, condições, natureza,\n  observação, justificativa) → **`NVARCHAR(MAX)`**."
    },
    {
      "id": "incidente-31-07",
      "alegacao": "Dois erros empilhados: o mascarador e o real.",
      "arquivo": "estado/estado.json",
      "linhas": [
        1311,
        1311
      ],
      "trecho": "            \"detalhe\": \"LEVA 2.0.126, incidente de PRODUCAO 31/07/2026: a SI parou de salvar e o usuario via um AccessDeniedException em runtime\\legal\\java.xml.crypto - pasta de licencas sem relacao nenhuma com o problema. Eram DOIS erros empilhados. (1) MASCARADOR (fechado em codigo): o catch (SQLException) de SolicitacaoDAO.executarQuerySi chamava e.getMessage() direto; a UcanaccessSQLException monta a mensagem varrendo o disco atras do…"
    },
    {
      "id": "incidente-03-08",
      "alegacao": "3 horas sem entrar, 27 reapontagens, 5 arquivos; causa tripla.",
      "arquivo": "estado/estado.json",
      "linhas": [
        2036,
        2036
      ],
      "trecho": "…sem conseguir entrar no SIGCOT e tentou 27 reapontagens com 5 .accdb diferentes. Causa raiz TRIPLA, cada parte tratada. (1) MANIFESTO: o fat-jar do shade nao gravava Implementation-Version, entao o VersionInfo do UCanAccess procurava a propria versao com …"
    },
    {
      "id": "incidente-459",
      "alegacao": "459 ocorrências reduzidas a \"Erro de rede inesperado\".",
      "arquivo": "estado/estado.json",
      "linhas": [
        2036,
        2036
      ],
      "trecho": "…de listagem isso lanca UncheckedIOException, que escapa do catch (IOException) do driver e ENGOLE a SQLException real - 459 ocorrencias reduzidas a 'Erro de rede inesperado'. Fix: manifestEntries…"
    },
    {
      "id": "incidente-07-08",
      "alegacao": "Uma SI não recuperada em 671, em dois meses.",
      "arquivo": "estado/estado.json",
      "linhas": [
        2220,
        2220
      ],
      "trecho": "…ma dos vizinhos de data (128, 134, 202) e o operador percebendo e redigitando. LICAO: a perda e REAL mas RARA, cerca de 1 nao-recuperada em 671 SIs em 2 meses - o que pede guarda barata de deteccao, nao re-arquitetura. ENTREGUE (merge 5e4cf50 …"
    },
    {
      "id": "incidente-rdo",
      "alegacao": "O envio devolvia sucesso por ter lançado o processo, não porque o e-mail saiu.",
      "arquivo": "estado/estado.json",
      "linhas": [
        3924,
        3924
      ],
      "trecho": "…m tocar no mecanismo de envio. A CAUSA REAL e que o log MENTE por construcao. O caminho e MonitorEnvioRdo -> EmailUtil.enviarSilenciosoComAnexo -> gera .vbs -> lanca wscript -> retorna true. O true significa 'consegui lancar o processo', nao 'o e-mail saiu': o dispararWscript nao esperava o processo nem lia o codigo de saida, e o .vbs comecava com On Error Resume Next SEM nenhuma verifi…"
    },
    {
      "id": "incidente-quedas",
      "alegacao": "Quedas 2 a 3 vezes por dia na 2.0.141; sinal de presença desligado na 2.0.142.",
      "arquivo": "estado/estado.json",
      "linhas": [
        4538,
        4538
      ],
      "trecho": "…2.0.142 - quedas 2-3x/dia da 2.0.141: heartbeat de presenca no .accdb desligado, retry por tipo,…"
    },
    {
      "id": "incidente-18-09",
      "alegacao": "O script de 18/09 derrubou a 2.0.147; resposta na 2.0.149; nenhum ALTER COLUMN com estação antiga.",
      "arquivo": "docs/migracao-sqlserver/0-ESTADO-DOS-PEDIDOS.txt",
      "linhas": [
        7,
        18
      ],
      "trecho": "*** FATO DE 18/09/2026 (noite) - O SIGCOT-11 DERRUBOU A 2.0.147; A 148 ENTROU PELO INSTALAR ***\n  Aplicar.cmd 20:30:28 e Conferir.cmd 20:31:14, codigo 0 nos dois (4 colunas\n  NVARCHAR(MAX)). Logo depois, nenhuma estacao abria a 2.0.147: o conferente\n  de schema da propria versao (ConferenteSchema, contrato dentro do jar)\n  classifica diferenca de TAMANHO como BLOQUEIA - mesmo coluna MAIOR - e o\n  boot morre em SchemaServidorException antes do login; a checagem de versao\n  publicada rodava DEPOIS do warm-up e nunca chegou a rodar. Saida: 148\n  publicada pelo card + Instalar-SIGCOT.cmd em cada estacao. A 149 entra pelo\n  atualizador (nao muda schema). Resposta (t146, 2.0.149): conferente\n  assimetrico (so bloqueia o que faz o app errar) + versao conferida na tela\n  de login antes do banco, com atualizacao automatica. REGRA ATE A FROTA\n  ESTAR NA 149: nenhum ALTER COLUMN no [banco corporativo] (ver ROTEIRO-PEDIDOS-DE-SCHEMA.md)."
    },
    {
      "id": "pv-planilha-levada",
      "alegacao": "A planilha de PV da pós-operação foi levada para o sistema.",
      "arquivo": "estado/estado.json",
      "linhas": [
        9156,
        9156
      ],
      "trecho": "…levar o Excel 'Indicador PV' da Pos-Operacao (PV e Disponibilidade) para o SIGCOT, com i…"
    },
    {
      "id": "pv-planilha-tamanho",
      "alegacao": "A planilha tinha 35 abas e cerca de 18 mil fórmulas.",
      "arquivo": "estado/estado.json",
      "linhas": [
        9156,
        9156
      ],
      "trecho": "…o arquivo e .xlsx, sem VBA; 35 abas, 20 graficos, cerca de 18 mil formulas, 94 coment…"
    },
    {
      "id": "skips",
      "alegacao": "Teste só é pulado com motivo, dono e validade.",
      "arquivo": "MEMORIA-PROJETO.md",
      "linhas": [
        131,
        131
      ],
      "trecho": "- Teste desligado exige entrada no allowlist de skips com razão, dono e validade, e o baseline do próprio allowlist sobe junto: o acoplamento é intencional para que skip novo não entre sem alguém olhar."
    },
    {
      "id": "guarda-desligada",
      "alegacao": "Guarda desligada por condição não é guarda.",
      "arquivo": "MEMORIA-PROJETO.md",
      "linhas": [
        58,
        58
      ],
      "trecho": "- Guarda desligada por `Assumptions` não é guarda: a classe sai da suíte com `tests=\"0\"` e o total verde continua subindo, então o relatório afirma cobertura que nunca rodou. As guardas que precisam ser confiáveis moram fora do portão, e o portão fica só para o que realmente exige ambiente especial."
    },
    {
      "id": "release",
      "alegacao": "Release fechado por padrão: suíte, SBOM, SCA e pacote selado por SHA-256.",
      "arquivo": "release.ps1",
      "linhas": [
        5,
        12
      ],
      "trecho": "  Fluxo autorizado:\n    1. valida JDK 21, Maven, jpackage, RetireJS e caches offline;\n    2. congela commit e entradas versionadas;\n    3. executa exatamente um Maven release lifecycle;\n    4. valida suite, harnesses, skips, SBOM, SCA e RetireJS;\n    5. sela target/SIGO.jar por tamanho + SHA-256;\n    6. prova a mesma identidade no input, app-image, pasta final e ZIP;\n    7. publica somente a saida local. Nao faz deploy e nao injeta configuracao."
    },
    {
      "id": "duas-etapas",
      "alegacao": "Publicação em duas etapas; o banco não volta.",
      "arquivo": "MEMORIA-PROJETO.md",
      "linhas": [
        190,
        190
      ],
      "trecho": "- A publicação de versão é **em duas etapas** (decisão do Jeremias, 12/10/2026, para a 2.10.0): primeiro com \"Versão mínima\" vazia (ninguém é obrigado), depois a prova de que **outra** estação subiu sozinha pela rede, e só então republicar o mesmo manifesto com a mínima da versão. Sem a prova numa estação que não é a do administrador, não há segunda etapa: a mínima transforma a estação que não acha o pacote em estação que não entra no SIGCOT. Rollback é republicar o manifesto da versão anterior com a mínima vazia; \"Despublicar\" é o freio de emergência. O banco não volta."
    },
    {
      "id": "rollback-banco",
      "alegacao": "Restaurar o banco compartilhado afetaria outros projetos.",
      "arquivo": "docs/migracao-sqlserver/PLANO-DE-MIGRACAO.md",
      "linhas": [
        230,
        230
      ],
      "trecho": "| **Rollback não pode ser \"restaurar o banco\"** | restaurar o [banco corporativo] derrubaria os outros projetos junto | critério de volta atrás **por dados do schema**, escrito antes do cutover |"
    },
    {
      "id": "access-no-codigo",
      "alegacao": "O driver do Access ainda é dependência do projeto.",
      "arquivo": "pom.xml",
      "linhas": [
        38,
        40
      ],
      "trecho": "            <groupId>io.github.spannm</groupId>\n            <artifactId>ucanaccess</artifactId>\n            <version>5.1.5</version>"
    },
    {
      "id": "access-retirada-a3",
      "alegacao": "A retirada do Access do binário é uma fase do plano (A3).",
      "arquivo": "docs/migracao-sqlserver/PLANO-APOSENTADORIA-ACCESS-E-DATAS-TIPADAS.md",
      "linhas": [
        48,
        48
      ],
      "trecho": "**A3 — Tirar o Access do binário, em duas ondas.** *Onda A3.1 (caminho de execução):* `DestinoBanco.access()`"
    },
    {
      "id": "datas-texto",
      "alegacao": "121 colunas de data como texto contra 51 DATETIME2.",
      "arquivo": "docs/migracao-sqlserver/PLANO-APOSENTADORIA-ACCESS-E-DATAS-TIPADAS.md",
      "linhas": [
        62,
        62
      ],
      "trecho": "**O inventário, do contrato (`esquema-esperado.tsv`):** 121 colunas `NVARCHAR` com nome de data/hora em 40"
    },
    {
      "id": "acessibilidade",
      "alegacao": "Cobertura de rótulos: 4% em 01/08, 47% em 26/09, seis telas de maior uso em 100%.",
      "arquivo": "src/test/java/com/sigo/util/AcessibilidadeTelasContratoTest.java",
      "linhas": [
        151,
        154
      ],
      "trecho": "        // ★ t35 (26/09/2026): as 6 telas de maior uso foram a 100%; a medição foi a 47% e o piso acompanha.\n        assertTrue(cobertura >= 47,\n                \"a cobertura de acessibilidade REGREDIU para \" + cobertura + \"% (medida na \"\n                        + \"auditoria de 01/08: 4%; em 02/09, apos a D4.3: 12%; em 26/09, apos a t35: 47%). Rótulo acessível \""
    },
    {
      "id": "informe-copiar-colar",
      "alegacao": "O informe sai pronto do sistema; o último passo é copiar e colar.",
      "arquivo": "docs/adr/ADR-007-whatsapp-confirmacao-destinos.md",
      "linhas": [
        8,
        9
      ],
      "trecho": "O Inf. COT já nasce pronto no GERO e no Informe WhatsApp, mas o último passo é copiar\ne colar. O operador não deve redigir o texto. Ele só confirma, edita se precisar e"
    }
  ]
}
