Skip to content

[Feat] 동일 원본 재수집을 원본 재게시 없이 재확인 원장 행으로 등록 - #911

Merged
AquilaXk merged 14 commits into
mainfrom
feat/same-raw-reverification-870
Oct 3, 2026
Merged

AquilaXk merged 14 commits into
mainfrom
feat/same-raw-reverification-870

Conversation

@AquilaXk

@AquilaXk AquilaXk commented Oct 2, 2026 •

Copy link
Copy Markdown
Owner

Related issue

Refs #870
Refs #862
Refs #903

Summary

  • 문제
    • 같은 공식 원본(바이트 sha256이 원장 head와 같음)을 다시 수집해 등록하면 두 곳에서 막혔습니다.
      • 코레일 게시기: 같은 UTC 날짜 키의 원본 객체가 이미 있으면 EXISTS로 실패했습니다. 대경선 재확인이 여기서 막혔습니다.
      • 수도권 시간표 등록기(KRIC 파일 900): snapshot 파일을 wx로 쓰다가 충돌했습니다.
    • 선례(2026-10-01·02 코레일 동일 파일 재확인)는 원본을 날짜 키로 다시 올렸습니다. 수도권은 재확인마다 16MB snapshot이 쌓일 구조였습니다.
  • 결과
    • 원본이 같으면 원본을 다시 게시하지 않습니다. 기존 객체를 실제로 읽어 확인한 뒤 재확인 기록만 append합니다.
      • 코레일: 원장 행
      • 수도권: inventory 재확인 이력
    • 원본이 다르면 기존 신규 등록 경로를 그대로 탑니다.

