feat: audited-decision gate for PIS/COFINS and CFOP_ENTRADA NOT_APPLICABLE/OPERATION_TIME

Missao 2 (fechamento de lacunas fiscais, read-only + UI/engine gated):
- field_contract: pis_cofins_profile now also accepts the literal sentinels
  NOT_APPLICABLE/OPERATION_TIME, resolving to NA only from an audited
  FiscalContextEntry - never inferred from emission statistics. CFOP_ENTRADA
  under an already-decided entry_scope=MIXED_OR_DYNAMIC now resolves to NA
  instead of MANUAL, so it stops blocking product completeness and stops
  re-asking an already-answered question. Regression tests prove: no ADMIN
  decision => unchanged old behavior; decision present => gated bucket, no write.
- context_keys: validate_entry accepts the two sentinels for pis_cofins_profile.
- Contexto Fiscal UI: PIS/COFINS and CFOP_ENTRADA cards show the Bloco 2
  cross-database evidence (5 installations, CRT 1 and 3: emission never reads
  the PIS/COFINS cadastral fields anywhere) and a link to an ADMIN-facing,
  anonymized dossie-for-the-accountant; entry_scope is now a dropdown.
- release/tests: decoupled the Hub's GTI_FISCAL_VERSION from the Agent's own
  version (test_versions_are_coherent_across_hub_and_packages vs the new
  test_agent_version_is_internally_coherent) - a Hub-only release must not
  require touching, rebuilding or republishing the Agent.
- New read-only evidence: docs/runs/GTI_dryrun_universe_summary.json (527
  products, Agent 2's real database), docs/runs/BLOCO2_PIS_COFINS_CROSS_DB_V1.json
  (5 installations), docs/fiscal_completeness_matrix.md, docs/dossie_contador.md
  (internal, real names) + central/static/docs/dossie_contador.md (public,
  anonymized - no CNPJ/razao social/product names), docs/AGENT2_UPGRADE_RUNBOOK_V1.md.
- CLAUDE.md: recorded the permanent fiscal-mission rules (no AI/scraping, no
  Firebird schema changes, deploy only via deploy_hub.ps1, never reenroll,
  no remote access to client Agent hosts, no client data in unauthenticated
  static routes).

No schema/migration change. Zero Firebird writes (new scripts never open a
write connection). Hub only - Agent code untouched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
gti
2026-09-28 09:44:05 -03:00
co-authored by Claude Sonnet 5
parent 1621ea4e0b
commit e935ed61d5
21 changed files with 1066 additions and 35 deletions
+21 -8
View File
@@ -369,7 +369,10 @@ def resolve_product(p, d, company, refs, ev, ctx, manual_ncm=None):
if valid_e:
out["CFOP_ENTRADA"] = _r("CFOP_ENTRADA", ALREADY, cfe, reason="DECLARED_VALID_OPERATION_DEPENDENT_MIXED_SCOPE")
else:
out["CFOP_ENTRADA"] = _r("CFOP_ENTRADA", MANUAL, cfe, reason="CFOP_ENTRADA_OPERATION_DEPENDENT_MIXED_SCOPE")
# Audited ADMIN decision (entry_scope=MIXED_OR_DYNAMIC) already says no static CFOP_ENTRADA is
# ever correct here: NA (never MANUAL) so this doesn't block product completeness and never
# raises a spurious "answer entry_scope" question — the scope question was already answered.
out["CFOP_ENTRADA"] = _r("CFOP_ENTRADA", NA, cfe, reason="CFOP_ENTRADA_OPERATION_DEPENDENT_MIXED_SCOPE")
else:
if scope_ctx in ("INTRA", "INTER") and role in ("RESALE", "OWN_PRODUCTION", "INPUT") and st != "UNKNOWN" and not (st == "SUBJECT" and withheld is None):
first = "1" if scope_ctx == "INTRA" else "2"
@@ -470,13 +473,23 @@ def resolve_product(p, d, company, refs, ev, ctx, manual_ncm=None):
# ---------------- PIS / COFINS ----------------
prof_raw, prof_scope = ctx.get("pis_cofins_profile", code, group)
import json as _json
try:
prof = _json.loads(prof_raw) if prof_raw else {}
except ValueError:
prof = {}
for field, pkey, dom in (("COD_ENTRADA_PIS", "pis_in_cst", "cst_pis"), ("COD_SAIDA_PIS", "pis_out_cst", "cst_pis"), ("ALIQ_PIS", "pis_rate", None),
("COD_ENTRADA_COFINS", "cofins_in_cst", "cst_cofins"), ("COD_SAIDA_COFINS", "cofins_out_cst", "cst_cofins"), ("ALIQ_COFINS", "cofins_rate", None)):
PIS_COFINS_FIELDS = ("COD_ENTRADA_PIS", "pis_in_cst", "cst_pis"), ("COD_SAIDA_PIS", "pis_out_cst", "cst_pis"), ("ALIQ_PIS", "pis_rate", None), \
("COD_ENTRADA_COFINS", "cofins_in_cst", "cst_cofins"), ("COD_SAIDA_COFINS", "cofins_out_cst", "cst_cofins"), ("ALIQ_COFINS", "cofins_rate", None)
if prof_raw in ("NOT_APPLICABLE", "OPERATION_TIME"):
# Audited ADMIN decision only (Missão 2 / Bloco 2.4): an operator explicitly recorded, in FiscalContextEntry,
# that this company/product's PIS/COFINS is never taken from the cadastral fields (real evidence: SGV emission
# never reads them) or varies per operation. Never inferred automatically from emission statistics -
# absent this exact recorded value, the field stays MANUAL (see the final `else` below), unchanged.
for field, _pkey, _dom in PIS_COFINS_FIELDS:
out[field] = _r(field, NA, cur[field], reason="ADMIN_DECISION_PIS_COFINS_" + prof_raw)
prof = None
else:
import json as _json
try:
prof = _json.loads(prof_raw) if prof_raw else {}
except ValueError:
prof = {}
for field, pkey, dom in ([] if prof is None else PIS_COFINS_FIELDS):
v = cur[field]
want = _s(prof.get(pkey)) if prof else None
if want is not None and dom and want not in refs[dom]: