Repository navigation
[Fix] 원천 갱신 workflow 실패를 이슈로 드러내고 광주 보관 시간표 갱신에 수동 실행 경로 추가 - #926
Conversation
- 원천 갱신 workflow 4개(수도권 topology·KRIC 편의시설·광주 보관 KRIC 시간표·서울 접근성)는 2026-09-04~09-20 동안 2시간마다 실패했지만 아무도 알림을 받지 못했다(#860). - 각 workflow 마지막 단계에서 실패 시 report-refresh-failure로 workflow별 열린 이슈를 하나 만들고, 다시 실패하면 그 이슈에 run 링크를 댓글로 붙인다. 같은 workflow 이슈가 둘 이상이면 고르지 않고 실패한다. - 광주 보관 KRIC 시간표 갱신은 schedule만 있어 #860 완료 조건의 수동 dispatch 검증을 할 수 없었다. workflow_dispatch를 추가한다(입력 없음, 판정은 기존 decide 그대로). - RED: 새 계약 테스트가 변경 전 workflow에서 issues: write·실패 단계·workflow_dispatch 부재로 실패. Refs #860 Refs #870
|
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 |
SonarCloud S4036(PATH 의존 실행)·S6353 지적을 반영한다. tools/route-map/svg-crop/render-svg.mjs의 git 고정 경로 탐색과 같은 방식으로 /usr/bin/gh 등에서만 gh를 찾고, 없으면 REFRESH_FAILURE_REPORT_GH_EXECUTABLE로 실패한다. Refs #860
AquilaXk
left a comment
There was a problem hiding this comment.
Actionable comments posted: 4
🎯 Linked issue & acceptance criteria audit
- Linked issue: #860 Fix: restore five manually disabled source refresh workflows
- Goal summary: Restore refresh workflows; this PR adds failure alerts and a dispatch path.
- Acceptance criteria verified: 2/2
| ID | Acceptance criterion | Status | Evidence |
|---|---|---|---|
| AC-ALERT | Repeated failures raise an alert instead of piling up silently | PASS | tools/ci/report-refresh-failure.mjs |
| AC-DISPATCH | Each workflow can be run once through workflow_dispatch | PASS | .github/workflows/retained-gwangju-timetable-refresh.yml |
🛡️ Adversarial audit evidence
- Falsifiability verified: Yes (Probe on lines 44 and 46 of the reporter killed mutants by assertion failure.)
- Hollow assertions detected: 0
- Production backdoors detected: 0
- Ground-truth sources verified:
gh issue list JSON shape number and bodyIssue 860 body acceptance criteriaubuntu-latest gh install path /usr/bin/gh
- Mutation testing evidence:
probe lines 44 and 46 killed; line 42 has no supported operator
🤖 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:
- `@.github/workflows/seoul-current-accessibility-refresh.yml:8-11`
Would moving the permissions block under the refresh job match the least-privilege
intent for later edits?
- `@tools/ci/report-refresh-failure.mjs:39-44`
Would restricting the match to issues created by the workflow token, or to a
dedicated label, avoid false duplicates? Alternatively the duplicate error could
name the issue numbers so the log points to the cleanup.
- `@tools/ci/report-refresh-failure.mjs:46-55`
Could the comment path skip a run URL that the issue already mentions, and throttle
to one comment per day, so a long outage stays readable? A test with the same run id
twice would pin the behavior.
- `@tools/ci/report-refresh-failure.mjs:92-98`
Could resolveGh accept an injectable existence check so a test can cover the found
and missing cases, with `GH_EXECUTABLE` asserted for the missing case?
---
Outside diff comments:
None.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Aquila review of easysubway-data PR 926 using CLAUDE.md and the issue 860 body
Review profile: ASSERTIVE
Plan: Aquila fallback
Run ID: N/A (Aquila fallback)
Review source: Aquila CLI
Repository visibility: public GitHub repository
Trigger:
Manual discovery review requested by QA for the draft PR at current head
Base:
main@53f01fc5c4c5d2b7630c2c6dcdb79608200eaa1c
Head:
fix/refresh-failure-issue-860@7731176798f04c0889050eeea7e3648bd659ce7a
Command:
node aquila-review/scripts/post-review.mjs input.json payload-1.json --repo AquilaXk/easysubway-data --pr 926
📥 Commits
Reviewing files changed in this pull request between:
- Base:
53f01fc5c4c5d2b7630c2c6dcdb79608200eaa1c - Head:
7731176798f04c0889050eeea7e3648bd659ce7a
📒 Files selected for processing (4)
.github/workflows/retained-gwangju-timetable-refresh.yml.github/workflows/seoul-current-accessibility-refresh.ymltools/ci/report-refresh-failure.mjstools/ci/report-refresh-failure.test.mjs
📜 Review details
#926 리뷰 F1: 2시간마다 도는 갱신 workflow가 계속 실패하면 같은 이슈에 하루 12개 댓글이 달리고, 같은 run을 재실행하면 같은 링크가 다시 붙었다. - 이슈 본문에 상태 블록(마지막 보고 시각, 보고한 run 최근 20개)을 둔다. - 이미 상태 블록이나 댓글에 있는 run은 아무것도 쓰지 않는다(skip). - 마지막 알림(이슈 생성 또는 알림 댓글) 뒤 24시간 안의 실패는 본문 상태만 갱신한다(status). - 24시간이 지나면 댓글 1개를 단 뒤 상태를 갱신한다(comment). 댓글을 먼저 달아 본문 갱신이 실패해도 run이 남는다. - 상태 블록이 없는 열린 이슈는 추정하지 않고 REFRESH_FAILURE_REPORT_STATUS_BLOCK으로 실패한다. RED: 상수만 둔 상태에서 새 반복 시나리오(3일 2시간 간격 36 run → 이슈 1·댓글 2·상태 33) 등 7건 실패. Refs #860
#926 리뷰 F2: 표지 문자열만 보고 이슈를 고르면, 사람이 표지를 인용한 이슈 하나로 중복 판정이 나서 이후 모든 보고가 영구히 멈췄다. - github-actions 봇(gh JSON login app/github-actions)이 만들고 제목이 정확히 같은 열린 이슈만 센다. - 중복이면 가장 오래된 이슈에 이번 실패를 그대로 기록(상태·하루 1회 댓글)하고, 댓글에 다른 이슈 번호를 적는다. 그다음 REFRESH_FAILURE_REPORT_DUPLICATE_ISSUES로 이슈 번호와 "하나만 남기고 나머지를 닫으면 정상 보고" 안내를 남기고 실패한다. RED: 새 테스트 2건(사람이 인용한 이슈 무시, 중복 시 기록 계속과 복구 안내)이 변경 전 코드에서 실패. Refs #860
|
No description provided. |
|
No description provided. |
|
* [Fix] KRIC 전국 시간표 파일 수집이 본문 수신 중 30초 한도로 끊기던 문제 수정 (#995) 연결·헤더 한도(30초)와 본문 수신 한도(5분)를 나누고, 본문 시간 초과는 BODY가 아니라 TIMEOUT으로 드러낸다. 504 run 37399282636이 17.9MB 본문을 받는 중 정확히 30초에 KRIC_TIMETABLE_FILE_BODY로 실패한 원인이다. 재시도·대체는 넣지 않는다(요청은 1회). Refs #995 * [Fix] PR 없는 claim 브랜치를 소유 workflow가 스스로 복구·정리하도록 하기 (#995) claim 브랜치(provider 접근 전에 push하는 빈 커밋)가 PR 없이 남으면 소유 workflow가 만든 run과 게시 증거로 판정한다. - 공유 모듈 claim-orphans: ACTIVE(run 진행 중, 기다림)·RECOVERABLE(출력 커밋 또는 receipt artifact, DUE·CURRENT와 무관하게 복구)·ABANDONED(빈 claim뿐, 보고 후 삭제) run 조회는 고아마다 gh run view 한 번, Not Found는 끝난 run, 그 밖의 gh 오류는 fail closed, claim 50개 상한 - remove-orphan-claims: #926 실패 보고를 먼저 하고 지운다. PR이 열려 있거나 닫혀 있거나 run이 진행 중이면 지우지 않고 실패한다. sha lease - 광주 보관 시간표는 CURRENT에서도 claim을 판정한다(504 사례). 서울 접근성·KRIC 편의시설·수도권 topology 갱신이 같은 판정을 쓴다 - KRIC 복구 artifact는 게시 receipt가 있을 때만 올린다. 등록·재확인 workflow의 정리도 보고 경로를 거친다 Refs #870 Refs #969 Closes #995 * [Fix] SonarCloud 지적 정리: 정렬 비교 함수, 인지 복잡도, top-level await (#995) - topology 정리 대상 claim 정렬에 비교 함수를 둔다(S2871, 신뢰성 gate 실패 원인) - 삭제 CLI·수집기·topology 판정의 큰 함수를 나눠 인지 복잡도를 15 이하로 낮춘다(S3776) - 중첩 삼항 제거(S3358), promise chain 대신 top-level await(S7785) Refs #995 * [Test] RED: claim 정리가 게시 step까지 갔는지로 판정하도록 하는 테스트 (#995 F1) 게시 여부를 receipt 표지가 아니라 만든 run의 step(게시 step 시작 여부)으로 판정한다. - 게시 step 이전 실패는 삭제, 게시 step 이후 실패는 삭제하지 않고 CLAIM_ORPHAN_PUBLISHED_UNREGISTERED - run 기록 없음·step 정보 없음은 빈 claim이라도 실패 - 광주·서울·KRIC 수집/게시 step 분리를 위한 controller phase와 workflow 계약 - KRIC decision.json·journal.json 항상 업로드 이 커밋은 의도적으로 실패한다(RED). Refs #995 * [Fix] claim 정리를 receipt 표지가 아니라 게시 step 시작 여부로 판정 (#995 F1) - 만든 run의 step 기록(gh run view --json jobs)으로 OCI 게시 step이 시작됐는지 판정한다. 게시 step 이전 실패는 ABANDONED(삭제), 시작된 뒤 출력 커밋·보존 증거가 없으면 CLAIM_ORPHAN_PUBLISHED_UNREGISTERED(삭제하지 않고 실패) - run 기록 없음(Not Found)·step 정보 없음은 빈 claim이라도 CLAIM_ORPHAN_RUN_UNAVAILABLE·STEPS_UNAVAILABLE로 실패 - 광주·서울·KRIC의 수집과 게시·등록을 서로 다른 step으로 나눈다(controller phase collect/publish, KRIC finalize step) - KRIC은 decision.json·journal.json을 항상 업로드한다 - 분리 전 step에서 실패한 504 run은 로그로 게시 전 실패가 확인된 명시 표(VERIFIED_PRE_PUBLICATION_RUNS)로만 ABANDONED - claim-orphans 헤더·emptyClaim 주석을 사실대로 고친다(빈 claim은 게시되지 않았다는 증거가 아니다) Refs #995 * [Test] RED: 삭제 guard 강화 테스트 (#995 F2) - lease는 판정 시점(--refs)의 sha, 그 뒤 브랜치가 움직였으면 거부 - push 직전에 빈 claim(ahead_by 1, files 0)과 run 상태를 다시 확인하고 출력이 있는 브랜치는 거부 - 병합된 PR의 잔여 claim은 예외 - 6개 workflow의 정리 step이 판정 시점 ls-remote 파일을 --refs로 넘긴다 이 커밋은 의도적으로 실패한다(RED). Refs #995 * [Fix] 삭제 guard 강화: 판정 시점 sha lease와 push 직전 재확인 (#995 F2) - 삭제 lease는 판정 시점(--refs)의 sha다. 그 뒤 브랜치가 움직였으면 지우지 않는다 - 보고 전과 push 직전에 만든 run이 completed인지, 브랜치가 빈 claim(ahead_by 1, 제목 일치, 변경 파일 0)인지 다시 확인한다 - 출력이 있는 브랜치는 어느 workflow에서 넘겨도 거부한다(등록·재확인 포함). 병합된 PR의 잔여 claim은 예외 - 6개 workflow의 정리 step이 판정 시점 ls-remote 파일을 --refs로 넘긴다 Refs #995 * [Test] RED: 삭제 기록과 보고 본문 테스트 (#995 F3) - 삭제할 때마다 notice와 step summary에 branch·producer run·conclusion·분류 reason·보고 action - 보고 본문은 producer run의 conclusion을 그대로 적고 삭제 사실을 포함한다. 이미 기록된 run도 삭제는 comment로 남긴다 - remover도 게시 step이 시작된 run은 거부한다 이 커밋은 의도적으로 실패한다(RED). Refs #995 * [Fix] claim 삭제 기록과 보고 본문 보강 (#995 F3) - 삭제할 때마다 ::notice와 GITHUB_STEP_SUMMARY에 branch·producer run·conclusion·분류 reason·보고 action을 남긴다 - #926 보고 본문은 producer run의 conclusion을 그대로 적고 claim 삭제 사실을 포함한다. 이미 기록된 run도 삭제는 comment로 남기고 같은 삭제는 한 번만 기록한다 - remover도 공유 판정의 분류가 여전히 ABANDONED인지 확인한다(게시 step이 시작된 run의 claim은 거부) Refs #995 * [Test] RED: KRIC Abandon claim에 PR이 붙으면 실패하는 검사 복원 (#995 F4) 이 커밋은 의도적으로 실패한다(RED). Refs #995 * [Fix] KRIC Abandon claim에 PR이 붙으면 실패하는 검사 복원 (#995 F4) - Abandon 커밋을 쓰는 workflow는 PR이 붙은 claim의 커밋도 증거로 수집하고, 닫은 claim에 PR이 붙으면 상태와 무관하게 이름 있는 이상으로 실패한다 - recover step의 Abandon 경로가 언제 닿는지 주석으로 남긴다 Refs #995 * [Test] RED: 본문 한도 5분의 근거를 상수와 테스트로 고정 (#995 F5) 이 커밋은 의도적으로 실패한다(RED). Refs #995 * [Fix] 본문 한도 5분의 근거를 상수로 고정 (#995 F5) 관측한 파일 크기(17,949,564 bytes)를 최소 처리량 60KB/s로 받는 시간을 분 단위로 올림한 값이다. 근거를 상수 주석과 테스트에 남긴다. Refs #995 * [Fix] SonarCloud 지적 정리: 미사용 변수, 인지 복잡도, 의도적 순차 await (#995) Refs #995 * [Test] RED: Abandon으로 닫힌 KRIC claim 삭제 허용과 이슈 본문 마커 검사 (#995 F2·F3 잔여) 이 커밋은 의도적으로 실패한다(RED). Refs #995 * [Fix] Abandon으로 닫힌 KRIC claim 삭제를 허용하고 이슈 본문 마커도 검사 (#995 F2·F3 잔여) - isClosedOutClaim(abandonedSubject를 쓰는 workflow의 claim 제목 + Abandon 제목 두 커밋, 변경 파일 0)을 판정과 remover가 공유한다. remover는 빈 claim 또는 닫힌 claim만 지우고 재판정이 CLAIM_CLOSED_OUT ABANDONED여야 한다 - 판정의 CLAIM_CLOSED_OUT도 같은 엄격한 조건을 쓴다(내용이 바뀐 Abandon 브랜치는 내용이 있는 브랜치) - 삭제 기록 마커를 이슈 본문에서도 찾는다(이슈 생성 때 본문에 적은 삭제를 comment로 되풀이하지 않는다) Refs #995
* [Chore] 외부 스케줄러 dispatch를 정기 실행과 같은 의미로 맞추고 스케줄러 중단을 실패 이슈로 감시 (#1001) - 변수 게이트 정기 workflow 4개: App(easysubway-release-chain[bot])의 dispatch는 DATAPACK_SCHEDULED_* 변수를 따른다 - datapack-expiry-alert: dispatch 입력 target으로 점검 job을 고른다 - data-workflow-scheduler-watchdog: App dispatch heartbeat를 점검하고 #926 실패 이슈로 알린다(DATAPACK_SCHEDULER_WATCHDOG 기본 꺼짐) * [Fix] 리뷰 반영: 사람 allow list 게이트, dispatch target별 heartbeat, 대기열 유지, 식 평가 테스트 (#1001)
…#870 전체 자동화) (#1014) * [Test] 정기 갱신 4종 자동 병합 정책의 반증 테스트 추가 (RED) 기록된 실제 갱신 PR(#937 #965 #1003 #1009 #1010 #1011)의 변경 파일·원장 행·inventory 변경 필드를 fixture로 두고 단계별 경로 allowlist·소유 항목·소유 필드·원장 방식, 증거 블록 검증, 게이트 재계산, emitter, recreate redispatch, workflow 배선을 구현 전에 고정한다. 추가 경로·정책 필드 변경·소유 밖 항목·위조된 head의 반증을 포함한다. Refs #1012 Refs #969 Refs #870 * [CI] 정기 갱신 4종 PR에 증거 블록을 싣고 자동 병합 정책·게이트 재계산·재생성 경로에 올리기 (GREEN) - refresh-stage-contracts: 단계별 경로 규칙(added·modified)·소유 inventory 항목과 필드·원장 방식·게이트 재계산(evaluateRefreshStage)의 정본 - automation-pr-evidence: 단계 gwangju-timetable-refresh·capital-topology-refresh·kric-facility-refresh·seoul-accessibility-refresh를 기존 단계 뒤에 더한다 - automation-pr-policy: API diff와 증거 경로의 정확 대조, 파일별 변경 종류, 게이트 재계산을 새 단계에 적용한다 - refresh-automation-pr: workflow가 push 전에 증거 본문을 만들고 어긋나면 push·PR 전에 실패한다 - automation-pr-recreate: 새 단계 4종의 뒤처진 PR을 닫고 같은 workflow를 다시 실행한다 - 4개 workflow의 PR 본문을 증거 블록이 든 본문 파일로 바꾼다(새 PR·복구 경로 모두) Refs #1012 Refs #969 Refs #870 * [Test] falsifiability probe로 드러난 검사 틈을 닫는 반증 추가 (#1012) Refs #1012 * [Test] fixture helper가 생산자 신원 규칙을 따르는 topology snapshot과 출처 표식 pack을 합성하도록 (#1012) 리뷰 F1·F2·F4의 반증을 쓰기 위한 선행 정비다. 동작은 바뀌지 않는다. Refs #1012 * [Test] topology snapshot 신원을 본문에서 다시 계산하는 반증 추가 (#1014 F2, RED) 선언된 contentSha256·lineCount·totalEdgeCount, 본문 간선 변조, 노선 해시, 노선 집합, 직전 snapshot 변조와 등록 workflow의 원본 sha 대조 코드 근거를 구현 전에 고정한다. Refs #1012 * [CI] topology snapshot 신원을 생산자 검증 함수로 본문에서 다시 계산하고 원본 출처 경계를 계약에 명시 (#1014 F2, GREEN) requireCurrentSourceSeparatedCapitalTopology로 head와 직전 snapshot의 노선 해시·개수·contentSha256·노선 집합을 다시 계산한다. 원본 응답의 출처는 병합 뒤 등록 workflow가 OCI 원본으로 확인한다(rawSha256 = sha256(topologyBytes), 영수증 rawObjectSha256 대조). Refs #1012 * [Test] topology 자동 경로가 제거를 허용하지 않고 추가는 2% 이내만 허용하는 반증 추가 (#1014 F4, RED) 간선·역 제거, 같은 수 교체, 같은 노선 치환, 추가·수정 합산 한도, 전용 override 사용 여부를 구현 전에 고정한다. Refs #1012 * [CI] topology 자동 경로에서 제거를 허용하지 않고 추가·수정은 전용 override 2%까지만 허용 (#1014 F4, GREEN) - 직전 노선별 역·간선 집합이 새 집합의 부분집합이 아니면 REFRESH_GATE(같은 수로 교체해도 제거로 잡힌다) - 추가·수정된 간선 합이 capital-route-topology 전용 override(sourceOverrides, maxRowDeltaRatio 0.02)를 넘으면 SOURCE_COUNT_DELTA - 정책 파일에 전용 override를 더하고 이를 고정하던 기존 테스트 두 곳을 맞춘다 Refs #1012 * [Test] canonical pack을 구조 diff로 비교해 표식 밖 변경을 막는 반증 추가 (#1014 F1, RED) 빈 pack, 접근성 값·정차 시각 변경, 간선 추가·삭제, 배열 순서·길이, 표식 키에 엉뚱한 값, 다른 원천의 표식, 키 구성 변경, 읽기 실패를 구현 전에 고정한다. 대조군은 기록된 갱신처럼 표식만 새 snapshot·증거 시각으로 바뀐 pack이다. Refs #1012 * [CI] canonical pack을 base·head 구조 diff로 비교해 출처 표식 밖 변경을 PACK_CONTENT로 막기 (#1014 F1, GREEN) 바뀔 수 있는 키는 sourceSnapshotId·updatedAt·lastVerifiedAt·reviewedAt뿐이고 값은 소유 원천의 직전→새 snapshot id, 증거 시각과 정확히 같아야 한다. 그 밖의 키·값·키 구성·배열 길이와 순서가 달라지면 위반이다. 실제 갱신 #936 #952 #965 #1003의 pack diff가 모두 통과한다. Refs #1012 * [Test] Seoul 입력 파일의 evidenceHash를 새 snapshot에서 다시 계산하는 반증 추가 (#1014 F3, RED) Refs #1012 * [CI] Seoul 입력 파일의 evidenceHash를 생성 코드의 계산 함수로 새 snapshot에서 다시 계산해 대조 (#1014 F3, GREEN) materialize-accessibility-source-input의 두 해시 계산을 이름 있는 함수로 내보내 생성 코드와 정책이 같은 구현을 쓴다(동작 불변). 계산 방식을 아는 행 목록(routeEdges, accessibilityStatusEvidence)만 허용한다. Refs #1012 * [Test] 허용 밖 경로의 실제 동작(push 전 거부)과 계약 주석의 일치를 고정 (#1014 F5, RED) Refs #1012 * [Docs] 계약 주석을 허용 밖 경로의 실제 동작(push 전 실패, #926 보고)에 맞춘다 (#1014 F5, GREEN) Refs #1012 * [Test] probe로 드러난 틈(소유 원천 표식 종류, 역만 제거, 해시 방식 모르는 입력 목록) 반증 보강 (#1014) Refs #1012



Related issue
Refs #860
Refs #870
Summary
disabled_manually)됐다.current-capital-topology-refresh(run 35508995939):Prepare current ITX collection의ITX current collection quota guard failed. 그날 첫 ITX 수집이 실패한 뒤 KST 하루 1회 한도 가드가 나머지 run을 모두 막았다. 일부 run은capital topology transport NETWORK_TIMEOUT(run 35491747180)으로 실패했다.kric-current-facility-refresh(run 35507969487):Recover claimed refresh의no valid artifacts found to download. 남은 claim을 회수하려면 원래 run의 artifact가 필요한데, 보관 14일이 지나 영구히 회수할 수 없었다.retained-gwangju-timetable-refresh(run 35508796441):retained timetable claim commit is invalid. 형태가 맞지 않는 claim 브랜치가 남아 매번 회수 단계에서 실패했다.seoul-current-accessibility-refresh(run 35508666263):closed Seoul refresh claim requires manual resolution. 닫힌 갱신 PR의 claim 브랜치가 남아 fail-closed로 멈췄다.automation/*claim 브랜치는 원격에 0개다.retained-gwangju-timetable-refresh에는 schedule만 있다. 그래서 [Fix] 수동 비활성화된 원천 자동 갱신 workflow 5개 복구 #860 완료 조건인 수동 dispatch 검증을 할 수 없다.workflow_dispatch로 실행할 수 있다.Changes
tools/ci/report-refresh-failure.mjs(신규)[Fix] 원천 자동 갱신 실패: <원천> (<file>)이며 workflow 표지(<!-- easysubway-refresh-failure:<file> -->)가 있는 이슈만 센다(리뷰 F2).Refs #860,Refs #870이다.REFRESH_FAILURE_REPORT_DUPLICATE_ISSUES로 실패한다(리뷰 F2).issues: write를 추가했다. workflow 레벨은permissions: {}다(리뷰 F4).if: ${{ failure() }}보고 단계를 추가했다.continue-on-error는 쓰지 않는다.retained-gwangju-timetable-refresh.yml에 입력 없는workflow_dispatch를 추가했다. 갱신 여부는 기존 decide(CURRENT면 외부 호출 전에 종료)가 그대로 판정한다.tools/ci/data-test-ownership.json에 새 테스트를 등록했다(owner data870).Scope
Included
Excluded
gh workflow enable): QA 승인 대상이라 메인 세션이 한다.SLACK_RELEASE_WEBHOOK_URLsecret이 없다(Data Pack Releaserun 37109648483 로그SLACK_RELEASE_WEBHOOK_URL is not configured). secret 설정은 QA 승인 대상이다.Ownership / dependencies
tools/ci/data-test-ownership.json을 [Fix] 자정 이후 시발 열차 시각을 데이터팩 SQLite에 운행일 경계(03:00) 기준 24시 이후 초로 적재 #921·#924도 고친다. 서로 다른 줄에 한 줄을 넣었으므로 나중에 병합되는 쪽이 rebase한다.Contract & Compatibility
failure()).Version impact
Product gate impact
Provenance impact
Version decision
Verification
current-capital-topology-refresh.yml needs issues: write와 retainedworkflow_dispatch정규식 불일치로 2건 실패. 변경 후node --test tools/ci/report-refresh-failure.test.mjs: 8/8 통과node --test갱신 workflow 계약·decide·delivery·ITX workflow 테스트 7개 파일: 53/53 통과.actionlint4개 workflow: 오류 없음.data-test-discovery verify: 통과. anti-cheat guard: PASSData contracts결과는 PR check에서 확인gh issue list(읽기)로 열린 이슈를 조회해 계획만 출력하는 건식 실행을 했다(이슈 생성 없음).issues: write하나다. 본문에는 run URL만 넣고 경로·secret을 넣지 않는다(테스트로 고정).Not run
Risk
Rollout / Recovery
[Fix] 원천 자동 갱신 실패: …이슈 또는 댓글이 생긴다.Review focus
failure()에서만 도는지Checklist