Skip to content

[Fix] 전국 정본 팩의 운행 요일 값·노선도 라벨 결함으로 release-candidate 빌드 실패 - #858

Merged
AquilaXk merged 6 commits into
mainfrom
fix/canonical-pack-calendar-label-854
Sep 30, 2026
Merged

AquilaXk merged 6 commits into
mainfrom
fix/canonical-pack-calendar-label-854

Conversation

@AquilaXk

Copy link
Copy Markdown
Owner

Related issue

Closes #854

Summary

  • Problem: 전국 정본 팩(tools/datapack/release/nationwide-production-canonical-pack.json)의 데이터 결함 때문에 release-candidate 빌드가 입력 생성 다음 단계에서 멈췄다. 노선도 감사는 라벨 불일치 HIGH 2건으로, 데이터팩 빌드는 운행 요일 값 형식으로 실패했다. 이 둘을 고치자 가려져 있던 결함 2건(지역 정차 시각 필드명, 계약 밖 칸·문 안내)이 더 드러났다(이슈 본문 "범위 추가", 2026-10-01 QA 결정).
  • Outcome: 네 결함을 모두 생성·감사 도구에서 고치고 공식 생성 명령으로 정본 팩과 연쇄 고정값을 다시 만들었다. release-candidate 경로를 로컬에서 재현하면 1(입력 생성)→2(노선도 감사)→3(데이터팩 빌드)이 모두 exit 0이다. 검사 기준은 낮추지 않았고 예외 목록도 추가하지 않았다.

Changes

