Skip to content

Add <response> element validation for SPS 1.10 compliance#1138

Draft
Copilot wants to merge 3 commits intomasterfrom
copilot/create-validations-for-response-element
Draft

Add <response> element validation for SPS 1.10 compliance#1138
Copilot wants to merge 3 commits intomasterfrom
copilot/create-validations-for-response-element

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 19, 2026

O que esse PR faz?

Implementa 7 regras de validação para o elemento <response> conforme SPS 1.10, cobrindo atributos obrigatórios, unicidade de IDs e estrutura mínima esperada.

# Regra Nível
1 @response-type presença CRITICAL
2 @response-type valor = "reply" ERROR
3 @xml:lang presença CRITICAL
4 @id presença CRITICAL
5 @id unicidade ERROR
6 <front-stub> presença WARNING
7 <body> presença WARNING

Onde a revisão poderia começar?

packtools/sps/validation/response.py — contém a classe ResponseValidation com todos os 7 métodos de validação.

Como este poderia ser testado manualmente?

from lxml import etree
from packtools.sps.validation.response import ResponseValidation

xml = """<article article-type="letter" xml:lang="en">
    <front><article-meta/></front>
    <body><p>Content</p></body>
    <response response-type="reply" xml:lang="en" id="S1">
        <front-stub/>
        <body><p>Response</p></body>
    </response>
</article>"""

tree = etree.fromstring(xml)
for result in ResponseValidation(tree).validate():
    print(result["title"], result["response"])

Testar também via orchestrator:

from packtools.sps.validation.xml_validator import get_validation_results
for r in get_validation_results(tree, {}):
    if r.get("group") == "response":
        print(r["title"], r["response"])

31 testes unitários em tests/sps/validation/test_response.py cobrem: atributos ausentes/vazios/whitespace, valores incorretos, IDs duplicados, respostas em <sub-article>, error levels customizáveis.

Algum cenário de contexto que queira dar?

O <response> identifica respostas a cartas/comentários publicadas no mesmo documento. Segue o mesmo padrão arquitetural dos validadores existentes (HistoryValidation, XMLPeerReviewValidation): classe de validação + rules JSON + integração no orchestrator via xml_validations.py / xml_validator.py.

Arquivos criados:

  • packtools/sps/validation/response.pyResponseValidation
  • packtools/sps/validation_rules/response_rules.json — configuração de níveis de erro
  • tests/sps/validation/test_response.py — 31 testes

Arquivos modificados:

  • packtools/sps/validation/xml_validations.py — import + validate_response()
  • packtools/sps/validation/xml_validator.py — yield do grupo "response"

Screenshots

N/A — validação backend sem componente visual.

Quais são tickets relevantes?

Referências

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.crossref.org
    • Triggering command: `/usr/bin/python python -c
      from lxml import etree
      from packtools.sps.validation.xml_validator import get_validation_results
      from packtools.sps.validation.xml_validator_rules import get_default_rules

Test that response_rules loads from the JSON

rules = get_default_rules()
assert` (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Criar validações para o elemento </issue_title>
<issue_description>## Objetivo

Implementar validações para o elemento <response> conforme a especificação SPS 1.10, aumentando a conformidade de X% para 70% (7 de 10 regras).

Nota: Algumas validações para <response> podem já estar parcialmente implementadas no repositório. Este Issue visa reavaliar, complementar e garantir cobertura completa das regras SPS 1.10.


Contexto

O elemento <response> identifica um conjunto de respostas referente a uma carta ou comentário, obrigatoriamente publicadas juntamente com a carta/comentário. É usado quando há múltiplas respostas no mesmo documento. Validações corretas garantem presença de atributos obrigatórios, unicidade de IDs, e estrutura mínima necessária.

Conformidade atual: X de 10 regras implementadas (X%)
Meta após implementação: 7 de 10 regras (70%)


Documentação SPS

Referência oficial: https://docs.google.com/document/d/1GTv4Inc2LS_AXY-ToHT3HmO66UT0VAHWJNOIqzBNSgA/edit?tab=t.0#heading=h.response

Regras principais conforme SPS 1.10:

  1. Ocorrência:

    • <response> pode aparecer zero ou mais vezes em <article> e <sub-article>
  2. Contexto de uso:

    • Tag para identificar conjunto de respostas referente a carta ou comentário
    • Obrigatoriamente publicadas juntamente com carta ou comentário
    • Se apenas uma resposta: usar <sub-article article-type="reply">
    • Se publicado com DOI separadamente: usar <article article-type="reply">
  3. Atributos obrigatórios:

    • @response-type="reply" (obrigatório)
    • @xml:lang (obrigatório)
    • @id (obrigatório)
  4. Unicidade de IDs:

    • Deve-se usar um @id diferente para cada <response>
  5. Estrutura esperada:

    • <front-stub> - Metadados da resposta
    • <body> - Conteúdo da resposta
    • <back> - Seção final (opcional, pode conter <ref-list>)

Regras a Implementar

P0 – Críticas (implementar obrigatoriamente)

# Regra Nível Descrição
1 Validar presença de @response-type CRITICAL O atributo @response-type é obrigatório em <response>
2 Validar valor de @response-type ERROR O valor de @response-type deve ser "reply"
3 Validar presença de @xml:lang CRITICAL O atributo @xml:lang é obrigatório em <response>
4 Validar presença de @id CRITICAL O atributo @id é obrigatório em <response>
5 Validar unicidade de @id ERROR Cada <response> deve ter um @id único (não pode repetir valores)

P1 – Importantes (implementar se possível)

# Regra Nível Descrição
6 Validar presença de <front-stub> WARNING Recomenda-se que <response> contenha <front-stub> com metadados da resposta
7 Validar presença de <body> WARNING Recomenda-se que <response> contenha <body> com o conteúdo da resposta

P2 – Futuras (fora do escopo deste Issue)

# Regra Motivo de exclusão
8 Validar contexto de uso (carta/comentário) Média complexidade - requer validação do article-type do documento pai
9 Validar uso de sub-article para resposta única Alta complexidade - requer análise de quantidade e contexto
10 Validar formato de @id conforme sugestões SPS Baixa prioridade - formato livre permitido

Arquivos a Criar/Modificar

Avaliar existentes (podem ter validações parciais):

  • packtools/sps/models/response.py ou similar – Verificar se modelo existe
  • packtools/sps/validation/response.py – Verificar validações existentes
  • packtools/sps/validation/rules/response_rules.json ou similar – Verificar configuração

Criar (se não existirem):

  • packtools/sps/models/response.py – Modelo de extração de dados
  • packtools/sps/validation/response.py – Validações
  • packtools/sps/validation/rules/response_rules.json – Configuração de níveis de erro
  • tests/sps/validation/test_response.py – Testes unitários

Referenciar (implementações similares):

  • packtools/sps/validation/sub_article.py – Validação de estrutura similar
  • packtools/sps/validation/utils.py – Funções auxiliares (build_response)

Exemplos de XML

XML Válido (deve passar sem erros):

<!-- Exemplo 1: Duas respostas em um documento -->
<article article-type="letter">
    <front>
        <!-- metadados da carta -->
    </front>
    <body>
        <!-- conteúdo da carta -->
    </body>
    <response response-type="reply" xml:lang="en" id="S1">
        <front-stub>
            <contrib-group>
                <contrib contrib-type="author">
                    <name>
                        <surname>Smith</surname>
                        <given-names>John</given-names>
                    </name>
                </contrib>
            </contrib-grou...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes scieloorg/packtools#1108

<!-- START COPILOT CODING AGENT TIPS -->
---

📱 Kick off Copilot coding agent tasks wherever you are with [GitHub Mobile](https://gh.io/cca-mobile-docs), available on iOS and Android.

Copilot AI and others added 2 commits March 19, 2026 12:07
Implements 7 validation rules for <response> element:
- Rule 1: @response-type presence (CRITICAL)
- Rule 2: @response-type value must be "reply" (ERROR)
- Rule 3: @xml:lang presence (CRITICAL)
- Rule 4: @id presence (CRITICAL)
- Rule 5: @id uniqueness (ERROR)
- Rule 6: <front-stub> presence (WARNING)
- Rule 7: <body> presence (WARNING)

New files:
- packtools/sps/validation/response.py - Validation class
- packtools/sps/validation_rules/response_rules.json - Rules config
- tests/sps/validation/test_response.py - 31 unit tests

Modified files:
- packtools/sps/validation/xml_validations.py - Import + wrapper function
- packtools/sps/validation/xml_validator.py - Orchestrator integration

Co-authored-by: robertatakenaka <505143+robertatakenaka@users.noreply.github.com>
Co-authored-by: robertatakenaka <505143+robertatakenaka@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement validations for the response element Add <response> element validation for SPS 1.10 compliance Mar 19, 2026
Copilot AI requested a review from robertatakenaka March 19, 2026 12:10
Copy link
Copy Markdown
Collaborator

@Rossi-Luciano Rossi-Luciano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Evidência de revisão — response.py

Data: 2026-04-25
Revisor: Luciano
Artefatos analisados:

  • response.py (validation) — módulo de validação (ResponseValidation)
  • response_rules.json — parâmetros de configuração
  • response.xml — XML artificial gerado para cobertura de testes
  • response-2026-25-04-145722-errors.csv — relatório de erros gerado pelo packtools

Metodologia

Análise cruzada entre o módulo de validação, o JSON de regras, o XML artificial
construído com o princípio do defeito isolado e o relatório CSV. O módulo é autocontido: _get_response_elements() extrai todos os campos diretamente do nó XML via XPath e .get(), sem delegar a nenhuma classe de model externa. Não foi necessário solicitar um módulo de model adicional.

O XML usa article-type="letter", que não consta em data_availability_required_article_types, evitando ruído do validador de disponibilidade de dados nas seções.


Regras validadas (7 métodos)

# Método Nível configurado
R1 validate_response_type_presence CRITICAL
R2 validate_response_type_value ERROR
R3 validate_xml_lang_presence CRITICAL
R4 validate_id_presence CRITICAL
R5 validate_id_uniqueness ERROR
R6 validate_front_stub_presence WARNING
R7 validate_body_presence WARNING

Casos de teste no XML artificial (9 elementos <response>)

Caso Defeito introduzido Nível esperado Isolamento
P1 Nenhum — caso ouro completo OK (ausente do CSV) todos os atributos e filhos válidos
C-R1 <response> sem @response-type CRITICAL R2 skipa (if not response_type: continue) — sem cascata
C-R2 @response-type="comment" (valor inválido) ERROR R1 passa (bool("comment")=True)
C-R3 <response> sem @xml:lang CRITICAL demais atributos válidos
C-R4 <response> sem @id CRITICAL R5 skipa (if not response_id: continue) — sem cascata
C-R5a @id="resp-dup" (1ª ocorrência) ERROR todos os outros atributos válidos para isolar R5
C-R5b @id="resp-dup" (2ª ocorrência) ERROR validate_id_uniqueness percorre todos os contextos e gera uma entrada por instância duplicada
C-R6 <response> sem <front-stub> WARNING demais atributos e <body> válidos
C-R7 <response> sem <body> WARNING demais atributos e <front-stub> válidos

Verificação cruzada com o CSV

Todas as 8 entradas esperadas do módulo response.py aparecem no CSV sob o
subject response, com os níveis de severidade corretos:

Subject Caso Nível Verificação
response C-R1 CRITICAL PASS — response @response-type presence
response C-R2 ERROR PASS — Replace @response-type with "reply"
response C-R3 CRITICAL PASS — response @xml:lang presence
response C-R4 CRITICAL PASS — response @id presence
response C-R5a ERROR PASS — Replace duplicate @id="resp-dup" (1ª instância)
response C-R5b ERROR PASS — Replace duplicate @id="resp-dup" (2ª instância)
response C-R6 WARNING PASS — response front-stub presence
response C-R7 WARNING PASS — response body presence

O caso ouro P1 não gera nenhuma entrada. Não foram identificados falsos positivos nem falsos negativos originados do módulo.

Nota sobre R5: validate_id_uniqueness coleta todos os contextos em uma única passagem, identifica os ids duplicados e gera uma entrada por instância. O resultado de 2 entradas para @id="resp-dup" é o comportamento esperado e correto.


Ruído identificado (outros módulos) — 20 entradas

Ruído estrutural (XML artificial mínimo): history dates ausentes (5 entradas),
subject/subj-group heading ausente (3 entradas), disp-formula, inline-formula, table-wrap e app ausentes, bibliographic strip incompleto.

Ruído de ambiente: rendition PDF ausente, article dates incompleto, DOI não
registrado no Crossref.

Ruído de referência (id and rid ERROR, 1 entrada): <ref id="B01"> presente no
<ref-list> sem <xref ref-type="bibr" rid="B01"> correspondente no corpo do
artigo. Para eliminar esse ruído nos próximos XMLs artificiais de módulos que não validam referências, incluir ao menos um <xref ref-type="bibr" rid="B01"> no corpo.

Ruído de open science (CRITICAL, 1 entrada): o validador de open science disparou mesmo para article-type="letter". Verificar se letter deveria estar isento da exigência de declaração de disponibilidade de dados nesse módulo.


Conclusão

O módulo response.py está correto. Todas as 8 entradas esperadas dispararam com os níveis de severidade corretos, sem falsos positivos nem falsos negativos originados do módulo. O comportamento de skip de R2 para response_type=None (C-R1) e de skip de R5 para id=None (C-R4) foi confirmado pela ausência de cascatas no CSV.

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.

3 participants