Skip to content

feat: motor de resolucao estrutural TXT-XML via XSD NF-e (issue #140) - #205

Merged
elson-vinicius-lopes merged 4 commits into
developfrom
feat/resolucao-estrutural-txt-xml-140
Aug 28, 2026
Merged

feat: motor de resolucao estrutural TXT-XML via XSD NF-e (issue #140)#205
elson-vinicius-lopes merged 4 commits into
developfrom
feat/resolucao-estrutural-txt-xml-140

Conversation

@elson-vinicius-lopes

Copy link
Copy Markdown
Collaborator

Resumo

Implementa o motor de resolução estrutural TXT↔XML para NF-e (issue #140), permitindo
mapear campos de origem TXT/IDOC/MQSeries para o XPath correto no XML de destino usando
o XSD oficial da SEFAZ como fonte de verdade — em vez de heurísticas de regex/nome.

  • Catálogo TargetElementGuid → XPath construído a partir do XSD SEFAZ NF-e (decisão do
    dono: escopo NF-e por ora, extensível por tipo de documento depois).
  • Classificador de mappingKind sem regex — resolução estrutural via schema.
  • Resolução de ocorrência física (índice real dentro de elementos repetíveis do XML).
  • Critério objetivo authoritative/best-effort: 5 condições de autoridade + degradação
    para best-effort quando a origem TXT vem de linha vazia/degradada (LineInfo).
  • Endpoint dedicado POST /api/TransformationExecution/field-mappingsnão foi
    adicionado ao contrato de execute-candidates (isso fica para a issue feature: adicionar fieldMappings opcional em execute-candidates, alimentado pelo parser de runtime #141).
  • Cache por TargetLayoutGuid.

Commits principais:

  • 36ae5cb — motor de resolução estrutural TXT→XML NF-e
  • 9b2d0d0 — wiring do motor ao pipeline real (@lp-backend-dev)
  • 110c998 — matriz de 20 cenários sintéticos de teste (@lp-qa)
  • 1992ed4 — fix: degradação para best-effort por LineInfo

Design: docs/architecture/design-resolucao-estrutural-txt-xml-issue-140.md
QA gate: .claude/agent-memory/lp-qa/issue140-resolucao-estrutural-qa-gate.md

⚠️ Limitação importante — validação comportamental pendente

O critério de aceite original da issue #140 previa validar 20 execuções reais contra o
LowCodeRunner (executável Windows-only, net481, interop nativo Sysmiddle). Isso
não foi possível neste ambiente (WSL/Linux não roda o runner). Em substituição, foram
criados 20+ testes determinísticos contra fixtures sintéticas que validam a resolução
estrutural (catálogo XSD, classificação, ocorrência física, authoritative/best-effort) —
mas isso é uma aproximação, não a validação comportamental real.

Ação pendente: rodar a validação comportamental completa contra o LowCodeRunner real
em ambiente Windows — do dono do projeto ou de um agente com acesso a esse ambiente.

Test plan

  • dotnet build — 0 erros
  • dotnet test — 461 passando, 4 falhas pré-existentes de path Windows×Linux (não
    relacionadas a esta mudança)
  • Validação comportamental real contra LowCodeRunner (Windows) — pendente, ver acima

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

elson-vinicius-lopes and others added 4 commits August 27, 2026 19:57
…(issue #140, itens 1/3/4/5)

Implementa XmlLayoutStructureParser (le XSD real da SEFAZ NF-e via XmlSchemaSet,
mirror nfephp-org/sped-nfe PL_009_V4 - fonte de verdade decidida pelo dono
2026-08-27), XmlLayoutCatalog (resolução por caminho/leaf-name + XPath absoluto
com namespace), MappingKindClassifier (direct/transformed/concatenated/static
sobre StructuredRule, sem regex ad-hoc) e OccurrenceResolver +
FieldToXmlMappingComposer (lineOccurrence->xmlOccurrence e critério objetivo
authoritative/best-effort do design, §5).

25 testes novos: 8 contra o XSD real da NF-e, 6 do classificador, 11 do
composer cobrindo direct/static/concatenated/N->1/1->N/grupo repetido/mismatch
de repetição/loop dinâmico/função desconhecida/FunctionCatalog indisponível/
fallback por nome de folha. Sem regressão (36/36 verdes no projeto).

Escopo: só NF-e por ora, extensível por tipo de documento (fonte é
XSD+elemento raiz passados pelo chamador). Não implementa endpoint HTTP nem
validação comportamental contra LowCodeRunner real - fica para #140 itens 6-8.
…>XML ao pipeline real (issue #140, itens 2/6-9)

Conecta o motor ja implementado (ai/XslSynth.Contracts/Core/StructuralResolution/, commit
36ae5cb) a dados reais: Layout/ParsedField do parse posicional real (ILayoutParserService) +
MapperVo real via RealMapperParser sobre mapper decifrado (MapperDatabaseService) + catalogo
XML de destino (XSD NF-e) cacheado por TargetLayoutGuid via IMemoryCache.

- Services/Transformation/StructuralResolution/StructuralXmlCatalogCacheService.cs: cache do
  XmlLayoutCatalog (parse de XSD e caro), chave "structural-xml-catalog:{docType}:{targetGuid}",
  degrada para null (sem lancar) quando StructuralResolution:NfeSchemaPath nao configurado.
- Services/Transformation/StructuralResolution/FieldMappingCompositionService.cs: crosswalk
  GUID/nome do Layout de origem, resolve sources (LinkMappingItem por GUID, MapperRule via
  StructuredRule.AllSources por nome), usa ParsedField.Occurrence fisico real (nunca sintetico)
  e compoe via FieldToXmlMappingComposer ja existente.
- Controllers/TransformationExecutionController.cs: novo endpoint dedicado
  POST api/TransformationExecution/field-mappings — deliberadamente SEPARADO do contrato de
  execute-candidates (issue #141 decide se/como fieldMappings entra la).
- Program.cs/appsettings.json: AddMemoryCache, secao StructuralResolution, registro dos 2
  servicos novos (Singleton para o cache, Scoped para a composicao).
- Testes de integracao (fixtures/XSD real da NF-e) validando o wiring ponta-a-ponta e a
  degradacao sem XSD configurado; ajuste de 2 testes existentes do controller (novos parametros
  do construtor).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ssue #140)

23 testes deterministicos cobrindo a matriz do design §6.1 (TXT/MQSeries/IDOC,
grupo repetido/aninhado, atributo, concatenação, estático, condicional, função
de transformação, loop dinâmico, N:1/1:N, namespace não-default, mismatch de
repetição, função desconhecida). Documenta 2 gaps reais no composer
(IsDeclaredEmpty/PositionalAlignmentFailed não chegam ao motor) e confirma
que o critério authoritative/best-effort é conservador quando FunctionCatalog
está indisponível. Validação comportamental contra o LowCodeRunner.exe real
fica pendente (Windows-only, não roda neste ambiente) — registrado em
.claude/agent-memory/lp-qa/issue140-resolucao-estrutural-qa-gate.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… é linha vazia/degradada

Achado do @lp-qa (issue140-resolucao-estrutural-qa-gate.md, gap 2): LineInfo.IsDeclaredEmpty e
LineInfo.PositionalAlignmentFailed (contrato de degradacao posicional de 2026-08-27) nao chegavam
ao FieldMappingCompositionService, permitindo que um mapeamento vindo de linha vazia/degradada
saisse Authoritative. Adiciona uma 6a condicao de pos-processamento (FieldMappingCompositionService.
DegradeForUnhealthySourceLines) que so pode degradar Authoritative->BestEffort, nunca promover o
contrario - sem reescrever o criterio objetivo ja existente em FieldToXmlMappingComposer.

ParsingResult.LineInfos ja era populado internamente mas nao chegava ao composer; agora e passado
via TransformationExecutionController -> FieldMappingCompositionService.Compose(..., lineInfos).
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@elson-vinicius-lopes
elson-vinicius-lopes merged commit 92ff11f into develop Aug 28, 2026
4 checks passed
@elson-vinicius-lopes
elson-vinicius-lopes deleted the feat/resolucao-estrutural-txt-xml-140 branch August 28, 2026 02:02
elson-vinicius-lopes added a commit that referenced this pull request Aug 28, 2026
…andidates-141

Reconcilia PR #207 (issue #141) com develop, que já absorveu as PRs
irmãs #200 (issue #86), #201 (issue #139), #203 (issue #138) e #205
(issue #140) da mesma cadeia de trabalho. Conflitos eram todos overlap
real entre PRs desta cadeia tocando os mesmos arquivos, não clash
semântico:

- LowCodeCandidateResult.cs: DecryptedMapperContent (#141) e
  MapperDecryptedContent (#138) eram o mesmo dado (mapper.DecryptedContent)
  sob nomes diferentes — unificado em DecryptedMapperContent, único campo,
  usado tanto por SysmiddleSectionMappingResolver (#138) quanto por
  TryComposeFieldMappings (#141).
- LowCodeAutoTransformationService.cs: mesma duplicação de atribuição
  nos dois pontos de criação de LowCodeCandidateResult.
- TransformationExecutionController.cs: TransformationCandidate agora
  preenche FieldMappings (#141) E SectionMappings/XmlNamespaces (#138)
  no mesmo objeto — funcionalidades complementares, ambas preservadas.
- README.md: seções de documentação de fieldMappings (#141) e
  sectionMappings (#138) são independentes, mantidas as duas em sequência.
- security-code-scan-baseline.json: entradas de linha para
  LowCodeAutoTransformationService.cs reconciliadas para 371/415 (linhas
  atuais pós-merge) — mesmos 2 achados de sempre (File.WriteAllTextAsync
  em inPath/metaPath), não vulnerabilidades novas. Nota adicionada ao
  _readme documentando o ajuste.

dotnet build: 0 erros. dotnet test: 413/417 passando — as 4 falhas
(SafePathResolverTests, LowCodeRunnerArgsTests) são pré-existentes,
específicas de ambiente (assumem paths Windows, falham sob WSL/Linux),
não relacionadas aos arquivos deste merge.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant