fix: gate cClassTrib applicability by CRT and date

This commit is contained in:
gti
2026-09-25 17:47:04 -03:00
parent 95605c2ff5
commit 4a12640031
25 changed files with 498 additions and 72 deletions
+2 -2
View File
@@ -536,8 +536,8 @@ See `docs/PRE_AI_LOCAL_COMPLETION_V3_REPORT.md` for measured values.
into a scratch database were exercised on production.
## RTC / cClassTrib closure (2026-09-24/25) — see docs/rtc_auto_apply.md, docs/cclasstrib_resolution.md, docs/unified_fiscal_completeness.md
- Unified fiscal coverage (PIS/COFINS applicability + conditional RTC) is one definition/queue/panel; RTC is ON only if the ERP says so (`PARAMETROS.USAR_REFORMA_TRIBUTARIA`, read live).
- cClassTrib resolver (`central/app/cclasstrib_resolver.py`, `rtc-rules-v2`): every rule is AUTO_APPLY_SAFE / VALIDATION_ONLY / SUGGESTION_ONLY / BLOCKED_BY_EVIDENCE. Only **RTC-R3** (LC 214 annex I/VII/VIII/XV, clean item, CRT 3) authorizes a write; **RTC-R4 is suggestion-only**. Simples: SAFE_BLOCKED (no official orientation; Ato Conjunto RFB/CGIBS 4/2026: Simples from 2027-01-01). Catalog states per class: MATCH_SAFE / MATCH_WITH_NON_MATERIAL_DIFFERENCE / MISMATCH / EXPIRED / MISSING_LOCAL / MISSING_OFFICIAL; write only for MATCH_SAFE.
- Unified fiscal coverage (PIS/COFINS applicability + conditional RTC) remains one definition/queue/panel; `PARAMETROS.USAR_REFORMA_TRIBUTARIA` enables RTC, while cClassTrib requiredness additionally uses live `C000004.CRT` and the effective date: CRT 3 from 2026-08-03, CRT 1/2/4 from 2027-01-01. Unknown CRT does not make cClassTrib required.
- cClassTrib resolver (`central/app/cclasstrib_resolver.py`, `rtc-rules-v2`) runs for products only while cClassTrib is applicable. Every rule is AUTO_APPLY_SAFE / VALIDATION_ONLY / SUGGESTION_ONLY / BLOCKED_BY_EVIDENCE. Only **RTC-R3** (LC 214 annex I/VII/VIII/XV, clean item, CRT 3) authorizes a write; **RTC-R4 is suggestion-only**. Simples before 2027-01-01: cClassTrib is outside completeness; once applicable, existing evidence rules still gate resolution. Catalog states per class: MATCH_SAFE / MATCH_WITH_NON_MATERIAL_DIFFERENCE / MISMATCH / EXPIRED / MISSING_LOCAL / MISSING_OFFICIAL; write only for MATCH_SAFE.
- Write is **centrally authorized per installation** (`installations.rtc_write_mode`: DISABLED default / DRY_RUN / APPROVAL_REQUIRED / ENABLED; migration 0028), delivered only inside the authenticated job (`authorizations`). The Agent has no local switch, only the capability `RTC_CCLASSTRIB_WRITE_V1`; allowlist = `C000025.CCLASSTRIB`.
- Preview/approval (`rtc_candidates`), audit (`rtc_write_audits`, append-only, rich fields) and per-record rollback (value must still equal the written one) live in the Hub; panel page `/agents/{id}/rtc`.
- Blocker persistence is bulk (`upsert_blockers_bulk`); 21k products persist in ~5 s (was 43 s).
+1 -1
View File
@@ -16,7 +16,7 @@ A variável de ambiente `GTI_SSH_PASSWORD`, se existir, tem prioridade. A senha
## Deploy
```
powershell -ExecutionPolicy Bypass -File .\scripts\deploy_hub.ps1
powershell -ExecutionPolicy Bypass -File .\scripts\deploy_hub.ps1 -PublishAgent -Version 1.2.4
powershell -ExecutionPolicy Bypass -File .\scripts\deploy_hub.ps1 -PublishAgent -Version 1.2.5
```
Parâmetros: `-Version` (padrão `release/VERSION`), `-PublishAgent`, `-SkipTests`, `-DryRun`.
+17 -10
View File
@@ -4,12 +4,17 @@ Substitui o modelo anterior de "escopo ampliado". Não existe segundo escopo, se
## Regra definitiva
`RTC_ENABLED = PARAMETROS.USAR_REFORMA_TRIBUTARIA truthy (1/S/T/TRUE) E o schema comporta RTC`
(`C000025.CCLASSTRIB`, `RTC_CCLASSTRIB(CCLASSTRIB, CSTIBSCBS)`, `RTC_CST(CSTIBSCBS)`).
(`C000025.CCLASSTRIB`, `RTC_CCLASSTRIB(CCLASSTRIB, CSTIBSCBS)`, `RTC_CST(CSTIBSCBS)`). Isso habilita o recurso RTC; **não** torna cClassTrib obrigatório para todos os produtos.
- `RTC_ENABLED=false` (parâmetro 0, nulo, ausente ou schema antigo): `CCLASSTRIB` e CST IBS/CBS **não entram** na completude; nenhum blocker RTC; o painel só mostra "Reforma Tributária: Desativada".
- `RTC_ENABLED=true`: RTC passa a ser obrigatório para todo produto.
`CCLASSTRIB_APPLICABLE = RTC_ENABLED E C000004.CRT conhecido E data atual >= data efetiva do CRT`:
Não há estado "desconhecido": um parâmetro ilegível conta como não habilitado pelo ERP (fail-closed para *escopo*, sem inflar cobertura porque o campo não é exigido).
- CRT 3: aplicável a partir de 2026-08-03.
- CRT 1/2/4: aplicável a partir de 2027-01-01.
- CRT ausente/desconhecido/conflitante: não aplicável até resolver o contexto, sem inferir regime.
- RTC desligada, CRT sem aplicabilidade na data, ou contexto não resolvido: `CCLASSTRIB` é ignorado na validação/completude; não cria blocker nem candidato e não escreve. Os outros campos fiscais continuam avaliados.
- RTC ligada e cClassTrib aplicável: validar o valor e manter os blockers de campo vazio/inválido/catálogo existentes.
Parâmetro ilegível ou conflito de valores continua fail-closed para o escopo RTC. A aplicabilidade de cClassTrib é calculada separadamente com CRT ao vivo de `C000004` e as datas efetivas.
## Validação com RTC ativa
`C000025.CCLASSTRIB → RTC_CCLASSTRIB.CSTIBSCBS → RTC_CST` (o CST IBS/CBS **não** é coluna do produto; é derivado pela relação).
@@ -27,13 +32,14 @@ Integridade do catálogo: sem órfãos (classe → CST inexistente), sem duplica
## O que NÃO é validado
O schema do produto não modela alíquota IBS/CBS, valor IBS/CBS nem `cCredPres`. Não existem blockers desses campos e nenhum write target foi inventado. A validação do produto reflete só o que o SGV guarda como default: `CCLASSTRIB`.
## Fontes (ACCESSED_AT 2026-09-24)
## Fontes (ACCESSED_AT 2026-09-24/25)
- NT 2025.002-RTC v1.51, Portal Nacional da NF-e (publicada 04/08/2026): campos IBS/CBS (grupo UB) obrigatórios em 2026; para emitentes CRT 1/2/4 as orientações "serão publicadas em NT futura" porque a tributação IBS/CBS/IS desses contribuintes ocorre a partir de 2027 (art. 348 da LC 214/2025).
- LC 214/2025 (Planalto, compilada): art. 348 (2026: IBS/CBS compensados com PIS/Cofins; alíquotas de teste).
- Catálogo local do ERP (`RTC_CCLASSTRIB`/`RTC_CST`, `PUBLICACAO`/`INICIO_VIGENCIA`) e cClassTrib oficial no Hub (`cClassTrib 2026-06-22.xlsx`).
- `PARAMETROS.USAR_REFORMA_TRIBUTARIA`: parâmetro do próprio SGV (executável 5.1.0.4 o lê; o 5.0.6.124 não tem RTC).
- `C000004.CRT`: regime da empresa lido ao vivo; a vigência de aplicabilidade segue o calendário oficial registrado por `legal_effective_context`.
Nota fiscal vs. regra do produto: para CRT 1 a legislação só exige IBS/CBS no documento a partir de 2027; a regra deste motor segue o **interruptor do ERP** — quando o cliente liga a reforma no SGV, o cadastro passa a ser cobrado.
O interruptor do ERP habilita o recurso RTC; `C000004.CRT` e a vigência decidem quando cClassTrib entra na completude. Assim, `USAR_REFORMA_TRIBUTARIA=1` por si só não causa 521 blockers em empresa CRT 1 antes de 2027.
## Fonte da verdade (ERP_RTC_ENABLED)
Quem decide é o **Agent**, lendo o banco real daquela instalação **a cada varredura** (nunca uma decisão guardada no Hub, nunca cache local):
@@ -41,13 +47,14 @@ Quem decide é o **Agent**, lendo o banco real daquela instalação **a cada var
O estado observado vai em `fiscal_context` do resultado do job e aparece no painel com proveniência (tooltip): `rtc_enabled`/`erp_rtc_enabled`, `rtc_source` (`PARAMETROS.USAR_REFORMA_TRIBUTARIA`), `rtc_param`, `rtc_param_rows`, `rtc_param_conflict`, `rtc_observed_at` (UTC), `rtc_supported`, `rtc_catalog_valid`.
O fingerprint dos blockers inclui o estado RTC: 0→1 cria blockers novos; 1→0 faz a varredura seguinte não reenviar os RTC e o Hub os fecha (`AUTO_REEVALUATION`).
## ERP_RTC_ENABLED × LEGAL_EFFECTIVE_CONTEXT (registrados separadamente)
- `ERP_RTC_ENABLED` é a regra operacional do produto e a única que entra na completude.
- `legal_effective_context(crt)` é **informativo** (`informational_only=true`, nunca blocker): para CRT 1/2/4 a NT 2025.002 v1.51 diz que as orientações de IBS/CBS em documentos virão em NT futura e que a tributação desses contribuintes ocorre a partir de 2027 (LC 214/2025 art. 348); para CRT 3 o preenchimento é obrigatório desde 01/01/2026. Uma empresa Simples com o interruptor ligado no SGV é validada; uma com o interruptor desligado não é, seja qual for o calendário legal.
## ERP_RTC_ENABLED × CCLASSTRIB_APPLICABLE
- `ERP_RTC_ENABLED` registra que o SGV ativou RTC e o schema suporta o recurso.
- `CCLASSTRIB_APPLICABLE` usa `C000004.CRT` e a data efetiva acima; só quando verdadeiro `CCLASSTRIB` participa da completude e pode gerar blocker/candidato.
- `legal_effective_context(crt)` continua reportando o contexto amplo de documentos; a decisão operacional por cClassTrib está registrada separadamente em `fiscal_context.cclasstrib_applicability` (`state`, `basis`, `effective_from`, `source`).
## Achado de corpus e causa da divergência de RTC (somente leitura)
Estado atual do parâmetro nas cópias locais: `CONSTRUCAO=1`, `TESTESOFICIAIS=1`, `MMMODAS=0`, `RINCAO=0`, `UNIAO=0` (cada uma com **uma** linha em `PARAMETROS`, `ODS 11.2`, Firebird 2.5.9). O discovery de `TESTESOFICIAIS.FDB` registrou `0` às 15:25 de 24/09 e a leitura de hoje (mesmo arquivo, mesmas 521 linhas) retorna `1`. Causas descartadas: linha errada / várias linhas (há 1), cache do Hub (a leitura é direta no Firebird, o Agent lê ao vivo), outro arquivo (mesmo caminho canônico). Causa real comprovada: **o valor mudou no próprio banco depois do discovery** (mesmo arquivo, mesma linha única). O autor da mudança não é rastreável (o Firebird 2.5 não guarda histórico de valores e o SGV não tem tabela de log de parâmetros); a hipótese mais simples é a alteração do parâmetro "usar reforma tributária" no SGV 5.1.0.4, que é quem lê esse parâmetro. Por isso o Agent nunca reaproveita um estado anterior.
Consequência medida (TESTESOFICIAIS, RTC ligada de fato): 521/521 produtos com `CCLASSTRIB_MISSING` ⇒ cobertura real 0%; com RTC desligada (estado do piloto) 94,82%.
Baseline anterior ao gate CRT/vigência (TESTESOFICIAIS, RTC ligada): 521/521 produtos foram contados como blockers cClassTrib e cobertura ficou em 0%. A validação pós-gate do Agent 2 deve registrar as novas contagens após executar o Agent atualizado; a medição antiga não representa a regra atual.
## Determinação e preenchimento do cClassTrib
Ver `docs/cclasstrib_resolution.md` (fontes oficiais, catálogo local × oficial, regras) e `docs/rtc_auto_apply.md` (auto-apply restrito a `CCLASSTRIB`, desligado por padrão).
@@ -0,0 +1,208 @@
# cClassTrib Applicability Implementation Plan
> **For agentic workers:** Execute this plan inline task-by-task with test checkpoints. Do not delegate or publish an Agent without following the release gate in Task 5.
**Goal:** Gate cClassTrib validation, blockers, and completeness by live company CRT and its official effective date, instead of treating global RTC enablement as universal requiredness.
**Architecture:** Keep `PARAMETROS.USAR_REFORMA_TRIBUTARIA` as the ERP-level RTC switch, then calculate a separate company-level cClassTrib applicability state from the already-read `C000004.CRT` and the current date. The shared pure evaluator owns the date/regime rule; the Agent carries the state into per-product findings and fingerprints; existing Hub presentation surfaces show a concise non-applicable label without adding another coverage panel.
**Tech Stack:** Python, pytest, SQLAlchemy-backed Hub presentation, Jinja templates, existing read-only Firebird Agent connection.
## Global Constraints
- Do not change architecture or add a new SGV flag, schema, API, or second coverage panel.
- Do not change NCM, PIS, COFINS, or other fiscal rules.
- Do not write to Firebird; reads use the existing `READ COMMITTED READ ONLY` Agent connection.
- Preserve Agent 2's current `rtc_write_mode=DRY_RUN`; `REAL_WRITES=0` and `CCLASSTRIB_WRITES=0`.
- `PARAMETROS.USAR_REFORMA_TRIBUTARIA` remains the RTC feature switch, not proof that every product requires cClassTrib.
- cClassTrib applicability uses live company CRT: CRT 3 from 2026-08-03; CRT 1/2/4 from 2027-01-01; unresolved/unsupported CRT is not applicable until resolved.
- Agent 2 baseline: total 521, complete 0, safe-blocked 521, failed 0, unclassified 0, coverage 0%; RTC 521 blockers; PIS 1, COFINS 1, NCM 26 distinct products/29 open rows.
- Current code uses Agent-side assessment; do not claim the live Agent 2 result changed until the updated Agent code is running and a new job completes.
---
### Task 1: Add failing pure applicability tests
**Files:**
- Modify: `central/tests/test_unified_fiscal_coverage.py`
- Test: `central/app/unified_fiscal_coverage.py`
**Interfaces:**
- Existing input is `evaluate_product(product, company, rtc, today)`; use `company["crt"]`, `rtc["enabled"]`, and the supplied date.
- Applicability states remain in `result["applicability"]["RTC"]`; basis is exposed in `result["basis"]["RTC"]`.
- [ ] **Step 1: Add the business-rule tests**
Add tests equivalent to:
```python
def test_cclasstrib_is_not_applicable_for_simples_before_2027_even_when_rtc_is_on():
result = evaluate_product({**EMPTY, "CCLASSTRIB": None}, SIMPLES, ON, date(2026, 9, 25))
assert result["applicability"]["RTC"] == "NOT_APPLICABLE"
assert "CCLASSTRIB" not in result["mandatory_fields"]
assert not [b for b in result["blockers"] if b["category"] == "RTC"]
def test_cclasstrib_effective_date_is_inclusive_by_crt():
for crt in ("1", "2", "4"):
before = evaluate_product({**EMPTY, "CCLASSTRIB": None}, {"crt": crt}, ON, date(2026, 12, 31))
on_date = evaluate_product({**EMPTY, "CCLASSTRIB": None}, {"crt": crt}, ON, date(2027, 1, 1))
assert before["applicability"]["RTC"] == "NOT_APPLICABLE"
assert "CCLASSTRIB_MISSING" in kinds(on_date)
before = evaluate_product({**EMPTY, "CCLASSTRIB": None}, NORMAL, ON, date(2026, 8, 2))
on_date = evaluate_product({**EMPTY, "CCLASSTRIB": None}, NORMAL, ON, date(2026, 8, 3))
assert before["applicability"]["RTC"] == "NOT_APPLICABLE"
assert "CCLASSTRIB_MISSING" in kinds(on_date)
def test_non_applicable_cclasstrib_does_not_mask_pis_cofins_blockers():
product = {**EMPTY, "CCLASSTRIB": None, "PISCOFINS": "S", "INCIDENCIA_PISCOFINS": "MONOFÁSICA"}
result = evaluate_product(product, SIMPLES, ON, date(2026, 9, 25))
assert kinds(result) == {"PIS_CST_MISSING", "COFINS_CST_MISSING"}
```
Also cover RTC off, missing/unsupported CRT, and applicable CRT 3 with empty cClassTrib.
- [ ] **Step 2: Run the tests and confirm the current code fails**
Run: `python -m pytest central/tests/test_unified_fiscal_coverage.py -q`
Expected: new applicability assertions fail because RTC enabled currently makes the empty field required for CRT 1/2/4 and before the effective dates.
---
### Task 2: Implement one shared applicability gate and carry it through Agent findings
**Files:**
- Modify: `central/app/unified_fiscal_coverage.py`
- Modify: `agent/src/gti_fiscal_agent/unified_fiscal.py`
- Test: `central/tests/test_unified_fiscal_coverage.py`
- Test: `agent/tests/test_unified_fiscal.py`
**Interfaces:**
- Add a pure helper with the stable signature `cclasstrib_applicability(crt, rtc_enabled, today) -> dict` returning `state`, `basis`, and `effective_from` as an ISO-8601 string or `None` so the summary is JSON serializable.
- Pass the result through the existing `rtc` context to `evaluate_rtc`; do not add a Firebird setting or database write.
- Add the applicability inputs to each product input fingerprint so changes in company CRT/effective state invalidate stale decisions.
- Include the company-level applicability result and source (`C000004.CRT` plus effective-date rule) in the Agent's `fiscal_context` summary.
- [ ] **Step 1: Implement the helper and make `evaluate_rtc` return no cClassTrib blocker when the gate is false**
Use these effective dates and exact CRT sets:
```python
CCLASSTRIB_EFFECTIVE_FROM = {
"3": date(2026, 8, 3),
"1": date(2027, 1, 1),
"2": date(2027, 1, 1),
"4": date(2027, 1, 1),
}
```
RTC disabled, CRT absent/unsupported, and dates before the CRT effective date must return `NOT_APPLICABLE`. For an applicable company, retain the existing catalog validation and missing-value blocker.
- [ ] **Step 2: Update the Agent evaluation context and input fingerprint**
Calculate the company gate once per assessment using the live `company["crt"]` and `today`; pass it to each `evaluate_product`. Extend fingerprint input with the resulting applicability state (not a cached Hub value). Continue to issue only SELECT statements to Firebird.
- [ ] **Step 3: Extend the Agent fake-cursor regression tests**
Cover RTC param on + CRT 1 before 2027 (no RTC finding), RTC param on + CRT 3 on/after 2026-08-03 (empty value blocked), separate PIS/COFINS findings preserved, the observed applicability source/state in `fiscal_context`, and a SELECT-only statement list.
- [ ] **Step 4: Run pure and Agent evaluator tests**
Run: `python -m pytest central/tests/test_unified_fiscal_coverage.py agent/tests/test_unified_fiscal.py -q`
Expected: PASS; all cursor statements in Agent discovery tests are SELECT-only.
---
### Task 3: Prove no candidates or writes while cClassTrib is not applicable
**Files:**
- Modify: `agent/tests/test_rtc_auto_apply.py` only if an existing case does not cover the no-finding path.
- Test: `agent/src/gti_fiscal_agent/rtc_auto_apply.py` and the assessment output from Task 2.
**Interfaces:**
- Candidate creation continues to consume the existing RTC findings; a non-applicable product must have no RTC missing finding and therefore no R3 candidate.
- Auto-apply authorization and allowed field remain unchanged.
- [ ] **Step 1: Add a focused candidate/write regression if needed**
Use RTC enabled, CRT 1, empty `CCLASSTRIB`, and the existing fake read-only Firebird connection. Assert zero `CCLASSTRIB_MISSING*` findings, zero preview candidates, zero write attempts, zero write successes, and no SQL other than SELECT on the assessment path.
- [ ] **Step 2: Run RTC auto-apply tests**
Run: `python -m pytest agent/tests/test_rtc_auto_apply.py agent/tests/test_unified_fiscal.py -q`
Expected: PASS; existing applicable CRT 3 safe-write unit tests remain valid and the non-applicable case has no candidate/write.
---
### Task 4: Present non-applicability on existing Hub views
**Files:**
- Modify: `central/app/panel_presentation.py`
- Modify: `central/templates/rtc_control.html`
- Modify: `central/templates/agent_detail.html`
- Test: `central/tests/test_control_panel_pages.py`
- Test: `central/tests/test_operational_view_models.py`
**Interfaces:**
- Preserve the existing `ops.rtc.enabled` value for the global RTC status.
- Add a presentation state for cClassTrib applicability; when false, do not render the current “cClassTrib pendente em N produtos” summary or RTC blocker empty-state warning for that field.
- Render one concise label in the existing RTC status areas: `cClassTrib: Não utilizado neste cliente`.
- [ ] **Step 1: Add a presentation test using Agent 2-like data**
Supply `rtc_enabled=true`, CRT 1, 521 resolution rows, 521 prior cClassTrib blocker products, and the derived non-applicable state. Assert the displayed label and assert that “cClassTrib pendente em 521 produtos” is absent on the Agent detail and RTC pages. Keep the single existing fiscal coverage metrics unchanged.
- [ ] **Step 2: Implement the smallest existing-view changes**
Have `rtc_status_view` use the Agent-reported applicability state. Show the concise label in the existing summary areas and suppress cClassTrib-pending metrics when not applicable. Do not add a new panel or alter the current RTC write mode.
- [ ] **Step 3: Run presentation tests**
Run: `python -m pytest central/tests/test_control_panel_pages.py central/tests/test_operational_view_models.py -q`
Expected: PASS; applicable CRT 3 views continue showing the existing candidate/coverage information.
---
### Task 5: Run the full suite, then gate Agent release and live reprocess
**Files:**
- Version/release files only after the user confirms the release action: `release/VERSION`, `central/app/version.py`, `release/RELEASE_MANIFEST.json`, and the installer metadata generated by `scripts/build_windows_installer.ps1`.
- No Firebird tables or records are modified.
**Interfaces:**
- The updated Agent must be running for Agent 2's live `REPROCESS_ALL` to exercise the new gate; the current production Agent is version 1.2.4.
- Official Hub deployment entry point is `scripts/deploy_hub.ps1`; a new Agent release uses `-PublishAgent` and the installer build script.
- [x] **Step 1: Run all offline tests before any version bump**
Run: `python -m pytest tests -q`
Also run the relevant Agent and Hub tests together: `python -m pytest central/tests/test_unified_fiscal_coverage.py central/tests/test_control_panel_pages.py central/tests/test_operational_view_models.py central/tests/test_zero_touch_hub.py agent/tests/test_unified_fiscal.py agent/tests/test_rtc_auto_apply.py agent/tests/test_zero_touch_agent.py -q`
Expected: PASS with no Firebird writes.
- [x] **Step 2: Pause at the Agent release gate**
Reported that the rule change is in Agent-executed logic, listed the Agent files/tests, and stated the current deployed version `1.2.4`. The operator explicitly authorized bumping to `1.2.5`, building/publishing, and upgrading Agent 2 in place.
- [ ] **Step 3: After release approval, build and publish through official scripts**
Run the repository's supported installer build script, then:
```powershell
powershell -ExecutionPolicy Bypass -File .\scripts\deploy_hub.ps1 -PublishAgent -Version 1.2.5
```
Do not use ad-hoc SSH/Docker deployment. Confirm the deployed Hub health/version and that Agent 2 is running the new Agent version before queuing its full reprocess.
- [ ] **Step 4: Reprocess Agent 2 and compare read-only ERP results**
Queue `REPROCESS_ALL` only after the updated Agent is confirmed running. Keep `rtc_write_mode=DRY_RUN`. Compare the new snapshot/job against the recorded baseline for total, complete, safe-blocked, failed, unclassified, coverage, cClassTrib blockers, and distinct NCM/PIS/COFINS blockers. Confirm `PARAMETROS.USAR_REFORMA_TRIBUTARIA` was observed live, `C000004.CRT=1` led to cClassTrib non-applicability as of 2026-09-25, and Firebird `WRITE_ATTEMPTS=0`, `WRITE_SUCCESSES=0`, `CCLASSTRIB_WRITES=0`.
Expected for this CRT 1 client before 2027-01-01: RTC cClassTrib blockers fall from 521 to 0; other fiscal field findings remain evaluated; RTC mode is unchanged; no candidates or writes are produced.
@@ -0,0 +1,67 @@
# cClassTrib applicability gate
## Purpose
Stop treating an empty `C000025.CCLASSTRIB` as a fiscal defect solely because
the global RTC feature is enabled. Keep the single existing fiscal-completeness
result and continue evaluating every other fiscal field normally.
## Evidence and selected applicability rule
The SGV database has `PARAMETROS.USAR_REFORMA_TRIBUTARIA=1` and RTC-capable
schema, but the inspected `PARAMETROS` and `C000004` schemas have no separate
cClassTrib enable flag. The SGV product screen exposes `C000025.CCLASSTRIB` as
an editable catalog-backed field; available evidence does not mark it required
for every product. The current code incorrectly promotes global RTC capability
to universal per-product requiredness.
Use the live company regime (`C000004.CRT`) together with the documented
effective-date gate:
- RTC capability/`USAR_REFORMA_TRIBUTARIA` must still be enabled for RTC
evaluation generally.
- CRT 3: cClassTrib is applicable from 2026-08-03.
- CRT 1, 2, or 4: cClassTrib is applicable from 2027-01-01.
- Missing, conflicting, or unsupported CRT: cClassTrib is not applicable for
completeness until the company context is resolved; never infer a regime.
- Before the applicable date, ignore cClassTrib completely: no blocker, no
candidate, no completeness penalty, and no write.
- Once applicable, preserve the existing validation/resolution behavior,
including a blocker for an empty value when no safe resolution is available.
This makes current Agent 2 (`CRT=1`, `OPTANTE_SIMPLES=S`) not applicable on
2026-09-25 even though `USAR_REFORMA_TRIBUTARIA=1`. Its current RTC write mode
(`DRY_RUN`) is not changed.
## Minimal implementation boundary
Add the gate to the existing shared fiscal evaluator/context using the already
resolved live company CRT and current date. Do not add a new SGV flag, table,
panel, or second coverage metric. Keep PIS/COFINS, NCM, resolver rules, RTC
write authorization, and Agent write allowlist unchanged. Because the evaluator
is executed by the Agent, this is an Agent code change. After test completion,
the operator explicitly authorized release 1.2.5 through the official Hub/Agent
deploy path and an in-place Agent 2 upgrade that preserves its identity.
The RTC page should present the existing single-panel status as
“cClassTrib: Não utilizado neste cliente” while the gate is false.
## Verification
Add the requested focused tests: not-applicable with empty cClassTrib (RTC off
and on), unrelated fiscal fields still evaluated, applicable with empty
cClassTrib still blocked, and zero write attempts. Then run a read-only
`REPROCESS_ALL` against Agent 2 and compare its latest result/snapshot and
blockers with the captured baseline. Preserve `RTC_WRITE_MODE=DRY_RUN` and
verify Firebird write attempts/successes remain zero. Report NCM/PIS/COFINS
blockers independently.
## Baseline captured before implementation
Agent 2 latest Hub snapshot/job: total 521, complete 0, safe-blocked 521,
failed 0, unclassified 0, coverage 0%; RTC blockers 521; PIS blocker products
1; COFINS blocker products 1; NCM blocker products 26 (29 open blocker rows).
The offline read-only Firebird discovery saw `USAR_REFORMA_TRIBUTARIA=1`,
`SISTEMA_TODO_FISCAL=0`, `C000004.CRT=1`, and
`C000004.OPTANTE_SIMPLES='S'`; its guarded query recorded zero write attempts
and zero successes.
+8 -5
View File
@@ -7,7 +7,7 @@ Uma definição de "completo", um painel, uma fila de blockers, uma cobertura.
campos obrigatórios(produto, empresa) =
campos fiscais base aplicáveis (NCM, CEST, CFOP, ICMS/CST/CSOSN, IPI ... — decididos pelo motor de decisão do Hub)
+ PIS/COFINS aplicáveis (docs/pis_cofins_applicability.md)
+ RTC (cClassTrib → CST IBS/CBS) SOMENTE quando o ERP tem a Reforma Tributária ligada (docs/rtc_pis_cofins_model.md)
+ RTC (cClassTrib → CST IBS/CBS) somente quando `PARAMETROS.USAR_REFORMA_TRIBUTARIA` habilita RTC **e** `C000004.CRT` já atingiu a data efetiva de aplicabilidade (docs/rtc_pis_cofins_model.md)
```
Campos `NOT_APPLICABLE` não contam contra a completude. Nenhum campo é exigido só porque a coluna existe.
@@ -39,9 +39,11 @@ Cada blocker fiscal é um blocker comum: `blocker_type=BLOCKED_FISCAL_DATA`, `fi
## Segurança
Somente leitura. `FIREBIRD_WRITES=0`: a avaliação abre uma conexão `READ COMMITTED READ ONLY`, executa apenas SELECT e nunca preenche `CCLASSTRIB`, PIS ou COFINS. Testes provam que só SELECT é emitido.
## Validação nos bancos reais (somente leitura, cinco bancos)
## Medição histórica antes do gate CRT/vigência (somente leitura, cinco bancos)
`scripts/unified_coverage_e2e.py` → `docs/runs/unified_coverage_e2e*.json`. RTC lida **do banco como está hoje**; "RTC desligada" é simulação pura do avaliador (o parâmetro nunca é tocado).
Os valores abaixo registram a regra anterior, na qual o interruptor global RTC tornava cClassTrib obrigatório em todos os produtos. Não os use como resultados pós-gate.
| Banco | CRT | RTC no banco | Produtos | Completos | Bloqueados | Não class. | Cobertura (como está) | Cobertura com RTC off |
|---|---|---|---|---|---|---|---|---|
| CONSTRUCAO | 1 | **ligada** | 3.712 | 0 | 3.712 (RTC) | 0 | 0% | 100% |
@@ -53,8 +55,9 @@ Somente leitura. `FIREBIRD_WRITES=0`: a avaliação abre uma conexão `READ COMM
Bancos além do piloto: medida só da parte fiscal (`--fiscal-only`, sem decisão do Hub). TESTESOFICIAIS: com a decisão do Hub (antes 495/521 = 95,01%). Bloqueios PIS/COFINS: TESTESOFICIAIS 1 produto (incidência SUBST.TRIBUTÁRIA com CST 01), RINCAO 1 produto (`049`/`000`), demais 0. Produtos com warning (não bloqueante): RINCAO 78 (`4`→`04`, não canônico), UNIAO 2 (CST `000`/`060` inválido, ignorado por ser Simples), TESTESOFICIAIS 1 (não canônico). Aplicabilidade: Simples ⇒ `NOT_APPLICABLE`; RINCAO ⇒ `OPTIONAL` (894); TESTESOFICIAIS 519 `NOT_APPLICABLE` + 2 `REQUIRED`.
## RTC no motor único (cClassTrib) — atualização
- **RTC ligada** ⇒ o Agent avalia cada produto com o resolver determinístico (`docs/cclasstrib_resolution.md`) e transforma o resultado em UM blocker de causa raiz por produto (mesma fila, categoria `RTC`): `CCLASSTRIB_MISSING` (pronto para preencher), `CCLASSTRIB_MISSING_UNRESOLVED`, `CCLASSTRIB_AMBIGUOUS`, `RTC_RULE_EVIDENCE_MISSING`, `RTC_LOCAL_CATALOG_OUTDATED`, `CCLASSTRIB_OFFICIAL_MISMATCH`, `CCLASSTRIB_CONFLICT`. **RTC desligada** ⇒ nenhuma avaliação, nenhum blocker, nada no painel além de "Desativada".
- **RTC ligada e cClassTrib aplicável** ⇒ o Agent avalia cada produto com o resolver determinístico (`docs/cclasstrib_resolution.md`) e transforma o resultado em UM blocker de causa raiz por produto (mesma fila, categoria `RTC`): `CCLASSTRIB_MISSING` (pronto para preencher), `CCLASSTRIB_MISSING_UNRESOLVED`, `CCLASSTRIB_AMBIGUOUS`, `RTC_RULE_EVIDENCE_MISSING`, `RTC_LOCAL_CATALOG_OUTDATED`, `CCLASSTRIB_OFFICIAL_MISMATCH`, `CCLASSTRIB_CONFLICT`.
- **RTC desligada ou cClassTrib não aplicável** ⇒ campo fora da completude; sem blocker, candidato ou write por cClassTrib. PIS/COFINS e os demais campos continuam avaliados.
- Cobertura continua UMA: produto só é completo quando o `CCLASSTRIB` é válido (ou seja, depois de preenchido pelo operador ou pelo auto-apply autorizado). Produtos "prontos para preenchimento" contam como bloqueados até a escrita.
- O painel explica o 0%: "Reforma Tributária ativa — cClassTrib pendente em N produtos" + resumo Total / válidos / prontos / ambíguos-bloqueados.
- Quando não aplicável, as views existentes exibem `cClassTrib: Não utilizado neste cliente` e não mostram pendência RTC por esse campo.
- Quando aplicável, o painel mantém o resumo Total / válidos / prontos / ambíguos-bloqueados.
- Preenchimento automático: `docs/rtc_auto_apply.md` (desligado por padrão; três chaves; somente `CCLASSTRIB`; auditado).