Commit Graph
74 Commits
Author SHA1 Message Date
gtiandClaude Sonnet 5 3dbd5078e4 docs: Missão 9 - correct the P2-P4 registry finding after resuming the session
The machine was shut down and restarted per the operator's earlier request,
then the operator asked to continue instead. On resume, Postgres data
persisted (same volume) and re-checking confirmed CFOP/TIPI_IPI/CEST/
NFE_MOC_TABLES were already ACTIVE (approved in Missão 8) - the earlier
"not found" finding only checked status='DRAFT' and missed that they had
already been promoted. No new approval was needed; register_draft()'s
idempotent lookup just confirmed the existing rows unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 09:00:30 -03:00
gtiandClaude Sonnet 5 c9f5f30742 docs: Missão 9 - record Cliente A's real completed job result
Job 648 (Cliente A/CONSTRUCAO, INITIAL_SYNC, DRY_RUN) completed for real
before the session had to close: 3712/3712 products COMPLETE, 0 blocked,
0 needs-review, 0 writes (as configured). Cliente B (MMMODAS, 20997
products) was still RUNNING when the session ended.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 00:46:56 -03:00
gtiandClaude Sonnet 5 156392e7e3 docs+setup: Missão 9 (parcial, encerrada a pedido do operador mid-execução)
Correção de fato: CONSTRUCAO/MMMODAS/RINCAO/UNIAO são cópias reais de 4
clientes (Cliente A-D), não dado de teste como uma sessão anterior (Missão
6/7) generalizou por engano a partir do Agent 2 (esse sim, teste).
docs/EVIDENCE_SOURCES.md e docs/PROJECT_STATE.md corrigidos.

Bloco 0 (setup seguro) concluído: os 4 originais copiados para work_copies/
(git-ignored, .FDB maiúsculo já coberto pelo padrão existente), hash SHA-256
idêntico antes/depois da cópia (manifestos commitados). CRT/UF/regime
confirmados direto de cada banco via company_context (nunca perguntado ao
operador): A=CONSTRUCAO CRT1, B=MMMODAS CRT1, C=RINCAO CRT3, D=UNIAO CRT1.
4 Agents novos registrados (IDs 618-621, installation_ids novos, nunca
reaproveitando o Agent 2), .env por instalação (gitignored - contém tokens
reais), FIREBIRD_WRITES=0, escrita restrita ao próprio work copy de cada um.
docs/LOCAL_WRITE_ALLOWLIST_V1.json atualizado para apontar a work_copies/ em
vez de Banco/ - os originais nunca mais devem ser abertos em modo de escrita.

Bloco 1.3 concluído: busca web real confirma cClassTrib já obrigatório desde
03/08/2026 para CRT=3 (Cliente C) e só a partir de 2027 para CRT=1 (A/B/D) -
o motor já implementava essa regra corretamente, nenhuma mudança de código.

Restante da missão (diagnóstico completo de 18 campos, aprovação dos
datasets P2-P4, cascata de escrita, lançamento dos Agents C/D) NÃO foi
executado: 3 ações foram negadas pelo classificador de modo automático desta
sessão (nunca contornadas por outra via, por instrução explícita da própria
negação) e a sessão foi encerrada a pedido do operador com 2 jobs reais
(Cliente A e B) ainda RUNNING no Hub local. Detalhe completo, incluindo o
que uma sessão futura deve verificar primeiro, em docs/MISSAO_9_LOG.md.

Nenhuma mudança de código nesta sessão - só documentação, setup de
ambiente de trabalho e tentativas de execução operacional. Nenhuma escrita
fiscal real em nenhum banco (nem original, nem cópia).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 00:45:14 -03:00
gti 26405b0144 feat(missao-8): bump Hub 1.3.15, restauracao de cfop_ippt_auto_apply e elevacao de cobertura 2026-09-28 22:14:39 -03:00
gti 0c10ddd761 feat(missao-7): bloco D - endurecimento HTTP, cobertura de testes e runbook de disaster recovery 2026-09-28 20:16:32 -03:00
gti 5510fdff60 feat(missao-7): bloco C - roteiro de onboarding seguro e prontidao para primeiro cliente real 2026-09-28 20:16:16 -03:00
gti 6d45afb117 feat(missao-7): bloco B - separacao estrita teste/producao e rotulo DADO_DE_TESTE=true 2026-09-28 20:16:00 -03:00
gti f5893ac860 feat(missao-6): finalizacao descoberta P5-P6, compatibilidade do motor e atualizacao PROJECT_STATE 2026-09-28 16:40:07 -03:00
gti cf5bb64d9b feat(bloco-b): ingestao P2-P4 e checklist tecnico de aprovacao no reference registry 2026-09-28 16:20:54 -03:00
gtiandClaude Sonnet 5 2ff79e3b0e docs: PROJECT_STATE.md - session closeout snapshot (Missões 1-5)
Factual, no client data: Hub 1.3.14 (deployed), Agent published 1.3.8,
Agent 2 1.3.8 (operator-reported, heartbeat not confirmed this session).
Migration heads confirmed via `alembic heads` on both branches: main at
0034_reference_data_registry, feature/cfop-ippt-write at
0033_cfop_ippt_write_mode - both children of 0032, so the two branches'
migration chains diverge and one must be renumbered/rebased before any
merge (flagged as an open risk, not resolved here).

Reference Data Registry status, the 3 pending Contexto Fiscal ADMIN
decisions, what each of Missões 1-5 completed vs. left undone, open risks,
and a docs/ index for the next session to start from.

CLAUDE.md now points to docs/PROJECT_STATE.md as the required first read
before any new fiscal mission.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 15:45:54 -03:00
gtiandClaude Sonnet 5 21e8282224 feat: Reference Data Registry (Fase 1) + P1 NCM validated + feasibility studies (Fase 5)
Missão 5:

Fase 1 (Reference Data Registry): migration 0034 adds licence_terms, valid_from/
valid_to, file_size_bytes, raw_file_path, parse_errors, submitted_by/approved_by/
approved_at to the existing `datasets` table (additive only - the 9 pre-existing
dataset kinds keep their current auto-activate behavior in
central/app/datasets/service.py, completely untouched, so this changes nothing
about the currently-running engine). New central/app/reference_registry.py is a
separate, NEW ingestion workflow: register_draft() always lands as DRAFT (never
auto-activates), diff_against_vigente() summarizes a draft against the current
VIGENTE of the same kind for admin review, approve_draft()/reject_draft() are
the only way to promote a DRAFT (refuses non-DRAFT rows and refuses a draft
with recorded parse_errors). New admin screen "Tabelas oficiais"
(/admin/reference-datasets, ADMIN only, CSRF, every decision audited as
REFERENCE_DATASET_APPROVE/REJECT) lists the registry with a diff view and
approve/reject buttons. New CLI (scripts/ingest_reference_dataset.py) downloads
an official source (currently: NCM/Siscomex, no login/captcha), validates
(minimum row count, a known-sample spot check), and registers a DRAFT - --dry-run
never writes anything.

P1 (NCM) validated for real: downloaded the live official Siscomex NCM JSON
(2026-09-28, sha256 8a3bf89a..., 15,156 entries) with an identifiable User-Agent,
one request. Its hash is IDENTICAL to the NCM dataset already ACTIVE in the Hub -
confirms the currently loaded table is already current against the official
source today. Raw file kept out of git (.gitignore:
sources/raw/reference_registry/); manifest (URL, date, hash, size) recorded in
docs/REFERENCE_DATASET_MANIFEST_V1.md, including P2-P6 sources still pending URL
confirmation.

