Implementar validações para elemento <history> conforme SPS 1.10 e integrar ao orquestrador#1096
Implementar validações para elemento <history> conforme SPS 1.10 e integrar ao orquestrador#1096
<history> conforme SPS 1.10 e integrar ao orquestrador#1096Conversation
Co-authored-by: robertatakenaka <505143+robertatakenaka@users.noreply.github.com>
Co-authored-by: robertatakenaka <505143+robertatakenaka@users.noreply.github.com>
<history> conforme SPS 1.10
Rossi-Luciano
left a comment
There was a problem hiding this comment.
O módulo de validação de history precisa ser considerado no orquestrador:
packtools/sps/validation/xml_validator.py
packtools/sps/validation/xml_validations.py
|
@copilot O módulo de validação de history precisa ser considerado no orquestrador: packtools/sps/validation/xml_validator.py |
…_validations) Co-authored-by: robertatakenaka <505143+robertatakenaka@users.noreply.github.com>
Done! The history validation module has been integrated into both orchestrator files:
The integration includes:
All 35 tests passing (30 original + 5 integration tests). See commit d930b09 for details.
Done! The history validation module has been integrated into both orchestrator files:
The integration includes:
All 35 tests passing (30 original + 5 integration tests). See commit d930b09 for details. |
<history> conforme SPS 1.10<history> conforme SPS 1.10 e integrar ao orquestrador
4e2c042 to
d930b09
Compare
There was a problem hiding this comment.
Pull request overview
Este PR adiciona um novo módulo de validação para o elemento <history> (SPS 1.10) e o integra ao orquestrador de validações (xml_validator), junto com testes unitários e de integração para garantir a execução no pipeline.
Changes:
- Adiciona
HistoryValidationcom regras estruturais para<history>(unicidade,@date-type, tipos permitidos, obrigatoriedade de received/accepted, completude de data para tipos críticos, presença de<year>). - Integra a validação no orquestrador via
validate_history()e um novo grupo"history"no pipeline. - Inclui testes unitários e testes de integração do orquestrador para o novo grupo.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
packtools/sps/validation/history.py |
Implementa as validações estruturais do elemento <history>. |
packtools/sps/validation/xml_validations.py |
Adiciona validate_history() e conecta o validador ao conjunto de validações. |
packtools/sps/validation/xml_validator.py |
Inclui o novo grupo "history" no pipeline do orquestrador. |
tests/sps/validation/test_history.py |
Testes unitários para as regras do HistoryValidation. |
tests/sps/validation/test_history_integration.py |
Testes de integração garantindo que o grupo "history" roda no orquestrador. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Get article type to determine if exempt from required dates | ||
| self.article_type = self._get_article_type() | ||
|
|
||
| def _get_article_type(self): | ||
| """Get the article type from the XML.""" | ||
| article = self.xmltree.find(".") | ||
| if article is not None: | ||
| return article.get("article-type") | ||
| return None |
There was a problem hiding this comment.
_get_article_type() always reads the root <article> @article-type, but this validator also targets <history> under <sub-article><front-stub>. For reviewer-report (and other sub-articles) this will misclassify exemption/required-date logic and produce incorrect parent_article_type in responses. Consider iterating per article/sub-article node (like XMLPeerReviewValidation does) and passing the correct node (and its @article-type) into the validation methods / parent metadata.
| # Check in article-meta | ||
| article_meta_history = self.xmltree.xpath(".//front/article-meta/history") | ||
|
|
||
| # Check in front-stub | ||
| front_stub_history = self.xmltree.xpath(".//front-stub/history") | ||
|
|
||
| # Combine all history elements | ||
| all_history = article_meta_history + front_stub_history | ||
| history_count = len(all_history) | ||
|
|
There was a problem hiding this comment.
The uniqueness rule is implemented as a single global count across .//front/article-meta/history plus all .//front-stub/history. This will flag valid documents that have one <history> in the main <article-meta> and additional <history> elements in one or more sub-articles’ <front-stub>, or multiple sub-articles each with their own <history>. The check should be scoped per container (each <article-meta> and each <front-stub> independently) and report duplicates within that specific parent.
| # Check if article type is exempt | ||
| is_exempt = self.article_type in EXEMPT_ARTICLE_TYPES | ||
|
|
||
| # Get all date-types from history | ||
| history_dates = self.xmltree.xpath(".//history/date") | ||
| found_date_types = [d.get("date-type") for d in history_dates if d.get("date-type")] | ||
|
|
There was a problem hiding this comment.
validate_required_dates() computes found_date_types from all .//history/date in the entire XML tree. If a sub-article has received/accepted, it can incorrectly satisfy the requirement for the main article (or vice-versa), and exemption is computed from a single self.article_type. This should validate required dates per <history> context (per article/sub-article) using that context’s @article-type, otherwise missing required dates can be silently missed.
| def validate_history(xmltree, params): | ||
| """Validate the <history> element according to SPS 1.10 rules.""" | ||
| rules = {} | ||
| rules.update(params.get("history_dates_rules", {})) | ||
| validator = HistoryValidation(xmltree, rules) | ||
| yield from validator.validate() |
There was a problem hiding this comment.
This integration passes params.get("history_dates_rules", {}) into HistoryValidation, but validation_rules/history_dates_rules.json currently defines keys like error_level and date_list, while HistoryValidation expects per-rule keys like history_uniqueness_error_level, required_date_error_level, etc. As written, the JSON configuration is effectively ignored (defaults always win), and the date_list/error_level payload is unused. Consider adding a dedicated history_rules.json with the keys HistoryValidation consumes, or adapting HistoryValidation to use the existing history_dates_rules schema (e.g., drive required/allowed types and error levels from it).
| self.assertTrue(all(r["response"] == "OK" for r in results)) | ||
| self.assertTrue(all(r["response"] == "OK" for r in results)) | ||
|
|
There was a problem hiding this comment.
There is a duplicated assertion (self.assertTrue(all(r["response"] == "OK" for r in results))) immediately repeated. It doesn’t add coverage and makes the test noisier; consider removing the duplicate line.
| def _get_parent_info(self, node=None): | ||
| """Build parent information for validation responses.""" | ||
| article = self.xmltree.find(".") | ||
| return { | ||
| "parent": "article-meta" if node is None else node.tag, | ||
| "parent_id": None, | ||
| "parent_article_type": self.article_type, | ||
| "parent_lang": article.get("{http://www.w3.org/XML/1998/namespace}lang") if article is not None else None, | ||
| } |
There was a problem hiding this comment.
_get_parent_info() sets parent to node.tag for date-level validations (so responses will have parent="date"). In other validators, parent identifies the container document (article / sub-article) plus parent_id, parent_article_type, and parent_lang (e.g., ArticleDoiValidation and XMLPeerReviewValidation). Aligning with that convention will make orchestrator outputs consistent and avoids mixing container context with the validated element (which is already represented by item/sub_item).
O que esse PR faz?
Implementa validações estruturais para o elemento
<history>conforme especificação SPS 1.10, alcançando 83% de conformidade (10 de 12 regras), superando a meta de 75%.Integração com orquestrador: O módulo de validação foi completamente integrado aos arquivos
xml_validator.pyexml_validations.py, permitindo execução automática das validações como parte do pipeline completo de validação.Regras implementadas:
@date-type, valores permitidos, datas obrigatórias (received/accepted), completude de datas críticas, presença de anodates.py(formato dia/mês, validação de data)Tipos de artigo isentos reconhecidos: correction, retraction, addendum, expression-of-concern, reviewer-report
Onde a revisão poderia começar?
packtools/sps/validation/history.py- Lógica de validação (384 linhas)packtools/sps/validation/xml_validations.py- Integração com orquestrador (funçãovalidate_history)packtools/sps/validation/xml_validator.py- Grupo de validação no pipelinetests/sps/validation/test_history.py- Cobertura de testes unitários (30 casos, 100% aprovados)tests/sps/validation/test_history_integration.py- Testes de integração com orquestrador (5 casos, 100% aprovados)Como este poderia ser testado manualmente?
Teste direto do módulo:
Teste via orquestrador (NEW):
Casos de teste:
errorsvazio@date-type→ erro CRITICAL<history>→ erro ERRORAlgum cenário de contexto que queira dar?
Decisões de design:
history.py) vs. validação de formato (dates.py)build_response()e validadores de formato existentesvalidate_X()→ yield no pipelineIntegração com orquestrador:
xml_validations.py: Adicionadovalidate_history()que recebe xmltree e params, retorna generator de resultadosxml_validator.py: Adicionado grupo "history" ao pipeline de validação (posicionado próximo a "article dates")history_dates_rules.jsonjá existente no diretóriovalidation_rulesTestes e segurança:
Valores permitidos para
@date-type:received,accepted,corrected,expression-of-concern,pub,preprint,resubmitted,retracted,rev-recd,rev-request,reviewer-report-receivedScreenshots
N/A
Referências
packtools/sps/validation/article_doi.pypacktools/sps/validation/xml_validations.pyOriginal 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
<history>conforme a especificação SPS 1.10, aumentando a conformidade de X% para 75% (9 de 12 regras).Nota: Algumas validações para
<history>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
<history>agrupa as datas de histórico do documento (recebido, aceito, revisado, preprint, correções, retratações, etc.). Validações corretas garantem que datas obrigatórias estejam presentes, que formatos sejam consistentes (dois dígitos para dia/mês), e que apenas valores permitidos sejam usados para@date-type.Conformidade atual: X de 12 regras implementadas (X%)
Meta após implementação: 9 de 12 regras (75%)
Documentação SPS
Referência oficial: https://docs.google.com/document/d/1GTv4Inc2LS_AXY-ToHT3HmO66UT0VAHWJNOIqzBNSgA/edit?tab=t.0#heading=h.history
Regras principais conforme SPS 1.10:
Ocorrência:
<history>deve aparecer no máximo uma vez em<article-meta>ou<front-stub>Datas obrigatórias:
<date date-type="received">é obrigatório (exceto para errata, retratação, adendo, manifestação de preocupação e parecer)<date date-type="accepted">é obrigatório (exceto para errata, retratação, adendo, manifestação de preocupação e parecer)Valores permitidos para
@date-type:received- Data de recebimento do manuscritoaccepted- Data de aceitação do manuscritocorrected- Data de aprovação de Errata ou Adendoexpression-of-concern- Data de aprovação de Manifestação de Preocupaçãopub- Data de publicaçãopreprint- Data de publicação como preprintresubmitted- Data de reenvio do manuscritoretracted- Data de aprovação de retrataçãorev-recd- Data de recebimento do manuscrito revisadorev-request- Data de solicitação de revisõesreviewer-report-received- Data de envio de parecer (exclusivo para@article-type="reviewer-report")Elementos obrigatórios por tipo de data:
received,accepted,corrected,retracted,expression-of-concern:<day>,<month>e<year>são obrigatórios<year>é obrigatórioFormato obrigatório:
<day>deve ter dois dígitos:01,02, ...,31<month>deve ter dois dígitos:01,02, ...,12Validação de data:
<day>,<month>e<year>devem formar uma data válidaRegras a Implementar
P0 – Críticas (implementar obrigatoriamente)
<history><history>deve aparecer no máximo uma vez em<article-meta>ou<front-stub>@date-typeem<date>@date-typeé obrigatório em todos os<date>dentro de<history>@date-type@date-typedeve estar na lista de valores permitidos<date date-type="received">@date-type="received"é obrigatória (exceto para errata, retratação, adendo, manifestação de preocupação e parecer)<date date-type="accepted">@date-type="accepted"é obrigatória (exceto para errata, retratação, adendo, manifestação de preocupação e parecer)received,accepted,corrected,retracted,expression-of-concern:<day>,<month>e<year>são obrigatórios<year><year>deve estar presenteP1 – Importantes (implementar se possível)
<day>(dois dígitos)<day>deve ter exatamente dois dígitos (01-31)<month>(dois dígitos)<month>deve ter exatamente dois dígitos (01-12)<day>,<month>e<year>devem formar uma data válida (ex: 31/02 é inválido)P2 – Futuras (fora do escopo deste Issue)
reviewer-report-receivedcom@article-type="reviewer-report"💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.