12 KiB
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 ONLYAgent connection. - Preserve Agent 2's current
rtc_write_mode=DRY_RUN;REAL_WRITES=0andCCLASSTRIB_WRITES=0. PARAMETROS.USAR_REFORMA_TRIBUTARIAremains 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); usecompany["crt"],rtc["enabled"], and the supplied date. -
Applicability states remain in
result["applicability"]["RTC"]; basis is exposed inresult["basis"]["RTC"]. -
Step 1: Add the business-rule tests
Add tests equivalent to:
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) -> dictreturningstate,basis, andeffective_fromas an ISO-8601 string orNoneso the summary is JSON serializable. -
Pass the result through the existing
rtccontext toevaluate_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.CRTplus effective-date rule) in the Agent'sfiscal_contextsummary. -
Step 1: Implement the helper and make
evaluate_rtcreturn no cClassTrib blocker when the gate is false
Use these effective dates and exact CRT sets:
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.pyonly if an existing case does not cover the no-finding path. - Test:
agent/src/gti_fiscal_agent/rtc_auto_apply.pyand 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.enabledvalue 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 byscripts/build_windows_installer.ps1. - No Firebird tables or records are modified.
Interfaces:
-
The updated Agent must be running for Agent 2's live
REPROCESS_ALLto 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-PublishAgentand the installer build script. -
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.
- 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 -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.