Skip to content

[Fix] 자정 이후 시발 열차 시각을 데이터팩 SQLite에 운행일 경계(03:00) 기준 24시 이후 초로 적재 - #921

Merged
AquilaXk merged 7 commits into
mainfrom
fix/incheon-service-day-boundary-918
Oct 4, 2026
Merged

AquilaXk merged 7 commits into
mainfrom
fix/incheon-service-day-boundary-918

Conversation

@AquilaXk

@AquilaXk AquilaXk commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

Related issue

Closes #918

Summary

  • Problem
    • 인천 1·2호선 공식 FILE(data.go.kr 15051203~15051210)은 자정 이후 시각을 00:09:30처럼 24시 미만으로 적는다. 24시 표기는 없다.
    • 수집기는 한 열차 안에서 시각이 줄어들 때만 하루를 더한다(자정을 넘는 열차). 그래서 00시대에 출발하는 막차(평일 하선 1305·1307·1309 등)는 0시대 값으로 남았다.
    • KRIC 역별 API(trainUseInfo/subwayTimetable)로 만든 GTX-A·의정부경전철 trip도 같다.
    • seq126 실측 결과는 다음과 같다. 44개 trip의 정차 552행이 03:00 이전 값이다. 박촌 송도달빛축제공원 방면 평일 "첫 출발"이 00:23(1410초)으로 나온다.
  • Outcome
    • 운행일 경계를 03:00으로 둔다. 데이터팩 SQLite의 transit_stop_times를 쓸 때 원천이 00:00~02:59로 적은 시각을 전날 운행일의 심야 시각(86400초 이상)으로 싣는다.
    • 원천과 상관없이 모든 trip에 같은 규칙을 적용한다. 서버 번들 timetable 구성요소와 모바일 카탈로그 팩에 모두 반영된다.
    • 바꾼 뒤 trip 안 시각이 줄어들면 validate-datapack의 기존 순서 검사(transit_stop_times must be monotonic)가 팩을 거부한다. 03:00 전후에 걸친 열차가 여기에 해당한다.
    • 불변식: validate-datapack은 컴파일된 SQLite에 03:00 전 도착·출발이 하나라도 남으면 기관과 상관없이 팩을 거부한다(리뷰 F1).

Changes

  • tools/datapack/lib/service-day-seconds.mjs (신규)
    • serviceDaySeconds: 03:00 이전 시각에 86400을 더한다. 정수 초가 아니면 실패한다.
    • serviceDayStopTimes: stop_time 행에 위 변환을 적용한다.
    • 경계는 기존 normalize-kric-timetable.mjs와 같은 03:00이다.
  • tools/datapack/build-datapack.mjs: transit_stop_times 적재 행을 serviceDayStopTimes로 바꿔 쓴다.
  • tools/datapack/validate-datapack.mjs: 03:00 전 정차 시각이 남으면 거부한다(리뷰 F1).
  • tools/datapack/normalize-kric-timetable.mjs: 별도 3시 상수 대신 공유 상수를 쓴다(리뷰 F3).
    • SERVICE_DAY_CUTOFF_LOCAL_TIME = "03:00"을 테스트로 고정한다.
    • 다른 레포 값은 읽기만 해서 대조했고 모두 같다: hub journey-v3 serviceDayCutoff, backend ServiceDayResolver.CUTOFF_LOCAL_TIME.
  • contracts/documentation/documentation-fragment.json: build-datapack.mjs blob 갱신(refresh-documentation-fragment --worktree → --check IN SYNC)
  • 테스트
    • lib/service-day-seconds.test.mjs (신규, data-test-ownership.json에 data918로 등록)
    • materialize-incheon-timetable.test.mjs: 빌드한 SQLite에 03:00 이전 인천 정차가 0행인지 확인한다. 박촌 1301~1309 출발 시각도 확인한다.
    • datapack-tools.test.mjs(리뷰 F1·F4)
      • 비인천(4호선) 00시대 trip이 86400초 이상으로 실리는지 확인한다.
      • 경계를 가로지르는 trip이 순서 검사로 거부되는지 확인한다.
      • 비인천 trip에 0시대 값이 남으면 검증이 거부하는지 확인한다.
  • 첫 커밋(a566db9)의 접근은 되돌렸다. 그 커밋은 materializer·KRIC adapter·후보 조립 단계에서 정본 팩 JSON을 바꿨다.
    • 이유는 build-datapack이 정본 팩의 인천 시간표를 materializer로 다시 만들어 비교하기 때문이다(validateProductionIncheonTimetableFixture). 수도권 정본 팩도 비교 대상이다.
    • JSON을 바꾸려면 수도권 정본 팩도 다시 만들어야 한다. 그 팩의 해시는 환승 지표·원장 등 여러 증거에 결속되어 있다. 이 연쇄 재생성(OCI 원문 재결속 포함)은 이 PR 범위 밖이다.
    • 첫 커밋의 CI 실패가 이 문제였다(production Incheon timetable fixture does not match pinned admission).

Scope

Included

  • 데이터팩 SQLite transit_stop_times의 운행일 경계 표현(인천 1·2호선, KRIC 역별 노선 GTX-A·의정부 포함 전 원천)

Excluded

  • 원천 스냅샷과 정본 팩 JSON 변경. 정본 팩은 원천 시각을 그대로 두고, 컴파일 단계에서 운행일 초로 바꾼다.
  • backend 변경. backend는 번들 값을 그대로 쓴다.
  • 현장 확인

Ownership / dependencies

Contract & Compatibility

  • Source / API / schema contract: 변경 없음. stop_time은 이미 86400초 이상 값을 쓰고 있었다(자정을 넘는 열차).
  • Artifact / provenance identity
    • 정본 팩 JSON·후보 spec·hash evidence는 그대로다.
    • 데이터팩 SQLite와 서버 번들 timetable 구성요소의 0시대 정차 552행만 바뀐다. trip id, 정차 수, providerRecordHash는 그대로다.
  • Backward compatibility: 변경 뒤 전체 최댓값은 90840초로 변경 전과 같다. backend seed 상한(107999초) 안이다.
  • Migration or cutover: 이 PR이 병합되면 다음 RC 빌드부터 반영된다. 정본 팩을 재생성할 필요는 없다.

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: 다음 재발행(seq127 이상)에서 반영
  • data contract: 변경 없음
  • route-map artifact / product gate: 변경 없음
  • promotion request id: 재발행 시 정한다

Verification

Check Result / Evidence
원천 대조 data.go.kr에서 원문 8개를 다시 받았다. sha256이 커밋 스냅샷 incheon-line1-train-timetable-20261003의 raw*Sha256과 같다(예: 15051204 72f548f4…). 1호선 평일 하선 원문의 마지막 행 154156은 1305·1307·1309이고 첫 시각은 00:09:30·00:21:30·00:30:30이다. 23시대 시발 행(1301·1303) 뒤에 있다. 8개 파일 모두 00시대 시발 행은 파일 끝에만 있다. 0204시 시각은 없다.
KRIC 대조 커밋 스냅샷 kric-subway-timetable-station-lines-20261003 기준이다. GTX-A는 00시대 시발 20개, 05시대 16개이고 의정부는 00시대 8개, 05시대 24개다. 01~04시 시발 열차는 없다.
Focused RED → GREEN RED: materialized SQLite와 provenance가 인천 schedule_timetable 2건을 SUPPORTED로 만든다에서 03:00 이전 인천 정차가 340행이었다(기대 0). GREEN: 같은 테스트 1/1, lib/service-day-seconds.test.mjs 3/3
순서 검사 회귀 datapack-tools.test.mjs의 데이터팩 검증기는 trip별 stop_time 시간이 역행하면 거부한다가 통과한다. 빌드 단계에 별도 순서 검사를 넣지 않고 기존 validator 검사를 그대로 쓴다.
Affected integration run-affected-tests 대상 50개 파일을 로컬에서 돌렸다. 실패는 bundle-component-contract.test.mjs의 contract mutations fail closed 하나이고, origin/main에서도 똑같이 실패하는 로컬 환경 문제다.
문서 파편 node tools/repo/refresh-documentation-fragment.mjs --worktree --check: IN SYNC, node tools/ci/check-documentation-fragment-sync.mjs --base origin/main: PASSED
seq126 동등 RC 재현 seq126 시계(2026-10-03T05:27:51.411Z)로 로컬 RC를 재현했다. 순서는 refresh-nationwide-candidate → build-current-release-candidate-accessibility-input → build-datapack(RC) → validate-datapack --require-production → stage-current-server-route-bundle-candidate이고 전 단계가 통과했다. 같은 절차로 main을 돌리면 seq126 번들의 timetable 표 해시와 같다. 서명은 로컬 임시 키를 썼다.
효과(seq126 동등) 번들 timetable과 모바일 카탈로그 팩에서 03:00 이전 정차가 44 trip·552행에서 0으로 줄었다. 박촌 하선 평일 1301·1303·1305·1307·1309 출발은 86430·87120·87810·88530·89070초다. 박촌 평일 하선 첫 출발은 1410초(00:23)에서 19800초(05:30)로 바뀌었다. trip 26,490개와 stop_time 677,156행 수는 그대로다.
Required CI PR CI에서 확인
Live provider / release data.go.kr 원문 재다운로드로 원천 대조(키 불필요). 발행은 하지 않음
Security / data integrity Not applicable — reason: 시크릿·인증 경계 변경 없음

Not run

  • Check: backend 역 시간표 실응답(박촌 첫 출발)
  • Reason: 재발행 번들이 배포된 뒤에 확인할 수 있다.
  • Rerun owner / condition: 10-10 재발행 뒤 backend 역 시간표에서 확인한다.

Risk

  • Level: High
  • Main risk
    • 정본 팩 JSON과 SQLite의 시각 표현이 다르다. JSON은 원천 시각, SQLite는 운행일 초다.
    • JSON을 직접 읽는 build-backend-timetable-seed·build-server-timetable-snapshot에는 운영 소비처가 없다(리뷰 F2 확인).
      • backend #479가 seed 로더와 리소스를 지웠다.
      • backend main 리소스에는 snapshot 산출물이 없다.
      • data 워크플로에도 이 두 도구를 부르는 곳이 없다.
    • 위 사실과 "다시 쓰면 같은 변환 필요"를 lib/service-day-seconds.mjs에 적었다.
  • Failure behavior: 03:00 전후에 걸친 열차가 생기면 변환 뒤 순서가 역전된다. validate-datapack이 팩을 거부해 RC가 실패한다.
  • Candidate / admission / publication state on failure: RC 실패, 발행 없음
  • Fallback or degraded-success path introduced: No

Rollout / Recovery

  • Rollout or promotion: 병합 → 다음 RC(10-10 09:05 KST 만료 전 재발행)
  • Monitoring / success signal: 재발행 번들에서 03:00 이전 정차가 0행이다. backend 역 시간표의 박촌 평일 첫 출발은 05:30이다.
  • Rollback or recovery: 이 PR revert
  • Existing artifact / schema compatibility after rollback: 스키마 변경이 없어 호환된다

병합 순서

Review focus

  • 변환 위치. 정본 팩 JSON(재현 비교·해시 결속 대상)이 아니라 SQLite 컴파일 단계에 뒀다.
  • 03:00 경계의 원천 근거. 파일 끝 00시대 행, 0204시 시각 부재, KRIC 0104시 시발 부재다.

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 상태를 확인했습니다.

- 인천 1·2호선 공식 FILE과 KRIC 역별 API(GTX-A·의정부)가 00시대로 적은 자정 이후 막차 시각을
  전날 운행일의 심야 시각(86400초 이상)으로 적재한다. 스냅샷은 바꾸지 않는다.
- 전국 후보 조립 뒤 운행일 경계 앞 정차 시각이 남으면 후보 생성을 실패시킨다.

Closes #918
@coderabbitai

coderabbitai Bot commented Oct 4, 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: 8866580e-26aa-4ec4-ad76-4528aba437cf
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

정본 팩 JSON의 인천 시간표는 build-datapack이 materializer로 다시 만들어 비교한다(수도권·전국 정본 팩 모두).
materializer 출력을 바꾸면 해시가 여러 증거에 결속된 수도권 정본 팩까지 다시 만들어야 하므로,
정본 팩은 원천 시각을 그대로 두고 transit_stop_times를 SQLite에 쓸 때 운행일 초로 바꾼다.

- build-datapack: transit_stop_times를 serviceDayStopTimes로 바꿔 쓴다(인천·KRIC 역별 노선 등 원천과 무관).
- 바꾼 뒤 trip 안 시각이 줄어들면 validate-datapack의 기존 순서 검사가 거부한다.
- materializer·KRIC 역별 adapter·후보 조립 검사 변경은 되돌린다.
- 문서 파편(build-datapack.mjs blob)을 갱신한다.

Refs #918
@AquilaXk AquilaXk changed the title [Fix] 자정 이후 시발 열차 시각을 운행일 경계(03:00) 기준 24시 이후 초로 적재 [Fix] 자정 이후 시발 열차 시각을 데이터팩 SQLite에 운행일 경계(03:00) 기준 24시 이후 초로 적재 Oct 4, 2026

@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 Compare source file notation and compiler conversion and record the result PASS PR body Verification table, source comparison row
AC-2 Fix the compiler and add an invariant check for the service-day boundary FAIL tools/datapack/build-datapack.mjs:4329
AC-3 If the representation is correct, record the evidence and close PASS Not applicable branch, the representation was wrong and is fixed
🛡️ Adversarial audit evidence
  • Falsifiability verified: Yes (Probe on service-day-seconds.mjs lines 13 and 14 killed 4 of 4 mutants.)
  • Hollow assertions detected: 0
  • Production backdoors detected: 0
  • Ground-truth sources verified:
    • Backend ServiceDayResolver cutoff 03:00 on origin/main
    • Issue 918 body Done When list and reproduction
    • Mobile station timetable repository on origin/main adding seconds to the date
    • normalize-kric-timetable cutoff and validate-datapack monotonic check
🤖 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/build-datapack.mjs:4329-4329`
  Could validate-datapack (and the route bundle build) reject any stop time below the
  03:00 boundary after compilation, reusing the shared boundary constant, with a test
  that feeds a 00:xx row for a non-Incheon trip and expects a failure? That would turn
  the rule into an enforced invariant that blocks merge until it exists.
- `@tools/datapack/lib/service-day-seconds.mjs:1-6`
  Could the two JSON-reading builders either apply the same conversion or fail when
  they meet a stop time below the boundary? Alternatively, could the contract note the
  SQLite-only scope so the divergence is a recorded decision rather than prose in the
  PR?
- `@tools/datapack/lib/service-day-seconds.mjs:7-7`
  Could normalize-kric-timetable import this constant, and could a contract test pin
  it to the serviceDayCutoff string in the Journey contract so drift fails CI?
- `@tools/datapack/materialize-incheon-timetable.test.mjs:438-451`
  Could one build-level test add a non-Incheon trip with a 00:xx start and expect 86400
  plus seconds, and a straddling trip that validate-datapack rejects with the monotonic
  message?

---

Outside diff comments:
None.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Aquila review skill, project CLAUDE.md, PR template full.md and issue 918 body

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 on the draft pull request

Base:
main@53f01fc5c4c5d2b7630c2c6dcdb79608200eaa1c

Head:
fix/incheon-service-day-boundary-918@87d3731064c195a01b90e55c60847a5bbb156dfb

Command:
node post-review.mjs input.json payload-1.json --repo AquilaXk/easysubway-data --pr 921

📥 Commits

Reviewing files changed in this pull request between:

  • Base: 53f01fc5c4c5d2b7630c2c6dcdb79608200eaa1c
  • Head: 87d3731064c195a01b90e55c60847a5bbb156dfb
📒 Files selected for processing (6)
  • contracts/documentation/documentation-fragment.json
  • tools/ci/data-test-ownership.json
  • tools/datapack/build-datapack.mjs
  • tools/datapack/lib/service-day-seconds.mjs
  • tools/datapack/lib/service-day-seconds.test.mjs
  • tools/datapack/materialize-incheon-timetable.test.mjs
📜 Review details

Comment thread tools/datapack/build-datapack.mjs
Comment thread tools/datapack/lib/service-day-seconds.mjs Outdated
Comment thread tools/datapack/lib/service-day-seconds.mjs
Comment thread tools/datapack/materialize-incheon-timetable.test.mjs
리뷰 F1(#921). 운행일 경계 변환을 SQLite 기록 한 곳에만 두면 다른 기록 경로나 이후 리팩터로
0시대 값이 돌아와도 검증을 통과했다. validate-datapack이 모든 기관의 transit_stop_times에서
03:00 전 도착·출발을 거부한다.

Refs #918
리뷰 F4(#921). catalog fixture의 4호선 trip을 00시대로 옮겨 빌드하면 SQLite에 86400초 이상으로 실리고
검증을 통과한다. 02:55→03:05로 경계를 가로지르는 trip은 변환 뒤 역행해 검증기가 거부한다.

Refs #918
리뷰 F3(#921). normalize-kric-timetable의 별도 3시 상수를 lib/service-day-seconds의 상수로 바꾼다.
SERVICE_DAY_CUTOFF_LOCAL_TIME("03:00")이 hub journey-v3 serviceDayCutoff·backend ServiceDayResolver와
같은 값임을 테스트로 고정한다.

Refs #918
리뷰 F2(#921). build-backend-timetable-seed·build-server-timetable-snapshot은 정본 팩 JSON을 읽지만
backend #479에서 seed 로더가 제거되어 운영 소비처가 없다. 다시 쓰려면 같은 변환이 필요함을 남긴다.

Refs #918
mobile-v19 CI 러너가 자원 한도로 중단(exit 143)되는 빈도를 줄이려고, 전국 RC 산출물을 새로 빌드하던 F1 테스트를
catalog fixture 빌드(4호선, 인천 아님)와 SQLite 직접 변조·fixture 서명 갱신으로 바꾼다. 검증기의 03:00 검사를 끄면
이 테스트가 실패한다.

Refs #918
@sonarqubecloud

sonarqubecloud Bot commented Oct 4, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@AquilaXk
AquilaXk merged commit abd7372 into main Oct 4, 2026
14 checks passed
@AquilaXk
AquilaXk deleted the fix/incheon-service-day-boundary-918 branch October 4, 2026 07:43
AquilaXk added a commit that referenced this pull request Oct 4, 2026
refresh-documentation-fragment --worktree로 다시 만들었다(손 편집 없음).

Refs AquilaXk/easysubway-backend#480
AquilaXk added a commit that referenced this pull request Oct 4, 2026
* [Fix] 서버 번들 환승 동선의 계단 칸을 stair_access_state 기준으로만 유도

- includes_stairs는 확인된 계단(STAIR_ONLY)일 때만 1이다. 0은 계단 없음이 아니다.
- 계단 없음은 STEP_FREE로만 나타낸다. 계단 정보가 없으면 UNKNOWN으로 남긴다.
- 입력의 includesStairs와 상태가 어긋나거나 상태 값이 계약 밖이면 번들을 만들지 않는다.
- SQLite 계약(includes_stairs INTEGER NOT NULL, 모바일 Drift bool)은 바꾸지 않는다.

Refs AquilaXk/easysubway-backend#480

* [Fix] 서버 시간표 스냅샷의 strict route 자격을 stairAccessState STEP_FREE에서만 부여

리뷰 F3(#923). includesStairs=false 기본값만으로 ENTRY·EXIT edge가 strict_route_eligible이 되던
유도를 고친다. 계단 상태가 UNKNOWN·STAIR_ONLY면 자격을 주지 않는다.

Refs AquilaXk/easysubway-backend#480

* [Test] 서버 번들 network_edges 계단 칸 규칙을 emitter 호출부에서 고정

리뷰 F1(#923). populateNationwideTopologyEdges를 내보내 catalog-schema의 network_edges DDL에 직접 채우고
STAIR_ONLY·STEP_FREE·미확인 행과 어긋난 입력 거부를 단언한다. 호출부를 이전 인자로 되돌리면 이 테스트가 실패한다.

Refs AquilaXk/easysubway-backend#480

* [Fix] 모바일 팩 build-datapack도 서버 번들과 같은 계단 칸 헬퍼와 불일치 거부를 공유

리뷰 F2(#923). lib/network-edge-stair-columns.mjs로 규칙을 옮겨 emitter와 build-datapack이 함께 쓴다.
계단 여부와 상태가 어긋나는 edge(STAIR_ONLY+false, STEP_FREE+true)는 이제 두 경로 모두 거부한다.
기존 legacy flag 테스트는 거부와 일치 입력의 유도를 함께 단언하도록 바꿨다. 문서 파편 갱신.

Refs AquilaXk/easysubway-backend#480

* [Docs] #921 병합 뒤 rebase에 맞춰 build-datapack 문서 파편을 재생성

refresh-documentation-fragment --worktree로 다시 만들었다(손 편집 없음).

Refs AquilaXk/easysubway-backend#480
AquilaXk added a commit that referenced this pull request Oct 4, 2026
refresh-nationwide-candidate --evaluated-at 2026-10-03T05:27:51.411Z --release-sequence 126
정본 팩 바이트는 그대로이고 spec·request·hash·preparation의 builder SHA만 바뀐다.

Refs #919
AquilaXk added a commit that referenced this pull request Oct 4, 2026
* [Fix] 부산·대구·대전 시간표 달력에 KASI 공휴일 예외를 싣고 공휴일 달력 불변식 추가

- 지역 시간표 통합기가 공휴일(HOLIDAYS_2026)마다 평일·토요일 달력을 빼고(2) 휴일 달력을 더한다(1).
  공휴일 목록이 없거나 형식이 틀리면 실패한다.
- 세 기관 원천에 명절 시간표가 없어 설·추석도 휴일 시간표로 운행한다.
- HOLIDAYS_2026이 KASI 2026년 특일 정보 원문과 같음을 보관 원문 fixture로 고정한다.
- 전국 후보 조립 뒤 공휴일에 평일·토요일 달력이 운행하거나 휴일 달력이 빠진 노선이 있으면 실패한다.

Closes #919

* [Chore] #919 공휴일 예외를 반영해 전국 후보(seq126 시계)를 재생성

refresh-nationwide-candidate --evaluated-at 2026-10-03T05:27:51.411Z --release-sequence 126
원천 snapshot과 fan-in head는 그대로다. 부산·대구·대전 공휴일 예외 192행이 정본 팩에 더해진다.

Refs #919

* [Refactor] 공휴일 달력 불변식의 정렬 비교 함수 명시와 노선별 판정 분리(SonarCloud)

동작은 같다. 문자열 정렬에 codepointCompare를 쓰고, 노선·날짜 판정을 routeHolidayViolations로 나눠
인지 복잡도를 낮춘다. 후보 조립의 통합기 import를 한 줄로 합친다.

Refs #919

* [Chore] #919 리팩터 커밋에 builder SHA를 맞춰 전국 후보 결속을 갱신

refresh-nationwide-candidate --evaluated-at 2026-10-03T05:27:51.411Z --release-sequence 126
정본 팩 바이트는 그대로이고 spec·request·hash·preparation의 builder SHA만 바뀐다.

Refs #919

* [Test] 달력 창 밖 공휴일의 예외 행·운행 판정 가드를 변이로 잡는 테스트 추가

리뷰 F1(#922). 2025-12-25·2027-01-01처럼 달력 창 밖 날짜로 holidayExceptionRows(창 가드)와
holidayCalendarViolations(calendarActiveOn 창 가드, 창 밖 날짜 건너뛰기)를 고정한다.
세 가드의 ||→&&·return false→true 변이 4개가 모두 실패로 잡힌다.

Refs #919

* [Fix] 공휴일 목록을 보관된 KASI 원문 전체 집합과 정확히 맞추고 불변식은 그 독립 집합과 비교

리뷰 F2(#922). 보관 원문을 release/kasi-public-holiday-2026으로 옮기고, 통합기는 넘겨받은 목록이
원문에서 도출한 공휴일 전체와 같지 않으면(빠진 날·더한 날) 실패한다. 후보 조립 불변식은
통합기 입력이 아니라 원문에서 따로 읽은 집합과 비교해 순환을 끊는다.

Refs #919

* [Chore] #919 리뷰 반영 커밋에 builder SHA를 맞춰 전국 후보 결속을 갱신

refresh-nationwide-candidate --evaluated-at 2026-10-03T05:27:51.411Z --release-sequence 126
정본 팩 바이트는 그대로다.

Refs #919

* [Chore] #921·#923 병합 뒤 rebase에 맞춰 전국 후보 결속(builder SHA)을 재생성

refresh-nationwide-candidate --evaluated-at 2026-10-03T05:27:51.411Z --release-sequence 126
정본 팩 바이트는 그대로이고 spec·request·hash·preparation의 builder SHA만 바뀐다.

Refs #919
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.

[Fix] 인천 1·2호선 자정 이후 열차가 86400초 이상과 0시대 값으로 섞여 표현되는지 원천·컴파일러 확인

1 participant