Visão executiva
Indicadores consolidados do andamento do projeto
Linha do tempo
Sprints concluídos, em andamento e planejados
Famílias de correção
Estratégia de execução incremental por categoria de risco
Marcação de retificadora (COD_FIN), recálculo do Bloco 9 com auto-referência, contadores X990 e propagação material controlada (C170 → C190 → C100; E110 → E116 com guarda de inversão de regime). Dois gates PVA reais aprovados — S1.0 (07/05) e S1.0b (08/05).
S1.1.A ✓ análise CST entrada read-only experimental fechada (66 testes, ~700 LOC). S1.1.B (próximo) habilita aplicação experimental — bloqueado por desalinhamento entre identificadores @norma: do YAML e filenames em docs/legislacao_md/.
Crédito do ativo permanente, parcela 1/48 e fator mensal de saídas tributadas. Aguarda extensão de schemas G110/G125 (TODO P0+1) antes do início. Estimativa revisada com base na velocidade real do S1.0/S1.0b.
CST IPI, alíquota, base de cálculo e crédito de entrada. Aguarda extensão dos schemas C170 (P0+2) e E520 (P0+3). Estimativa revisada com base na velocidade real.
Riscos ativos
Situações que podem impactar prazo ou escopo
@norma: do YAML não batem com filenamesValidação E2E do S1.1.A revelou que IDs do YAML matriz_cst.yaml não casam por igualdade exata com arquivos em docs/legislacao_md/ — exemplos: Lei_Kandir_LC87_1996 vs LC_87_1996_Kandir.md; Convenio_ICMS_142_2018 vs Convenio_ICMS_142_2018_ST.md; Guia_Pratico_EFD_ICMS_IPI_v3 vs Guia_EFD_ICMS_IPI_v3.2.1.md. Consequência: toda recomendação sai com bloqueada=True e normas=(). Antes do S1.1.B é preciso alinhar os identificadores ou implementar alias map.
Antes do Sprint S1.1.B avançar para CST de saída, é necessário decidir se a categoria C2 (CST ICMS) abrange saída. S1.1.A entregou apenas análise para CST de entrada — escopo recomendado pela documentação canônica P1+1. Se a decisão incluir saída, será necessária implementação de classificar_cst_icms_saida() ainda inexistente.
Bloqueia Sprint S1.2 (Família CIAP). Extensão do REGISTRO_SCHEMAS conforme Guia Prático EFD ICMS/IPI precisa ser executada antes do início do sprint.
Próximos marcos
Cronograma realista com base na velocidade observada de S1.0 e S1.0b. Datas em dias úteis, ajustáveis conforme gates externos (decisões fiscais, entregáveis de identidade visual, validações PVA).
@norma: ↔ filenamesmain + S2 (linguagem natural)Tarefas pendentes e débito técnico
Pré-requisitos formais dos próximos sprints
@norma: em config/matriz_cst.yaml com filenames reais de docs/legislacao_md/, ou implementar alias map deterministico. Pré-requisito do S1.1.B — sem isso, todas as recomendações da matriz CST ficam bloqueadas (bloqueada=True, normas=()).classificar_cst_icms_saida().tasks/REGRA_APURACAO_ICMS_S1_1.md. Define fórmula canônica do E110 conforme Guia v3.2.1: VL_ICMS_RECOLHER = VL_SLD_APURADO − VL_TOT_DED; DEB_ESP entra na coerência posterior com E116. Concluído em 08/05/2026 (commit dc17e69).motor.py (Contribuições): revalidação na entrada com TipoObrigacaoIncompativelError. Hoje só motor_icms_ipi revalida — chamadores diretos do motor de Contribuições dependem implicitamente do roteador.app/parsers/efd_icms_ipi.py: tentar ISO-8859-1 PRIMEIRO em parsers de EFD da ReceitaNetBX (Convênio ICMS 143/2006). Auto-detect probabilístico (chardet) gera replacement chars silenciosos em arquivos grandes.Decisões arquiteturais
Trinta decisões tomadas e registradas no plano canônico (drill-down técnico)
Decisões de escopo e arquitetura geral
Decisões de tipo de dado e schemas
Decisões de preservação byte-a-byte e robustez (D-24 e correlatas)
Decisões de processo, validação e versionamento
Sprints concluídos
Histórico de entregas com hashes de commits e principais resultados
P0 — Pavimentação · 5 relatórios + extração de detectar_encoding
Status: Concluído (GO COM RESSALVAS)
Commits: fc9bf85 · 734c8cf · 7ca75bb
Entregas: Mapeamento de tipos C1-C20, pré-condições normativas, cross-check de schemas, cobertura de utilitários ICMS, resultado consolidado. Identificou que 20 tipos do plano provisório precisavam ser reduzidos a famílias menores (D-18) e que vários schemas precisariam ser estendidos.
Lição-chave: P0 não é "rodar checks", é descoberta. Plano pós-P0 pode ser substancialmente diferente do plano pré-P0.
Pcanon — Plano canônico de retificação
Status: Concluído
Commit: dccd48b
Entrega: Documento de 731 linhas estabelecendo arquitetura, decisões D-1 a D-30, sequência S1.0 a S7, gotchas conhecidas e lições do P0. Vira fonte canônica que sprints seguintes referenciam.
P1+0 — Detector de tipo de obrigação SPED
Status: Concluído
Commits: f0049b4 · 85319fd · 34dd1f0 · f3d7321
Entrega: Módulo app/parsers/_detector_obrigacao.py com duas APIs (bytes e Path), adapter no dashboard preservando vocabulário legado, suite de testes com 30 casos, cobertura 93%. Cenário identificado: A (função pura existente, extração mecânica).
P1+0.1 — Correção de bug crítico no detector (consenso multi-sinal)
Status: Concluído
Commit: 6f8e5e9
Entrega: Refatoração do detector para usar voto por consenso em vez de early-return em sinal único. Bug detectado: fixture base do S1.0 era classificada como Contribuições por causa de DT_INI no campo 5 (sinal 2 disparava antes do sinal 1 de IND_PERFIL).
Lições registradas: L-DET-01 (early-return em sinal único é falso-positivo esperando para acontecer); L-DET-02 (fixtures podem mascarar bugs); L-DET-03 (preservar comportamento durante extração não significa preservar bugs no canônico).
S1.0 — Motor estrutural mínimo (família E) · gate D-20 APROVADO
Status: Concluído (Tentativa 6 ACEITA pelo PVA real em 07/05/2026)
Commits principais: a34f054 (recálculo Bloco 9) · 67d2608 (E1/E2/E3) · e474b56 (motor com defesa em profundidade) · 6841023 (motor universal — roteador) · 0ea68e3 (E2 num_linha real) · 36d4c7e (suite final byte-a-byte) · a7d1e4e (Tentativa 6 — registro 1010 obrigatório) · 8999b32 (Tentativa 6 ACEITA — gate D-20 fechado)
Entregas: motor de retificação EFD ICMS/IPI completo para a família estrutural — marcação de retificadora via COD_FIN (D-IND_SIT), recálculo determinístico do Bloco 9 com auto-referência (D-26), correções E1/E2/E3 estruturais, motor universal com roteamento Contribuições↔ICMS/IPI, suite de testes byte-a-byte completa.
Caminho até o gate D-20: 6 tentativas no PVA. Tentativa 5 confirmou (b9ebe30) que fixtures sintéticas mínimas "nascem condenadas" — solução foi usar EFD real anonimizada com registro 1010 obrigatório (Tentativa 6).
Hash do arquivo aceito: 28cbc41d…0825cf713c · Checkpoint: tag v3.13.0-rc1 (anotada).
S1.0+1 — Cristalização das decisões emergentes
Status: Concluído (07/05/2026, commit 3371c9c)
Entrega: três decisões arquiteturais que emergiram da execução do S1.0 e foram cristalizadas no plano canônico para guiar sprints subsequentes.
Decisões cristalizadas:
· D-31 — schemas do motor cristalizam apenas os índices dos campos efetivamente tocados em cada sprint (ex: 0000 minimalista no S1.0 — só REG/COD_VER/COD_FIN). Razão: layouts variam por versão do Guia e por perfil de obrigação; cristalizar com base em fixture sintética não-padrão gera falso positivo (L-DET-01/02/03 do P1+0.1).
· D-32 — ModificacaoRegistro.num_linha declara sempre posição real 1-based (no original para deletes, no retificado para inserts). num_linha=0 proibido. Reordenações = par delete+insert; duplicatas removidas declaradas na posição da duplicata.
· D-33 — defesa em profundidade dupla na detecção de tipo de obrigação: motor_universal valida no roteador e cada motor especializado revalida na entrada. motor_icms_ipi ✓; motor.py (Contribuições) pendente — TODO T-2.
P1+1 — Regra canônica de apuração ICMS
Status: Concluído (08/05/2026, commit dc17e69)
Entrega: documento canônico tasks/REGRA_APURACAO_ICMS_S1_1.md separa propagação estrutural S1.0b, mérito fiscal S1.1 e ajustes E111. Define a fórmula canônica do E110 conforme Guia v3.2.1: VL_ICMS_RECOLHER = VL_SLD_APURADO − VL_TOT_DED; DEB_ESP entra na coerência posterior com E116.
Recomendações fixadas: C2 inicial cobre apenas CST de entrada (D-22 mantida pendente); C18/E111 fica bloqueado até validar a ordem real do E111 contra Guia + SPED real.
Consequência imediata: revelou bug latente no S1.0b — _recalcular_saldos_e110 somava DEB_ESP em VL_ICMS_RECOLHER, divergindo da fórmula canônica. Mitigado por D-34 (guarda DebEspNaoSuportadoError, commit d9d616e) e registrado como L-35.
S1.1.A — Análise CST entrada read-only experimental · FECHADO
Status: Concluído (08/05/2026, commit final fa1021d)
Commits principais: bc2c8bc (dataclasses ContextoCSTEntrada e RecomendacaoCSTEntrada) · bf54c81 (analisar_cst_icms_entrada read-only com resolução de @norma:) · 326f72f (testes E2E sem mocks contra matriz e docs/legislacao_md/ reais) · fa1021d (registro de saída e critérios de aceite atendidos)
Entregas: ~700 LOC totais (incluindo testes), 66 testes em tests/test_analise_cst_entrada.py. Análise read-only que examina CST de entrada e gera RecomendacaoCSTEntrada com normas resolvidas via registry.
Bloqueio identificado: identificadores @norma: do YAML não casam por igualdade exata com filenames em docs/legislacao_md/ — exemplos: Lei_Kandir_LC87_1996 vs LC_87_1996_Kandir.md; Convenio_ICMS_142_2018 vs Convenio_ICMS_142_2018_ST.md. Consequência: toda recomendação hoje sai com bloqueada=True e normas=(). Pré-requisito explícito do S1.1.B.
Critérios de aceite: 13/13 atendidos (incluindo workaround documentado para CPython gh-91054, isolamento via monkeypatch, validação E2E sem mocks).
S1.0b — Propagação estrutural do motor ICMS/IPI · gate PVA APROVADO
Status: Concluído (Tentativa 3 ACEITA pelo PVA real em 08/05/2026 12:48)
Commits principais: 3d6c2f7 (schemas e erros) · 86d7454 (primitivo de alteração material) · 7b5aecb (propagação C170→C190) · 11414d8 (delta E110) · a90dcca (integração ao motor) · d9b98f5 (propagação C170→C100 pai) · 4a5aff1 (propagação E110→E116 com guarda) · aa2acd2 (integração C100/E116) · ac3e7a7 (Tentativa 3 — propagações C100/E116) · bae76b2 (gate PVA fechado)
Entregas: motor expandido para suportar propagação estrutural quando o operador altera materialmente um C170. Whitelist estrita do primitivo AlteracaoMaterialControlada (apenas C170.VL_ICMS, linha_sped > 0, Decimal finito não-negativo). Cinco propagações documentadas:
· _aplicar_alteracao_c170_e_c190 — altera C170, propaga delta para o C190 do grupo
· _aplicar_propagacao_c100 — propaga delta para o C100 pai
· _aplicar_delta_e110 — atualiza E110, recalcula saldos, com guarda contra inversão de regime (DeltaApuracaoNaoSuportadoError)
· _aplicar_propagacao_e116 — propaga delta de obrigação para E116, com RegistroE116AusenteError em caso de ausência
Hash do arquivo aceito: 81356267…0825cf713c · Checkpoint: tag v3.13.0-rc2 a criar nesta semana.
Lições recentes capturadas
Aprendizados convertidos em regra preventiva nas últimas duas semanas
L-35 — Validação PVA com fixture de campo zerado mascara divergência da fórmula canônica
Domínio: qualidade · apuração ICMS · S1.0b · Data: 08/05/2026 · Commit: b694c8d
Erro: S1.0b foi validado no PVA com fixture-base contendo DEB_ESP=0. A função interna _recalcular_saldos_e110 derivava VL_ICMS_RECOLHER somando DEB_ESP ao saldo apurado, divergindo da fórmula canônica P1+1 (VL_ICMS_RECOLHER = VL_SLD_APURADO − VL_TOT_DED). PVA aceitou silenciosamente porque DEB_ESP=0 torna a divergência invisível.
Causa raiz: validação PVA com fixture mínima não exercita campos opcionais não-zero. Reverse-engineering de helpers antigos sem cristalizar a fórmula canônica primeiro.
Mitigação aplicada: D-34 (guarda explícita DebEspNaoSuportadoError, commit d9d616e) — motor falha de forma controlada ao receber DEB_ESP > 0 até cobertura PVA específica.
Regra preventiva: validar PVA com cobertura de cenários (DEB_ESP, VL_TOT_DED, ajustes E111, estornos, saldo credor anterior) — não apenas com fixture mínima. Cristalizar fórmulas canônicas em documento separado antes de implementar. Preferir guarda explícita (raise) a comportamento incorreto silencioso.
L-31 — ISO-8859-1 é canônico em EFDs ICMS/IPI da ReceitaNetBX
Domínio: parsing / qualidade · Data: 06/05/2026 · Commit: 78ef416
Erro: Auto-detect chardet retornou None com confidence 0,95 em EFDs grandes — pipeline gravou replacement chars (�) no Parquet/XLSX. Quebra de qualidade em entregas a clientes (SIB, HueHoco): ?LEO DE CORTE, M?QUINA, AQUISI??O.
Causa raiz: EFDs ReceitaNetBX são padronizadas em ISO-8859-1 (Latin-1) pelo Convênio ICMS 143/2006 + tooling SEFAZ. Confiar em auto-detect probabilístico em arquivo padronizado é over-engineering com regressão silenciosa.
Regra preventiva: em parsers de EFD, tentar iso-8859-1 PRIMEIRO; só cair em outras codificações se houver erro real. Validar pós-decodificação a contagem de � — se >0, decode está errado mesmo sem exceção.
L-32 — chunking glob → rglob para indexar subdirectórios da base normativa
Domínio: RAG / normas · Data: 06/05/2026 · Commit: c96eb36
Causa raiz: base_dir.glob("*.md") não visita subdirectórios. 14 normas catalogadas em estadual/sp/portaria_sre/, decretos/, leis/ existiam há meses sem ser indexadas pelo BM25.
Regra preventiva: sempre usar rglob em walkers de bases normativas hierárquicas. Adicionar smoke test que conta arquivos por subdiretório.
L-33 — CST 70 não pertence à lista _CST_NUNCA_GERADORA
Domínio: e-CredAc · Data: 06/05/2026 · Commit: 3edc238
Causa raiz: CST 70 (tributado com redução de BC e cobrança por ST) tem manutenção de crédito específica por norma — não bloqueia geração de crédito acumulado de forma absoluta. Inclusão indevida em _CST_NUNCA_GERADORA bloqueava classificação Inciso II.
Regra preventiva: "nunca geradora" deve listar APENAS CSTs que explicitamente excluem manutenção de crédito (CST 50 — suspensão; CST 90 — outros sem manutenção). Demais CSTs são tratados condicionalmente no bloco do Inciso II.
L-34 — Valores absolutos fiscais não devem aparecer em mensagens de exceção (LGPD)
Domínio: segurança / LGPD · Data: 06/05/2026 · Commit: 3edc238
Causa raiz: reconciliador_blocos.py incluía valores absolutos de saldo credor nos campos detalhes e fontes de divergência. Logs com saldo credor expostos violam diretriz LGPD do projeto (regra 8 do CLAUDE.md).
Regra preventiva: em campos de exceção, log ou detalhe, usar valores de divergência (R$ 0,02), faixas (>1mi, 100k–1mi) ou referências sem valor absoluto ("[ver EFD]"). Nunca expor saldo_credor_fim, parcela_ca ou ICMS total em mensagens.