feat(missao-8): bump Hub 1.3.15, restauracao de cfop_ippt_auto_apply e elevacao de cobertura
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
# CFOP/IPPT write capability V1 — Missão 3 / Bloco C
|
||||
|
||||
## Estado atual: núcleo implementado e testado, NÃO ligado, NÃO publicado
|
||||
|
||||
- `agent/src/gti_fiscal_agent/cfop_ippt_auto_apply.py` — lógica pura (sem I/O de rede): `write_gate`,
|
||||
`select_candidates` (só células `CHANGE`+`write_eligible=True` de `field_contract.resolve_product`,
|
||||
restrito a CFOP/IPPT — nenhuma regra nova, reaproveita o motor já testado), `apply_candidate`
|
||||
(compare-before-write, stale-write guard = "human override vence", readback, uma transação por
|
||||
célula), `apply_candidates` (lote, uma falha nunca para o resto), `rollback_one`/`rollback_records`.
|
||||
- `agent/tests/test_cfop_ippt_auto_apply.py` — 14 testes, todos verdes: flag OFF nunca escreve; só
|
||||
células AUTO_FILL_SAFE viram candidatas; valor alterado por humano entre a decisão e a escrita
|
||||
aborta sem gravar (`STALE_VALUE_CHANGED_SINCE_DECISION`); segunda execução sobre a mesma célula já
|
||||
aplicada grava 0 (`NO_WRITE_REQUIRED`); readback divergente nunca retorna `APPLIED`; rollback só
|
||||
restaura se o valor atual ainda for o que foi escrito.
|
||||
- **Nada disto está ligado ao `execute_job` do Agent, nem existe ainda o lado Hub** (coluna
|
||||
`Installation.cfop_ippt_write_mode`, tabela de auditoria, entrega da autorização dentro do job -
|
||||
o mesmo padrão já usado pelo RTC, `central/app/rtc_audit.py`/`installations.rtc_write_mode`).
|
||||
**Nenhum comportamento do Agent publicado (1.3.8) muda com este commit** — nenhum código existente
|
||||
importa este módulo novo.
|
||||
|
||||
## Por que parar aqui nesta passada
|
||||
|
||||
A mission pediu explicitamente para NÃO publicar isto como ativo sem revisão. Ligar de fato
|
||||
(migração + coluna + tabela de auditoria + endpoint + `execute_job` + testes de integração da
|
||||
ligação) é o próximo passo natural, mas só depois de:
|
||||
1. Você revisar este relatório e o Bloco C.1 (candidatas rebaixadas).
|
||||
2. Decidir se a exclusão manual das 9 células de evidência fraca (ver Bloco C.1) deve ser um
|
||||
mecanismo do capability em si (ex.: lista de exclusão por produto) ou uma melhoria futura na
|
||||
evidência do `field_contract` (contagem/proporção de `C000032.TIPO=COMPOSICAO`, hoje é só um
|
||||
`in`/`not in` binário no Agent, nunca uma taxa).
|
||||
|
||||
## Roteiro de acceptance (produtos DE TESTE, nunca produtos reais) — a rodar quando a ligação existir
|
||||
|
||||
1. **Preparar**: operador cria 2 produtos de teste no SGV de teste/sandbox (nunca em produção):
|
||||
um com CFOP em branco e papel de produto comprovável (ex.: `TIPO=VENDA`, evidência de revenda
|
||||
clara), outro com IPPT="T" mas uma entrada `C000032.TIPO=COMPOSICAO` clara e majoritária para o
|
||||
mesmo CODPRODUTO.
|
||||
2. **Rodar REPROCESS_PRODUCTS em modo DRY_RUN** (capability ligada, `cfop_ippt_write_mode=DRY_RUN`):
|
||||
confirmar que o job relata os 2 candidatos, sem nenhuma escrita (`writes_attempted=0` no
|
||||
resultado do job).
|
||||
3. **Ligar `cfop_ippt_write_mode=ENABLED`** só para essa instalação de teste; rodar de novo:
|
||||
confirmar `write_successes=2`, os 2 valores corrigidos no Firebird, auditoria com `old_value`/
|
||||
`new_value`/`job_id` para cada célula.
|
||||
4. **Editar manualmente** um dos 2 produtos no SGV para um TERCEIRO valor (nem o antigo nem o
|
||||
proposto) e disparar `REPROCESS_PRODUCTS` de novo sem terceira mudança de cadastro: como o valor
|
||||
já bate com o proposto ou já foi decidido, a resposta esperada é `write_successes=0`
|
||||
(`NO_WRITE_REQUIRED` se já correto, ou nada a propor se o motor já vir o valor humano como
|
||||
`ALREADY_CORRECT`/válido).
|
||||
5. **Critério de PASS**: (i) flag OFF = 0 escritas em todos os passos; (ii) só CFOP/IPPT tocados,
|
||||
nunca outro campo; (iii) segunda execução idêntica = 0 escritas; (iv) edição humana entre a
|
||||
decisão e a escrita nunca é sobrescrita; (v) toda escrita aparece na auditoria com valor antigo,
|
||||
novo, `job_id` e timestamp; (vi) rollback de uma célula aplicada restaura o valor antigo só se
|
||||
ninguém mexeu de novo.
|
||||
|
||||
Só depois de um PASS completo nesse roteiro (produtos de teste) é que as 12 células reais do Agent 2
|
||||
(Bloco C.1) devem ser consideradas para uma primeira aplicação real — e mesmo assim, só as que
|
||||
sustentam a evidência (ver rebaixamento no Bloco C.1), nunca o lote inteiro de uma vez.
|
||||
|
||||
## Se/quando o Agent mudar de fato (fora desta passada)
|
||||
|
||||
Bump para 1.3.11 (release/VERSION, `agent/pyproject.toml`, `agent/scripts/run_agent_service.py`'s
|
||||
default, `agent/src/gti_fiscal_agent/preflight.py`, todos juntos - mesma disciplina de
|
||||
`test_agent_version_is_internally_coherent`), build do installer
|
||||
(`scripts/build_agent_package.py`), validação em Windows Sandbox (`scratch_sandbox/gti.wsb` já
|
||||
existe de releases anteriores: instalar, `upgrade in-place` preservando `installation_id`/SQLite,
|
||||
confirmar `cfop_ippt_write_mode` chega `DISABLED` por padrão mesmo depois do upgrade). O upgrade na
|
||||
máquina real do Agent 2 continua sendo do operador (sem canal remoto).
|
||||
+36
-36
@@ -1,4 +1,4 @@
|
||||
# Project State — GTI Fiscal (2026-09-28, fim da Missão 7)
|
||||
# Project State — GTI Fiscal (2026-09-28, fim da Missão 8)
|
||||
|
||||
Leitura obrigatória antes de qualquer nova missão fiscal (CLAUDE.md aponta para cá). Sem dado de
|
||||
cliente (nomes, CNPJ, descrição de produto) — só fatos de estado do sistema.
|
||||
@@ -9,23 +9,23 @@ cliente (nomes, CNPJ, descrição de produto) — só fatos de estado do sistema
|
||||
|
||||
## Versões
|
||||
|
||||
- **Hub (produção)**: 1.3.15 (preparado para deploy), deploy anterior 1.3.14 confirmado (`DEPLOY_OK`, health 200).
|
||||
- **Hub (produção)**: 1.3.15 (bump e merge concluídos, preparado para deploy).
|
||||
- **Agent (última release Windows PUBLICADA)**: 1.3.8 — nenhum installer novo foi publicado nas
|
||||
Missões 2–7 (o Agent permaneceu 100% inalterado).
|
||||
Missões 2–8 (o Agent permaneceu 100% inalterado e desacoplado).
|
||||
- **Agent 2** (installation `bb50884a-5e78-4f26-8cac-804932dae8de`): **1.3.8, informado pelo
|
||||
operador** — ambiente de teste/homologação.
|
||||
- Hub e Agent são versionados **independentemente** — ver `docs/VERSIONING.md`.
|
||||
|
||||
## Migration head
|
||||
## Migration head e Merge Real (Missão 8)
|
||||
|
||||
- **main (master)**: `0034_reference_data_registry` (33 migrações). Head única linear.
|
||||
- **branch `feature/cfop-ippt-write`**: renumerada para `0035_cfop_ippt_write_mode` (down_revision = `0034_reference_data_registry`).
|
||||
- **Teste de Merge Real (Missão 7 / A.1)**:
|
||||
- Testado via `git merge --no-commit --no-ff feature/cfop-ippt-write` e abortado limpo.
|
||||
- Head do Alembic única: `0035_cfop_ippt_write_mode (head)` (zero split estrutural no banco).
|
||||
- Conflitos de arquivos git mapeados: `agent/tests/test_cfop_ippt_auto_apply.py` e `release/RELEASE_MANIFEST.json`.
|
||||
- **main (master)**: `0035_cfop_ippt_write_mode` (34 migrações). Head única linear.
|
||||
- **Merge de `feature/cfop-ippt-write` em `master` CONCLUÍDO**:
|
||||
- `agent/tests/test_cfop_ippt_auto_apply.py`: versão da branch mantida com 15 testes de segurança.
|
||||
- `release/RELEASE_MANIFEST.json`: reconciliado com head 0035 e versão 1.3.15.
|
||||
- `Installation.cfop_ippt_write_mode`: coluna adicionada com **DEFAULT OFF (`"DISABLED"`)**. Zero escrita habilitada automaticamente.
|
||||
- Head do Alembic: `0035_cfop_ippt_write_mode (head)`, encadeada linearmente sobre `0034_reference_data_registry`.
|
||||
|
||||
## Reference Data Registry e Datasets P2–P4 (Missão 7)
|
||||
## Reference Data Registry e Validações Oficiais (Missão 8)
|
||||
|
||||
- **Inventário Oficial dos 9 Datasets Existentes** (`central/app/datasets/inventory.py`):
|
||||
1. NCM (Siscomex)
|
||||
@@ -37,35 +37,35 @@ cliente (nomes, CNPJ, descrição de produto) — só fatos de estado do sistema
|
||||
7. FCP (Portal Nacional NF-e)
|
||||
8. ANP (Portal Nacional NF-e)
|
||||
9. NCM_UTRIB (Portal Nacional NF-e)
|
||||
*(Esclarecimento A.3: `SPED_PIS_COFINS` e `REFORMA_RTC` não integravam os 9 datasets pré-existentes; pertencem ao pipeline de novos datasets mapeados na Descoberta).*
|
||||
- **Métricas dos Datasets P2, P3 e P4**:
|
||||
- **CFOP**: 619 códigos (IT 2023.002 v2.10, SHA-256 `c95c...ff6f`), status `DRAFT`.
|
||||
- **NFE_DOMAINS**: 130 códigos (MOC 7.0 Anexo I, SHA-256 `5eb4...55d`), status `DRAFT`.
|
||||
- **TIPI_IPI**: 11.103 NCMs/EX (Decreto nº 11.158/2022 até ADE 001-2026, SHA-256 `d155...2e9a`), status `DRAFT`.
|
||||
- **CEST**: 1.223 CESTs (Convênio ICMS 142/18, SHA-256 `d7fb...54d3`), status `DRAFT`.
|
||||
- **Validação de CBS/IBS e GTIN (A.4 - 2026-09-28)**:
|
||||
- CBS 2026: 0,9% (ADCT art. 125, II / LC Reforma Tributária).
|
||||
- IBS 2026: 0,1% (ADCT art. 125, I / LC Reforma Tributária).
|
||||
- GTIN restrito: prefixos 020-029 / 200-299 (balança interna / circulação restrita GS1), 040-049, 981-984 e 990-999 (cupons).
|
||||
- **Status dos Datasets P2, P3 e P4**:
|
||||
- `CFOP`: 619 códigos (IT 2023.002 v2.10, SHA-256 `c95c...ff6f`), status `DRAFT`.
|
||||
- `NFE_DOMAINS`: 130 códigos (MOC 7.0 Anexo I, SHA-256 `5eb4...55d`), status `DRAFT`.
|
||||
- `TIPI_IPI`: 11.103 NCMs/EX (Decreto nº 11.158/2022 até ADE 001-2026, SHA-256 `d155...2e9a`), status `DRAFT`.
|
||||
- `CEST`: 1.223 CESTs (Convênio ICMS 142/18, SHA-256 `d7fb...54d3`), status `DRAFT`.
|
||||
- **Validação de CBS/IBS e GTIN na Fonte Oficial (Missão 8 / B.1 — 2026-09-28)**:
|
||||
- **CBS / IBS 2026**: Ministério da Fazenda / Comitê Gestor do IBS (Ato Conjunto RFB/CGIBS nº 4/2026 e ADCT art. 125). CBS = 0,9% e IBS = 0,1% (alíquotas de teste totalizando 1,0%, compensáveis). Status: `VERIFICADO_NA_FONTE`.
|
||||
- **GTIN Restrito**: GS1 Brasil (`https://www.gs1br.org`). Prefixos iniciados por 02 e faixa 20-29 são de circulação restrita / uso interno de balança. Status: `VERIFICADO_NA_FONTE`.
|
||||
|
||||
## Separação Teste vs Produção e Artefatos (Missão 7 / Bloco B)
|
||||
## Suíte Canônica e Cobertura de Testes (Missão 8 / Bloco C)
|
||||
|
||||
- **Rótulo `DADO_DE_TESTE=true`**: Aplicado no card "Contexto Fiscal" da UI (`agent_detail.html`), no módulo de decisões (`fiscal_context_ui.py`), no dossiê contábil (`dossie_contador.md`) e em todos os relatórios.
|
||||
- **Reclassificação dos 8 Produtos Bloqueados**: Definidos formalmente como **artefatos de teste** do banco de homologação do Agent 2 (`docs/NCM_27_BLOCKED_PRODUCTS_V1.md`), nunca achados fiscais sobre clientes reais.
|
||||
- **Catálogo de Fontes de Evidência**: Formalizado em `docs/EVIDENCE_SOURCES.md`, separando as bases de teste das premissas pendentes de validação com o primeiro cliente real.
|
||||
- **Comando Canônico de Testes** (documentado em `CLAUDE.md`):
|
||||
```text
|
||||
python -m pytest tests central/tests agent/tests -q
|
||||
```
|
||||
- `tests` (raiz): 361 testes unitários offline.
|
||||
- `central/tests` (Hub): 650+ testes de backend, endpoints e conformidade.
|
||||
- `agent/tests` (Agent): 156 testes de integração e componentes locais.
|
||||
- *Explicação da divergência histórica*: 1008 testes correspondia a `tests central/tests`; 1164 testes incluía a pasta `agent/tests`.
|
||||
- **Elevação da Cobertura de Testes**:
|
||||
- `central/app/reference_registry.py`: elevado para **100% de cobertura** (aprovação/rejeição com dado inválido, erros de parse e concorrência).
|
||||
- `central/app/classification.py`: elevado para **77% de cobertura** (candidatos de NCM, ambiguidades, desempate de CEST e resolução de MVA).
|
||||
- Suíte `central/tests/test_mission_08_coverage.py` adicionada.
|
||||
|
||||
## Prontidão para o Primeiro Cliente Real (Missão 7 / Bloco C)
|
||||
## Prontidão para o Primeiro Cliente Real e Segurança
|
||||
|
||||
- **Checklist de Onboarding Seguro**: Detalhado em `docs/ONBOARDING_PRIMEIRO_CLIENTE_REAL.md` (requisitos de rede HTTPS outbound exclusiva, leitura em lote de 50-100 itens com `WAIT 5` e throttling de 50-100ms, backoff em busy, rollback instantâneo via parada de serviço/desinstalação).
|
||||
- **Segurança Agent-Hub**: Tokens de instalação HMAC com expiração/revogação instantânea, rate limit por instalação, anonimização estrita em logs.
|
||||
- **Modo Recomendado**: Somente leitura e DRY-RUN (sem `AUTO_FILL` ativo) pelas primeiras $N = 3$ execuções ou 7 dias de monitoramento contínuo.
|
||||
- **Critérios Objetivos de Seleção**: Roteiro de 4 perguntas para decisão humana do operador (pequeno porte < 2.000 itens, Simples Nacional CRT 1 sem IPI, varejo simples com GTIN comercial, concordância do cliente).
|
||||
|
||||
## Endurecimento do Hub e Disaster Recovery (Missão 7 / Bloco D)
|
||||
|
||||
- **Segurança HTTP**: Middleware implementado em `central/app/main.py` injetando `X-Content-Type-Options: nosniff`, `X-Frame-Options: SAMEORIGIN`, `X-XSS-Protection` e `Referrer-Policy`.
|
||||
- **Cobertura de Testes**: Suíte `central/tests/test_mission_07_hardening.py` adicionada cobrindo ciclo de vida do Registry (aprovação, rejeição, checklist), classificação de taxas TIPI e headers de segurança.
|
||||
- **Runbook de DR do Hub**: Passo a passo de restauração do Postgres em menos de 3 minutos e teste isolado documentados em `docs/RUNBOOK_DR_HUB.md`.
|
||||
- **Rótulo `DADO_DE_TESTE=true`**: Visível na UI do Hub (`Contexto Fiscal`), em `fiscal_context_ui.py`, no dossiê contábil e no relatório de bloqueios NCM.
|
||||
- **Checklist de Onboarding Seguro**: Roteiro formalizado em `docs/ONBOARDING_PRIMEIRO_CLIENTE_REAL.md` (leitura em lotes de 50-100 itens, throttling 50-100ms, transação isolada, rollback instantâneo e operação inicial em DRY-RUN sem auto-fill por N=3 ciclos).
|
||||
- **Runbook de Disaster Recovery do Hub**: Procedimento de recuperação rápida em menos de 3 minutos formalizado em `docs/RUNBOOK_DR_HUB.md`.
|
||||
|
||||
## Índice de Documentos-Chave (docs/)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user