Skip to content

feat(export): preserve canonical NewsDOM JSONL artifacts atomically - #791

Draft
seonghobae wants to merge 12 commits into
developfrom
feature/export-jsonl-7558109478667000697
Draft

feat(export): preserve canonical NewsDOM JSONL artifacts atomically#791
seonghobae wants to merge 12 commits into
developfrom
feature/export-jsonl-7558109478667000697

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

범위

tools/export_jsonl.py는 NewsDOM의 canonical response model을 그대로 소비해 article 단위 JSONL artifact를 만듭니다. exporter가 별도 schema truth를 만들거나 malformed node를 silent-skip하지 않습니다.

  • protected base: develop@e06b1f3fb10903569124af011da213951e6e2473
  • exact head: 10b85cce7b12b6c11d4a9817cba200fb1918e841
  • Draft / mechanically mergeable

계약

  • 입력 전체를 production API와 같은 ParseResponse로 검증합니다.
  • 각 record는 document_id, page_number와 canonical ArticleNode.model_dump(mode="json") 전체를 보존합니다. bbox, images, captions, footnotes, body_blocks provenance를 축소하지 않습니다.
  • input과 동일 path 또는 hard-link alias를 output으로 지정하면 쓰기 전에 거부합니다.
  • 기존 output은 완성된 새 artifact가 준비되기 전까지 보존합니다. destination과 같은 directory의 temporary artifact에 전체 JSONL을 직렬화하고 flush/fsync 뒤 os.replace()로 publish하며 실패 시 temp를 제거합니다.

RED → GREEN lineage

  • canonical fidelity RED e1f6e0c85ab886e4d403acb8b452c5222cbcc061 → GREEN 6894960e6b67d25a32dfce7d98cf66a0c6497a46
  • input overwrite RED 9fe476719b73befd6342e126c62571d4bf5bcd60, hard-link RED f341bb1f45625662506a1e718eebf94a11d356a6 → GREEN 934da87ae774a46a80ff681555015370f63388d3
  • partial replacement RED 4ee1fe616bfd9986d12c12c980cba23546b8a36b → atomic publish GREEN 50fdd8170a3bcf4c24e6e9a3d0f8115013327615
  • code-current decisions/Gaps are recorded in docs/product-technical-gap-baseline.md.

Successor consolidation

Generated PR #810 adds another tools/export_jsonl.py, but its valid product intent is fully represented here: JSON input checks, .json extension rejection, invalid-JSON error mapping, article-per-line JSONL output, CLI success/error behavior, UTF-8/ensure_ascii=False, tests, and CHANGELOG coverage.

#810 additionally silent-skips malformed pages/articles, invents Unknown identifiers, and replaces canonical body_blocks/provenance with a lossy body_text projection. Those are alternate schema semantics, not valid canonical NewsDOM contracts, and are intentionally not inherited. Its generated "100% coverage" statement is not exact-head hosted evidence.

Exact-head verification state

The latest known runs on unchanged exact head 10b85cce... are terminal but non-passing as a set: tests 33908836843, codeql 33908836910, ClusterFuzzLite 33908836854, container-image 33908836836, Security Scan 33908836822, SAST 33908837011, CodeQL PR 33908836983, and scorecards 33908836920 all concluded cancelled. They are not GREEN and predecessor results do not transfer.

Remaining gap / promotion boundary

The implementation still uses read_text() + json.loads() and therefore does not claim large-dataset streaming or bounded-memory behavior. Follow-up acceptance requires canonical fidelity and atomic publish to survive an incremental path plus real/right-cleared NewsDOM corpus peak-RSS/throughput evidence.

Keep Draft until unchanged exact-head applicable tests/security/static-analysis/review gates are terminal-valid. No source-neutral retrigger, self-approval, protection bypass, force update, or predecessor-evidence substitution.

@google-labs-jules

Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

@seonghobae
seonghobae marked this pull request as draft September 2, 2026 22:49

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 5 new potential issues.

Devin Review

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 연구 근거 자료 누락

새 내보내기 기능에 관련 논문 PDF가 없다. 재배포할 수 없다면 인용, 링크, 요약을 대신 추가해야 한다.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread tools/export_jsonl.py

from pydantic import ValidationError

from newsdom_api.schemas import ParseResponse

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 직접 실행 시 내보내기 시작 실패

소스 체크아웃에서 python tools/export_jsonl.py ...를 실행하면 newsdom_api.schemas를 찾지 못한다. 도구는 도움말과 내보내기를 시작하기 전에 종료된다.

Prompt for agents
tools/export_jsonl.py가 설치되지 않은 저장소 체크아웃에서도 다른 스키마 기반 CLI처럼 직접 실행되도록 수정한다. tools/validate_dom.py, tools/split_dom.py, tools/anonymize_dom.py는 저장소의 src 디렉터리를 sys.path에 추가한 뒤 newsdom_api.schemas를 import한다. export_jsonl.py에도 같은 실행 경로 지원을 적용하고, src가 sys.path에 없는 상태에서 스크립트의 --help 또는 실제 변환을 runpy/subprocess로 실행하는 회귀 테스트를 추가한다.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread tools/export_jsonl.py Outdated
except ValidationError as exc:
raise ValueError("Input is not canonical NewsDOM JSON") from exc

with output_path.open("w", encoding="utf-8") as jsonlfile:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 동일 경로 내보내기가 원본 삭제

입력과 출력에 같은 경로를 지정하면 export_jsonl이 검증된 원본을 JSONL로 덮어쓴다. 성공한 변환 뒤 원본 문서는 복구할 수 없다.

Prompt for agents
tools/export_jsonl.py의 export_jsonl에서 입력 파일과 출력 파일이 같은 실제 파일을 가리키는 경우 쓰기 전에 거부해 원본 손실을 막는다. 상대/절대 경로, 정규화된 동일 경로, 가능한 경우 심볼릭 링크나 하드 링크 별칭도 고려한다. 같은 경로를 전달했을 때 예외가 발생하고 입력 내용이 그대로 유지되는 회귀 테스트를 추가한다.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread tools/export_jsonl.py Outdated
Comment on lines +25 to +30
try:
document = ParseResponse.model_validate(data)
except ValidationError as exc:
raise ValueError("Input is not canonical NewsDOM JSON") from exc

with output_path.open("w", encoding="utf-8") as jsonlfile:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📝 Info: 검증 실패는 쓰기 전에 종료

ParseResponse.model_validate()가 출력 파일을 열기 전에 전체 문서를 검증한다. 잘못된 페이지나 기사는 부분 출력 없이 변환을 중단한다.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread tools/export_jsonl.py Outdated
Comment on lines +33 to +38
article_data = {
"document_id": document.document_id,
"page_number": page.page_number,
**article.model_dump(mode="json"),
}
jsonlfile.write(json.dumps(article_data, ensure_ascii=False) + "\n")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📝 Info: 기사 출처 정보 보존

기사 전체를 JSON 모드로 직렬화한다. 상위 식별자와 충돌하는 기사 필드가 없어 위치, 이미지, 캡션, 각주가 유지된다.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@seonghobae seonghobae changed the title ✨ NewsDOM JSON을 JSONL 포맷으로 내보내는 도구 추가 feat(export): preserve canonical NewsDOM JSONL artifacts atomically Sep 4, 2026
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