결함 1: 운행 요일 값이 0/1 숫자 (870b574, #814 도입)

  • tools/datapack/lib/regional-timetable-integrator.mjs: 부산·대구·대전·광주 serviceCalendars 16개의 요일 값을 같은 의미의 true/false로 쓴다. build-datapack.mjs boolFlag 검사는 그대로 둔다.

결함 2: 노선도 원천 라벨 불일치 HIGH 2건

  • 두 역 모두 공식 개명이다. 공식 역사 좌표 파일은 개명 전 역명을 유지하고, 승인 개명 기록(OFFICIAL_RENAME, #2470)도 이미 있다. 역 이름·노선 매핑·원천 라벨은 모두 맞다(아래 대조표).
  • 원인은 감사 도구다. tools/route-map/audit-route-map.mjs의 승인 개명 판정이 개명 기록 scopeKey의 권역을 pack.id와 비교했다. 7a75638([Feat][DataPack] Advance nationwide accessibility pipeline (elevator, barrier-free routes, timetables) and bind nationwide.sqlite pack identity #800/[Feat] Ingest nationwide barrier-free routes and regional accessibility facilities (#800) #801)에서 정본 팩 id가 capital에서 nationwide로 바뀌면서 이 비교가 깨졌다. 같은 두 행을 커밋된 capital-production-canonical-pack.json으로 감사하면 지금도 APPROVED_ROUTE_MAP_SOURCE_LABEL_RENAME INFO로 통과한다.
  • 수정: 권역 결속 기준을 pack.id에서, 팩이 선언한 coverageLineOperatorScopes의 정확한 region:operator:line 조합으로 바꿨다. 선언이 없거나 조합이 다르면 전과 같이 HIGH다. 선언이 없는 capital 팩은 오히려 더 엄격해졌다. 그래서 tools/route-map/route-map-tools.test.mjs의 기존 단위 fixture에 capital:seoul-metro:seoul-4 선언 한 줄을 추가했다.

결함 3: 지역 정차 시각 필드명·노선 누락 (#814)

  • regional-timetable-integrator.mjs: stopId·arrivalTimeSeconds·departureTimeSeconds를 계약 필드 stationId·arrivalSeconds·departureSeconds로 바꾸고, 각 정차 행에 trip과 같은 lineId를 싣는다. 시각 값과 산출 방식은 바꾸지 않는다.
  • tools/datapack/lib/regional-timetable-integrator.test.mjs: 옛 필드 참조를 계약 필드로 바꿨다.

결함 4: 계약 밖 KRIC 칸·문 안내 (#814 Phase 3)

  • tools/datapack/prepare-nationwide-candidate-run.mjs: carDoorHintContractViolations로 KRIC 파생 행을 station_car_door_hints 계약과 대조한다. 계약은 catalog-schema.sql CHECK(대상 시설 STAIR/ELEVATOR/ESCALATOR/TRANSFER, 칸 110, 문 14)와 빠른하차 importer(import-car-door-hints.mjs)의 방향 어휘(UP/DOWN/INNER/OUTER, 방향 미상은 빈 문자열)다.
  • 위반 행은 팩에 싣지 않고 tools/datapack/release/nationwide-car-door-hint-quarantine.json에 격리한다. 값을 다른 값으로 바꾸지 않는다.
  • tools/datapack/prepare-nationwide-candidate-run.test.mjs: 칸·문 행 수 기대값을 49로 바꾸고, 격리 합계(49 + 386 = 435)도 검사한다.

테스트·소유권

  • 신규 테스트 3개(required-pr, tools/ci/data-test-ownership.json의 data854 소유):
    • tools/datapack/canonical-pack-service-calendar-flags.test.mjs
    • tools/route-map/nationwide-route-map-official-rename.test.mjs
    • tools/datapack/canonical-pack-transit-car-door-contract.test.mjs

재생성 산출물

  • 명령: node tools/datapack/prepare-nationwide-candidate-run.mjs --requested-by=data-operator-lead --approved-by=data-release-authority
  • 바뀐 파일:
    • nationwide-production-canonical-pack.json
    • nationwide-car-door-hint-quarantine.json (신규)
    • candidate-build-spec.json fixtureSha256: a1c21d91… → 064fa48a…
    • hash-evidence.json fixturePath.sha256: a1c21d91… → 064fa48a…
    • release-request.json buildSpecSha256: 6e7a3947… → 418a7756…
    • nationwide-candidate-preparation.json builderIdentity.gitSha: 생성 시점 HEAD
  • 재생성 전 확인: main 입력으로 돌린 결과가 커밋본과 바이트 단위로 같았다(도구 결정성).
  • 재생성 전후 팩 차이는 아래뿐이다.
항목 차이
serviceCalendars 지역 16개 × 7요일 = 112개 값이 0/1 → false/true (의미 동일)
transitStopTimes 244,325행 수 유지. 지역 202,495행의 필드명 변경과 lineId 추가. 역·순번·시각 값 차이 0건
stationCarDoorHints 435 → 49행 (KRIC 파생 404행 중 386행 격리, 서울교통공사 31행은 그대로)
minimumTableRows.station_car_door_hints 435 → 49
그 밖의 값 차이 0건

결함 2: 두 역 공식 원천 대조표

역 / 노선 공식 역사 좌표 파일 (data.go.kr 15099316, 2025-08-14 기준) 팩 역 좌표 MOLIT 도시철도 전체노선 역 목록 (2025-12-11) 팩 표시명 (nameKo(nameSub)) 승인 개명 기록
station-f306bbca9985 / line-15b3b8a93259 (7호선) 호선 7, 외부역코드 2730, 뚝섬유원지, 37.531558 / 127.066714 37.531558 / 127.066714 (동일) 서울교통공사 7호선 순번 20 자양(뚝섬한강공원) 자양(뚝섬한강공원) capital:seoul-metro:line-15b3b8a93259 뚝섬유원지→자양(뚝섬한강공원), 서울특별시고시 제2024-109호(2024-02-29 시행)
station-871f17171f3c / seoul-4 (4호선) 호선 4, 외부역코드 409, 당고개, 37.66956 / 127.078404 37.66956 / 127.078404 (동일) 서울교통공사 4호선 순번 4 불암산(당고개) 불암산(당고개) capital:seoul-metro:seoul-4 당고개→불암산(당고개), 2025-05-15 시행
  • nationwide-route-map-official-rename.test.mjs가 위 값을 원천 파일(EUC-KR CSV)에서 다시 읽어 대조하고, release-candidate 감사 인자로 BLOCKER·HIGH 0을 확인한다.

결함 4: 격리 증거 (tools/datapack/release/nationwide-car-door-hint-quarantine.json)

  • 증거 파일 내용: 원천(kric-station-convenience-standard, sourceSnapshotId, rawSha256), 적용한 계약, 요약, 격리 행 전체. 각 행은 id·stationId·lineId·direction·targetFacilityType·carNumber·doorNumber·gubun·원문 dtlLoc·providerRecordHash·reasons를 가진다.
  • 요약: generatedCount 404, admittedCount 18, quarantinedCount 386
격리 사유 행 수 판단 근거
DIRECTION_OUTSIDE_CONTRACT (방향 BOTH) 386 계약 방향 어휘(UP/DOWN/INNER/OUTER, 미상은 빈 문자열)에 BOTH가 없다. 원문 dtlLoc에 방향 표기가 없는데 생성 도구가 "양방향"으로 채워 넣었다. 빈 문자열로 바꾸는 것도 값 치환이라 격리했다
TARGET_FACILITY_TYPE_OUTSIDE_CONTRACT (WHEELCHAIR_LIFT) 8 (모두 위 386행에 포함) 스키마 CHECK 밖. 계약 확장은 #856
DOOR_NUMBER_OUTSIDE_CONTRACT (문 번호 5 이상) 2 (모두 위 386행에 포함) 스키마 CHECK(문 1~4) 밖
  • 이슈 본문에 적힌 10행(WHEELCHAIR_LIFT 8 + 문 번호 2)은 모두 방향도 BOTH여서, 방향 위반 386행 안에 들어 있다.
  • provenanceKind OFFICIAL_SOURCE는 격리하지 않았다.
    • provenance_kind에는 어휘 제약이 없고, OFFICIAL_SOURCE는 pathway edge·노선도 좌표 등에서 쓰는 저장소 표준 값이다.
    • build-datapack은 OFFICIAL일 때만 원천 필드를 필수로 요구한다. 격리되지 않은 KRIC 18행은 sourceId·sourceSnapshotId·providerRecordHash를 모두 가진다.

Scope

Included

  • 결함 1~4의 원인 수정
  • 정본 팩과 연쇄 고정값의 공식 재생성
  • 실패 테스트 3개 파일
  • release-candidate 로컬 재현

Excluded

Ownership / dependencies

Contract & Compatibility

  • Source / API / schema contract: 스키마·계약 변경 없음. 팩 데이터가 기존 build-datapack 계약과 station_car_door_hints CHECK를 지키도록 생성 쪽을 고쳤다.
  • Artifact / provenance identity: 정본 팩 sha256이 바뀌어 fixtureSha256·hash-evidence·release-request.buildSpecSha256을 공식 생성 명령으로 다시 맞췄다. sourceSnapshotSetHash와 원천 스냅샷은 그대로다.
  • Backward compatibility: 앱 스키마 변화는 없다. 칸·문 안내가 435 → 49행으로 줄지만, 빠진 386행은 원래 계약 밖 값(BOTH·WHEELCHAIR_LIFT·문 5 이상)이었다.
  • Migration or cutover: 없음. 다음 release-candidate 실행부터 반영된다.

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: 변경 없음. 후보 nationwide-candidate-20260923-seq122의 입력 고정값만 재산출
  • data contract: 변경 없음
  • route-map artifact / product gate: 변경 없음
  • promotion request id: 해당 없음(발행 안 함)

Verification

Check Result / Evidence
Focused RED → GREEN 아래 "RED/GREEN" 참조
Affected integration release-candidate 로컬 재현 1→2→3 모두 exit 0 (아래 "재현 로그")
Required CI Data required checks, PR에서 확인
Live provider / release Not required — reason: 커밋된 원천 스냅샷만 쓰고 발행·배포를 하지 않는다
Security / data integrity 시크릿 미사용. 3단계 빌드 서명에는 로컬 임시 디렉터리에서 만든 1회성 RSA 키만 썼다. 커밋·출력 없음

RED/GREEN

  • RED (1fed1962, 7278bf08: 수정 전 테스트 커밋)
    • canonical-pack-service-calendar-flags.test.mjs: 2/2 실패 (busan-weekday-2026.monday=1 … 112개 값)
    • nationwide-route-map-official-rename.test.mjs: 3/4 실패. HIGH ROUTE_MAP_SOURCE_LABEL_MISMATCH 2건(station-f306bbca9985/line-15b3b8a93259, station-871f17171f3c/seoul-4). 공식 원천 대조 1개는 데이터가 맞아 통과
    • canonical-pack-transit-car-door-contract.test.mjs: 4/4 실패. stationId: undefined, busan-transportation-timetable:… stationId,lineId,arrivalSeconds,departureSeconds, carDoorHintContractViolations export 없음, 계약 밖 칸·문 행 존재
  • GREEN (HEAD)
테스트 결과
canonical-pack-service-calendar-flags.test.mjs 2/2
nationwide-route-map-official-rename.test.mjs 4/4
canonical-pack-transit-car-door-contract.test.mjs 4/4
release-pin-drift.test.mjs 4/4
release-candidate-accessibility-input.test.mjs 11/11
lib/regional-timetable-integrator.test.mjs 1/1
route-map/route-map-tools.test.mjs 39/39
prepare-nationwide-candidate-run.test.mjs 7/7
build-nationwide-candidate.test.mjs 13/13
ci/guard-datapack-anti-cheat.test.mjs 11/11
node --test --test-concurrency=1 --test-name-pattern "release candidate|production" tools/datapack/datapack-tools.test.mjs 50/50
  • 게이트
    • node tools/ci/data-test-discovery.mjs verify --class required-pr: exit 0 (366개, data854 3개 포함)
    • node tools/ci/guard-datapack-anti-cheat.mjs: PASS
    • node tools/datapack/validate-source-inventory.mjs: exit 0
    • node tools/repo/refresh-documentation-fragment.mjs --check: IN SYNC
    • node tools/ci/check-documentation-fragment-sync.mjs --base origin/main: "No tracked documentation resources modified"

release-candidate 로컬 재현 로그

.github/workflows/datapack-release.yml release-candidate 경로를 같은 인자로 실행했다. build spec은 tools/datapack/release/candidate-build-spec.json, 출력과 --candidate-fixture-override는 os.tmpdir() 아래다. 발행·업로드 단계는 실행하지 않았다.

단계 main (366d83b) 이 PR (HEAD)
stage-contracts / validate-candidate-source-set exit 0 / exit 0 exit 0 / exit 0
1. build-current-release-candidate-accessibility-input.mjs exit 0 exit 0
2. audit-route-map.mjs --fail-on BLOCKER,HIGH exit 1 (HIGH 2) exit 0 (BLOCKER 0, HIGH 0, MEDIUM 209, INFO 3: 두 역 승인 개명)
3. build-datapack.mjs --candidate-fixture-override … exit 1 (serviceCalendars.monday must be a boolean) exit 0 (current.json·current.provenance.json·catalog/ 생성)
  • 결함 1만 고친 중간 상태에서는 3단계가 transitStopTimes.stationId must be a non-empty string(결함 3)으로 실패했다.
  • 결함 3까지 고친 상태에서는 CHECK constraint failed: target_facility_type IN (...)(결함 4)으로 실패했다.
  • 3단계는 서명을 위해 EASYSUBWAY_DATAPACK_SIGNING_*가 필요하다. CI에서는 워크플로가 시크릿으로 넣고, 로컬에서는 1회성 키를 썼다.

3단계 이후 release-candidate 실패 (범위 밖, 보고만)

단계 결과 비고
Validate source inventory exit 0
Validate generated data packs / Verify staged checksums manifest.keyId is unknown 로컬 1회성 키라서 생긴 실패. 운영 서명키가 필요해 로컬에서 판정할 수 없다
Stage current server route bundle candidate key id must be production-v1 같은 이유(운영 서명키 필요)
Validate accessibility source coverage NO_GO 4개 권역 접근성 원천 SNAPSHOT_TIME_INVALID·LICENSE_EVIDENCE_MISMATCH, molit-railway-transfer-movement:LICENSE_NOT_REDISTRIBUTABLE, 다수 행 CLAIM_SNAPSHOT_BINDING_MISMATCH
Write coverage gap evidence exit 0
Write route graph topology evidence ITX topology evidence pack identity mismatch
Write headway evidence exit 0
Verify current ITX-청춘 release freshness ITX topology source artifact is expired

id === "capital" 조회 후속 목록 (release-candidate 경로에서 실행되지 않음)

  • 대상 8곳:
    • tools/datapack/apply-accessibility-evidence-to-bundled-pack.mjs: overlayReviewedSourcesOnCanonicalRoster(268), syncCanonicalFixture(297), activeReleaseSnapshots(699), currentCandidateReleaseSnapshots(742), main(918·937·961)
    • tools/datapack/register-current-seoul-accessibility-snapshot.mjs(161)
  • 확인 방법: 8곳에 임시 표시를 넣고 위 재현(1~3단계와 이후 단계)을 실행했다. 한 번도 실행되지 않았다. 임시 표시는 되돌렸다.
  • build-datapack이 쓰는 함수는 PR #852에서 고친 syncCanonicalAccessibilityEvidence·retainPreAuthorityRideEdges뿐이다.
  • 이 PR에서는 코드를 바꾸지 않았다. 해당 경로(접근성 원천 재등록·활성화 도구)를 전국 팩에서 쓸 때 같은 manifest.activePack 정확히-하나 선택으로 고쳐야 한다.

Not run

  • Check: 3단계 이후 서명 의존 검증(validate-datapack --require-production, server route bundle staging)
  • Reason: 운영 서명 키(시크릿)가 필요하다. 로컬에서는 쓰지 않는다
  • Rerun owner / condition: 이 PR 병합 뒤 QA가 승인한 release-candidate workflow 실행

Risk

  • Level: High
  • Main risk: 칸·문 안내가 435 → 49행으로 준다. KRIC 파생 386행은 방향 미상인 행을 BOTH로 채운 값이라 계약 밖이어서 격리했다. 방향 미상 행을 계약에 어떻게 싣을지(빈 문자열 허용 등)는 따로 결정이 필요하다.
  • Failure behavior: 계약 밖 행은 격리 증거에 남고 팩에 들어가지 않는다. 다른 계약 위반은 build-datapack·validate-datapack이 그대로 실패시킨다.
  • Candidate / admission / publication state on failure: 발행하지 않으므로 운영 상태에 영향이 없다.
  • Fallback or degraded-success path introduced: No

Rollout / Recovery

  • Rollout or promotion: 다음 release-candidate workflow 실행(QA 승인 필요)
  • Monitoring / success signal: release-candidate 실행에서 노선도 감사·데이터팩 빌드 단계 통과
  • Rollback or recovery: 이 PR revert(정본 팩과 고정값이 함께 되돌아간다)
  • Existing artifact / schema compatibility after rollback: 스키마 변경이 없어 영향 없음

Review focus

  • audit-route-map.mjs 승인 개명 권역 결속: pack.id → 팩이 선언한 coverageLineOperatorScopes 조합. 선언 없는 팩은 더 엄격해진다.
  • BOTH 방향 386행 격리 판단: 계약 어휘에 없는 값을 빈 문자열로 바꾸지 않고 격리했다.
  • 재생성 산출물 차이가 위 표의 항목뿐인지

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

- canonical-pack-service-calendar-flags.test.mjs: 지역 시간표 통합 출력과
  커밋된 전국 정본 팩의 serviceCalendars 요일 값이 모두 boolean인지 검사한다.
  현재 main은 부산·대구·대전·광주 16개 달력이 0/1 숫자라 실패한다.
- nationwide-route-map-official-rename.test.mjs: 자양(뚝섬한강공원)·불암산(당고개)
  두 역을 공식 역사 좌표 파일(data.go.kr 15099316)·MOLIT 역 목록·승인 개명 기록과
  대조하고, release-candidate 감사 인자로 커밋된 전국 팩을 감사해 BLOCKER·HIGH 0을
  요구한다. 현재 main은 ROUTE_MAP_SOURCE_LABEL_MISMATCH HIGH 2건으로 실패한다.
  승인 개명 권역은 팩이 선언한 coverageLineOperatorScopes 조합으로만 인정하는
  단위 검사도 추가했다.
- data-test-ownership.json에 data854 소유자와 두 테스트를 required-pr로 등록한다.
결함 1: regional-timetable-integrator가 부산·대구·대전·광주 serviceCalendars
16개의 요일 값을 0/1 숫자로 써서 build-datapack boolFlag가
"serviceCalendars.monday must be a boolean"으로 실패했다(870b574, #814 도입).
요일 값을 같은 의미의 true/false로 쓴다. 검사는 그대로 둔다.

결함 2: audit-route-map의 승인 개명(OFFICIAL_RENAME) 판정이 개명 기록
scopeKey의 권역을 pack.id와 비교했다. 7a75638(#800/#801)에서 정본 팩 id가
capital에서 nationwide로 바뀌어, capital 팩에서는 승인 개명으로 통과하던
같은 두 행(자양(뚝섬한강공원)/7호선, 불암산(당고개)/4호선)이 전국 팩에서
ROUTE_MAP_SOURCE_LABEL_MISMATCH HIGH가 됐다. 권역 결속을 팩 id 대신 팩이 선언한
coverageLineOperatorScopes의 정확한 region:operator:line 조합으로 바꾼다.
선언이 없거나 조합이 다르면 전과 같이 HIGH로 막는다(예외 목록·기준 변경 없음).
기존 단위 테스트 fixture에는 capital:seoul-metro:seoul-4 선언을 추가했다.
node tools/datapack/prepare-nationwide-candidate-run.mjs \
  --requested-by=data-operator-lead --approved-by=data-release-authority

- nationwide-production-canonical-pack.json: 부산·대구·대전·광주 serviceCalendars
  16개 x 7요일 = 112개 값이 0/1에서 같은 의미의 true/false로 바뀌었다.
  그 밖의 값 차이는 없다(재생성 전 main 입력으로 돌린 결과는 커밋본과 바이트 동일).
- candidate-build-spec.json fixtureSha256, hash-evidence.json fixturePath.sha256:
  a1c21d91… → 9e647a85…
- release-request.json buildSpecSha256: 6e7a3947… → b3fe97eb…
- nationwide-candidate-preparation.json builderIdentity.gitSha: 생성 시점 HEAD
범위 추가(2026-10-01 QA 결정)의 결함 3·4 실패 테스트.
- 결함 3: 지역 시간표 통합 출력과 커밋된 전국 정본 팩의 transitStopTimes가
  stationId·lineId·arrivalSeconds·departureSeconds를 갖고, lineId가 trip 노선·
  stationLines와 맞는지 검사한다. 현재 통합 도구는 stopId·arrivalTimeSeconds·
  departureTimeSeconds를 쓰고 lineId를 빠뜨려 실패한다.
- 결함 4: 칸·문 안내 계약 검사(대상 시설 STAIR/ELEVATOR/ESCALATOR/TRANSFER,
  칸 1~10, 문 1~4, 방향 ''/UP/DOWN/INNER/OUTER)와 격리 증거 파일을 요구한다.
  현재 생성 도구에 계약 검사·증거 파일이 없고 팩에 계약 밖 행이 있어 실패한다.
- data-test-ownership.json에 data854 소유로 required-pr 등록.
결함 3: regional-timetable-integrator가 transitStopTimes를 stopId·
arrivalTimeSeconds·departureTimeSeconds로 쓰고 lineId를 빠뜨렸다. build-datapack
계약 필드 stationId·lineId·arrivalSeconds·departureSeconds로 쓰고 각 정차 행에
trip과 같은 노선 id를 싣는다. 시각 값과 산출 방식은 바꾸지 않는다(#855 범위 제외).
regional-timetable-integrator.test.mjs의 옛 필드 참조도 계약 필드로 바꿨다.

결함 4: KRIC 칸·문 안내 확대가 station_car_door_hints 계약 밖 행을 팩에 실었다.
생성 단계에서 carDoorHintContractViolations로 대상 시설(STAIR/ELEVATOR/ESCALATOR/
TRANSFER), 칸 1~10, 문 1~4, 방향(''/UP/DOWN/INNER/OUTER, 빠른하차 importer 어휘)을
검사하고, 위반 행은 팩에 싣지 않고 사유·식별자·원문(dtlLoc)·개수를
tools/datapack/release/nationwide-car-door-hint-quarantine.json에 남긴다.
값을 다른 값으로 바꾸지 않는다. WHEELCHAIR_LIFT 계약 확장은 #856.
node tools/datapack/prepare-nationwide-candidate-run.mjs \
  --requested-by=data-operator-lead --approved-by=data-release-authority

- nationwide-production-canonical-pack.json
  - transitStopTimes 244,325행 수 유지. 지역 202,495행의 필드명만 계약 필드로 바뀌고
    lineId가 붙었다. 역·순번·시각 값 차이 0건.
  - stationCarDoorHints 435 → 49행, minimumTableRows.station_car_door_hints 435 → 49.
    KRIC 파생 404행 중 386행 격리(방향 BOTH 386, 그중 WHEELCHAIR_LIFT 8·문 번호 5 이상 2).
- nationwide-car-door-hint-quarantine.json(신규): 격리 386행의 id·역·노선·방향·시설·
  칸·문·원문 dtlLoc·gubun·providerRecordHash·사유와 사유별 개수.
- fixtureSha256·hash-evidence fixturePath.sha256: 9e647a85… → 064fa48a…
- release-request buildSpecSha256: b3fe97eb… → 418a7756…
- nationwide-candidate-preparation builderIdentity.gitSha: 생성 시점 HEAD
- prepare-nationwide-candidate-run.test.mjs: 칸·문 행 수 기대값을 49와
  격리 합계(49 + 386 = 435)로 바꿨다.
@coderabbitai

coderabbitai Bot commented Sep 30, 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: 067647ea-9b23-4de1-a448-3eb3ea797a14

  • 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 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: 0

🎯 Linked issue & acceptance criteria audit
ID Acceptance criterion Status Evidence
AC-1 Weekday flags are booleans from the generator PASS tools/datapack/lib/regional-timetable-integrator.mjs
AC-2 Official renames pass the audit without exceptions PASS tools/route-map/audit-route-map.mjs
AC-3 Stop time field names and out-of-contract car-door rows quarantined PASS tools/datapack/prepare-nationwide-candidate-run.mjs
🛡️ Adversarial audit evidence
  • Falsifiability verified: Yes (Reverting the audit scope binding fails three rename tests.)
  • Hollow assertions detected: 0
  • Production backdoors detected: 0
  • Ground-truth sources verified:
    • catalog-schema.sql station_car_door_hints CHECK
    • data.go.kr 15099316 station coordinates and MOLIT station list for both renamed stations
  • Mutation testing evidence: Restoring scope.regionId === pack.id: rename test 1 pass, 3 fail.
🤖 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: aquila-review by Claude Code against issue #854 and hub CLAUDE.md

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@366d83bd16cc3cebb398f41f4397c63fc1b3596d

Head:
fix/canonical-pack-calendar-label-854@fecba49d27ea410b92c180194a529ac52fe2aa47

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

📥 Commits

Reviewing files changed in this pull request between:

  • Base: 366d83bd16cc3cebb398f41f4397c63fc1b3596d
  • Head: fecba49d27ea410b92c180194a529ac52fe2aa47
📒 Files selected for processing (16)
  • tools/ci/data-test-ownership.json
  • tools/datapack/canonical-pack-service-calendar-flags.test.mjs
  • tools/datapack/canonical-pack-transit-car-door-contract.test.mjs
  • tools/datapack/lib/regional-timetable-integrator.mjs
  • tools/datapack/lib/regional-timetable-integrator.test.mjs
  • tools/datapack/prepare-nationwide-candidate-run.mjs
  • tools/datapack/prepare-nationwide-candidate-run.test.mjs
  • tools/datapack/release/candidate-build-spec.json
  • tools/datapack/release/hash-evidence.json
  • tools/datapack/release/nationwide-candidate-preparation.json
  • tools/datapack/release/nationwide-car-door-hint-quarantine.json
  • tools/datapack/release/nationwide-production-canonical-pack.json
  • tools/datapack/release/release-request.json
  • tools/route-map/audit-route-map.mjs
  • tools/route-map/nationwide-route-map-official-rename.test.mjs
  • tools/route-map/route-map-tools.test.mjs
📜 Review details

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

Copy link
Copy Markdown
Contributor

No description provided.

@AquilaXk
AquilaXk merged commit af03e04 into main Sep 30, 2026
14 checks passed
@AquilaXk
AquilaXk deleted the fix/canonical-pack-calendar-label-854 branch September 30, 2026 23:13
@sonarqubecloud

Copy link
Copy Markdown

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] 전국 정본 팩의 운행 요일 값·노선도 라벨 결함으로 release-candidate 빌드 실패

1 participant