Fase 5 (feasibility studies, no code): docs/VIABILIDADE_CCG_DFE_V1.md - CCG/SEFAZ
GTIN lookup and Distribuição DF-e both require the client's own ICP-Brasil
certificate; recommendation is NOT to implement now (would require either the
Hub holding a client certificate - breaks the project's core security model - or
the Agent making new outbound internet calls, against this mission's fixed
rules). Reading the already-authorized purchase-NFe XML from disk via the Agent
(path already stored in XML_MES) is recommended as the next concrete step
instead: no certificate, no new internet call, opt-in per installation, result
always tagged DECLARADO (never auto-promoted - consensus across purchase
invoices is not fiscal truth). Open Food Facts stays identity-only, unchanged.

21 new tests, all passing. Full suite: 1147 passed, 1 skipped.

No write to any Firebird database anywhere. No Agent code touched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 15:24:55 -03:00
gtiandClaude Sonnet 5 8f3dcaada9 docs: Missão 5 addendum (Z.1-Z.6) - correct labels, add tables, adopt VERSIONING.md
Z.1: KB conflict counts were reported as ROW counts (kb_knowledge rows), not
DISTINCT GTIN counts - a single conflicted product with 2 competing NCM
candidates produces 2 rows, doubling the apparent conflict count. Real
number, measured directly in production: 262 distinct GTINs in CONFLICT
(all under knowledge_key=ncm), matching the ~264 baseline closely - no real
growth, just a row-vs-GTIN counting mismatch in the earlier report.

Z.3: corrected the Missão 4 claim that NFCE_ITENS was the "fonte encontrada"
for what PIS/COFINS was actually transmitted - that overstated certainty.
Relabeled PISCOFINS_FONTE_TRANSMITIDA = NÃO_CONCLUSIVO in
docs/PISCOFINS_TRANSMITTED_SOURCE_V1.md and both dossiê copies: a blank
NFCE_ITENS column is equally consistent with "nothing was transmitted" and
"the SGV transmitted a value in the XML but never wrote it back to that
column" - we cannot tell without the actual XML.

Z.4: docs/AUTOFILL_SAFE_3_CELULAS_V1.md - table of the 3 real AUTO_FILL_SAFE
cells (000801/000802 CFOP, 000697 IPPT) with proposed value, field_contract
rule and concrete evidence for each.

Z.5: docs/NCM_27_BLOCKED_PRODUCTS_V1.md now marks the 15 test/garbage-named
products as "produto de teste" in the kb.attest queue (still counted in
coverage, just lower priority); the 3 legacy + 5 out-of-table NCMs are
flagged for reclassification once the official NCM catalog (Fase 2 of this
mission) is loaded and approved.

Z.6: CLAUDE.md records independent Hub/Agent versioning (docs/VERSIONING.md)
as the adopted standard going forward.

No schema/migration change. No Firebird write anywhere.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 15:03:22 -03:00
gtiandClaude Sonnet 5 f34f001ed5 docs: Missão 4 Bloco C/D - PIS/COFINS source search and the 27 NCM-blocked products
Bloco C.1-C.4: searched every BLOB column and every XML/IMPOSTO/TRIBUT-named
table across all 5 databases - no authorized NFC-e/NF-e XML is stored
anywhere (XML_MES only holds a filesystem path on the original machine;
CARTA_CORRECAO/MDFES_XML are for correction letters and cargo manifests;
DEOLHONOIMPOSTO is the national IBPT reference table, not per-item data).
FONTE_ENCONTRADA = NFCE_ITENS's own PIS/COFINS columns (the same values used
to build the XML) - docs/PISCOFINS_TRANSMITTED_SOURCE_V1.md.

Bloco D.1-D.3: the 27 products blocked by NCM on Agent 2, categorized
(4 placeholder 00000000, 3 legacy/vencido, 5 valid-format-but-not-in-the-
active-table, 15 obvious test/garbage values) with a prioritized kb.attest
queue - real products first (Coca-Cola, chicken cuts, pâté, broths), test
cadastro last. All 27 lack a real GTIN, so none can be resolved by barcode
lookup - documented in docs/NCM_27_BLOCKED_PRODUCTS_V1.md.

dossie_contador.md (internal + anonymized) updated with the Bloco C finding.

No schema/migration change. Zero Firebird writes (read-only SQL only).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 14:26:30 -03:00
gtiandClaude Sonnet 5 8130c4fbdb docs: Hub/Agent independent versioning (Missão 4 / Bloco B.3)
Documents what the code already does (no behavior change): GTI_FISCAL_VERSION
(Hub) and the Agent's own version are separate numbers with separate release
cycles; central.app.installation_identity.reference_agent_version() already
compares an Agent's heartbeat version against the highest PUBLISHED Windows
AgentRelease, never against the Hub's version - verified against
test_version_reference.py. Also documents that there is no real minimum-
version connection gate today (only SCHEMA_FINGERPRINT is enforced) and where
one would go if ever needed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 11:22:18 -03:00
gtiandClaude Sonnet 5 0973c41580 chore: move CFOP/IPPT write-capability code off main to feature/cfop-ippt-write
Missão 4 / Bloco B.2: this repository is local-only (no remote configured,
nothing ever pushed), so moving these files off main is a plain history
edit with no shared-history risk. agent/src/gti_fiscal_agent/cfop_ippt_auto_apply.py,
its tests and docs/CFOP_IPPT_WRITE_CAPABILITY_V1.md now live only on
feature/cfop-ippt-write (created from this same point in history, with one
extra commit adding the Bloco A.3 end-to-end regression test). Nothing on
main imports this code - no behavior changes; this main commit is a pure
file move recorded as a normal new commit, not a rewrite of existing history.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 10:53:45 -03:00
gtiandClaude Sonnet 5 1abb7e516e fix: product_role never infers OWN_PRODUCTION from a single COMPOSICAO occurrence
Missão 4 / Bloco A.1 (prioridade máxima): central.app.field_contract.infer_role
treated ANY C000032.TIPO=COMPOSICAO row for a product as proof of own
production, with no ratio check - a beer sold 19 times and used once as a
recipe component (Agent 2, real data) was classified OWN_PRODUCTION from
that single occurrence, proposing to change its CFOP and IPPT.

New deterministic threshold in field_contract.py: COMPOSICAO must be a
majority (>=70%) of that product's own C000032 movement history, with at
least 5 total events, to count as own-production evidence. Below 30% the
evidence is discarded entirely (falls through to other role evidence,
e.g. TIPO=VENDA -> RESALE). Between 30% and 70% (with enough events to be
meaningful) is genuinely conflicting evidence -> UNKNOWN, never guessed
either way. RECEITA_INGREDIENTES/PROD_COZINHA-based evidence (a direct
recipe-table linkage, not a statistical ratio) is untouched.

agent/src/gti_fiscal_agent/firebird_reader.py now counts COMPOSICAO vs other
C000032 rows per product (read_product_evidence: single indexed query;
read_evidence: one grouped query for the whole catalog) into a new
ev["composed_ratio"] key, alongside the existing "composed" set (kept for
other, non-role consumers like coverage.py). central/app/enrichment/api.py's
sanitize_product_evidence and fiscal_completion.py's empty-ev fallback both
carry the new key through.

New tests (central/tests/test_field_contract.py) cover the 5 real cases named
in the mission: the beer (1 vs 19, 5% - discarded), a second beer (3 vs 4,
42.9% - MIXED/UNKNOWN), the liqueur (34 vs 22, 60.7% - still MIXED/UNKNOWN,
below the 70% bar), the juice with PROD_COZINHA=1+RECEITA_INGREDIENTES
(unaffected, stays OWN_PRODUCTION), and the tilapia/corvina fish (no
composed evidence at all, stays RESALE) - plus a strong 90% majority case
and an insufficient-sample (<5 events) case. A new end-to-end test in
agent/tests/test_cfop_ippt_auto_apply.py (committed separately, see the
feature/cfop-ippt-write branch) proves the weak-evidence beer never reaches
select_candidates as a write candidate, independent of any write flag.

Re-running the dry-run over Agent 2's real database (GTI.FDB, 527 products)
after this fix: AUTO_FILL_SAFE CFOP/IPPT cells drop from 12 to 3 (the two
fish CFOP fills + the juice's IPPT, all with strong, non-statistical
evidence) - docs/runs/GTI_dryrun_universe_summary_after_A1.json. This
corrects the Missão 3 report's 12/9(downgraded)/4(sustained) manual
judgment call with a deterministic, tested engine rule.

No schema/migration change. Zero Firebird writes (read-only analysis only).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 10:53:10 -03:00
gtiandClaude Sonnet 5 3e3858054f feat: CFOP/IPPT write-capability core (inert, not wired, not activated)
Missao 3 / Bloco C.1-C.2: new agent/src/gti_fiscal_agent/cfop_ippt_auto_apply.py
mirrors the existing rtc_auto_apply.py safety model for a new, narrower
capability (CFOP_IPPT_WRITE_V1): compare-before-write, stale-write guard
("human override sempre vence" - a value changed since the candidate was
selected is never overwritten), one transaction per cell, readback
verification, and rollback that only restores a value still equal to what
was written. Candidates come exclusively from field_contract.resolve_product's
own AUTO_FILL_SAFE classification for CFOP/IPPT - no new fiscal rule.
14 new tests (agent/tests/test_cfop_ippt_auto_apply.py) prove: flag OFF means
the caller never reaches a write; only CHANGE+write_eligible CFOP/IPPT cells
become candidates; a human edit between decision and write blocks the write;
a second run over an already-applied cell writes zero; a technical failure on
one cell never stops the batch; rollback refuses when the value changed again.

Deliberately NOT wired into agent/scripts/run_agent_service.py::execute_job,
and the Hub-side authorization/audit plumbing (Installation.cfop_ippt_write_mode,
audit table, job-delivered authorization - the same pattern as
central/app/rtc_audit.py) does not exist yet. No currently-published Agent
behavior (1.3.8) changes with this commit - nothing imports this new module.
See docs/CFOP_IPPT_WRITE_CAPABILITY_V1.md for the acceptance roteiro (test
products only, never real ones) and what remains before this can ever be
activated for a real installation - deliberately left for review before any
further step, per this mission's explicit instruction not to publish it active.

Also: dossie_contador.md (internal + anonymized) updated with the Bloco B
finding that the ~9.5% CST=01 anomaly is confined to a single calendar month
(not the whole year), with no fiscal-dimension (NCM/CFOP/CSOSN/ICMS group)
explaining which items got it - consistent with a one-off technical event,
not a deliberate rule.

REAL_PRODUCT_FISCAL_WRITES=0 (no write path exists in this commit).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 10:12:39 -03:00
gtiandClaude Sonnet 5 9fce13881e docs: Missão 3 Bloco B — read-only correlation analysis for emitted PIS/COFINS CST
New script (scripts/blocoB_pis_cofins_source.py) and evidence artifact
(docs/runs/BLOCOB_PIS_COFINS_SOURCE_V1.json): tests whether NCM, CODGRUPO, CFOP,
CSOSN or GRUPO_ICMS determine the CST_PIS_COFINS value emitted in NFCE_ITENS,
across all 5 installations. Read-only; no Firebird write path exists in this script.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 09:50:36 -03:00
gtiandClaude Sonnet 5 e935ed61d5 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>
2026-09-28 09:44:05 -03:00
gtiandClaude Sonnet 5 fbff392ec9 fix: KB dashboard search was applying the strict fiscal name-match rule (used to authorize automatic writes) to human browsing, so a natural query (e.g. missing the unit word) found nothing; now a separate, lenient, global, paginated server-side search — filter over the whole KB, then count/order/paginate. 1.3.6 (Hub only)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-27 10:33:45 -03:00
gti 1333ac1bc4 feat: visible per-product enrichment status, flagged re-evaluation (panel/Reprocessar/Sincronizar/KB decision), operator NCM decision, deterministic name-only match, stale-write guard; 1.3.5 2026-09-26 14:37:37 -03:00
gtiandClaude Sonnet 5 ab65ddd679 fix: OSCBR role is IDENTITY (V3 contract has no NCM/CEST): v3 endpoint, provides_ncm=false, leading-zero NCM guard, backfill refuses until NCM is proven
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 12:00:05 -03:00
gtiandClaude Sonnet 5 c68c6c67ed feat: TECHNICAL_PLACEHOLDER (NCM 00000000) is replaceable by the product enrichment; real values preserved; Agent 1.3.4
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 10:50:12 -03:00
gtiandClaude Sonnet 5 ac1ecccc50 feat: coverage V2 - historical evidence miner, KB evidence model + promotion audit + revalidation, Kodebar/OSCBR limits, KB/provider panel, seed import; 1.3.2 (Hub only)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 08:14:57 -03:00
gti 19e145ea47 docs: sandbox post-reboot E2E evidence, benchmark refresh 2026-09-26 01:02:40 -03:00
gtiandClaude Sonnet 5 e6bcf12d53 feat: OSCBR optional provider, re-baseline after inactivity, field audit, provider UI/feature matrix tests, benchmark chain; 1.3.1
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 00:48:18 -03:00
gti c3c9d1b4e0 docs: project state for product enrichment 2026-09-25 19:50:32 -03:00
gtiandClaude Sonnet 5 4fc83a33d5 feat: product enrichment observability, lab KB study, benchmark, copy + local-Hub E2E, docs; 1.3.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 19:26:13 -03:00
gti 4a12640031 fix: gate cClassTrib applicability by CRT and date 2026-09-25 17:47:04 -03:00
gtiandClaude Sonnet 5 d8f1bd3415 fix: Agent tolerates ~3 minutes of network outage mid-job (10 attempts with backoff); 1.2.4
Sandbox test: a 26 s outage exhausted the previous 15 s retry budget and failed a REPROCESS_ALL.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 12:46:20 -03:00
gtiandClaude Sonnet 5 6f0f072d84 fix: fresh install archives stale state of a previous installation; a fatal Agent loop error stops the service instead of leaving a dead 'Running' one; 1.2.3
Found by uninstall + fresh install on the clean Windows Sandbox: the old agent_state.sqlite identity conflicted with the new enrollment and the service sat idle.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 12:25:53 -03:00
gtiandClaude Sonnet 5 2e5598ce9c fix: Agent retries transient transport errors/proxy 5xx with backoff (classify, complete, fail); hide console behind the GUI wizard; 1.2.2
Found in the clean-Windows recovery test: a single TLS handshake failure mid-job failed a whole sync.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 12:02:11 -03:00
gtiandClaude Sonnet 5 af5d9b4436 feat: RBAC for RTC write modes (Gerenciador ADMIN only, denials audited), central backpressure for heavy jobs (HEAVY_JOB_CONCURRENCY_LIMIT), concurrency simulation evidence
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 09:46:21 -03:00
gtiandClaude Sonnet 5 7063c8c161 feat: re-check central RTC authorization right before every write (GET /v1/agents/me/authorizations), human labels on the cClassTrib control page, final corpus/scale evidence; 1.2.1
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-25 08:57:45 -03:00
gtiandClaude Sonnet 5 42dc172763 feat: central RTC write modes (DISABLED/DRY_RUN/APPROVAL/ENABLED), R4 suggestion-only, preview/approval, per-record rollback, bulk blocker upsert; 1.2.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 22:46:05 -03:00
gtiandClaude Sonnet 5 9f08998800 feat: deterministic cClassTrib resolver + gated CCLASSTRIB auto-apply (default OFF), RTC panel summary; 1.1.9
- resolver (rules RTC-R0..R4/A1..A3/G1..G2) over the official cClassTrib table 2026-06-22 and LC 214/2025 annexes; local vs official catalog comparison
- ONE root-cause RTC blocker per product (missing/unresolved/ambiguous/conflict/official mismatch/catalog outdated/evidence missing)
- auto-apply: C000025.CCLASSTRIB only, three switches (FIREBIRD_WRITES + RTC_AUTO_APPLY_ENABLED + Hub authorization), per-product re-read and re-decision, never overwrites, rowcount 1, audit table rtc_write_audits (migration 0027)
- copy-only write E2E (280/280 applied, only CCLASSTRIB changed, 2nd run 0 writes, stale decision 0 writes); real databases untouched
- docs: cclasstrib_resolution, rtc_auto_apply, unified_fiscal_completeness

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 21:18:34 -03:00
gtiandClaude Sonnet 5 88f4318072 fix: RTC observed live with provenance, non-circular PIS/COFINS applicability, canonical CST normalization (1.1.8)
- RTC: Agent reads ALL PARAMETROS rows every sync (conflict => off), reports rtc_source/rtc_observed_at/rtc_param_rows; legal_effective_context is informational only
- PIS/COFINS: applicability from CRT + PISCOFINS flag + incidence only (never from empty fields); Simples w/o special treatment NOT_APPLICABLE, taxed regime with explicit N OPTIONAL, unreadable declaration NEEDS_REVIEW
- CST: one digit with an official zero-padded form is VALID_AFTER_NORMALIZATION (non-blocking warning), nothing is written to the ERP
- tests: RTC toggle 0->1->0 across syncs (Agent + Hub stale closing), non-circularity, normalization, panel provenance

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 17:46:45 -03:00
gtiandClaude Sonnet 5 1430042322 release: 1.1.8 - unified fiscal coverage (PIS/COFINS applicability + conditional RTC)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 16:43:39 -03:00
gtiandClaude Sonnet 5 b15dbea213 feat: unified fiscal coverage - PIS/COFINS applicability + conditional RTC in one definition, one queue, one panel
- central/app/unified_fiscal_coverage.py: pure rules (PIS/COFINS NOT_APPLICABLE/REQUIRED/OPTIONAL/NEEDS_REVIEW, RTC only when the ERP switch is on)
- agent: read-only loader (unified_fiscal.py) replaces the legacy/expanded module; findings feed the single operational state, coverage and blocker queue
- hub: BLOCKED_FISCAL_DATA blockers (PIS/COFINS/RTC) share the queue; stale ones close on the next full pass; dashboard breakdown gains CEST/PIS/COFINS/RTC
- panel: legacy/expanded coverage block removed; discreet 'Reforma Tributaria: Ativa/Desativada'
- docs: unified_fiscal_completeness, pis_cofins_applicability, rtc_pis_cofins_model + official source manifests; read-only E2E script

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 16:39:53 -03:00
gtiandClaude Sonnet 5 d897cceebb feat: read-only RTC + PIS/COFINS assessment (capabilities, validators, applicability, legacy vs expanded coverage) with panel labels and docs
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 15:41:51 -03:00
gtiandClaude Sonnet 5 e0ea842168 docs: read-only fiscal/RTC/PIS-COFINS discovery of TESTESOFICIAIS.FDB
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 15:25:31 -03:00
gtiandClaude Sonnet 5 9a142975a6 feat: operational panel UI - active-scope dashboard, drill-down cards, scoped Agents/Blockers/Jobs, PT-BR labels, responsive CSS
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 13:38:40 -03:00
gtiandClaude Sonnet 5 f5f05d87e6 fix: installer tolerates localized 'service exists' (1073) and restarts the service if an upgrade step fails; 1.1.7
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 11:13:19 -03:00
gtiandClaude Sonnet 5 40a4d835fe fix: installer starts the service reliably (retry + verify + installer.log), fails loudly; 1.1.6
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 10:54:19 -03:00
gtiandClaude Sonnet 5 7dc437c01c feat: official operator-run Hub deploy script (backup, migrate, health, release, rollback)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 10:02:28 -03:00
gtiandClaude Sonnet 5 bb663a979c feat: zero-touch Agent — central scheduler, central pause, delta sync, discovery-driven installer
Hub: installations.processing_enabled / sync_interval_seconds / last_sync_* (migration 0026).
The first heartbeat of an installation without coverage queues exactly one INITIAL_SYNC;
afterwards one SYNC_INCREMENTAL per interval (idempotent, backs off on failure). One fiscal
job at a time per Agent (FIFO, stale RUNNING recovery). Job completion now updates the
coverage snapshot, blockers and JOB_STARTED/COMPLETED/FAILED events. Panel: Sincronizar
agora / Reprocessar tudo / Pausar / Retomar + status; pause is enforced Hub-side.
Agent: local AGENT_JOBS_ENABLED is ignored (central control); SYNC_INCREMENTAL re-classifies
only new/changed products via a per-product fingerprint+decision cache and rebuilds coverage
from it; results carry operational summary and blockers; Firebird credentials come from a
DPAPI firebird.bin. Setup: read-only SGV Firebird discovery (auto-select only when
unambiguous, wizard chooser otherwise), starts the service, waits for the first heartbeat,
upgrade-in-place mode. All jobs stay read-only (FIREBIRD_WRITES=0). Version 1.1.3.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 08:47:00 -03:00
gtiandClaude Sonnet 5 ac7b503c2f fix: persist and recover the Agent's real installation_id (heartbeat activation)
POST /v1/agents/enroll now returns installation_id; new installs persist it
to agent.env immediately. Runtime recovery precedence: existing SQLite
installation_identity -> configured INSTALLATION_ID -> authenticated
GET /v1/agents/me/identity. Recovery fails closed on missing/malformed/
mismatched identity rather than inventing a UUID (which the Hub would then
reject as a conflicting Installation on an already-enrolled Agent). An
explicit AGENT_JOBS_ENABLED gate stops the service from claiming a job right
after the first heartbeat.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 22:13:56 -03:00
gti b058affa29 docs: windows installer EXE V1 implementation plan 2026-09-23 16:02:30 -03:00
gti 701d7dafdd docs: windows installer EXE V1 design (approved with adjustments) 2026-09-23 16:01:44 -03:00
gtiandClaude Sonnet 5 8d6122c096 feat: Agent distribution with secure enrollment from the control panel
One universal Windows Agent package per version (agent_releases: version/
platform/architecture/sha256/status DRAFT|PUBLISHED|REVOKED; the binary
lives on a local release-storage volume, never in PostgreSQL). An operator
creates a pending installation (agent_enrollments) from Agents / Servidores
-> + Nova instalação, then either downloads it directly or generates a
one-time HTTPS link (short TTL, single use). Either path streams the
package plus a freshly minted enrollment.json whose token is never written
to storage in plaintext, only its SHA-256 hash. On the client host,
gti-agent.ps1 install-auto verifies the bundle's SHA-256, refuses a non-
HTTPS Hub, enrolls via POST /v1/agents/enroll (deleting the enrollment
token immediately after, success or failure), writes an ACL-restricted
.env with the newly issued permanent Agent token, and registers the
Windows Service without starting it (Firebird stays unconfigured on
purpose). Idempotent, replay-proof, rate-limited per IP, fully audited,
never logs a secret.

Migration 0022_agent_releases_enrollment (verified fresh-DB ==
upgrade-from-0021 by pg_dump diff). GTI_FISCAL_VERSION/AGENT_VERSION
bumped to 1.1.0 as the single source of truth across code, packages, the
release manifest and every published AgentRelease row.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 13:19:31 -03:00