Changes

  • tools/datapack/lib/same-raw-reverification.mjs(공용, [Refactor] 데이터 파이프라인 운영 방식 전환: 자동 갱신·개발/발행 게이트 분리·생성 산출물 축소 #870 일일 자동 재확인에 재사용)
    • planRawObjectPublication: 원장 head와 원본 sha가 같으면 REVERIFY_EXISTING, 다르면 PUBLISH_NEW를 돌려줍니다. head의 크기나 URI가 맞지 않으면 실패합니다.
    • verifyReusedRawObject: 기존 OCI 객체를 GET으로 읽어 크기와 sha를 확인합니다. 객체가 없거나 다르면 실패합니다.
    • appendLedgerRow: append-only로 붙입니다. snapshot이 충돌하거나 head 계보가 맞지 않으면 실패합니다.
  • 코레일 원본 게시기(publish-korail-metropolitan-timetable-raw.mjs)
    • 원장 head와 원본이 같으면 PUT 없이 head 객체를 확인합니다.
    • 확인 결과로 korail-metropolitan-timetable-raw-reverification-receipt를 남깁니다. 기록 항목: verifiedAt, reusedFromSnapshotId
  • 대경선 topology 등록기(register-korail-route-topology.mjs)
    • 재확인 영수증은 원장 head 객체(URI, snapshot, sha, 크기)를 정확히 가리킬 때만 받습니다.
    • 새 원장 행에 rawObjectReusedFromSnapshotId를 남기고, appendLedgerRow로 잇습니다.
  • 계획 시간표 등록기(register-korail-timetable.mjs): 부모 topology가 재확인 행이면, 같은 기존 객체를 가리키는 재확인 영수증을 받습니다.
  • 수도권 시간표(kric-capital-timetable-records, capital-official-timetable, register-kric-capital-timetable). QA 결정(2026-10-03, B안)을 따랐습니다.
    • snapshot(schemaVersion 2)은 원본 내용만 담습니다. 관측 시각과 수집 파일명과는 무관하며, id와 records는 이전과 같습니다.
    • inventory capitalScheduleAdmissionEvidence.reverifications
      • 형식: [{observedAt, rawSha256, collectionReceiptSha256}], append-only
      • observedAt은 마지막 항목과 같고, prepare가 신선도 기준으로 씁니다.
    • 같은 원본이면 기존 snapshot을 재사용하고 파일을 쓰지 않습니다. 기존 snapshot 바이트와 records sha가 정확히 같아야 하며, 다르면 실패합니다.
    • 새 관측은 직전 관측보다 뒤여야 합니다. 이력 앞부분이 바뀌거나 지워지면 실패합니다.
    • 리뷰 F1 반영: 등록기는 --operation-directory만 받습니다.
      • 원본을 직접 수집(실제 GET·sha)하고, 같은 실행에서 만든 영수증만 씁니다. 외부 영수증 인자는 받지 않습니다.
      • 관측 시각이 실행 시계보다 미래이거나 1시간보다 오래되면 실패합니다.
    • 리뷰 F3 반영: 원본이 A → B → A로 돌아오면, 기존 snapshot 바이트가 같을 때만 재사용합니다.
  • 리뷰 F4 반영: 재확인은 실제 GET 본문으로 sha를 계산하는 저장소 클라이언트(verifiesObjectBytes: true, PAR 클라이언트)만 받습니다.
  • purge-expired-source-raw.mjs
    • 같은 object key는 같은 원본 hash일 때만 공유를 허용합니다. hash가 다르면 conflicting object key로 거부합니다.
    • 참조하는 entry 가운데 하나라도 보호 중이면 보호하고, 하나라도 만료 전이면(가장 늦은 만료 전) 보존합니다. 모두 만료됐을 때만 삭제합니다.
  • 데이터
    • 기존 수집본(2026-10-02T15:57:05.773Z, raw 218f76dd…)으로 수도권 snapshot을 새 형식으로 다시 등록했습니다. 관측 시각은 그대로입니다.
    • 전국 후보를 재생성했습니다(seq125). 팩과 외부 시간표 파일 바이트는 바뀌지 않았습니다.

Scope

Included

  • 같은 원본 재확인 등록에 쓰는 공용 lib
  • 코레일 topology 게시·등록과 계획 시간표 등록
  • 수도권 시간표 등록
  • purge 공유 객체 가드
  • 수도권 snapshot 형식 전환에 따른 후보 재생성

Excluded

Ownership / dependencies

Contract & Compatibility

  • Source / API / schema contract
    • 새 외부 API나 원천은 없습니다. 카탈로그 대조 대상이 아닌 파이프라인 도구 변경입니다.
    • 기존 원천 kric-nationwide-timetable-file, korail-metropolitan-timetable-file의 등록 계약만 확장했습니다.
  • Artifact / provenance identity
    • 재확인 원장 행은 기존 원본 객체 URI를 참조하고, rawObjectReusedFromSnapshotId로 출처 행을 남깁니다.
    • 수도권 snapshot id는 records sha 기반이라 그대로입니다. 관측 시각은 evidence 재확인 이력에서 정합니다.
  • Backward compatibility
    • 기존 신규 게시 영수증(korail-metropolitan-timetable-raw-receipt)과 기존 원장 행은 그대로 받습니다.
    • 수도권 snapshot schemaVersion 1(observedAt 포함)은 더 이상 받지 않습니다. 커밋된 snapshot은 이 PR에서 전환했습니다.
  • Migration or cutover: 수도권 snapshot 재등록과 후보 재생성을 이 PR에 담았습니다.

Version impact

  • no version change
  • datapack release only
  • route-map artifact change
  • data contract change
  • product gate JSON change
  • CI workflow·계약 테스트 change

Product gate impact

  • release/product-gates/** 영향 없음
  • 변경한 gate의 근거를 갱신했습니다.
  • 검증되지 않은 지원 범위 claim을 추가하거나 확대하지 않습니다.

Provenance impact

  • source inventory·geometry provenance manifest 영향 없음
  • 제공처·라이선스·갱신 시점·적용 범위를 갱신했습니다.
  • 공식 source로 확인되지 않은 값을 배포 artifact에 추가하지 않습니다.

Version decision

  • datapack version: 후보 releaseSequence 125(nationwide-candidate-20261002-seq125). 발행은 이 PR 밖에서 합니다.
  • data contract: 수도권 snapshot schemaVersion 2, 재확인 영수증 kind 추가, inventory reverifications
  • route-map artifact / product gate: 변경 없음
  • promotion request id: release-request-nationwide-candidate-20261002-seq125

Verification

Check Result / Evidence
Focused RED → GREEN 아래 "RED와 GREEN" 참고
Affected integration 아래 "통합 테스트" 참고
Required CI PR CI 결과로 확인합니다
Live provider / release 아래 "실제 원본 재확인" 참고
Security / data integrity 기존 객체를 실제 GET으로 확인합니다(sha·크기). 재확인 영수증은 head와 정확히 결속돼야 하고, 원장과 이력은 append-only입니다. purge는 공유 객체를 보존합니다.

RED와 GREEN

  • RED: 테스트를 먼저 커밋한 상태에서 실패를 확인했습니다.
    • 코레일 쪽
      • lib 테스트 파일은 모듈이 없어 실패했습니다.
      • 게시기 재확인 테스트 2건이 실패했습니다.
      • 등록기 테스트 2건이 RAW_RECEIPT, PUBLICATION_RECEIPT로 실패했습니다.
    • purge: 공유 객체 테스트 4건이 실패했습니다.
    • 수도권
      • snapshot 관측 무관 테스트와 lib 테스트가 실패했습니다.
      • 등록 계획 테스트 파일은 모듈이 없어 실패했습니다.
  • GREEN
    • register-korail-timetable 10건, 게시기·lib 테스트 통과
    • purge-expired-source-raw 40건 통과
    • 수도권 lib·등록 테스트 15건 통과
  • mutant: 등록기의 head 결속 검사(assertReverificationReceiptMatchesHead 호출)를 제거하면 테스트가 실패합니다.

통합 테스트

  • 영향 테스트 묶음(korail·원장·purge·수도권·팩·inventory·후보 관련 테스트 파일): 2,075건 모두 통과했습니다.
  • 파일을 쓰는 테스트(prepare, capital-official-timetable, canonical-pack-* 2개, regional-timetable-official-stop-times)는 직렬로 돌려 모두 통과했습니다.
  • 문서 파편 --check: IN SYNC

실제 원본 재확인

  • KRIC 파일 900을 다시 수집했습니다(2026-10-02T22:25:12Z, raw sha256 218f76dd…로 이전과 같음).
  • 임시 저장소 사본에서 registerKricCapitalTimetable을 실행한 결과는 REVERIFY_EXISTING이었습니다.
    • snapshot 파일 바이트는 바뀌지 않았습니다(cmp 일치).
    • reverifications가 2건으로 append됐고, observedAt이 갱신됐습니다.

Not run

  • Check 1: 코레일 대경선 실제 재수집과 OCI 재확인 실행
    • Reason: 데이터 PR과 운영 실행 범위입니다. OCI PAR 키가 필요합니다.
    • Rerun owner / condition: 메인 세션이 맡습니다. 대경선 데이터 갱신 PR에서 register-korail-route-topology.mjs publish-register로 실행합니다.
  • Check 2: collect-korail-itx-cheongchun-timetable.test.mjs
    • Reason: 로컬 SQLite 3.53.3 런타임 고정 조건 때문에 로컬에서는 실행할 수 없습니다. CI에서 실행됩니다.

Risk

  • Level: High
  • Main risk
    • 공유 원본 객체의 보존
      • purge는 공유 객체를 가장 늦은 만료와 보호에 맞춰 보존합니다.
      • 다만 retention ledger 생성기와 purge workflow는 아직 없습니다. 지금은 가드와 테스트만 넣은 상태입니다.
    • 수도권 snapshot 형식 전환(schemaVersion 2): 이전 형식은 더 이상 받지 않습니다.
  • Failure behavior: 다음 경우 등록이 실패하고 아무것도 쓰지 않습니다.
    • head와 결속이 맞지 않음
    • 기존 객체를 읽을 수 없거나 크기·sha가 다름
    • records 불일치
    • 관측 시각 역전
    • 재확인 이력 변조
  • Candidate / admission / publication state on failure: 원장과 inventory는 바뀌지 않습니다(트랜잭션 원복과 단일 쓰기).
  • Fallback or degraded-success path introduced: No

Rollout / Recovery

  • Rollout or promotion: 병합한 뒤 데이터 PR에서 재수집과 재확인 등록을 실행합니다. 수도권 시간표 신선도 연장과 대경선 재확인이 대상입니다.
  • Monitoring / success signal: 재확인 등록 결과가 REVERIFY_EXISTING이고, 원장과 이력이 1건 append됩니다.
  • Rollback or recovery: 이 PR을 revert하면 이전 등록 경로로 돌아갑니다. 커밋된 수도권 snapshot도 revert로 복원됩니다.
  • Existing artifact / schema compatibility after rollback: 원장의 기존 행은 바뀌지 않아 호환됩니다.

Review focus

  • 재확인 영수증과 원장 head의 결속(URI, snapshot, sha, 크기)
  • 수도권 재확인 이력의 append-only 보장과 관측 시각 규칙
  • purge 공유 객체 규칙(보호·만료 결합, hash 충돌 거부)

Checklist

  • 이슈 범위와 실제 diff가 일치합니다.
  • 관련 없는 변경이나 다른 owner의 surface를 포함하지 않았습니다.
  • 위험에 필요한 검증과 미실행 사유를 기록했습니다.
  • 실패·호환성·promotion·recovery 동작이 명확합니다.
  • current failure를 이전·stale·alternate 결과의 성공으로 바꾸지 않습니다.
  • GitHub PR Review 객체가 있는지 확인했습니다. CodeRabbit status check만으로는 리뷰 완료로 보지 않습니다.
  • CodeRabbit Review 객체가 없으면 지원되는 Codex CLI 폴백 Review를 단일 GitHub PR Review로 게시했습니다.
  • datapack 배포 영향이 있는 경우 release workflow 상태를 확인했습니다.

- lib/same-raw-reverification: 원장 head와 원본 sha가 같으면 REVERIFY_EXISTING(기존 객체 재사용),
  다르면 PUBLISH_NEW. head 크기·URI 불일치, 기존 객체 미존재·크기·sha 불일치는 실패. 원장 append-only 헬퍼.
- 코레일 원본 게시기: 같은 원본이면 PUT 없이 head 객체를 읽어 확인하고 재확인 영수증을 남긴다
  (같은 UTC 날짜 키 EXISTS로 막히던 대경선 재확인 해소).
- 대경선 topology 등록기: 재확인 영수증이 원장 head 객체를 정확히 가리킬 때만 받고, 재확인 행에
  rawObjectReusedFromSnapshotId를 남긴다. 원장은 append-only 헬퍼로 잇는다.
- 계획 시간표 등록기: 부모 topology가 재확인 행이면 같은 기존 객체를 가리키는 재확인 영수증을 받는다.

Refs #870
Refs #862
Refs #903
같은 원본 재확인 행이 기존 원본 객체를 공유하므로(#870), purge는 같은 object key를 같은 원본 hash일 때만
허용하고(다르면 conflicting object key로 거부), 참조 entry 중 하나라도 보호되면 보호, 하나라도 만료 전이면
보존한다. 모두 만료됐을 때만 공유 객체를 삭제한다.

Refs #870
QA 결정(2026-10-03, #870 B안): 같은 원본 재수집마다 13.8MB snapshot을 쌓지 않는다.
- snapshot(schemaVersion 2)은 원본 내용만 담고 관측 시각·수집 파일명과 무관하다.
- inventory capitalScheduleAdmissionEvidence.reverifications: [{observedAt, rawSha256, collectionReceiptSha256}]
  append-only 이력. evidence.observedAt은 마지막 항목과 같고, prepare 신선도 기준이다.
- 등록기: 같은 원본이면 기존 snapshot 바이트·records sha가 같을 때만 재사용(파일 미작성), 다르면 실패.
  다른 원본이면 새 snapshot. 새 관측은 직전 관측보다 뒤여야 하고 이력 앞부분은 바뀌면 안 된다.

Refs #870
Refs #899
기존 수집본(2026-10-02T15:57:05.773Z, raw sha256 218f76dd…)으로 register-kric-capital-timetable.mjs를
다시 실행했다. snapshot(schemaVersion 2)에서 observedAt·rawFile을 빼고(id·records 동일), inventory
evidence에 reverifications 첫 항목을 둔다. 관측 시각은 그대로다.

Refs #870
…6-10-02T22:25:42.708Z)

공식 refresh-nationwide-candidate.mjs(--evaluated-at 2026-10-02T22:25:42.708Z --release-sequence 125
--requested-by data-operator-lead --approved-by data-release-authority). 팩·외부 시간표 파일 바이트는 같다.

Refs #870
@coderabbitai

coderabbitai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f8dd1664-a0ad-4ee6-a09b-fa743645ae26
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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.

@AquilaXk
AquilaXk marked this pull request as ready for review October 2, 2026 23:10

@AquilaXk AquilaXk left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🎯 Linked issue & acceptance criteria audit
ID Acceptance criterion Status Evidence
AC-1 New publication only when content changed; same raw is reverified PASS tools/datapack/lib/same-raw-reverification.mjs
AC-2 Failed reverification stays explicit with no fallback success PASS tools/datapack/publish-korail-metropolitan-timetable-raw.mjs
AC-3 Same-date snapshot re-registration no longer blocks PASS tools/datapack/register-kric-capital-timetable.mjs
🛡️ Adversarial audit evidence
  • Falsifiability verified: Yes (Manual mutants of purge ordering, capital order checks and OCI authority were killed.)
  • Hollow assertions detected: 0
  • Production backdoors detected: 0
  • Ground-truth sources verified:
    • Committed capital snapshot records sha unchanged
    • Issue 870 same-raw and Fallback rules
    • preauthenticatedObjectStorageClient GET plus sha verification
  • Mutation testing evidence: Survivors: receipt byteSize and register-korail-timetable receipt field comparisons.
🤖 Prompt for all review comments with AI agents
Could we verify each finding against the current code and keep only those that
still apply? Could we make the smallest validated fix and briefly note why any
finding no longer applies?

Inline comments:
- `@tools/datapack/lib/same-raw-reverification.mjs:50-50`
  Could the helper call readObject and hash the body itself, or assert the
  client kind, so the actual-bytes guarantee does not depend on the caller?
- `@tools/datapack/lib/same-raw-reverification.mjs:58-63`
  Could a table-driven rejection test tamper each bound receipt field one at a
  time and expect RECEIPT_HEAD or PUBLICATION_RECEIPT? That would make each
  binding falsifiable.
- `@tools/datapack/register-kric-capital-timetable.mjs:75-75`
  Could registration require capturedAt to be at or before the injected clock and
  within a short window of it, and cross-check the date in rawFile? Adding a test
  with a forged receipt that keeps the sha but advances capturedAt would prove it.
- `@tools/datapack/register-kric-capital-timetable.mjs:92-92`
  Should the plan compare against an existing snapshot file by bytes and reuse it,
  as the REVERIFY branch does? A test for A to B to A would pin the behavior.

---

Outside diff comments:
None.

ℹ️ Review info
⚙️ Run configuration

Configuration used: aquila-review skill run by Claude Code with hub CLAUDE.md invariants

Review profile: ASSERTIVE

Plan: Aquila fallback

Run ID: N/A (Aquila fallback)

Review source: Aquila CLI

Repository visibility: public GitHub repository

Trigger:
Discovery review of the current change set for the automerge review gate

Base:
main@c8f83ea1c54ad7110ff51dcff85d4fb3e4ae06cb

Head:
lib/same-raw-reverification@e7cc6ba82df6a698f798d9c84946ab9cda38df58

Command:
node scripts/compile-review-payload.mjs input.json --output payload-1.json

📥 Commits

Reviewing files changed in this pull request between:

  • Base: c8f83ea1c54ad7110ff51dcff85d4fb3e4ae06cb
  • Head: e7cc6ba82df6a698f798d9c84946ab9cda38df58
📒 Files selected for processing (25)
  • contracts/documentation/documentation-fragment.json
  • tools/ci/data-test-ownership.json
  • tools/datapack/lib/capital-official-timetable.mjs
  • tools/datapack/lib/capital-official-timetable.test.mjs
  • tools/datapack/lib/kric-capital-timetable-records.mjs
  • tools/datapack/lib/kric-capital-timetable-records.test.mjs
  • tools/datapack/lib/same-raw-reverification.mjs
  • tools/datapack/lib/same-raw-reverification.test.mjs
  • tools/datapack/publish-korail-metropolitan-timetable-raw.mjs
  • tools/datapack/publish-korail-metropolitan-timetable-raw.test.mjs
  • tools/datapack/purge-expired-source-raw.mjs
  • tools/datapack/purge-expired-source-raw.test.mjs
  • tools/datapack/register-korail-route-topology.mjs
  • tools/datapack/register-korail-timetable.mjs
  • tools/datapack/register-korail-timetable.test.mjs
  • tools/datapack/register-kric-capital-timetable.mjs
  • tools/datapack/register-kric-capital-timetable.test.mjs
  • tools/datapack/release/candidate-build-spec.json
  • tools/datapack/release/current-five-region-source-fan-in.json
  • tools/datapack/release/hash-evidence.json
  • tools/datapack/release/nationwide-candidate-preparation.json
  • tools/datapack/release/release-request.json
  • tools/datapack/reports/nationwide-requirement-ownership-ledger.json
  • tools/datapack/source-inventory.json
  • tools/datapack/sources/kric-nationwide-timetable-file-capital-dec3ef2fdb5318efd9cff47c6b012e88c80c34f7b4866106eabbed6e1e7bdd00.json
📜 Review details

Comment thread tools/datapack/lib/same-raw-reverification.mjs
Comment thread tools/datapack/lib/same-raw-reverification.mjs
Comment thread tools/datapack/register-kric-capital-timetable.mjs
Comment thread tools/datapack/register-kric-capital-timetable.mjs
- 등록기가 원본을 직접 받아(실제 GET·sha 계산) 같은 실행의 수집 영수증만 쓴다. --workbook/--receipt
  외부 영수증 인자를 없앴다(--operation-directory만). 손으로 고친 capturedAt이 끼어들 경로가 없다.
- 등록 계획은 실행 시계를 받아 관측 시각이 미래이거나 1시간보다 오래되면 실패한다(18MB 다운로드·파싱 수 분 +
  느린 망·시계 오차 여유).

Refs #870
- lib: rawObjectUri·reusedFromSnapshotId·rawObjectSha256·byteSize를 각각 바꾸면 RECEIPT_HEAD로 실패
- 계획 시간표 등록기 재확인 분기: rawObjectUri·reusedFromSnapshotId·byteSize·collectionReceiptSha256을
  각각 바꾸고 부모 원장 영수증 hash는 다시 맞춘 경우 PUBLICATION_RECEIPT로 실패
- topology 등록기 재확인 영수증: byteSize·collectionReceiptSha256 변조 사례 추가
각 비교를 지운 mutant 6개가 모두 죽는다.

Refs #870
원본이 A → B → A로 돌아오면 A snapshot 파일이 이미 있어 PUBLISH_NEW의 wx 쓰기가 EEXIST로 실패했다.
기존 파일 바이트가 같으면 다시 쓰지 않고 재사용하고, 다르면 SNAPSHOT_MISMATCH로 실패한다.

Refs #870
서명(S3 호환) 클라이언트의 verifyObject는 HEAD 메타데이터만 비교한다. 재확인은 verifiesObjectBytes: true
(실제 GET 본문으로 크기·sha256 계산)를 표시한 클라이언트만 받고, 없으면 SAME_RAW_REVERIFICATION_STORAGE로
실패한다. PAR 클라이언트에 이 능력을 표시하고, HEAD 전용 fake가 거부되는 테스트를 더했다.

Refs #870
@AquilaXk AquilaXk added the automerge FIFO 병합 큐 대상 — 코디네이터가 순서대로 update-branch 후 auto-merge label Oct 3, 2026
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@AquilaXk
AquilaXk merged commit 7f1594b into main Oct 3, 2026
15 checks passed
@AquilaXk
AquilaXk deleted the feat/same-raw-reverification-870 branch October 3, 2026 00:03
@sonarqubecloud

sonarqubecloud Bot commented Oct 3, 2026

Copy link
Copy Markdown

AquilaXk added a commit that referenced this pull request Oct 3, 2026
* [Data] 대경선 코레일 광역전철 시각표 topology 동일 원본 재확인 등록(P7D)

- 공식 첨부(sha c28dcd…)를 2026-10-03T00:05Z에 재수집해 원본 재게시 없이 재확인 원장 행으로 등록한다(#911 경로).
- topology head를 5d68004f…에서 a2fee5ce…로 잇고 freshUntil은 2026-10-10T00:05Z다.

Refs #903 #862

* [Data] 대경선 계획 시각표를 재확인한 topology head에 다시 결속해 등록

- planned timetable을 topology a2fee5ce…에 결속해 재등록한다(동일 원본, 운행 194 trip).
- 달력 창은 2026-10-03~2026-11-02(KASI 10·11월), freshUntil은 2026-11-02T00:05Z다.
- materializeKorailTimetable 부모 불일치(PARENT)가 해소된다(10-03·10-08 시각 건식 실행 194 trip).

Refs #903 #862

* [Feat] 코레일 6개 노선 projection·station-lines 스냅샷을 공용 시간표 적재기 입력으로 연결하는 lib

- 수도권 등록기가 같은 관측에서 코레일 projection snapshot을 만들고 korailScheduleAdmissionEvidence에 결속한다
  (재확인 이력 append-only, 수도권과 같은 관측 시각).
- 코레일 provider: 휴일→WEEKEND_HOLIDAY, alias 근거 동반, 급행은 trip 단위 고정 집합(경춘 5·수인분당 22·경의중앙 28).
- station-lines provider: 등록 파생 스냅샷의 내용 해시·inventory 결속을 다시 확인하고 trip을 그대로 넘긴다.

Refs #903 #862

* [Data] KRIC 파일 900 재수집: 수도권 동일 원본 재확인과 코레일 6개 노선 projection 첫 등록

- 2026-10-03T00:11Z 재수집(원본 sha 218f76dd…). 수도권 snapshot은 재사용하고 재확인 이력만 append한다.
- 같은 관측에서 코레일 projection(59,346행, snapshot c186585e…)을 korailScheduleAdmissionEvidence로 등록한다.

Refs #903 #862

* [Chore] Hub data 계약 pin을 905ae116(#3025, planned_timetable station-lines 포함)으로 상향

Refs #903

* [Data] KRIC 역별 시간표 5개 노선(kric-subway-timetable-station-lines) 첫 등록과 필수 원천 지정

- 2026-10-03T00:12Z 실수집(응답 210, 3,956 trip, 기대값 일치), OCI 원본 게시(sha 3a8c462a…), 명시 검토 admission
  (data-release-authority, QA 승인 2026-10-03 채팅: 출시 범위 전 노선 공식 시간표 적재)으로 등록한다.
- governance(kric-subway-timetable과 같은 약관)·freshness(planned_timetable)·원장·inventory·파생 스냅샷을 한 트랜잭션으로 쓴다.
- production scope requiredSourceIds에 추가한다.

Refs #903 #862

* [Feat] 전국 후보 prepare에 코레일 6개 노선·KRIC 역별 5개 노선·대경선 시간표 적재 연결

- 코레일 projection(korailScheduleAdmissionEvidence)은 수도권과 같은 inventory evidence·정책 신선도로 고르고,
  대경선 계획 시각표·station-lines 파생 스냅샷은 원장 head·fan-in으로 고른 뒤 내용 해시를 원장·inventory와 대조한다.
- 두 원천은 공용 적재기로 싣고 station-lines는 외부 시간표 파일(sidecar) 원천에 추가한다. 코레일은 수도권과 같은
  원천의 두 번째 섹션이 된다. 노선별 요약·격리 행은 nationwide-official-line-timetable-report.json에 남긴다.
- 대경선은 materializeKorailTimetable로 싣는다. e2e에 '팩의 전 노선 trip 1건 이상' 단언을 추가한다(RED).

Refs #903 #862

* [Test] e2e 후보 건수를 노선 추가분만큼 갱신하고 입력 선택 17개로 고정

- trip 19,973→26,240, 정차 561,983→671,914, route 26→39, 달력 24→30, 달력 예외 132→200.
  증가분은 코레일 6개 노선·KRIC 역별 5개 노선·대경선뿐이고 기존 노선 건수는 같다.

Refs #903

* [Data] 전국 후보 재생성(seq125, 후보 시계 2026-10-03T00:17:16.988Z): 전 노선 시간표 적재

- 노선 36개 전부 trip 1건 이상(이전 12개 노선 0건). trip 26,240·정차 671,914.
- 팩 JSON 59,147,366B, 외부 시간표 파일 gzip 5,641,204B(펼침 58,866,238B).

Refs #903 #862

* [Test] 새 등록 데이터에 맞춰 저장소 상태 의존 테스트를 갱신

- 수도권 외부 시간표 단언은 같은 원천의 코레일 섹션과 구분하도록 snapshot으로 고른다.
- 대경선 재확인 head의 신선도 값과 이전 head lineage를 반영한다.
- car-door 등록 테스트의 'inventory·governance 끝' 위치 가정을 '하나만, 기존이면 제자리'로 바꾼다.
- station-lines 등록·게시 테스트는 저장소 사본을 등록 전 상태로 되돌려 첫 등록부터 시험한다.

Refs #903

* [Data] station-lines·코레일 evidence 등록에 따른 전국 coverage tally 재생성

Refs #903

* [Data] coverage tally 재생성 뒤 전국 후보 재결속(seq125, 후보 시계 2026-10-03T00:25:30.412Z)

- 팩·외부 시간표 파일 바이트는 같고 fan-in·소유권 원장·spec·request·hash 결속만 갱신된다.

Refs #903 #862

* [Data] 수도권·인천 현행 topology 입력 재수집(2026-10-03)

current-capital-topology-refresh 절차와 같은 공식 수집기 출력 4개다(ITX admission은 10-11까지 유효해 재수집하지 않는다).

Refs #903 #862

* [Data] 수도권 현행 topology admission 활성화(2026-10-03 수집 입력)

activate-current-source-set --topology-source-admission 결과(inventory·canonical pack·재검증 증거)다.

Refs #903 #862

* [Data] 수도권 topology 원본 OCI 게시·원장 등록(capital-route-topology-20261003)

run-current-capital-route-topology-registration 결과다.

Refs #903 #862

* [Data] 광주 topology 재수집·OCI 게시·원장 등록(2026-10-03, 원본 sha 동일)

register-gwangju-route-topology publish-register 결과다. 같은 도구가 topology에 묶인 접근성·노선도 위치 snapshot 결속을 새 topology로 다시 맞췄다.

Refs #903 #862

* [Data] 부산 topology 재수집·OCI 게시·원장 등록(2026-10-03, 원본 sha 동일)

register-busan-route-topology publish-register 결과다.

Refs #903 #862

* [Data] 대전 역간 거리·운임 topology 재수집·OCI 게시·원장 등록(2026-10-03, 원본 sha 동일)

register-daejeon-route-topology publish-register 결과다. 같은 도구가 topology에 묶인 접근성·노선도 위치 snapshot 결속을 다시 맞췄다.

Refs #903 #862

* [Data] 대구 1·2·3호선 topology·시간표 재수집·OCI 게시·원장 등록(2026-10-03, 원본 sha 9개 모두 동일)

register-daegu-datapack-sources publish-register 결과다. data.go.kr 파일은 #890 미해결로 포털 다운로드 버튼과 같은 경로(임시 방식, 키 없음)로 받았다.

Refs #903 #862 #890

* [Data] 대전·광주 접근성 재수집·OCI 게시·원장 등록(2026-10-03, 원본 sha 동일)

topology 재등록이 접근성 결속을 새 topology 계보로 바꿔서, #892와 같이 접근성을 다시 수집해 원장 행을 맞췄다. data.go.kr 파일은 #890 미해결로 임시 포털 경로로 받았다.

Refs #903 #862 #890

* [Data] 재수집으로 대체된 접근성 중간 snapshot 제거

topology 재등록이 만든 접근성 중간 snapshot 2개는 같은 브랜치의 재수집 등록으로 대체돼 inventory·원장 어디에서도 참조되지 않는다.

Refs #903

* [Data] 부산 topology 재등록에 맞춰 부산 환승 지표 재결속

build-busan-transfer-metrics 결과다. 지표 12개와 제외 행 6개는 같고 원천 식별만 새 topology head로 바뀐다.

Refs #903 #862

* [Data] 수도권 정본 팩 재결속에 맞춰 서울 실측 환승 지표 재생성

build-seoul-measured-transfer-metrics 결과다. 지표 263개는 같고 정본 팩 sha만 8102f1f6…에서 83e11161…로 바뀐다.

Refs #903 #862

* [Data] 서울 환승 거리·시간 admission을 새 수도권 정본 팩에 재결속

rebind-current-seoul-transfer-source-admission(#893) 결과다. 잠긴 원본은 OCI에서 GET만 했다(PUT 없음). 원천 값은 같고 정본 팩 결속만 바뀐다.

Refs #903 #862

* [Data] topology 7개 재등록 뒤 전국 후보 재결속(seq125, 후보 시계 2026-10-03T00:40:43.059Z)

시간표 내용은 같고 인천 1·2호선 snapshot 식별(20261003)과 fan-in·spec·request·hash 결속만 바뀐다.

Refs #903 #862

* [Fix] 광주 시간표 materializer의 topology evidence 창을 #904 컷오버 규칙으로 검사

컷오버 이후 수집한 광주 topology(P7D)를 24시간 고정값으로 검사해 보관본 등록 경로가 실패했다(register-retained-kric-timetable 테스트가 실데이터로 RED). topologySnapshotFreshnessMillis로 컷오버 전 P1D, 후 P7D를 정확값으로 검사한다.

Refs #903 #904

* [Test] 컷오버 이후 첫 topology 데이터에 맞춰 저장소 상태 의존 테스트 갱신

- 공용 materialize fixture는 대전 topology 창을 커밋된 evidence 창이 아니라 수집 시각 기준 컷오버 규칙으로 유도한다.
- 인천 station-info 수집기·후보 입력 만료 테스트의 24시간 고정값을 컷오버 규칙으로 바꾼다.
- 인천 시간표 만료 테스트는 후보 시계를 옮기지 않고 수집 시각을 옮겨 다른 입력의 만료와 섞이지 않게 한다.
- 후보 입력 pin을 10-03 원장 head로 갱신한다.
- 코레일 projection 결정성 단언을 독립 해시 계산으로 바꾼다(anti-cheat ANTI-CIRCULAR-ORACLE).

Refs #903

* [Docs] source-inventory·governance blob 변경에 맞춰 문서 파편 갱신

Refs #903

* [Test] 코레일 급행 고정 집합이 기본 경로 binding과 노선 보고서에 붙는지 단언

리뷰 F1: 기본 allowance 경로를 타는 테스트가 없어 고정 집합 부착 분기를 지우는 변이가 살아남았다. 기본 경로에서 경춘 5·수인분당 22·경의중앙 28 trip 고정 집합이 붙고 나머지 3개 노선에는 붙지 않음을 단언하고, e2e에서 노선 보고서 pinnedQuarantine을 노선별로 단언한다. 부착 분기를 false로 바꾸면 두 테스트가 모두 실패한다.

Refs #903

* [Fix] station-lines·코레일 격리 행의 운행일을 명시 값만 받도록 엄격화

리뷰 F2: 격리 행은 평일이 아닌 값을 모두 주말·휴일로 기록했다. station-lines는 dayCd 8=평일·9=주말·휴일, 코레일은 요일구분 평일·휴일만 받고 그 밖의 값은 SERVICE_DAY로 실패한다. 현재 데이터의 격리 행·보고서·팩 바이트는 바뀌지 않는다.

Refs #903
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automerge FIFO 병합 큐 대상 — 코디네이터가 순서대로 update-branch 후 auto-merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant