Repository navigation
[Fix] 부산·대구·대전 시간표 달력에 KASI 공휴일 예외를 싣고 공휴일 달력 불변식 추가 - #922
Conversation
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
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. Comment |
AquilaXk
left a comment
There was a problem hiding this comment.
Actionable comments posted: 3
🎯 Linked issue & acceptance criteria audit
- Linked issue: #919 [Fix] Busan, Daegu and Daejeon calendars lack holiday exception rows
- Goal summary: Three agencies run holiday timetables on KASI holidays via calendar exceptions.
- Acceptance criteria verified: 3/3
| ID | Acceptance criterion | Status | Evidence |
|---|---|---|---|
| AC-1 | Holiday exception rows for the three agencies match the KASI decision | PASS | tools/datapack/lib/regional-timetable-integrator.mjs:50 |
| AC-2 | Add an invariant check that a holiday calendar is active on holidays for all agencies | PASS | tools/datapack/prepare-nationwide-candidate-run.mjs:1573 |
| AC-3 | Record that sources lack holiday-festival timetables and keep the holiday timetable | PASS | tools/datapack/lib/regional-timetable-integrator.mjs:657 |
🛡️ Adversarial audit evidence
- Falsifiability verified: No (Failed: Probe left 3 mutants alive on the window guards, see F1.)
- Hollow assertions detected: 0
- Production backdoors detected: 0
- Ground-truth sources verified:
Clean clone refresh at builder commit 61c7cb5b reproduced the committed artifactsIssue 919 body and the QA day policy for Saturday holidays and holiday fallbackKASI fixture months match HOLIDAYS_2026 and months.json hashes, no service keySource day types for Busan, Daegu and Daejeon named in the PR body
🤖 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/regional-timetable-integrator.mjs:37-37`
Could the production path read the retained KASI months instead of a constant, or
could the candidate build compare the list with the retained KASI files and fail
on a difference? A refresh step for 2027 would then be forced by CI.
- `@tools/datapack/lib/regional-timetable-integrator.mjs:59-59`
Could one test pass a holiday list with a date before the calendar start and after
the calendar end, then assert that no exception row is created and that
holidayCalendarViolations reports nothing for those dates? That would kill the
surviving mutants. Until the guard is pinned, the window rule is unproven.
- `@tools/datapack/prepare-nationwide-candidate-run.mjs:1573-1577`
Could the merge order be recorded on both PRs, with the second one regenerating the
candidate after rebase, and could the count assertions be re-checked at that time?
---
Outside diff comments:
None.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Aquila review skill, project CLAUDE.md, PR template full.md and issue 919 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/regional-holiday-calendar-exceptions-919@c4efaabe7cfc7e7de3d621c46a2fdfa5827bfc2d
Command:
node post-review.mjs input.json payload-1.json --repo AquilaXk/easysubway-data --pr 922
📥 Commits
Reviewing files changed in this pull request between:
- Base:
53f01fc5c4c5d2b7630c2c6dcdb79608200eaa1c - Head:
c4efaabe7cfc7e7de3d621c46a2fdfa5827bfc2d
📒 Files selected for processing (8)
tools/datapack/fetch-kasi-public-holiday-calendar.test.mjstools/datapack/fixtures/kasi-public-holiday-2026/months.jsontools/datapack/lib/regional-timetable-integrator.mjstools/datapack/lib/regional-timetable-integrator.test.mjstools/datapack/prepare-nationwide-candidate-run.mjstools/datapack/prepare-nationwide-candidate-run.test.mjstools/datapack/release/candidate-build-spec.jsontools/datapack/release/hash-evidence.json
📜 Review details
- 지역 시간표 통합기가 공휴일(HOLIDAYS_2026)마다 평일·토요일 달력을 빼고(2) 휴일 달력을 더한다(1). 공휴일 목록이 없거나 형식이 틀리면 실패한다. - 세 기관 원천에 명절 시간표가 없어 설·추석도 휴일 시간표로 운행한다. - HOLIDAYS_2026이 KASI 2026년 특일 정보 원문과 같음을 보관 원문 fixture로 고정한다. - 전국 후보 조립 뒤 공휴일에 평일·토요일 달력이 운행하거나 휴일 달력이 빠진 노선이 있으면 실패한다. Closes #919
refresh-nationwide-candidate --evaluated-at 2026-10-03T05:27:51.411Z --release-sequence 126 원천 snapshot과 fan-in head는 그대로다. 부산·대구·대전 공휴일 예외 192행이 정본 팩에 더해진다. Refs #919
동작은 같다. 문자열 정렬에 codepointCompare를 쓰고, 노선·날짜 판정을 routeHolidayViolations로 나눠 인지 복잡도를 낮춘다. 후보 조립의 통합기 import를 한 줄로 합친다. Refs #919
refresh-nationwide-candidate --evaluated-at 2026-10-03T05:27:51.411Z --release-sequence 126 정본 팩 바이트는 그대로이고 spec·request·hash·preparation의 builder SHA만 바뀐다. Refs #919
refresh-nationwide-candidate --evaluated-at 2026-10-03T05:27:51.411Z --release-sequence 126 정본 팩 바이트는 그대로다. Refs #919
cca8b5f to
894b73b
Compare
AquilaXk
left a comment
There was a problem hiding this comment.
Actionable comments posted: 0
🎯 Linked issue & acceptance criteria audit
- Linked issue: #919 Busan, Daegu and Daejeon calendars lack holiday exception rows
- Goal summary: Three agencies run holiday timetables on KASI holidays via calendar exceptions.
- Acceptance criteria verified: 3/3
| ID | Acceptance criterion | Status | Evidence |
|---|---|---|---|
| AC-1 | Holiday exception rows for the three agencies match the KASI decision | PASS | tools/datapack/lib/regional-timetable-integrator.mjs |
| AC-2 | Add an invariant check that a holiday calendar is active on holidays for all agencies | PASS | tools/datapack/prepare-nationwide-candidate-run.mjs |
| AC-3 | Record that sources lack holiday-festival timetables and keep the holiday timetable | PASS | tools/datapack/lib/regional-timetable-integrator.mjs |
🔄 PR review lifecycle & thread tracking
- Previous review ID: 5404237023
- Previous commit SHA:
c4efaabe7cfc7e7de3d621c46a2fdfa5827bfc2d - Resolved findings: 3
- Active tracked threads: 0
| Status | Finding / Thread | Path | Resolution note |
|---|---|---|---|
| RESOLVED | F1 | tools/datapack/lib/regional-timetable-integrator.mjs |
Out-of-window holiday tests kill the four window-guard mutants |
| RESOLVED | F2 | tools/datapack/lib/regional-timetable-integrator.mjs |
Holiday list must equal the retained KASI set; invariant uses that set |
| RESOLVED | F3 | tools/datapack/prepare-nationwide-candidate-run.mjs |
Merge order is recorded; this head was rebased and refreshed after 921 and 923 |
🛡️ Adversarial audit evidence
- Falsifiability verified: Yes (Four window-guard mutants on lines 50, 59 and the skip guard now fail)
- Hollow assertions detected: 0
- Production backdoors detected: 0
- Ground-truth sources verified:
Issue 919 body and the QA day policy for Saturday holidaysRetained KASI getRestDeInfo 2026 months with sha256 manifest, 22 holidaysSource day types for Busan, Daegu and Daejeon named in the PR body
🤖 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:
None.
---
Outside diff comments:
None.
ℹ️ Review info
⚙️ Run configuration
Configuration used: CLAUDE.md, AGENTS.md and .github/PULL_REQUEST_TEMPLATE/full.md in easysubway-data
Review profile: ASSERTIVE
Plan: Aquila fallback
Run ID: N/A (Aquila fallback)
Review source: Aquila CLI
Repository visibility: public GitHub repository
Trigger:
Closure review of frozen findings F1 to F3 on the rebased head of PR 922
Base:
main@397d6e74e75685c96e0eb4204346a98498b48eef
Head:
fix/regional-holiday-calendar-exceptions-919@894b73b27b65e931207afe93653cd219ed6289c0
Command:
node aquila-review/scripts/compile-review-payload.mjs input.json --output payload-1.json
📥 Commits
Reviewing files changed in this pull request between:
- Base:
397d6e74e75685c96e0eb4204346a98498b48eef - Head:
894b73b27b65e931207afe93653cd219ed6289c0
📒 Files selected for processing (27)
tools/datapack/canonical-pack-service-calendar-flags.test.mjstools/datapack/canonical-pack-transit-car-door-contract.test.mjstools/datapack/fetch-kasi-public-holiday-calendar.mjstools/datapack/fetch-kasi-public-holiday-calendar.test.mjstools/datapack/lib/regional-timetable-integrator.mjstools/datapack/lib/regional-timetable-integrator.test.mjstools/datapack/prepare-nationwide-candidate-run.mjstools/datapack/prepare-nationwide-candidate-run.test.mjstools/datapack/regional-timetable-official-stop-times.test.mjstools/datapack/release/candidate-build-spec.jsontools/datapack/release/hash-evidence.jsontools/datapack/release/kasi-public-holiday-2026/2026-01.xmltools/datapack/release/kasi-public-holiday-2026/2026-02.xmltools/datapack/release/kasi-public-holiday-2026/2026-03.xmltools/datapack/release/kasi-public-holiday-2026/2026-04.xmltools/datapack/release/kasi-public-holiday-2026/2026-05.xmltools/datapack/release/kasi-public-holiday-2026/2026-06.xmltools/datapack/release/kasi-public-holiday-2026/2026-07.xmltools/datapack/release/kasi-public-holiday-2026/2026-08.xmltools/datapack/release/kasi-public-holiday-2026/2026-09.xmltools/datapack/release/kasi-public-holiday-2026/2026-10.xmltools/datapack/release/kasi-public-holiday-2026/2026-11.xmltools/datapack/release/kasi-public-holiday-2026/2026-12.xmltools/datapack/release/kasi-public-holiday-2026/months.jsontools/datapack/release/nationwide-candidate-preparation.jsontools/datapack/release/nationwide-production-canonical-pack.jsontools/datapack/release/release-request.json
📜 Review details
|
No description provided. |
|
No description provided. |
|
* [Fix] 1호선 주말 원천 중복 행을 공식 근거로 격리하고 같은 출발 trip 중복을 후보 생성에서 막음 - KRIC 전체_도시철도운행정보 파일의 1호선 '토요일+공휴일' 512·514 행은 같은 시각 506·508 행과 정차·시각이 모두 같다. KRIC 역별 API(subwayTimetable, 2026-10-04 실측)는 휴일에 506·508만, 평일에 512·514를 준다. 고정 근거로 512·514 주말 행을 DUPLICATE_SERVICE_ROW로 격리한다. 근거 없는 내용 중복은 적재를 실패시킨다. - 전국 후보 조립 뒤 같은 달력에서 (노선, 역, 출발 시각, 다음 역, 종착역)이 같은 trip이 있으면 후보 생성을 실패시킨다. Closes #920 * [Chore] #920 적재 변경으로 전국 후보(seq126 시계)를 재생성 refresh-nationwide-candidate --evaluated-at 2026-10-03T05:27:51.411Z --release-sequence 126 원천 snapshot과 fan-in head는 그대로다. 1호선 주말 중복 trip 2개(정차 36행)가 빠지고 격리 보고서에 남는다. Refs #920 * [Test] 중복 행 규칙이 행 해시와 열차 번호가 함께 맞을 때만 적용됨을 고정 리뷰 F1(#924). 해시만 맞는 규칙, 열차 번호만 맞는 규칙, 노선·요일구분만 다른 규칙은 모두 DUPLICATE_TRIP_UNRESOLVED로 실패한다. member()와 규칙 필터의 &&→|| 변이가 이 테스트로 잡힌다. Refs #920 * [Test] 1호선 주말 중복 판정 근거인 KRIC 역별 API 응답을 키 없이 보관하고 규칙과 대조 리뷰 F2(#924). 서동탄·수원·금정 dayCd 7·8·9 응답 원문(2026-10-04 수집, 서비스 키 미포함)과 sha256 manifest를 fixture로 둔다. 휴일 23:14·23:34 계열은 K506·K508, 평일 같은 시각은 K512·K514이고 토요일은 데이터 없음(03)임을 원문에서 확인한 뒤 고정 규칙의 유지·제외 선택과 대조한다. Refs #920 * [Chore] #922 병합 뒤 rebase에 맞춰 전국 후보(seq126 시계)를 재생성 refresh-nationwide-candidate를 같은 인자로 다시 실행했다. 정본 팩에 #919 공휴일 예외와 #920 중복 행 격리가 함께 들어간다. trip 26,488 · 정차 677,120 · 달력 예외 398행, 같은 출발 중복 묶음 0, 공휴일 달력 위반 0. Refs #920



Related issue
Closes #919
Refs AquilaXk/easysubway-backend#479
Summary
lib/regional-timetable-integrator.mjs)는 부산·대구·대전 달력을 요일 플래그로만 만든다. 공휴일 예외 행은 만들지 않는다.HOLIDAYS_2026)으로 예외 행을 싣는다. 세 기관만 빠져 있었다.materialize-busan/daegu/daejeon-timetable.mjs의 목록은 전국 후보 경로에서 쓰지 않는다.service_calendar_dates가 0행이다.TIMETABLE_NOT_COVERED를 낸다.Changes
lib/regional-timetable-integrator.mjsholidayDates를 필수 인자로 받는다. 형식은 YYYYMMDD이고 중복 없이 2026년 날짜를 하나 이상 포함해야 한다. 어기면REGIONAL_TIMETABLE_HOLIDAY_DATES_INVALID로 실패한다.holidayCalendarViolations(신규 export)는 노선별 공휴일 달력 불변식을 검사한다. 명절 전용 달력(요일 운행 없음)은 공휴일에 운행해도 된다.prepare-nationwide-candidate-run.mjsHOLIDAYS_2026을 넘긴다.release/kasi-public-holiday-2026/: 2026-10-04에 수집한 KASIgetRestDeInfo2026년 1~12월 응답 원문과 months.json이다. 기존 수집기fetch-kasi-public-holiday-calendar.mjs로 받았다. 서비스 키는 응답에 없다.retainedKasiHolidayDates()가 원문에서 공휴일 집합을 도출한다.fetch-kasi-public-holiday-calendar.test.mjs:HOLIDAYS_2026이 KASI 원문 공휴일 22일과 같음을 고정한다.lib/regional-timetable-integrator.test.mjs: 예외 행, 실패 조건, 불변식을 검사한다.prepare-nationwide-candidate-run.test.mjs: 조립 팩 불변식을 검사하고, 고정 예외 행 수를 206에서 398로 바꿨다.holidayDates를 넘긴다.refresh-nationwide-candidate --evaluated-at 2026-10-03T05:27:51.411Z --release-sequence 126Scope
Included
Excluded
Ownership / dependencies
prepare-nationwide-candidate-run.mjs조립 구간에 각자 검사를 더한다. 줄은 겹치지 않는다.원천·카탈로그 대조
api-catalog.mjs list --query kasi의 결과는provider:kasi-public-holiday-calendar(getRestDeInfo, statuspreflight_only)다.source-candidates.json에는kasi-public-holiday-calendar(P0,preflight_only)가 있다.source-inventory.json에는 KASI 항목이 없다.fetch-kasi-public-holiday-calendar.mjs: 광주 보관본 계약과 코레일 등록이 쓴다.materialize-incheon-timetable.mjs의HOLIDAYS_2026을 인천·KRIC·코레일 달력에 쓴다.HOLIDAYS_2026과 정확히 같다.18, 03-01·02, 05-01·05·24·25, 06-03·06, 07-17, 08-15·17, 09-2426, 10-03·05·09, 12-25다.busan-transportation-timetable:day1·2·3(평일·토요일·휴일)WEEK·SAT·HOLIdaejeon-train-timetable:dayType0·1(평일·휴일)병합 순서
refresh-nationwide-candidate를 다시 돌린다. 재생성 산출물은 손으로 고치지 않는다.도구/데이터 PR을 한 PR에 둔 이유
prepare-nationwide-candidate-run.test.mjs의writeFiles: true테스트가 실행 중에 정본 팩을 덮어쓰기 때문이다.refresh-nationwide-candidate를 다시 돌린다. 재생성 산출물은 손으로 병합하지 않는다.Contract & Compatibility
service_calendar_dates형식(serviceId·date·exceptionType)이다.Version impact
Product gate impact
Provenance impact
Version decision
Verification
holidayDates: ["20261009"]를 넘기면 예외 행이 0개다(기대 12). 새 테스트는holidayCalendarViolationsexport가 없어 실패했다. GREEN: 통합기 테스트 4/4, 관련 5개 파일 40/40이 통과했다.holidayCalendarViolations를 seq126 동등 번들에 적용하면 312건이다. 부산 4노선은 각 40, 대구 3노선은 각 40, 대전은 32이고 다른 기관은 0이다.node tools/ci/run-affected-tests.mjs: 12개 파일, 127/127 통과refresh-nationwide-candidate→ RCbuild-datapack→validate-datapack --require-production→ 번들 staging이 통과했다. 서명은 로컬 임시 키를 썼다.service_calendar_dates는 206행에서 398행으로 늘었다..env에 있고 출력하지 않았다. 발행은 하지 않음ServiceKey0건).10-03·10-05·10-09에 운행하는 달력과 편수(seq126 동등 번들, 역 기준 trip 수)는 다음과 같다.
Not run
Risk
HOLIDAYS_2026은 2026년만 다룬다. 달력 창이 2027년으로 넘어가면 목록을 KASI로 다시 받아야 한다.Rollout / Recovery
TIMETABLE_NOT_COVERED해소).Review focus
sunday=true이면 휴일, 일요일 미운행이면서 월~토 중 하루 이상 운행하면 평일·토요일이다. 요일 운행이 없으면 명절이다.Checklist