3RD
TECH / BIKE / PHOTO / BOOKS / MOBILE
VAULT .NET

System Changelog

RELEASE LOG

써드 볼트의 개발 내역, 각종 변경 사항, 기능 업데이트 및 디자인 리뉴얼 내역을 트래킹합니다.
지속적으로 업데이트되는 블로그의 버전 히스토리입니다.

Project Milestone [v2.0 - v3.0]
v2.0
v3.0
STATUS: v2.4.4.84 (헤더 TDF 메뉴 툴팁 — 3대 대회 안내 문구 + 2열 그리드로 개편) PROGRESS: 52%
v1.x Era Achievements
🏆

v1.x Era — Achievements Unlocked

10 Major Milestones · 2026.02 ~ 2026.05 상세 →
🥇
v 1.0
3rd Vault Foundation
2026.02.01 ~ 03.10
🤖
v 1.1
AI Newsroom System
2026.03.11 ~ 03.12
⚙️
v 1.2
System Architecture & Optimization
2026.03.13 ~ 03.23
🎨
v 1.3
Identity & Landing Renewal
2026.03.24
🎮
v 1.4
Game Review System Launch
2026.03.25 ~ 03.26
👾
v 1.5
Game Review RPG Header & Darkmode
2026.03.30 ~ 03.31
🧊
v 1.6
Header Architecture & UI Refinement
2026.04.01
🪪
v 1.7
Logo Wordmark Redesign & Dark Mode 2.0
2026.04.04 ~ 04.18
🏆
v 1.8
Game Archive Trophy Modal & Dark Admin
2026.04.14
🚴
v 1.9
Strava Analytics & Mobile Optimization
2026.04.19 ~ 05.07
Release History Log
v 2.4.4.84
2026.07.27

헤더 TDF 메뉴 툴팁 — 3대 대회 안내 문구 + 2열 그리드로 개편

  • [UI/UX] **헤더 `[TDF]` 메뉴 툴팁 문구 변경 + 대회명 2열 그리드 추가** (`inc/custom-header.php`) — "투르 드 프랑스 스테이지 아카이브"(단일 대회 한정 문구)를 "세계 3대 자전거 대회 기록 아카이브"로 교체하고, 그 아래 `Tour de France` / `Giro d'Italia` / `Vuelta a España` 영문 풀네임 3종을 2열 그리드(`grid-template-columns: repeat(2, auto)`)로 표기. 부엘타 대응으로 아카이브가 3대 그랜드투어 전체를 다루게 된 최근 재설계(v2.4.4.83)와 문구를 맞춤.
  • [UI/UX] **툴팁 폭 자동 확장 — 제목 줄바꿈 방지** (`css/custom-header.css`) — 툴팁 박스는 `position: absolute`로 shrink-to-fit 폭 계산이 기본이라, 제목(`.vault-tdf-tooltip-title`)에 `white-space: nowrap`만 추가해 별도 `width` 지정 없이 "세계 3대 자전거 대회 기록 아카이브"가 한 줄로 표시되도록 폭이 자동으로 늘어나게 처리.
  • [CORE] fix: **블링킹 커서(빨간 도트) 위치 — 그리드 아래 → 제목 옆으로 이동, 중복 표시 제거** — 기존 `.vault-nav-tooltip::after` 커서는 박스의 마지막 자식(그리드) 뒤에 찍혀 "아카이브" 옆이 아닌 하단에 따로 떠 있었음. `.vault-tdf-tooltip-title::after`에 동일 커서를 새로 붙이고, 원본 `.vault-nav-tooltip::after`는 `.vault-nav-tooltip.vault-tdf-tooltip::after { content: none; }`로 예외 처리. 단일 클래스 선택자끼리는 소스 순서상 원본 규칙이 나중에 선언돼 있어 `content: none`이 먼저 시도한 걸 덮어썼던 것 — 클래스 2개를 묶어 특이성을 높여 해결.
  • [CORE] **저지 설명 매칭을 라벨 문자열 → `type`(gc/points/mountain/youth) 기준으로 전환** — `vault_tdf_jersey_meaning()`이 "옐로우/그린/폴카닷/화이트" 한글 부분매칭이라 부엘타 GC 저지("레드 저지")가 매칭 안 되던 문제 수정. project_tdf `sync_to_wp.py`가 각 저지 항목에 `type` 필드를 새로 보내도록 변경(자세한 내용은 project_tdf `changelog.md` 참고).
  • [SYS] fix: **기존 TDF 21개 글 회귀 방지 — 하위호환 폴백 추가** — 이미 발행된 글의 `_tdf_jerseys` JSON엔 `type` 키가 없어(백필 전) 배포 직후 저지 설명이 빈 텍스트가 될 뻔한 걸 로컬 검증 중 발견. `vault_tdf_jersey_meaning( $type, $label = '' )`로 시그니처 확장해 `type` 없으면 예전 라벨 매칭으로 폴백하도록 안전망 추가(`single-tdf_stage.php`/`inc/cpt-tdf-stage.php` 양쪽 호출부 수정).
  • [UI/UX] **`/tdf/` 아카이브를 "연도별 전체 나열" → 대회/연도 탭 + URL 쿼리 파라미터 기반으로 전면 재설계** — 부엘타 로컬 테스트 중 "한 페이지에 모든 대회·연도를 다 보여주는 건 문제가 많다"는 판단으로 방향 전환. 처음엔 클라이언트사이드 칩 필터(게임리뷰 아카이브 패턴)도 검토했으나, 특정 대회·연도를 링크로 공유·북마크할 수 있어야 한다는 요구로 `?race=vuelta&season=2026` 형태의 서버사이드 필터(`WP_Query` + `meta_query`)로 확정. `/tdf/` 전용 서브헤더(사이트 전역 헤더는 안 건드림)에 대회 탭 3개(고정, 데이터 없어도 항상 노출) + 선택된 대회의 연도 칩을 배치.
  • [SYS] fix: **쿼리 파라미터명 `year` → `season`으로 변경(코어 예약어 충돌)** — `?year=2026`을 쓰면 워드프레스 코어가 날짜 아카이브용 공개 쿼리 변수로 인식해 `redirect_canonical()`이 `/2026/`으로 301 리다이렉트시켜 CPT 아카이브 컨텍스트 자체가 사라지는 실제 버그를 로컬 테스트에서 발견. URL 파라미터 이름만 `season`으로 바꾸고 ACF 필드명(`year`)은 그대로 유지.
  • [CORE] **신규 ACF 필드 `race_name`** — 아카이브 대회 섹션 제목/타이틀/현재순위 배너에 쓸 대회 한글명을 project_tdf가 매번 전송(0-1 원칙: PHP에 별도 매핑 테이블 안 둠). 기존 21개 TDF 글엔 아직 값이 없어 `?: strtoupper($race_slug)` 폴백 유지.
  • [UI/UX] **대회 탭 라벨 영문 풀네임 + 대회별 GC 저지 색상** — "TDF/지로/부엘타" 국문 축약 라벨로 시작했다가 사용자 요청으로 "Tour de France"/"Giro d'Italia"/"Vuelta a España" 영문 풀네임으로 변경. 배경색은 각 대회 GC 저지 색(옐로 `#FFD700`/핑크 `#FF69B4`/레드 `#DC143C`, project_tdf `config.json`의 `jerseys.gc.color`와 동일값)을 `--tdf-race-color`/`--tdf-race-text` 인라인 커스텀 프로퍼티로 주입. 처음엔 미선택 탭도 살짝 색이 배어들게 했다가, 사용자 피드백으로 미선택 상태는 그레이스케일로 통일하고 선택된 탭만 풀톤 배경으로 확정.
  • [UI/UX] fix: **다크모드에서 미선택 탭 텍스트가 사이트 하이라이트(링크) 색을 따라가던 버그** — `dark-mode-core.css`의 전역 `body.dark-theme a { color: var(--link); }`가 특이성(0,1,1 > 0,1,0)으로 `.tdf-race-tab`의 회색 텍스트 규칙을 이겨버리던 문제. 2026-07-11(v2.4.4.58) "전체보기" 탭에서 겪었던 것과 동일 계열 버그 — 이번엔 `body.dark-theme .tdf-race-tab`에 `!important`로 하드코딩해 고정(사용자가 이번엔 변수 대신 하드코딩을 명시적으로 요청).
  • [SYS] **SEO — `document_title_parts` 필터로 대회/연도 조합별 `<title>` 동적 구성** — 예: "부엘타 아 에스파냐 2026 아카이브 | 3RD VAULT". `get_header()` 호출(= `wp_head` 트리거) 이전에 race/season 파라미터를 먼저 resolve하도록 템플릿 상단 순서 조정. RankMath 메타 디스크립션 세밀 튜닝은 후순위로 보류.
  • [SYS] **아카이브 쿼리를 서버사이드 `meta_query`로 전환** — 기존엔 `posts_per_page => -1`로 전체를 긁어와 PHP에서 연도별로 그룹핑했으나, 이제 `race_slug`+`year` 조합으로 서버에서 필터링해 조회(연도가 쌓여도 가벼움). 스테이지 정렬도 PHP `usort` 대신 `orderby => meta_value_num`(WP 표준 기능, 가드레일 예외 항목)으로 변경.
  • [UI/UX] **헤더 레이아웃 — 진행상황(Stage Progress) 위젯을 제목 옆 → 대회 탭 옆으로 이동** — 제목(H1)과 나란히 있던 게 위계상 어색하다는 피드백으로, H1은 단독 줄로 올리고 그 아래 한 줄에 대회 탭(좌)·Stage Progress 위젯(우)을 배치.
  • [SYS] 로컬(`https://mac-mini.tail0ea415.ts.net`, wp-cli로 로컬 전용 가짜 부엘타 테스트 글 생성) 검증 완료 — `/tdf/`(파라미터 없음), `?race=tdf`(기존 21개 글, 하위호환 폴백 확인), `?race=vuelta&season=2026`(레드 저지 포함 4종 정상), `?race=giro`(빈 상태 정상) 4가지 시나리오 확인 후 테스트 글 삭제. PHP lint 전 파일 통과.
v 2.4.4.82
2026.07.25

RON Training Status "상태 없음" 오분류 버그 수정 — 오버리칭 상태 신설

  • [AI] fix: **`strava_get_training_status()` 분류 로직 구멍 발견 및 수정** (`strava-personal/includes/10-training-load.php`) — TSB가 -10~-30 구간(빌드업/피크)이면서 CTL 추세가 급상승(`ctl_trend > 1`)할 때 기존 8개 분기 조건 중 어디에도 해당하지 않아 catch-all `no_status`("상태 없음")로 떨어지던 버그. 실사용 데이터(CTL 17.7, CTL_prev 15.1 → trend +2.6, TSB -11)로 실제 재현 확인. 데이터/타임존 문제가 아닌 순수 분류 함수 로직 결함이었음.
  • [UI/UX] **신규 상태 `overreaching`(오버리칭) 추가** — 가민 커넥트 8단계 체계의 "Overreaching"에 대응. 라벨 `오버리칭`, 색상 `#fb7185`, 메시지 "체력은 빠르게 늘고 있지만 훈련 부하가 과도합니다. 회복에 신경 쓰세요." 조건은 `$tsb < -10 && $ctl_trend > 1`로, 기존 `productive`(생산적, `tsb>=-10 && trend>0.5`) 조건과 상호배타적이라 다른 분기 동작에는 영향 없음.
  • [SYS] WP-CLI eval로 실데이터 재계산 검증 — 수정 전 `no_status` 반환 → 수정 후 `overreaching` 정상 반환 확인. `templates/topbar.php`는 label/msg만 동적 렌더링하므로 추가 템플릿 수정 불필요.
  • [UI/UX] **BOX4 TSB 박스 하위 요소 7종에 툴팁 신규 추가** — 상태칩, ATL/CTL 바 라벨, R/A/M 부상위험 LED 3개(RAMP·ACWR·Monotony 정의 + 임계값 구간표 + 현재값), 부상위험 판정문구(4단계 레벨표 + 한계 고지). 기존엔 헤더 "훈련 분석 가이드" 하나뿐이라 새로 추가된 R/A/M LED가 무엇을 뜻하는지 설명이 전무했던 문제 해소.
  • [SYS] **`strava-personal/templates/topbar.php`** — R/A/M LED foreach를 `$led_defs` 배열(제목/설명/임계값 행/색상)로 재구성, `strava_get_load_risk_metrics()`가 이미 계산해 둔 `$load_metrics`의 value/unit/band_text를 그대로 재사용해 툴팁에 "현재값" 표시.
  • [UI/UX] **툴팁 타이포그래피 CSS 변수화** — `--ron-tt-font-base`(15px)/`--ron-tt-font-name`/`--ron-tt-font-small`/`--ron-tt-font-hint`를 `:root`에 도입, 기존 11px/10.5px/9.5px로 시인성이 낮던 본문/이름/범례 폰트를 확대. 변수 공유 방식이라 BOX3·Walk Intensity 등 RON 전역 기존 툴팁 3곳에도 자동 반영됨.
  • [UI/UX] fix: **`.strd-tooltip-box` 뷰포트 클램프 추가** — `max-width: min(340px, calc(100vw - 32px))` — 기존엔 반응형 대응이 전혀 없어 좁은 화면에서 잘릴 위험이 있었음. `white-space: normal` 추가로 nowrap 트리거(상태칩·바 라벨) 하위에서 툴팁 텍스트 줄바꿈이 깨지는 문제도 예방.
  • [UI/UX] fix: **`.strava-box-tsb .strd-has-tooltip { position:static }` 오버라이드를 헤더 타이틀 전용으로 좁힘** — 기존엔 BOX4 내부 모든 `.strd-has-tooltip`에 걸려 있어, 트리거를 여러 개(LED 3개 등)로 늘리면 전부 컨테이너 기준으로 뭉쳐 개별 위치를 잡지 못하는 문제가 있었음.
  • [SYS] 좌/우 앵커 분기 규칙 도입(`.strd-tooltip-chip`/`.strd-tooltip-bar`/`.strd-tooltip-injury`는 `right:0`) — 박스 우측에 가까운 요소가 뷰포트 밖으로 나가지 않도록.
  • [SYS] **신규 문서 `doc/strava/ron-tooltip-guide.md`** — 툴팁 시스템 기준(CSS 변수, 오버플로우 규칙, 신규 추가 체크리스트) 문서화.
  • [UI/UX] **ⓘ 아이콘 제거** — 헤더 타이틀·상태칩·부상위험 판정문구에 남아있던 ⓘ 아이콘을 제거(트리거 텍스트 전체가 이미 호버 영역이라 중복이라는 사용자 피드백). `.strd-has-tooltip` 기본 `cursor`를 `default`→`help`로 변경해 아이콘 없이도 호버 가능함을 시각적으로 알림.
  • [SYS] **미완료 항목** — 폰트 크기 13/15/17px 3안 브라우저 실측 비교는 이번 세션에서 Chrome 확장 미연결 + macOS 화면 기록 권한 미승인으로 보류. 현재 15px(중간값)이 기본 적용된 상태이며, 로컬 확인 후 필요시 CSS 변수 값만 조정하면 됨.
v 2.4.4.80
2026.07.18

공지 티커 — 여러 공지 연속 출력에서 1개씩 순차 전환 방식으로 변경

  • [UI/UX] **공지 티커 노출 방식 변경** — 기존에는 공지 여러 건을 `•`로 이어붙여 한 줄로 계속 흘려보내는 방식(`padding-left:100%` + `animation: infinite`)이었는데, 공지가 2건 이상일 때 문구들이 서로 붙어 가독성이 떨어진다는 피드백으로 "한 번에 하나만 노출 → 좌측으로 완전히 퇴장 → 다음 공지 노출" 순차 전환 방식으로 교체.
  • [SYS] **`inc/notice-ticker.php`** `vault_render_notice_ticker_row()` — 공지 배열을 `implode`로 이어붙이던 방식에서 각 공지를 개별 `<span class="vault-ticker-content vault-ticker-item">`로 렌더링하도록 변경.
  • [SYS] **`css/notice-ticker.css`** — `.vault-ticker-content` 애니메이션을 `infinite`에서 `1`회 재생 + `animation-fill-mode: forwards`로 변경(전환 제어를 JS로 이관), `.vault-ticker-item:not(:first-child)`에 기본 `display:none` 추가(no-js 상태에서도 첫 공지만 노출).
  • [SYS] **신규 `js/notice-ticker.js`** — `animationend` 이벤트로 공지 퇴장 완료를 감지해 400ms 대기 후 다음 `.vault-ticker-item`으로 전환(마지막 다음엔 첫 항목으로 순환). `animation: none` → reflow → 복원 트릭으로 항목 전환마다 애니메이션을 처음부터 재시작. 공지 1건뿐이어도 동일 로직으로 계속 반복 재생되도록 처리(단순히 아이템 2개 미만이면 조기 종료하면 1건짜리 공지가 한 번 퇴장한 뒤 영영 사라지는 회귀가 생겨 수정).
  • [SYS] **`functions.php`** — `vault-notice-ticker` JS 신규 enqueue 추가(`notice-ticker.css`와 동일하게 전체 페이지 공통, filemtime 캐시버스팅).
  • [SYS] 로컬 검증 — PHP lint 통과, `node --check`로 JS 문법 확인, 2건짜리 가짜 데이터로 마크업 구조 확인, 프론트엔드 curl로 신규 CSS/JS 200 응답 및 변경된 마크업 확인.
v 2.4.4.79
2026.07.18

공지 티커 — 새 글 자동 안내 기능 추가 (뉴스룸 자동 감지 패턴 재사용)

  • [SYS] **`inc/notice-ticker.php`에 세 번째 자동 항목 타입 추가** — 기존 `vault_get_newsroom_notice_entry()`(뉴스룸 슬러그 자동 감지)와 동일한 패턴으로, IT Things/Road Bike/Photo/Others 카테고리에 새 글이 발행되면 별도 포스트 생성 없이 "{제목} 글이 발행되었습니다." 항목을 동적으로 생성해 발행일로부터 3일간 티커에 노출. 뉴스룸·Notice 카테고리는 `category__in`에서 자연히 제외(중복 방지).
  • [SYS] 신규 함수 `_vault_new_post_notice_query_args()` / `vault_get_new_post_notice_entries()` 추가, `vault_get_notice_posts()`에 `array_merge`로 병합(뉴스룸 → notice 카테고리 → 신규 글 순).
  • [SYS] 별도 옵션 `vault_new_post_notice_enabled` 신설(기본값 off) — 기존 마스터 스위치 `vault_notice_enabled`와 이중 게이트 구조(마스터가 꺼지면 신규 기능도 함께 꺼짐, 기존 `vault_get_notice_posts()` 조기 반환 구조 그대로 유지). `티커 및 스위치` 어드민 페이지에 체크박스 및 "최근 3일 내 발행된 새 글" 미리보기 섹션 추가.
  • [SYS] 로컬 검증 — PHP lint 통과, `wp eval`로 `vault_get_new_post_notice_entries()` 단독 호출 및 날짜 범위 확장 테스트로 title/url/excerpt 배열 포맷 확인, 옵션 임시 활성화 후 `vault_get_notice_posts()` 병합 결과 확인, 프론트엔드 curl로 `vault-notice-ticker` 정상 렌더 확인.
v 2.4.4.78
2026.07.16

GSC 색인 모니터링 자동화 2단계 — 추이 비교 + Telegram 알림 + 주간 스케줄

  • [SYS] **`gsc-monitor/notify.py` 신규** — `history/` 최신 스냅샷 2개를 URL 단위로 diff해 coverageState 변화(예: Unknown → Discovered → Submitted and indexed)와 전체 집계 증감을 계산, 기존 배포 알림과 같은 Telegram 봇으로 HTML 포맷 전송. 스냅샷이 1개뿐일 때는 baseline 요약만 전송. `check_index_status.py` 실행 끝에서 자동 호출되도록 연결.
  • [SYS] **`~/Library/LaunchAgents/com.jieun.gsc-monitor.plist` 등록** — `~/scripts/safe-reboot.sh`(매월 자동 재부팅)와 동일한 launchd 컨벤션으로 매주 월요일 09:00 자동 실행. GitHub Actions가 아니라 맥미니 로컬에서 도는 이유: 이 스크립트는 Google API로 아웃바운드 HTTPS만 하면 되므로 `deploy.yml`이 겪는 인바운드 SSH IP 차단 문제(위 self-hosted runner 이슈)와 무관 — 서비스 계정 키를 GitHub Secrets로 옮길 필요 없이 로컬 파일 그대로 사용 가능해 더 단순함.
  • [SYS] **`gsc-monitor/config.env` 신규** — 기존 `~/.config/safe-reboot/config.env`의 TELEGRAM_BOT_TOKEN/CHAT_ID를 복사해 재사용(중복 발급 없음). `.env` 파서가 따옴표로 감싼 값을 못 벗겨내 최초 전송이 404로 실패했던 버그 즉시 수정(`strip('"')` 추가) — 재시도 후 실제 텔레그램 수신 확인 완료.
  • [SYS] `.gitignore`에 `gsc-monitor/` 추가 커밋 — 서비스 계정 JSON 키, Telegram 토큰이 담긴 config.env 모두 git 추적 대상에서 제외됨(코드 자체도 로컬 전용, 이번 변경은 changelog 기록 목적으로만 남김 — git diff 없음).
  • [CORE] **GSC URL Inspection API 전수 조사로 game-review CPT 66~68개 중 대다수가 "URL is unknown to Google"(발견조차 안 됨) 상태임을 규명** — 뉴스룸/RON의 "발견됐지만 색인 보류"와는 다른, 더 근본적인 문제. 원인: 2026-04~05 약 5주간 67개 리뷰 대량 동시 발행 + `single-game-review.php`에 다른 리뷰로 가는 내부링크가 0개(완전 고립 구조, 실 라이브 페이지 curl로 확인) + 아카이브 페이지 한 곳(66개 링크)에 아웃바운드가 몰려 링크당 권위 신호 희석. RankMath `rank_math_seo_score`(13/100, 내부링크 결핍 지적)도 같은 결함을 독립적으로 뒷받침. 검토 후 배제한 방안: Google Indexing API(JobPosting/BroadcastEvent 전용이라 일반 콘텐츠엔 부적절), 사이트맵 재제출(이미 정확해 효과 없음).
  • [SYS] **신규 파일 `inc/game-review-related-posts.php`** — 전체 발행 리뷰를 트랜지언트로 캐싱(`inc/game-review-home-widget.php` 패턴 재사용, `save_post_game-review` 훅으로 무효화), genre/genre_2/platform/hw/출시연도 스코어링으로 관련 리뷰를 뽑고 **부족하면 최신순으로 채워 항상 6개 노출을 보장하는 폴백 체인** 적용(ACF `genre` 값이 롱테일 자유텍스트라 장르 매칭만으로는 0~1개만 나오는 페이지가 다수 발생함을 실측 확인했기 때문).
  • [SYS] `single-game-review.php`에 관련 리뷰 섹션 삽입(entry-content 뒤), `archive-game-review.php`의 `.gr-card` 마크업을 그대로 재사용해 실제 정적 `<a href>`로 렌더(JS 동적 생성 금지 — 최초 HTML에서 크롤러가 바로 인식하도록). `css/game-review.css`에 `.gr-related-section`/`.gr-related-grid`만 추가, 기존 `--gr-card-*` 변수 재사용이라 신규 다크모드 프리셋 불필요.
  • [SYS] 로컬 검증 — 장르 매칭 케이스(The Swapper/Puzzle)와 롱테일 케이스(Humble Indie Bundle 6/genre="Mix" 유일값) 둘 다 실제 페이지에서 정적 링크 6개 렌더 확인. 배포 후 수 주 뒤 `gsc-monitor/check_index_status.py` 재실행으로 실제 색인 상태 변화 추적 예정.
v 2.4.4.76
2026.07.15

RON 사이트맵 제외 최종 검증 완료 + 테스트 잔재 페이지 3건 추가 정리

  • [SYS] **v2.4.4.75 백필 실행 및 최종 검증** — 프로덕션 `wp eval`로 `rank_math_robots` postmeta 백필 151건 적용(초기 조사 시점 161건에서 일부 차이 있었으나 실제 대상 전량 처리 확인) + 사이트맵 캐시 무효화. `page-sitemap.xml` curl 재확인 결과 163개 URL → 9개로 축소, `strava_YYYYMM` 잔존 0건 확인.
  • [SYS] **테스트 잔재 페이지 3건(`test-strava_202602`, `test-strava_202601`, `test_strava_202603`) 추가 noindex 처리** — 정식 슬러그 패턴(`strava_YYYYMM`)과 달라 이번 자동화 대상에서는 제외돼 있던 개발 중 잔재 페이지. ID 472/537/1889에 동일하게 `rank_math_robots` postmeta 수동 적용 + 사이트맵 캐시 재무효화. 최종 `page-sitemap.xml`은 실제 편집 콘텐츠(홈/about/changelog/now/newsroom/vaults 등) 9개만 남음.
v 2.4.4.75
2026.07.15

RON 페이지 사이트맵 제외 버그 수정 — 존재하지 않는 필터 사용이 원인

  • [CORE] **v2.4.4.74에서 적용한 RankMath 사이트맵 제외가 실제로는 동작하지 않던 버그 수정** — `rank_math/sitemap/exclude_posts`는 RankMath에 실존하지 않는 필터였음(웹 검색 결과를 신뢰한 게 원인). 프로덕션 소스(`class-post-type.php`) 직접 확인 결과 RankMath는 필터가 아니라 `rank_math_robots` postmeta 값을 SQL로 직접 조회해 사이트맵 포함 여부를 판단함 — 이 값이 한 번도 기록된 적이 없어 배포 후에도 `page-sitemap.xml`에 strava_ 페이지 154개가 그대로 남아있었음(curl로 확인).
  • [SYS] **`strava-personal/includes/05-page-builder.php`** — 페이지 생성/갱신(`wp_insert_post`/`wp_update_post`) 직후 `update_post_meta($page_id, 'rank_math_robots', ['noindex'])` 추가. `save_post` 훅이 자동 발생해 RankMath 사이트맵 캐시도 해당 페이지 기준으로 자동 무효화됨(`Cache_Watcher::save_post`) — 매달 크론 갱신마다 자연히 최신 상태 유지.
  • [SYS] **`strava-personal/includes/20-seo-noindex.php`** — 존재하지 않던 사이트맵 제외 필터 삭제, 프론트엔드 메타 로봇 필터(`rank_math/frontend/robots`)는 실동작 확인되어 유지(postmeta 백필 전에도 화면 노출은 즉시 차단하는 보조 안전망).
  • [SYS] 기존 161개 페이지는 SSH로 프로덕션 `wp eval` 일회성 백필 + `\RankMath\Sitemap\Cache::invalidate_storage()`로 사이트맵 캐시 즉시 무효화 처리(코드 배포와 별개, DB 직접 반영).
v 2.4.4.74
2026.07.15

GSC 색인 제외 285건 원인 규명 — RON 월별 페이지 noindex + 사이트맵 제외

  • [CORE] **Search Console "발견됨 - 현재 색인이 생성되지 않음" 285건의 원인 규명** — 발행 콘텐츠 375개 전수 조사 결과, `strava_YYYYMM`(RON 개인 대시보드 월별 페이지) 161개 + `_newsroom`(일일 뉴스 큐레이션) 116개, 합계 277개(전체의 74%)가 자동 생성·고템플릿 반복 콘텐츠였음. RankMath 점수(60~70점대)는 키워드/메타description 등 페이지 단위 온페이지 신호만 체크할 뿐, 페이지 간 구조적 중복이나 개인 대시보드성 콘텐츠 여부는 반영하지 않아 실제 색인 저하 원인과 무관했음.
  • [SYS] **신규 파일 `strava-personal/includes/20-seo-noindex.php`** — `rank_math/frontend/robots` 필터로 `strava_\d{6}` 슬러그 페이지에 noindex 메타 적용, `rank_math/sitemap/exclude_posts` 필터로 동일 페이지를 XML 사이트맵에서 제외. 슬러그 패턴 기반 동적 매칭이라 기존 161개 + 향후 자동 생성될 페이지까지 별도 DB 백필 없이 즉시 커버.
  • [SYS] 페이지 렌더링·`/strava/` 리다이렉트(`07-redirect.php`)·cron 동기화 등 기존 기능은 변경 없음(순수 검색엔진 신호 레이어만 추가). WP 부트스트랩 + 실제 페이지 HTTP 200 렌더링 + 에러 로그로 무영향 확인 후 적용.
v 2.4.4.73
2026.07.14

홈 위젯 4종 포인트 애니메이션 추가 — NOW 브리딩·뉴스룸 핵심 배지 반짝임·RON 회전·게임 랜덤 발광

  • [UI/UX] **NOW 타임라인 이미지 있는 날(B타입) 원형 마커에 브리딩 확산 링 추가** — `.ntw-marker`에 box-shadow 기반 sonar-ping 애니메이션(`ntw-marker-breathe`, 2.4s 주기). 위치 정렬용 `transform: translateX(-50%)`와 애니메이션 대상(box-shadow)을 분리해 충돌 방지.
  • [UI/UX] **뉴스룸 "⭐ 핵심" 배지의 별 아이콘만 분리해 반짝임 효과 적용** — 큐레이터(`project_newsroom/wp_poster.py`)가 importance=5 기사에 이미 심어둔 "⭐ 핵심" 텍스트를 접두사 정규식으로 감지, 별도 span으로 렌더링(`inc/newsroom-home-widget.php`). 원본 큐레이터 CSS의 `badge-importance` 레드 컬러 계열도 함께 복원(`.nhw-badge-key`) — 기존엔 다른 카테고리 배지와 구분 없이 회색 pill로만 표시되던 상태.
  • [UI/UX] **RON BOX1 옆 세로쓰기 캡션("운동 기록, 분석 OS")에 3D 자체축 회전 추가** — `perspective` + `rotateY` 키프레임으로 11초 주기 중 마지막 구간에만 글자 폭 중심축을 기준으로 한 바퀴 회전(`nhw-caption-spin`). transform이라 옆 BOX1 카드 레이아웃에 영향 없음.
  • [UI/UX] **게임 아카이브 카드 10초 주기 랜덤 발광** — 신규 `js/game-review-home-widget.js`가 `.grhw-grid .gr-card` 중 매번 직전과 다른 카드를 랜덤 선택해 `gr-card-glow` 클래스 토글, CSS에서 box-shadow 펄스 애니메이션 처리.
  • [SYS] **NOW 마커 브리딩 링이 다크모드에서 거의 안 보이던 문제 수정** — `--point-color`(#C21807)는 다크/라이트 공통 고정값이라, 다크모드의 어두운 `--bg-panel` 위에서는 저채도 레드 글로우끼리 루미넌스 차이가 거의 없어 대비가 사라짐. `body.dark-theme .ntw-marker`에서만 더 밝은 살몬레드(`--ntw-glow-rgb: 255,92,74`)로 교체하는 스코프 변수 오버라이드로 해결 — `css/ron-box1-home-widget.css`의 기존 패턴과 동일, 전역 프리셋 시스템 변경 불필요(단순 인버전으로 충분).
  • [SYS] 4개 애니메이션 전부 `@media (prefers-reduced-motion: reduce)` 대응 — 시스템 설정 시 즉시 정지. 신규 색상 변수는 다크모드 전용 값이 필요했던 NOW 글로우를 제외하면 전부 기존 `--point-color`/`--gr-card-hover-border` 재사용, 신규 프리셋 추가 없음.
v 2.4.4.72
2026.07.14

커스텀 푸터 전면 리뉴얼 — 게임 리뷰·TDF 링크 추가, 인라인 CSS 분리

  • [UI/UX] **3컬럼 구조 재설계** — 브랜드 컬럼에 다크모드 테마 인디케이터를 통합(기존 카테고리 컬럼 하단 pill/shimmer 배지를 걷어내고 WIP 링크와 동일한 담백한 텍스트+dot 형태로 재배치), Pages 컬럼에 GAME REVIEW(`/game-review/`)·TDF STAGE(`/tdf/`) 항목 신설(NEW 배지), Ride or Not 설명 문구를 "운동 기록, 그리고 분석용 OS"로 변경.
  • [UI/UX] **카테고리 태그 영역(로드바이크/IT/포토) 전면 삭제**, 해당 컬럼을 상/하 2단으로 재구성 — 위 칸은 사이트 이용 안내 문구(비정기 업데이트 공지 + about 페이지 연락처 유도), 아래 칸은 뉴스레터 구독 폼 자리를 `disabled` 인풋/버튼 + "Coming Soon" 태그로 미리 확보(실제 구독 로직은 별도 작업).
  • [SYS] **인라인 `style` 블록 451줄을 `css/custom-footer.css`로 완전 분리**, `functions.php`의 `vault_enqueue_separated_snippets()`에 전역(전체 페이지) 등록. 다크모드 변수는 기존과 동일하게 `var()` fallback 형태 유지, `dark-mode-core` 이후 로드해 오버라이드 순서 보장.
  • [SYS] `css/dark-mode-core.css`에 남아있던 구식 죽은 셀렉터(`footer#footer`, `.ct-footer-copyright`, `.thirdvault-footer`) 삭제 — 이전 리팩터링에서 클래스명이 전부 `.vault-footer-*`로 바뀐 뒤 매칭되지 않던 잔재.
v 2.4.4.71
2026.07.13

라이트박스 앵커 자동 삽입 기능 신규 — 글목록 "a 태그 삽입" 행 액션

  • [CORE] **본문 이미지 라이트박스가 6/2 이후 작성된 글에서 전부 작동 안 하던 원인 규명** — `lightbox/js/custom-lightbox.js`의 `collectGallery()`는 `.entry-content .wp-block-image a`에만 클릭 핸들러를 걸어 `<a>` 태그가 없으면 아예 동작하지 않는데, Gutenberg 이미지 블록 "링크 대상" 에디터 기본값이 2026-06-02 즈음 "미디어 파일"에서 "없음"(`linkDestination:"none"`)으로 굳어져 그 이후 전체 글에서 `<a>` 태그가 생성되지 않고 있었음. `wp eval-file`로 전체 포스트 스캔해 확인.
  • [CORE] **신규 파일 `inc/lightbox-link-fixer.php`** — 글목록(`edit.php`, post 타입) 행 액션에 "a 태그 삽입" 링크 추가. 클릭 시 AJAX로 해당 글의 `core/image` 블록 중 링크 없는 것만 미디어 파일 URL로 감싸고 `linkDestination`을 `media`로 갱신. 이미 연결된 이미지(6/2 이전 글 등)는 자동 스킵(idempotent, 재실행 안전).
  • [SYS] **`parse_blocks()`/`serialize_blocks()` 전체 재직렬화 대신 정규식으로 `<!-- wp:image {...} --> ... <!-- /wp:image -->` 구간만 오려내 문자열 치환하는 방식 채택** — 전체 재직렬화 시 손대지 않은 블록까지 공백이 미세하게 달라져 Gutenberg가 "블록 검증 실패"를 띄울 위험이 있어 회피. `wp_update_post()`로 저장해 리비전을 남김(되돌리기 안전망, `post_modified`는 갱신됨).
  • [SYS] `core/image` 블록 외(클래식 에디터 자유 HTML 등) 이미지는 이번 기능 범위 밖 — 처리 결과 메시지에 "수동 확인 필요" 안내 포함.
  • [SYS] `wp eval-file`로 실제 포스트(25개 이미지, gallery 중첩 포함) 대상 드라이런 검증 — 전량 갱신, 재실행 시 idempotent, 이미지 외 본문 바이트 단위 동일 확인.
v 2.4.4.70
2026.07.13

NOW 타임라인 관리자 저장 시 정렬 버그 수정

  • [CORE] **`inc/now-timeline.php` `usort` 비교 함수가 항상 정렬 무효화 상태였던 버그 수정** — `date`(`"2026.07"`)와 `day`(`"08"`)를 점(.)으로 이어붙인 `"2026.07.08"`을 그대로 `strtotime()`에 넘겼는데, PHP `strtotime()`은 점 구분 날짜 형식을 파싱 못해 항상 `false`(=0)를 반환 → 비교 함수가 늘 0을 반환해 실질적으로 정렬이 동작하지 않던 상태(어제 `now-timeline-home-widget.php` 작업 중 동일 패턴 발견, `doc/TODO.md` 기록해둠).
  • [SYS] 기존 데이터가 우연히 정렬돼 보인 이유는 신규 항목이 `array_unshift`로 항상 맨 앞에 들어가서였을 뿐 — 항목 수정(edit) 시에는 순서가 깨질 수 있는 상태였음.
  • [SYS] `now-timeline-home-widget.php`에서 이미 쓴 `str_replace('.', '-', ...)` 치환 패턴을 동일하게 적용. PHP 린트 통과 + 셔플 데이터로 정렬 동작 검증 완료.
v 2.4.4.69
2026.07.13

홈 위젯 4종 On/Off 제어판 신설 — "티커 및 스위치"

  • [CORE] **신규 파일 `inc/home-widget-switches.php`** — NOW/뉴스룸/RON BOX1/게임 아카이브 개별 토글 4개 + 전체를 한번에 끄는 마스터 토글 1개, 총 5개 옵션(`vault_home_widgets_master_enabled` + 위젯별 `..._home_widget_enabled`, 전부 `register_setting('vault_home_widget_switches', ...)`). 마스터는 개별 설정을 덮어쓰지 않고 **AND로 결합**(`vault_home_widget_is_enabled()`) — 마스터 OFF면 개별 상태 보존한 채 전부 숨김, ON이면 각자 개별 설정을 따름.
  • [UI/UX] **관리자 페이지는 기존 "공지 티커"(`vault-notice-ticker` 슬러그·콜백 유지)를 재활용**해 메뉴/페이지 타이틀만 "티커 및 스위치"로 변경. `inc/notice-ticker.php`에 `do_action('vault_ticker_switches_page_content')` 훅 한 줄만 추가해 신규 파일이 그 자리에 UI를 주입 — 기존 파일 침습 최소화.
  • [UI/UX] **토글 UI는 TDF의 기존 패턴 재사용** — `.vault-toggle-switch`/`.vault-toggle-slider`(`css/tdf-widget-admin.css`, 위젯 이름과 무관한 범용 클래스) 그대로 활용, `<form action="options.php">` + `settings_fields()` 표준 Settings API 패턴.
  • [UI/UX] **레이아웃 1차 구현이 토글 5개가 다닥다닥 붙어 보이는 문제 발견 → 재정비**(신규 `css/ticker-switches-admin.css`) — 티커 설정 폼과 스위치 폼을 각각 `.tvs-panel` 카드로 감싸 두 섹션을 시각적으로 분리, 마스터 토글은 옅은 회색 배경의 별도 행(`.tvs-master-row`)으로 강조, 개별 토글 4개는 세로 나열 대신 2열 그리드(`.tvs-grid` + `.tvs-toggle-item`)로 재배열해 충분한 여백 확보.
  • [CORE] **RON BOX1이 꺼지면(토글 OFF 또는 데이터 없음) 뉴스룸 카드 그리드가 5열→6열로 자동 확장**해 빈 공간을 채움(`.newsroom-home-widget-wrap.ron-off .nhw-grid`). 뉴스룸 렌더 함수가 RON 마크업을 먼저 변수(`$ron_html`)로 받아 1회만 호출 후 `empty()` 여부로 `ron-off` 클래스를 판단 — "토글 OFF"와 "데이터 없음"이 이미 RON 함수의 early-return에서 빈 문자열로 수렴하므로 뉴스룸 쪽엔 별도 토글 체크 로직 불필요(단일 진실 공급원). 카드 개수(`VAULT_NEWSROOM_HOME_CARDS_PER_CATEGORY=2`)는 그대로 두고 컬럼 수만 조정 — 카테고리 수가 매일 5개라는 보장이 없어 카드 개수 로직을 건드리는 대신 그리드 컬럼만 바꾸는 쪽을 선택.
  • [CORE] **`functions.php` enqueue를 TDF와 동일한 `$vault_X_active` 변수 패턴으로 4개 독립 게이팅**하도록 재구성 — 기존엔 뉴스룸+RON폰트+게임아카이브 CSS가 하나의 `if()` 블록에 뭉쳐있고 게임아카이브가 뉴스룸 CSS 핸들에 의존해서, 개별 토글 시 뉴스룸이 꺼지면 게임아카이브 CSS가 미등록 핸들에 의존하는 문제가 생길 뻔함 — 의존성 제거 후 분리.
  • [SYS] `wp eval`로 개별/마스터 토글 조합 전수 검증(개별 OFF 시 해당 위젯만 공백, 마스터 OFF 시 개별 설정 '1' 유지 상태에서도 4개 전부 공백, RON OFF 시 `ron-off` 클래스+6열 CSS 동시 반영, enqueue 분리 후 RON 끄면 RON CSS만 빠지고 나머지는 정상 로드).
v 2.4.4.68
2026.07.13

홈 위젯 4종 절제된 호버 포인트 액션 추가

  • [UI/UX] **NOW 눈금/마커 호버 피드백** — 콘텐츠 있는 날 호버 시 막대는 `filter: brightness(1.15)`, 원형 마커는 밝기+`scale(1.15)`. 위젯의 핵심 인터랙션 표면(`.ntw-day`)이 클릭 가능함에도 호버 시 아무 변화가 없던 문제 해결(JS 툴팁만 반응하던 상태).
  • [UI/UX] **RON BOX1 카드 호버 리프트 신설** — `.nhw-col-right:hover .strava-box-combined`에 `translateY(-2px)` + 테두리·그림자 악센트. 4개 위젯 중 유일하게 호버 규칙이 전혀 없던 클릭 카드였음. 색상은 사이트 공통 레드(`--point-color`) 대신 **RON 고유 색상 `--ron-orange`** 사용 — 바로 옆 "RIDE OR NOT" 태그가 이미 레드라 차별화.
  • [UI/UX] **뉴스룸·게임 아카이브 배지 캐스케이딩 디테일** — 두 위젯 모두 카드 자체엔 이미 호버(테두리+그림자)가 있었으나, 카드 내부 배지(`.nhw-badge`, `.gr-pill`)는 정적이었던 것에 `transform: translateY(-1px)` 추가해 카드 호버가 레이어드로 반응하도록 통일.
  • [SYS] `prefers-reduced-motion`은 NOW 파일에 기존 블록이 있어 신규 transition을 거기에 포함시킴. RON/뉴스룸/게임 3개 파일은 기존 호버 효과(카드 리프트 등)에도 원래 이 처리가 없었던 상태라 이번 범위에선 그대로 둠 — 별도 작업으로 검토 필요.
v 2.4.4.67
2026.07.13

NOW 타임라인 눈금자 홈 위젯 신규 — 전체 홈 위젯 최상단

  • [UI/UX] **NOW 타임라인을 눈금자형 가로 그래프로 시각화하는 홈 위젯 신설** (`inc/now-timeline-home-widget.php`, `css/now-timeline-home-widget.css`) — TDF/뉴스룸/RON/게임 리뷰보다 위, 전체 홈 위젯 최상단에 배치(`blocksy:content:top` priority 5).
  • [CORE] **콘텐츠 있는 날을 두 타입으로 구분** — 이미지/갤러리 있거나 그 날 글이 2개 이상이면 B타입(막대보다 긴 이벤트 마커), 텍스트만 있는 단일 글이면 A타입(짧은 막대). 판정은 `vault_now_data` 옵션 배열을 날짜별로 그룹핑해 항목 수와 `img`/`gallery` 존재 여부로 계산.
  • [UI/UX] **TODAY를 정중앙이 아닌 전체 폭의 75% 지점에 고정** — 전체 60칸 중 실제 데이터가 있는 과거 45칸(75%) + 아직 오지 않은 미래 15칸(25%). 미래 구간은 별도 배경 처리 없이 빈 날과 동일한 흐린 눈금으로 자연스럽게 이어짐. TODAY 라벨은 세로 점선과 겹치지 않도록 점선 위쪽 끝에 별도 칩으로 배치.
  • [CORE] **다크모드는 케이스 A(전역 변수 재사용)** — `--bg-panel`/`--text-main`/`--text-soft`/`--border-main` 등 기존 변수에 라이트 폴백값만 명시, `--point-color`는 프리셋 무관 고정값이라 별도 다크 선언 불필요. 신규 변수 추가 없음.
  • [SYS] 데이터 소스가 CPT/DB쿼리가 아니라 단일 옵션 배열이라 트랜지언트 캐싱 없이 매 요청 라이브 조회(TDF 위젯과 동일 방침).
  • [SYS] **`strtotime()`이 점(.) 구분 날짜(`"2026.07.08"`)를 파싱하지 못해 항상 `false`를 반환하는 버그 발견 및 이 위젯 코드에서 회피** — 대시(-)로 치환 후 파싱하도록 처리. `inc/now-timeline.php`의 기존 정렬 로직(`usort` 비교 함수, 690줄대)도 동일한 패턴(`strtotime($item['date'].'.'.$item['day'])`)을 쓰고 있어 실제로는 정렬이 동작하지 않고 있을 가능성이 높음 — 이번 작업 범위 밖이라 별도 이슈로 남김, 확인 후 수정 필요.
v 2.4.4.66
2026.07.13

게임 리뷰 카드 그리드 홈 위젯 신규 — 뉴스룸+RON 로우 아래 세 번째 모듈

  • [UI/UX] **최신 게임 리뷰 카드 그리드 위젯 신설** (`inc/game-review-home-widget.php`, `css/game-review-home-widget.css`) — 뉴스룸 요약+RON BOX1 로우 바로 아래 세 번째 모듈로 배치. 썸네일 있는 최신 게임 리뷰만 트랜지언트 캐싱 조회, `save_post_game-review` 시 캐시 무효화.
  • [CORE] `archive-game-review.php`의 대형 검색/필터 헤더는 제외하고 카드 그리드(`.gr-card` 계열)만 재사용, `game-review.css` 전체가 아닌 카드 관련 규칙만 추출한 전용 CSS로 구성.
  • [CORE] 원본에 있던 기존 버그(라이트 모드에서 `--gr-pill-steam`/`-origin`/`-uplay`/`-gog` 및 genre/year 배지 배경 변수가 어디에도 정의되어 있지 않던 문제)를 라이트 폴백값 직접 채워 회피.
  • [UI/UX] "Game Review" 헤더를 뉴스룸과 달리 우측 끝에 배치(마크업 순서만 반전), 아카이브 페이지 링크 + 호버 액션 추가. 다크모드 프리셋 액센트가 옐로 계열일 때 텍스트 대비가 사라지는 문제를 발견해 다크모드에서만 텍스트를 검정으로 전환.
v 2.4.4.65
2026.07.13

RON BOX1(연간 기록 그래프) 홈 위젯 이식 — 뉴스룸 8:2 좌우 분할

  • [UI/UX] **RON(Strava) 연간 기록 그래프 BOX1을 홈 위젯으로 이식** (`inc/ron-box1-home-widget.php`, `css/ron-box1-home-widget.css`) — 뉴스룸 요약 위젯을 8:2로 좌우 분할해 우측 컬럼에 배치.
  • [CORE] 현재/폴백 월 Strava 페이지(`strava_YYYYMM`, `post_type=page`)에서 `.strava-box-combined` 프래그먼트만 DOM 파싱으로 추출. `frontend-style.css` 전체 대신 BOX1 관련 규칙만 추출해 `--ron-` 접두어로 스코프 다운, `:root` 변수 전역 오염 방지.
  • [UI/UX] Bebas Neue 폰트 홈에서도 로드. NEWSROOM 헤더 구분선을 좌측 컬럼 안으로 옮겨 BOX1과 상단 라인 정렬, 전체 높이는 `align-items: stretch`로 자동 매칭. BOX1 왼쪽에 검색 태그(`css/search-tag.css`)와 동일한 다크그린 세로 태그 "RIDE OR NOT" 추가.
  • [SYS] 캐싱은 post ID 기반 트랜지언트(3시간 TTL), 파싱 실패 시 우측 컬럼만 조용히 생략.
v 2.4.4.64
2026.07.13

뉴스룸 홈 화면 요약 위젯 신규 — TDF 위젯 바로 아래 카테고리별 미니 카드 노출

  • [UI/UX] **뉴스룸 요약 위젯 신설** (`inc/newsroom-home-widget.php`, `css/newsroom-home-widget.css`) — TDF 위젯 바로 아래, 오늘(또는 폴백) 뉴스룸 글을 DOM 파싱해 카테고리 5종 × 2개(총 10장) 배지+제목+출처 카드를 고정 5열 그리드로 표시. 카드 클릭 시 오늘의 뉴스룸 글로 이동.
  • [UI/UX] 코너 리본(호버 시 노출) + NEWSROOM 칩 라벨 구분선 추가.
  • [SYS] 무거운 파싱은 post ID 기반 트랜지언트로 캐싱. ON/OFF 어드민 토글은 별도 작업으로 마지막에 진행 예정(미착수).
v 2.4.4.63
2026.07.12

TDF 어드민 메뉴 트리 단순화 — "TDF 설정" 단일 페이지로 통합

  • [UI/UX] **CPT 라벨 `menu_name`을 "TDF 스테이지" → "TDF 설정"으로 변경** (`inc/cpt-tdf-stage.php`) — 사이드바 최상위 메뉴명이 실제 용도(제어판)에 맞게 표시되도록.
  • [UI/UX] **홈 위젯 On/Off 토글을 별도 서브메뉴 페이지에서 목록 페이지(`edit.php?post_type=tdf_stage`) 상단 인라인 박스로 이동** (`inc/tdf-home-widget.php`) — `all_admin_notices` 훅으로 `.tdf-widget-inline-box` 렌더링, 저장은 기존 Settings API(`options.php`) 그대로 재사용해 스테이지 글 목록과 같은 화면에서 확인·저장 가능.
  • [CORE] **서브메뉴 정리** — "새 스테이지 추가"/"태그" 서브메뉴 제거. `remove_submenu_page()`의 정확한 슬러그 매칭 실패(태그 서브메뉴가 남아있던 버그)를 확인 후, `$submenu['edit.php?post_type=tdf_stage']` 배열을 직접 순회해 부모와 슬러그가 다른 항목을 전부 걸러내는 방식으로 교체(`vault_tdf_admin_menu_cleanup()`). 남는 서브메뉴가 부모와 슬러그가 같은 "목록" 1개뿐이면 워드프레스 코어가 자동으로 드롭다운 없는 단일 링크로 접어주는 기본 동작을 활용 — 별도 UI 코드 불필요.
  • [UI/UX] `css/tdf-widget-admin.css` — `.tdf-widget-inline-box` 카드 스타일 추가(기존 페이지 전용 스타일 → 목록 페이지 인라인 박스 전용으로 용도 변경).
v 2.4.4.62
2026.07.12

TDF 아카이브 스테이지 카드 레이아웃 개선

  • [UI/UX] **연도별 아카이브 목록의 스테이지 카드 레이아웃 조정** — 타입 배지(`.tdf-type-badge`)를 스테이지 번호와 같은 줄 오른쪽으로 이동(`.tdf-stage-card-head` flex, `justify-content: space-between`), 코스명(출발지→도착지) 옆에 ACF `km` 필드 기반 거리 `(Nkm)` 표시 추가.
  • [UI/UX] 스테이지 번호 중 숫자만 별도 `span.tdf-stage-card-num-value`로 분리해 볼드+골드(`#b8971a`, TDF 리더 저지 컬러) 강조, "스테이지" 라벨 텍스트는 원래 크기(0.92rem)·색상(`var(--text-main)`) 유지.
v 2.4.4.61
2026.07.12

공지 티커 20단어 표시 제한 제거

  • [CORE] **`inc/notice-ticker.php`의 `wp_trim_words($raw, 20, '...')` 제거** — 프론트 렌더링(`vault_get_notice_posts()`)과 어드민 미리보기(`vault_notice_ticker_settings_page()`) 두 곳 모두 `trim(wp_strip_all_tags($raw))`로 교체. 티커가 CSS `translateX` 애니메이션으로 어차피 전체 텍스트를 흘려보내는 구조라 단어 수 제한이 불필요했고, 프로덕션에서 TDF 관련 공지 뒷부분이 `...`로 잘려 표시되던 문제의 직접 원인이었음.
  • [SYS] 원인 파악 과정에서 로컬(LocalWP) DB의 `notice` 카테고리 포스트 2건이 설정된 표시 기간(9일)보다 오래돼 로컬에서는 티커 자체가 렌더링되지 않는 것을 확인 — 이번 수정 범위 밖이라 별도 이슈로 남김.
v 2.4.4.60
2026.07.12

TDF 홈 위젯 설정 체크박스 → 토글 스위치 UI로 교체

  • [UI/UX] **어드민 "TDF 홈 위젯 설정" 페이지의 On/Off 체크박스를 RON(Strava) 제어판과 동일한 형식의 토글 스위치로 교체** — `strava-personal/assets/admin-style.css`의 `.sa-toggle-switch`/`.sa-toggle-slider` 트랙·놉 셰이딩을 그대로 이식해 `css/tdf-widget-admin.css`(신규)에 `.vault-toggle-switch`/`.vault-toggle-slider`로 재정의. Strava 모듈 전용 `:root` 변수·거대 스타일시트 전체를 끌어오지 않도록 필요한 규칙만 추출해 독립 파일로 분리.
  • [SYS] 이 CSS는 홈 위젯 설정 페이지에서만 필요하므로 `admin_enqueue_scripts`에서 `$_GET['page'] === 'vault-tdf-widget-settings'`일 때만 로드(`inc/tdf-home-widget.php` `vault_tdf_widget_admin_assets()`) — 다크모드 어드민 CSS 로딩 방식(`$_GET['page']` 화이트리스트 체크)과 동일 패턴.
  • [UI/UX] 저장 방식은 기존 Settings API(`options.php` + 저장 버튼) 그대로 유지 — RON처럼 onchange 즉시 자동저장 방식은 이번 변경 범위 밖(시각적 스타일만 교체).
v 2.4.4.59
2026.07.11

TDF 홈 위젯 어드민 On/Off 스위치 추가

  • [UI/UX] **TDF 홈 위젯 표시 여부를 어드민에서 제어 가능하도록 스위치 신설** — 어드민 `TDF 스테이지` CPT 메뉴 하위에 `홈 위젯 설정` 서브메뉴(`vault-tdf-widget-settings`) 추가, 체크박스 1개로 홈/프론트 위젯 전체(Stage Progress + 요약 카드 + 저지 4종)를 그룹째 켜고 끔. 옵션 `vault_tdf_home_widget_enabled`(기본값 `1`=켜짐)을 `notice-ticker.php`의 기존 on/off 패턴 그대로 재사용해 구현(`inc/tdf-home-widget.php`).
  • [CORE] **끄면 CSS도 함께 스킵** — `functions.php`의 `vault-tdf-stage.css`/`vault-tdf-home-widget.css` 홈 조건부 enqueue에 동일 옵션 체크를 추가해, 위젯을 꺼도 불필요한 CSS 요청이 남지 않도록 정리. 단 `/tdf/` 아카이브·싱글 페이지의 로드 조건은 그대로 유지(회귀 없음).
  • [SYS] 신규 서브메뉴 추가 전 기존 어드민 메뉴 3개(공지 티커/다크모드/Strava)와 `register_setting` 그룹명·메뉴 슬러그·`admin_enqueue_scripts` 훅서픽스 충돌 여부 전수 조사 — 충돌 없음 확인. `functions.php`에 이미 CSS enqueue 핸들로 쓰이던 `vault-tdf-home-widget` 문자열과의 혼동을 피하기 위해 어드민 페이지 슬러그는 `vault-tdf-widget-settings`로 별도 명명.
v 2.4.4.58
2026.07.11

TDF 홈 위젯 "전체보기" 링크를 헤더 박스 우측 탭 버튼으로 재배치 + 다크모드 텍스트색 버그 수정 + 그리드 상단 여백 축소

  • [UI/UX] **"TDF 아카이브 전체보기" 링크를 박스 하단에서 헤더 박스(`.tdf-home-group-progress`) 우측 끝 탭 버튼으로 이동** — 세로 구분선(`.tdf-home-more-sep`)으로 기존 콘텐츠와 분리, 스테이지 배지/진행바에 쓰던 `#F5A623`(황색) 배경 + 흰 글씨로 버튼화. 박스를 `padding:0; overflow:hidden`으로 바꾸고 콘텐츠를 `.tdf-home-progress-main`으로 감싸 탭이 박스 우측 모서리(둥근 모서리 포함)까지 세로로 꽉 차게 붙도록 구조 변경. 기존 하단 `.tdf-home-more-link` 제거.
  • [UI/UX] 탭 호버는 색상 반전 대신 `filter: brightness(0.88)`로 배경만 살짝 어둡게 — 반전+테두리 방식은 시안성이 떨어져 폐기.
  • [CORE] **다크모드에서 탭 글씨가 흰색이 아니라 골드/그린으로 보이던 버그 수정** — `css/dark-mode-core.css`의 `body.dark-theme a`(요소 2개+클래스 1개, 명세도 0-1-2)와 `body.dark-theme a:visited`가 단일 클래스 선택자(`.tdf-home-more-tab`, 명세도 0-1-0)보다 명세도가 높아 흰 글씨를 덮어쓰고 있었음. 방문한 링크는 `:visited` 규칙(명세도 0-2-2)까지 걸려 이중으로 밀림. 조상 클래스로 감싼 `.tdf-home-widget-wrap .tdf-home-more-tab`(+ `:visited`/`:hover` 동반 명시)으로 명세도를 올려 해결.
  • [UI/UX] **홈 위젯 바로 아래 본문 그리드 상단 여백 50% 축소** — Blocksy 전역 변수 `--theme-content-vertical-spacing`(`[data-vertical-spacing*=top]`, 부모테마 `main.min.css`)을 직접 바꾸면 사이트 전체 아카이브 그리드에 영향을 주므로, `.tdf-home-widget-wrap + [data-vertical-spacing] { padding-top: calc(var(--theme-content-vertical-spacing) / 2) }`로 홈 위젯 뒤에 오는 그리드에만 스코프 한정.
  • [SYS] 지난 세션(v2.4.4.54) TODO에 남아있던 "라이트/다크 모드 실제 토글 시각 확인 필요" 항목, 이번 세션에서 사용자가 실제 다크모드 스크린샷으로 버그를 제보→수정→재확인까지 완료해 해소.
v 2.4.4.57
2026.07.11

헤더 메뉴 액센트(색상+바운스 애니메이션) GAME → TDF로 이관

  • [UI/UX] **GAME 메뉴의 색상·바운스 애니메이션을 TDF로 이관** — `inc/custom-header.php`의 GAME 항목(데스크탑 text-long/short, 모바일)에만 있던 액센트 컬러(`--hdr-nav-accent`)와 랜덤 바운스 애니메이션(`vault-g-bounce`)을 신규 클래스 `.vault-tdf-accent`로 분리해 TDF 항목(데스크탑·모바일 전 위치)에 적용. GAME은 색상·애니메이션이 제거되어 다른 메뉴 항목과 동일한 속성으로 복귀.
  • [UI/UX] **GAME 전용 폰트(Doto)는 이관 대상에서 제외, 현행 유지** — `.vault-g-accent` 클래스는 폰트 설정(`font-family: 'Doto'`, `font-size: 30px`, `font-weight: 800`)만 남기고 GAME 텍스트에 그대로 적용 유지.
  • [UI/UX] TDF 전용 폰트로 Rockstar-ExtraBold 적용을 시도했으나 최종적으로 원복 — TDF는 다른 메뉴와 동일하게 `.vault-nav-item`의 기본 폰트(Abel/Pretendard)를 상속.
  • [SYS] `js/custom-header.js`의 랜덤 바운스 스케줄러(`scheduleGBounce`) 셀렉터를 `.vault-g-accent` → `.vault-tdf-accent`로 변경.
v 2.4.4.56
2026.07.11

RON 자동 DB 백업이 한 번도 실행된 적 없던 버그 수정 + 로그/백업 파일이 배포마다 삭제되던 구조적 문제 해결

  • [CORE] **자동 백업 활성화 스위치가 애초에 존재하지 않던 버그 발견·수정** — `strava_auto_backup_enabled` 옵션을 `'1'`로 켜는 코드가 프로젝트 전체 어디에도 없었음(`06-cron.php`는 이 옵션값을 읽어 크론을 스케줄하는 부트스트랩 로직만 갖고 있었고, 관리자 화면엔 주기 선택 드롭다운만 있을 뿐 on/off 토글 자체가 없었음 — `"+ 향후 토글 자리"`라는 미완성 placeholder만 남아 있었음). `wp cron event list`로 실제 이 훅이 한 번도 스케줄된 적 없음을 확인, `strava_last_backup` 옵션도 항상 `type: manual`(수동 다운로드)뿐이었음. 기존 "자동 동기화" 토글 패턴(`strava_autosync_on/off`)을 그대로 복제해 `strava_autobackup_on/off` 핸들러(중복 스케줄 방지 가드 포함)를 `02-admin-page.php`에 추가하고 placeholder를 실제 토글로 교체.
  • [CORE] **로그·백업 파일이 배포할 때마다 삭제되던 구조적 문제 발견·수정** — 배포 워크플로우(`.github/workflows/deploy.yml`)가 `rsync -avzr --delete`를 쓰는데, `strava-personal/logs/`가 `.gitignore` 대상이라 git 체크아웃(rsync 소스)엔 이 파일들이 존재하지 않음 → `--delete` 옵션 때문에 `main`에 push할 때마다 서버의 `backup.log`/`sync.log`/`ron.log`와 롤링 백업(`ron-db-0/1/2.sql.gz`)이 통째로 삭제되고 있었음(로그가 "오늘자 1줄"만 남는 것처럼 보인 원인). 저장 위치를 테마 폴더 밖 `wp-content/uploads/ron-logs/`로 이전(`19-logging.php`) — uploads/는 rsync 배포 대상(theme 폴더) 밖이라 구조적으로 배포에 영향받지 않음. `wp_upload_dir()` 호출은 플러그인 `upload_dir` 필터가 아직 등록 전일 수 있는 이론적 위험을 피하기 위해 `init`(우선순위 1) 훅으로 지연.
  • [CORE] **DB 덤프 공개 노출 방지 fail-safe 추가** — 새 저장 위치는 URL로 직접 접근 가능한 경로이므로, `.htaccess`(sql.gz/log 확장자 차단) + `index.php`(목록 노출 차단) 자동 생성이 실패하면 `strava_run_auto_backup()`이 조용히 넘어가지 않고 백업 자체를 중단하도록 `17-backup.php`에 방어 체크 추가.
  • [SYS] 로컬(LocalWP)은 nginx라 `.htaccess`가 원천적으로 해석되지 않아 로컬에서 403 검증이 불가능함을 확인 — 대신 프로덕션(3rdvault.net, Hostinger/Apache)에 이미 배포돼 있던 기존 `.htaccess`를 대상으로 직접 curl 검증(`sync.log`/`ron.log`/`.htaccess` 모두 403)해 실제 배포 환경에서 보호가 정상 작동함을 확인. 배포 후 사용자가 신규 경로(`wp-content/uploads/ron-logs/`)에 대해서도 동일하게 403 뜨는 것을 직접 재확인 완료.
  • [UI/UX] **DB & Log 백업 카드 정리** — 카드 안에 있던 "자동 주기" 드롭다운을 새로 생긴 "DB 자동백업" 토글 쪽으로 이동(토글 이름 앞에 배치), 라벨 "자동 주기" → "백업 주기"로 변경(토글 이름 아래 캡션으로 표시). 기존 "자동 동기화" 토글과 동일한 3열 그리드에 나란히 배치.
v 2.4.4.55
2026.07.11

RON 대시보드 Last ride 위젯 타임존 버그 수정 — KST 오후 라이딩이 "미래 데이터"로 오인돼 누락되던 현상 해결

  • [CORE] **`strava-personal/includes/05-page-builder.php:324-354` 타임존 버그 발견·수정** — ICU가 내려주는 `start_date_local`은 오프셋 없는 naive 로컬(KST) 문자열인데, 이를 파싱하는 `strtotime()`이 PHP 서버 ini 타임존(UTC, 사이트 설정 Asia/Seoul과 불일치)을 기준으로 해석해왔음. 그 결과 KST 기준 대략 오후 6시 이후(UTC 09시 이후)에 올린 라이딩은 실제보다 9시간 늦은 시각으로 계산되어 `$ref_ts`(현재 시각) 필터에서 "아직 안 온 미래 데이터"로 오인돼 통째로 제외됨 — 오늘 라이딩을 올려도 topbar의 "Last ride"가 그 이전 라이딩 기준 며칠 전으로 표시되는 원인이었음. `wp_timezone()`을 명시 지정한 `DateTime`으로 교체해 `$last_ride_days_ago`/`$days_since_last`를 계산하고, `$is_current_month` 판별도 raw `date()` 대신 `current_time()`으로 통일.
  • [CORE] 동일 패턴이 있던 `strava-personal/includes/11-db-tables.php:441-442`(관리자 무결성 검사 `$days_since`)도 함께 수정.
  • [SYS] `strava_update_monthly_page(2026, 7)` 실제 재실행 후 `strava_202607` 페이지 `post_content`에서 `ssb-lr-val`(Last ride 표시값)이 `0`으로 정상 출력됨을 확인해 검증 완료.
v 2.4.4.54
2026.07.11

TDF 홈 화면 미리보기 위젯 신규 — Stage Progress·요약·저지4종 카드형 노출

  • [UI/UX] **홈/프론트 화면 최상단에 TDF 미리보기 위젯 신규** — 최신 발행 스테이지 1건 요약을 홈 그리드 바로 위에 노출. Blocksy 부모 테마가 `<main>` 태그 직후(홈 그리드 렌더링 직전)에 호출하는 `blocksy:content:top` 훅에 `is_home()/is_front_page()` 조건으로 등록(신규 `inc/tdf-home-widget.php`). 박스 2개 구성 — ① 헤더(대회명·연도·스테이지 번호·우승자) + Stage Progress 진행바, ② GC 1위/팀 1위 요약 카드 + 저지4종 카드 = **개별 박스 5개를 감싸는 배경 없이 한 줄 배치**(`.tdf-jersey-grid` 그리드 컨테이너를 `display:contents`로 무력화해 저지 카드 4개가 상위 flex 행의 직접 자식으로 흐르도록 처리). 하단에 `/tdf/` 아카이브 전체보기 링크 포함.
  • [CORE] **중복 제거 리팩터** — `archive-tdf_stage.php`에 있던 Stage Progress 계산 로직(타임존 변환 포함)과 저지 카드 마크업을 `inc/cpt-tdf-stage.php` 공용 함수(`vault_tdf_get_latest_stage_post`/`vault_tdf_get_progress_data`/`vault_tdf_render_progress_widget`/`vault_tdf_render_jersey_grid`)로 추출 — 아카이브 페이지와 홈 위젯이 동일 코드를 공유해 3번째 위치 복붙을 피함. 아카이브 페이지 출력은 리팩터 전후 동일함을 확인.
  • [UI/UX] **저지 카드 슬림화(홈 위젯 전용)** — `vault_tdf_render_jersey_grid()`에 `$show_meaning` 파라미터 추가(기본값 `true`)로 하단 획득조건 설명을 홈 위젯에서만 생략, 아카이브 배너는 기존 노출 그대로 유지. flex 기본값 `align-items: stretch` 때문에 5개 박스가 가장 큰 형제(요약 카드) 높이에 맞춰 늘어나는 것을 확인하고, 요약 카드 내부 줄간격·패딩을 축소하고 저지 카드 헤더 하단 구분선도 홈 컨텍스트에서만 제거해 실제 콘텐츠 높이 자체를 낮춤.
  • [UI/UX] 스테이지 우승자 표시를 요약 카드(기존 3줄: 우승/GC/팀)에서 상단 헤더 타이틀 줄(스테이지 번호 옆)로 이동 — 요약 카드가 GC 1위/팀 1위 2줄로 줄어 박스 높이 추가 축소.
  • [SYS] 신규 파일 `inc/tdf-home-widget.php`, `css/tdf-home-widget.css`(새 다크모드 변수 없이 기존 전역 변수만 재사용 — 케이스 A, `tdf-stage.css`와 동일 원칙). `functions.php`에 require 등록 + 홈/프론트 페이지에 `tdf-stage.css`(저지·진행바 클래스 재사용)와 신규 CSS 조건부 로드.
  • [SYS] **미검증 항목**: 이번 세션은 Chrome 확장 미연결로 브라우저 스크린샷 확인을 못함 — curl로 렌더링 결과(마크업·PHP 에러 유무)만 확인. 라이트/다크 모드 실제 토글 시각 확인 필요.
v 2.4.4.53
2026.07.10

TDF 아카이브 모듈 1.0 — GPX 코스 지도, 상단 하이라이트 모듈 재구성, 타이포그래피 정합, 저지 복구, 코스 타입 배색

  • [UI/UX] **GPX 코스 지도 + 코스 해설 섹션 신규**(싱글 페이지 하단) — `profile_image`(고도 프로필 이미지)/`gpx_file`(GPX 원본)/`stage_desc_ko`(코스 해설 텍스트) ACF 필드 3종 신규 등록(`inc/cpt-tdf-stage.php`). Leaflet + `leaflet-gpx` 플러그인(CDN)으로 지도 렌더링, 배경 지도 타일(OpenTopoMap/Esri)만 CDN 유지하고 GPX·프로필 이미지는 **WP 미디어 라이브러리에 자체 업로드**(외부 CDN 상시 의존 회피 — 사용자 방침). `upload_mimes`/`wp_check_filetype_and_ext` 필터로 `.gpx` 확장자 업로드 허용(WP 기본 차단 대상). 신규 `js/tdf-stage-map.js`, GPX 필드 있는 스테이지에서만 조건부 로드.
  • [UI/UX] **싱글 페이지 상단 2단 하이라이트 모듈 신설**(`.tdf-highlight-section`, 3:7 그리드) — 왼쪽(3)에 미니배지 3종(우승/GC1위/팀1위) → 스테이지 Top5 결과(세로 리스트, `.tdf-result-list`, 구분선) → 저지 4종(세로 스택, 맨 아래) 순서로 배치, 오른쪽(7)에 하이라이트 본문(`article_ko`, 드롭캡)을 페이지 하단에서 이 위치로 이동. 기존 가로 배지행(`.tdf-badge-row`)·가로 리본(`.tdf-result-ribbon`) 마크업은 세로 스택형(`.tdf-badge-stack`/`.tdf-result-list`)으로 교체, 하단 맵+코스해설 섹션(`.tdf-course-section`, 4:6)은 구조 유지.
  • [UI/UX] **저지 4종 배지 싱글 페이지 복구**(2026-07-10 초 임시 비활성화했던 것 재활성화) — 정보 밀도 보강 목적으로 하이라이트 모듈 왼쪽 컬럼 맨 아래에 세로 스택(`.tdf-jersey-grid-stack`, 1열)으로 배치. 저지 의미 매핑(`$tdf_jersey_meaning` 로컬 클로저)을 `inc/cpt-tdf-stage.php`의 공용 함수 `vault_tdf_jersey_meaning()`으로 추출해 archive/single 양쪽 템플릿이 공유하도록 리팩터(중복 매핑 테이블 제거).
  • [CORE] **드롭캡(`.has-drop-cap`) `float:left` 누락 버그 발견·수정** — WP 코어의 드롭캡 `float:left` 규칙은 콘텐츠가 실제 Gutenberg `core/paragraph` 블록(`<!-- wp:paragraph -->` 주석)을 포함할 때만 `core-paragraph-inline-css`가 조건부 로드되며 딸려옴. TDF `article_ko`는 Python이 REST로 넣은 순수 HTML `<p>`라 블록으로 인식되지 않아 이 스타일시트 자체가 로드되지 않았고, 테마 자체 규칙(`style.css`)엔 `float`이 없어 드롭캡 글자가 감싸이지 않고 어색하게 떠 있었음. `style.css`의 `.has-drop-cap::first-letter` 규칙에 `float: left !important;` 추가로 수정 — 일반 포스트는 기존에도 코어 CSS로 이미 float 적용 중이라 회귀 없음.
  • [CORE] **본문 폰트 크기 불일치 발견·수정** — TDF 하이라이트 텍스트가 18px(`.entry-content` 기본값)로 렌더링되고 있었는데, 실제 프로덕션 본문은 블록 에디터가 붙이는 `has-medium-font-size` 프리셋 클래스(`theme.json` `medium` = **20px**, `--wp--preset--font-size--medium`)를 쓰고 있어 실제로는 20px이었음. TDF 본문엔 이 프리셋 클래스가 안 붙으므로 `.tdf-content p`에 `font-size: var(--wp--preset--font-size--medium, 20px)`를 직접 지정해 일치시킴. `line-height`(1.75)/`margin-bottom`(1.4em)도 TDF 전용 오버라이드(1.9/1.1rem)를 걷어내고 `style.css` `.entry-content` 표준값으로 통일.
  • [UI/UX] **코스 타입 pill(스테이지 타입 배지) 색상 구분 추가** — 지금까지 회색 단일톤이었던 `.tdf-type-badge`에 원본 코스 타입(`stage_type` ACF, tt/hilly/mountain/flat)별 색상 클래스(`.tdf-type-tt`/`.tdf-type-hilly`/`.tdf-type-mountain`/`.tdf-type-flat`) 추가 — project_tdf 자체 뷰어 앱(`viewer/templates/base.html`)의 라이트/다크 배색을 그대로 이식(산악=보라, 평지=초록, 구릉=주황, 개인TT=파랑), archive/single 양쪽에 적용.
v 2.4.4.52
2026.07.10

TDF 싱글/아카이브 후속 다듬기 — 스테이지 결과 리본, 저지 배지 재설계, Stage Progress 위젯, 헤더/미니배지 정리

  • [UI/UX] 싱글 페이지 스테이지 결과(Top5)를 세로 표에서 **가로 리본 카드 5개**(`.tdf-result-ribbon`)로 복원. 헤더 상단 이전 스테이지(← S{n}) 버튼을 삭제하고 같은 자리에 훨씬 넓은 "TDF 메인 페이지로" 버튼(`.tdf-nav-btn-home`)으로 교체, 다음 스테이지 버튼은 유지. 결과 섹션과 해설 사이 여백(`margin-bottom`) 복원.
  • [UI/UX] 아카이브 저지 4종 배지 2차 재설계 — 라벨에 붙던 이모지(2~3개 원형 아이콘) 제거하고 플랫 dot 하나만 색상 지표로 남김 → 이후 좌측 두꺼운 컬러 바 + 상단(선수명/팀 ↔ 배지 dot+라벨 좌우 배치) + 구분선 + 하단 전체폭 문장형 획득 조건 설명(`.tdf-jersey-meaning`, 예: "누적 주행 시간 종합 1위 선수에게 수여")으로 최종 구조 확정. 저지 색상-순위 매핑은 투르 드 프랑스 고정 관례라 PHP에 두어도 0-1 원칙 위반 아님으로 판단.
  • [UI/UX] 아카이브 헤더에 **Stage Progress 위젯** 신규 추가(최신 발행 스테이지 기준 상시 표시, 날짜 일치 조건 없음) — 배지(스테이지 번호)·경로·거리·출발/도착 시각·진행바·상태 텍스트(출발 N분 전 ≈ / 진행 중 / 스테이지 종료), 페이지 로드 시점 값으로 계산(실시간 갱신 아님).
  • [CORE] **Stage Progress 위젯 타임존 버그 발견·수정** — `project_tdf`가 WP로 보내는 `start_time`/`finish_time`은 사실 `sync_to_wp.py`가 `start_cest`/`finish_cest`(letour.fr 실측 프랑스 현지시각, CEST/UTC+2)를 가공 없이 그대로 보낸 값인데, 처음 구현 시 이걸 이미 KST인 것처럼 계산해 최대 7시간 오차가 났음. `project_tdf/viewer/app.py`의 `api_stage_timing()` 로직을 참고해 `DateTimeZone('Europe/Paris')`로 파싱 후 `wp_timezone()`(Asia/Seoul)으로 변환하도록 수정, 로컬 3케이스(출발 전/진행 중/종료) 검증 완료.
  • [UI/UX] 싱글 페이지 헤더 — 타이틀 줄과 코스명/거리/날짜 줄을 한 줄로 병합(`.tdf-title-row`), km에 앰버(#F5A623) 색상 부여해 Stage Progress 위젯과 톤 통일.
  • [CORE] **미니배지(우승/GC1위/팀1위) `border-left` 컬러 리본 제거 + 클래스 충돌 버그 수정** — `.tdf-mini-badge-team`이 "팀순위 배지"(초록 리본 대상)와 "우승 배지 안의 팀명 텍스트" 두 군데에 동일하게 쓰여, 팀순위용 초록 `border-left`가 우승 배지의 팀명 텍스트에도 새고 있었음. 팀명 텍스트 클래스를 `.tdf-mini-badge-team-name`으로 분리해 근본 수정. 배지 내부는 1:3 비율 좌(아이콘+타이틀)/우(선수명+팀명) 구분선 레이아웃으로 재구성, 종합순위(GC) 배지에도 팀명 라인 추가.
v 2.4.4.51
2026.07.10

TDF 싱글 페이지 풀폭 버그 — 진짜 근본 원인 (CSS 주석 내 리터럴 "별표+슬래시")

  • [CORE] **v2.4.4.50에서 시도한 수정들(var 폴백, `is_singular()` 제외, `article{}` 회피, 컨테이너 폭 분리)은 전부 정당한 버그였지만, 싱글 페이지가 계속 풀폭으로 렌더링되는 증상 자체는 고치지 못했음.** 클래스명을 몇 번을 바꿔도(`.tdf-container` → `.tdf-single-container` → 완전히 다른 이름들), 로딩 순서를 바꿔도, `<article>`을 `<div>`로 바꿔도 재현이 지속됨 — 심지어 진단용으로 만든 별도 WP 페이지(`.tdf-archive-container` 단독 테스트)조차 한 번은 정상이다가 나중에 다시 깨지는 등 종잡을 수 없는 패턴을 보임.
  • [CORE] **진짜 원인**: `css/tdf-stage.css` 파일 맨 위 헤더 주석에 다크모드 변수 목록을 `--bg-*/--text-*/--border-*/--link*` 형태로 축약해서 적었는데, 이 표기 안에 **리터럴 `*/`가 3번** 들어있었음(`--bg-*` 다음의 `/`, `--text-*` 다음의 `/`, `--border-*` 다음의 `/`). `*/`는 CSS 주석을 닫는 진짜 기호와 완전히 같은 문자열이라, 브라우저의 CSS 파서가 파일 최상단 헤더 주석을 6번째 줄에서 조기 종료시켰고, 그 여파로 그 직후에 오는 **첫 번째 실제 규칙**(`.tdf-container`/이후 `.tdf-archive-container`)이 파서 혼란 속에 통째로 드롭됨. 두 번째 규칙(`.tdf-breadcrumb`)부터는 파서가 재동기화되어 정상 작동 — 그래서 클래스명을 아무리 바꿔도 "맨 위에서 두 번째로 오는 규칙"이라는 위치 자체가 안 바뀌니 계속 실패했던 것. curl로 파일 내용을 아무리 대조해도 육안상 완전히 정상으로 보였고, `{`/`}` 괄호 균형 체크로도 못 잡아내는 유형의 버그였음.
  • [CORE] **진단 방법**: 브라우저 DevTools 콘솔에서 `document.styleSheets`를 순회하며 `.tdf-archive-container`에 매치되는 CSS 규칙을 소스 파일과 함께 나열해보니 tdf-stage.css의 해당 규칙 자체가 목록에 없었음. 이어서 tdf-stage.css의 `cssRules`를 전부 인덱스와 함께 나열해보니 파일에 있는 규칙 개수(약 72개)는 맞는데 목록이 `.tdf-breadcrumb`부터 시작 — 즉 첫 번째 규칙이 파싱 단계에서 사라졌음을 확인. 이후 `/*`/`*/` 개수를 세어보니 14 vs 17로 불일치, 정확한 위치를 스캔해 6번째 줄의 축약 표기를 특정.
  • [SYS] 수정 후 컨테이너 클래스를 `.tdf-container`/`.tdf-single-container`(모두 폐기)에서 **`.tdf-archive-container` 하나로 통일** — 싱글 페이지(`single-tdf_stage.php`)도 아카이브와 동일한 컨테이너·테이블 마크업(`.tdf-tables-grid` > `.tdf-table-card` > `table.tdf-race-table`)을 재사용하도록 재작성. 이 과정에서 실험적으로 넣었던 "가로 리본형" 스테이지 결과(`.tdf-result-ribbon` 등)는 걷어내고 검증된 표 패턴으로 되돌림. `functions.php`의 `vault-tdf-stage` 로딩 순서 강제 의존성(진짜 원인이 아니었으므로 불필요)도 원상복구.
  • [SYS] **교훈**: CSS 주석 안에 변수/선택자 이름을 축약 나열할 때 `단어*/단어*` 같은 패턴(별표 바로 뒤에 슬래시)을 쓰면 안 됨 — 쉼표나 다른 구분자를 쓸 것. `{`/`}` 균형만 체크하는 정적 검증으로는 이 클래스의 버그를 못 잡으므로, 향후 CSS 파일 수정 시 `/*`/`*/` 개수 일치 여부도 함께 확인하는 습관 필요.
v 2.4.4.50
2026.07.10

TDF 페이지 레이아웃 리뉴얼 — GAME 페이지 수준 시인성 확보

  • [CORE] **라이트 모드 테두리/배경 소실 버그 수정** — `css/tdf-stage.css`가 쓰던 8개 공유 다크모드 변수(`--bg-panel`/`--bg-soft`/`--border-main`/`--border-divider`/`--text-main`/`--text-soft`/`--link`/`--link-hover`)가 `body.dark-theme` 프리셋 안에서만 정의되고 라이트 `:root` 정의가 전혀 없었음. fallback 없는 `var()`는 선언 전체를 무효화해 라이트 모드에서 `border`가 통째로 사라지는 버그였음 — 기존 `css/changelog-v1.css` 컨벤션(`var(--x, #fallback)`)을 전체 적용해 수정.
  • [UI/UX] 싱글 페이지에서 종합순위(GC)/팀순위 테이블 제거, 아카이브(메인) 페이지로 이전 — 최신 스테이지의 스테이지결과·GC·팀순위 3개 표를 나란히 배치. 아카이브 스테이지 카드 정렬을 내림차순→오름차순으로 변경, 코스명/우승자에 서로 다른 폰트 색상 부여.
  • [UI/UX] 싱글 페이지 — 우승 콜아웃(풀폭 1개)을 미니배지 3종(🏆 스테이지 우승 / 🎽 종합순위 1위 / 🚴 팀순위 1위)으로 교체. 스테이지 결과(Top5)를 가로 리본형 카드 5개로 재구성. 첫 문단에 드롭캡(`.has-drop-cap`, 기존 Gutenberg 컨벤션+다크모드 변수 재사용) 적용.
  • [UI/UX] 저지 배지 상단의 입체형 컬러 바(`border-top`) 제거 — 플랫한 원형 dot만 색상 지표로 유지. 사용자 요청으로 싱글 페이지의 저지 배지 자체는 CSS 한 줄(`display:none`)로 임시 비활성화(마크업·카드 CSS는 그대로 유지, 추후 복구 용이).
  • [CORE] **`functions.php`의 `is_singular()` 전역 에셋 블록 버그 발견·수정** — 모든 싱글 페이지(TDF CPT 포함)에 무조건 `mini-panel.js`(플로팅 타이틀 패널 — 사이드바처럼 보임), `reading-time`, `single-post-components.css`, `footnote-popup`, `entry-table.css`가 로드되고 있었음. `tdf_stage`를 이 블록에서 제외 처리(`is_singular() && !is_singular('tdf_stage')`).
  • [SYS] 싱글/아카이브 컨테이너 폭을 GAME 페이지 전례에 맞춰 분리 — 싱글은 `.single-game-review .gr-container`와 동일한 1100px, 아카이브(3표 배치 필요)는 1300px 유지. 초기엔 둘 다 1300px로 묶어서 노트북 해상도 기준 여백이 부족했던 문제 발견해 수정.
  • [CORE] **싱글 페이지 풀폭 렌더링 버그 — 근본 원인 규명·수정**. 프로덕션에서도 동일 재현되어 LocalWP 환경 차이가 아님을 확인 후 추가 조사. 원인: Blocksy 부모 테마 `main.min.css`에 스코프 없는 전역 `article {}` 규칙이 있음 — `width: var(--has-boxed-structure, var(--theme-container-width)); max-width: var(--has-boxed-structure, var(--theme-boxed-content-max-width));`. game-review/일반 포스트·페이지는 Blocksy 커스터마이저가 생성하는 동적 CSS(`wp-content/uploads/blocksy/css/global.css`)에서 `[data-prefix="game-review_single"] [class*="ct-container"] > article[class*="post"] {--has-boxed:false;--has-wide:true;}` 같은 스코프 규칙으로 관련 변수를 미리 받지만, `tdf_stage`는 그런 커스텀 레이아웃 설정이 없어 테마 기본값(넓은 폭)이 `<article class="tdf-article post ...">` 요소 자체에 그대로 적용되고 있었음. `.tdf-container`(부모 div)는 애초부터 정상이었으나 자식 `<article>`이 부모와 무관하게 자기 폭을 갖고 있었던 것 — 아카이브 페이지는 `<article>` 태그 자체를 쓰지 않는 구조(div/section)라 이 문제를 원천적으로 피해갔음. `.tdf-article { width: 100% !important; max-width: 100% !important; margin-inline: 0 !important; }` 추가로 수정.
  • [CORE] **사용자 제안으로 근본 해결** — `!important` 오버라이드는 증상만 되돌릴 뿐, Blocksy `article {}` 규칙이 함께 걸어둔 `border`/`padding`/`box-shadow`/`border-radius`(`--has-boxed` 기반, 아직 눈에 안 띈 잠재 지뢰)까지 하나씩 패치해야 하는 구조였음. `single-tdf_stage.php`가 댓글·related posts 등 WP 표준 post 기능을 전혀 안 쓰고 Rank Math SEO도 DOM이 아니라 포스트 메타에서 스키마를 생성해 무관하다는 점에 착안해, `<article id="post-N" <?php post_class('tdf-article'); ?>>`를 아카이브 페이지와 동일한 일반 `<div id="post-N" class="tdf-article">`로 교체 — `article` 셀렉터 자체가 매치하지 않게 되어 `!important` 오버라이드도 제거. Blocksy의 article-scoped 규칙 전체를 구조적으로 회피해 향후 유사 재발을 원천 차단.
v 2.4.4.49
2026.07.09

TDF 저지 라벨 하드코딩 제거 (가드레일 위반 수정) + sync_to_wp.py 설계 확정

  • [CORE] **가드레일 위반 발견 및 수정** — `single-tdf_stage.php`/`archive-tdf_stage.php`에 저지 한글명·색상(`옐로 저지` `#FFDD00` 등)을 PHP `$jersey_meta` 배열로 하드코딩했던 것을 확인. `doc/plans/tdf-thirdvault-migration-plan.md` 가드레일 2번("정적 라벨 매핑은 Python이 완성된 문자열로 전송, PHP에 매핑 테이블 금지") 위반이라 제거하고, `_tdf_jerseys` meta에 담긴 값(`label`/`emoji`/`color`)을 그대로 렌더링하도록 수정.
  • [SYS] project_tdf 쪽 `publisher/sync_to_wp.py` 신규 작성(별도 레포, 이 커밋 범위 밖) — `wp_publisher.py` 인증/재시도/태그 생성 패턴 재사용, curated JSON + SQLite(`stage.date`) + `config.json`(저지 라벨/색상) → `tdf_stage` CPT REST POST/PUT. `--dry-run`으로 페이로드 구성 검증 완료. 프로덕션(3rdvault.net)엔 아직 CPT 코드가 배포되지 않아 실사용 전 배포 필요.
v 2.4.4.48
2026.07.09

TDF 스테이지 CPT 1차 구현 — CPT/메타/템플릿

  • [CORE] `inc/cpt-tdf-stage.php` 신설 — `tdf_stage` CPT(REST 노출) + ACF 스칼라 필드 15개 + JSON meta 4종(`_tdf_jerseys`/`_tdf_stage_top5`/`_tdf_gc_top10`/`_tdf_team_results`) 등록. `register_post_meta` auth_callback 실동작 검증 완료(내부 REST 디스패치로 인증/미인증 양쪽 확인).
  • [CORE] **버그 발견 및 수정** — `supports`에 `custom-fields` 누락 시 REST 스키마에 `meta` 필드 자체가 노출되지 않아 메타 쓰기가 조용히 실패하는 것을 확인(notice-ticker.php 과거 auth_callback 누락 사례와 유사 계열의 함정, `doc/darkmode` 문서화된 절차로 재검증해 사전 차단).
  • [UI/UX] `single-tdf_stage.php`, `archive-tdf_stage.php` 신규 — 스테이지 개요/저지4종/Top5/GC Top10(순위변동 화살표)/팀순위/하이라이트(article_ko) 렌더링. 아카이브는 연도별 그룹핑 + 최신 스테이지 순위 배너(비시즌엔 직전 대회 최종 결과로 자동 대체) 포함.
  • [SYS] 파일명은 CPT 슬러그(`tdf_stage`, 언더스코어)와 정확히 일치해야 WP 템플릿 계층이 인식함 — 최초 `single-tdf-stage.php`(하이픈)로 작성했다가 Blocksy 기본 템플릿으로 폴백되는 것을 발견해 `single-tdf_stage.php`로 정정.
  • [UI/UX] `css/tdf-stage.css` — 신규 다크모드 변수 없이 기존 전역 변수(`--bg-panel`/`--text-main`/`--border-main` 등)만 재사용(다크모드 가이드 케이스 A). 16개 프리셋 전체에 추가 작업 불필요.
  • [SYS] stage_05 curated JSON 실데이터로 REST 발행 → 렌더링 → 삭제까지 왕복 검증 완료(테스트 포스트는 정리함). project_tdf 쪽 `sync_to_wp.py` 작성은 별도 세션 대상(doc/plans/tdf-thirdvault-migration-plan.md 6절 참고).
v 2.4.4.47
2026.07.04

RON 활동 카드 3단 높이 전환 슬라이드 애니메이션 추가

  • [UI/UX] `strava-personal/templates/card.php` — 활동 카드 본문을 `memo / analysis / details` 3개 collapse wrapper로 분리해 상태별 슬라이드 전환 진입점 정리.
  • [UI/UX] `strava-personal/assets/frontend-script.js` — `full / nomemo / min` 토글 시 각 wrapper의 실제 높이를 측정해 `height + opacity` 전환으로 펼침/접힘 애니메이션 적용. 초기 렌더와 resize 시 상태 재동기화 추가.
  • [UI/UX] `strava-personal/assets/frontend-style.css` — 기존 `display:none` 기반 즉시 숨김 규칙 제거, 카드 collapse 전용 transition 규칙 추가. 메모 편집/다크모드/모바일 토글 구조는 유지.
v 2.4.4.46
2026.06.29

sitemap XML 선행 출력 오류 수정

  • [SYS] fix: `inc/custom-header.php` 파일 시작부의 선행 공백 제거 — 테마 include 시 XML 선언보다 먼저 공백이 출력되던 문제 수정. Rank Math sitemap 응답에서 `XML declaration allowed only at the start of the document` 오류를 유발하던 원인.
v 2.4.4.45
2026.06.28

본문 플로팅 사이드바 RON 라벨 확장 및 테마 의존성 감사 문서 추가

  • [UI/UX] `js/mini-panel.js` — 우측 본문 플로팅 사이드바 하단 바로가기 `STRAVA` 라벨을 `RIDE OR NOT`으로 변경.
  • [UI/UX] `css/single-post-components.css` — `NOW / RIDE OR NOT` 서브 버튼 비율을 분리해 `NOW` 폭은 줄이고 `RIDE OR NOT` 폭은 넓혀 긴 라벨이 한 줄로 안정적으로 보이도록 조정.
  • [CORE] docs: `docs/RON-THEME-DEPENDENCY-AUDIT.md` 신규 — RON의 테마/Blocksy 결합 지점을 실제 코드 기준으로 조사한 플러그인 전환 사전 감사 문서 작성.
v 2.4.4.44
2026.06.28

RON 초심자용 프로젝트 설명서 HTML 작성

  • [UI/UX] docs: `doc/strava/ron-project-guide.html` 신규 — RON을 처음 보는 사람도 이해할 수 있도록 개념, 핵심 기능, 구현 개요, 운영 흐름, 상세 사용법, FAQ를 담은 독립 HTML 설명서 작성.
  • [CORE] docs: 구현 파트는 상품화 가능성을 고려해 세부 기술 대신 계층 구조와 운영 관점 중심으로 정리. 시각 이해를 돕기 위해 카드형 섹션과 간단한 SVG 흐름 다이어그램 포함.
  • [AI] docs: `doc/strava/ron-technical-brief.html` 신규 — 다른 LLM/리뷰어가 구조적·기능적 조언을 줄 수 있도록 모듈 맵, 데이터 흐름, 저장 구조, known issues, 아키텍처 질문, 전달용 프롬프트 컨텍스트까지 포함한 상세 기술 브리프 작성.
v 2.4.4.43
2026.06.27

RON 종합 로그창 표시 수 축소 및 내부 스크롤 고정

  • [UI/UX] `02-admin-page.php` — 우측 `종합 로그`는 최근 30건 렌더를 유지하고, 헤더 보조 문구를 `최근 30건 / 내부 스크롤` 기준으로 정리.
  • [UI/UX] `admin-style.css` — 로그 레일을 `header / latest / scroll area` 3행 구조로 재정의. 내부 로그 표시창이 남는 높이를 전부 차지하도록 보정.
  • [UI/UX] `02-admin-page.php` — 좌측 패널 실제 높이를 기준으로 우측 로그 레일 높이를 동기화하는 경량 JS 추가. 데스크톱에서는 하단선을 토글바와 맞추고, 1열 반응형 구간에서는 자동 해제.
  • [UI/UX] `02-admin-page.php` + `admin-style.css` — 종합 로그 액션 칩에 modifier 클래스 추가. `DONE/RESUME/FAIL/START/DL/PAUSE/TEST` 계열에 지정 색상(`#82c91e`, `#c026d3`, `#fa5252`, `#1098ad`, `#ffa94d`, `#ff8787`, `#4c6ef5`) 적용.
  • [UI/UX] `02-admin-page.php` + `admin-style.css` — 종합 로그창을 `헤더 / 범례 / 스트림` 구조로 리뉴얼. 최신 상태 배지, TYPE·STATUS 범례, 카드형 로그 아이템(타입/상태/타임스탬프/메시지/서브정보) 레이아웃으로 전환.
  • [UI/UX] `02-admin-page.php` + `admin-style.css` — 종합 로그 범례 제거. 로그 레일은 투명 컨테이너로 바꾸고, 헤더 영역과 개별 이벤트 카드를 각각 독립 패널처럼 보이도록 보정. 스크롤바는 숨기고 스크롤 기능만 유지, 칩 텍스트는 배경 대비에 맞춰 흰색/검정으로 재배색.
  • [UI/UX] `admin-style.css` — 종합 로그 헤더를 STATUS 밴드와 동일한 다크 톤으로 통일하고 텍스트를 반전. STATUS 칩들도 색상별 배경/테두리/텍스트를 명시해 `START/FAIL/PAUSE/RESUME/DL/INFO` 포함 모든 액션 배지가 안정적으로 읽히도록 보정.
  • [UI/UX] `02-admin-page.php` + `admin-style.css` — 종합 로그 헤더에서 최신 상태 배지와 다운로드 버튼 제거. `종합 로그 Event Stream` 단일 헤더 줄로 정리하고, 최상단 latest 카드에는 약 5초간 반전 깜빡임 액션을 추가.
  • [UI/UX] `02-admin-page.php` + `admin-style.css` — 카드형 로그 UI는 유지한 채, 각 로그 카드 왼쪽에 4px 상태 컬러바 추가. `DONE/START/ERROR/WARN/UNKNOWN` 상태를 `action 우선 + level 폴백`으로 매핑하고 hover 시 컬러바가 더 선명해지도록 보정.
v 2.4.4.42
2026.06.27

RON 헤더 외부 바로가기 배지 추가

  • [UI/UX] `02-admin-page.php` — 제어판 헤더 우측에 `Intervals.icu / Strava / Garmin Connect` 외부 바로가기 배지 3종 추가. 각 배지는 공식 SVG 기반 아이콘만 사용하고 새 탭으로 열리도록 구성.
  • [UI/UX] `admin-style.css` — 헤더 바로가기 배지의 원형 버튼, hover/focus 반응, 모바일 줄바꿈 정렬 규칙 신규 추가.
v 2.4.4.41
2026.06.26

RON DB 백업 박스 로그 다운로드 드롭다운 전환

  • [UI/UX] `02-admin-page.php` — DB 백업 박스 로그 액션을 셀렉터+버튼 2단계에서 단일 드롭다운 버튼으로 정리. `종합 로그 / 백업 로그 / 동기화 로그` 항목 클릭 시 즉시 다운로드되도록 변경.
  • [UI/UX] `02-admin-page.php` — 백업 STATUS 컬럼 헤더를 `DB & Log 백업`으로 조정해 실제 기능 범위와 라벨을 일치시킴.
  • [UI/UX] `admin-style.css` — 좁은 STATUS 컬럼 안에서도 안정적으로 보이도록 compact 드롭다운 패널과 chevron 토글 스타일 추가. `hidden` 상태 강제와 STATUS 래퍼 overflow 보정으로 잘림/닫힘 문제를 함께 수정.
v 2.4.4.40
2026.06.26

RON 제어판 중앙 정렬 보정

  • [UI/UX] `admin-style.css` — 최상위 `.sa-wrap`에 `margin-inline: auto`와 좌우 패딩을 추가해 초고해상도(4K) 데스크톱에서도 제어판 전체가 중앙 기준으로 안정적으로 배치되도록 보정.
v 2.4.4.39
2026.06.26

RON 통합 로그창 정렬·타임스탬프 가독성 보정

  • [UI/UX] `02-admin-page.php` — 통합 로그 시간값을 `DATE / TIME` 2행 스택으로 분리 렌더. 날짜는 더 작고 옅게, 시간은 보조 기준으로 읽히도록 구조화.
  • [UI/UX] `admin-style.css` — 우측 로그 레일 폭 `300px → 336px` 확장. 타임라인 세로선과 상태 도트 중심축을 재정렬하고, 로그 본문/메타 우측 여백을 소폭 보정.
v 2.4.4.38
2026.06.26

RON 통합 로그 Phase 6 — 옵션 최근 로그 저장 락 보강

  • [CORE] `19-logging.php` — `ron_event_log` 옵션 갱신을 `ron-event-log.lock` 파일 기반 임계영역으로 직렬화. 동시 기록 시 최근 로그 option이 서로 덮어쓰는 위험을 완화.
  • [SYS] verify: LocalWP WP-CLI로 테스트 이벤트를 추가 기록해 `ron_event_log` 옵션과 `ron.log` 파일 갱신을 재확인. 완전한 고부하 동시성 스트레스 테스트는 미실시.
v 2.4.4.37
2026.06.26

RON 통합 로그 Phase 5 — 다운로드 공존 정리

  • [UI/UX] `02-admin-page.php` — 우측 로그 헤더에 레거시 `sync.log` 다운로드 버튼 복구. 통합 `ron.log` 버튼과 병행 배치해 기존 동선을 유지하면서 통합 로그 접근도 유지.
  • [UI/UX] `admin-style.css` — 로그 헤더 액션 그룹 정렬 추가.
v 2.4.4.36
2026.06.26

RON 통합 로그 Phase 4 — 우측 로그창을 공통 이벤트 로그로 전환

  • [UI/UX] `02-admin-page.php` — 우측 `종합 로그` 데이터 소스를 `strava_sync_log`에서 `ron_event_log` 최근 30건으로 교체. latest 박스는 notice 우선, 없으면 최신 통합 로그 메시지를 사용하도록 정리.
  • [UI/UX] `02-admin-page.php` — 로그 리스트 항목을 `domain / action / time / message / context` 구조로 렌더 변경. 상태 카드용 `$last_sync`는 기존 `strava_sync_log` 유지로 회귀 방지.
  • [UI/UX] `17-backup.php` — AJAX 로그 다운로드에 `log_type=ron` 추가해 통합 로그 파일 `ron.log` 다운로드 지원.
  • [UI/UX] `admin-style.css` — 로그 타임라인을 level(`ok/warn/err/info`) 기반 점색상과 `action` 보조 pill 구조에 맞게 보정.
v 2.4.4.35
2026.06.26

RON 통합 로그 Phase 3 — OAuth·백필·업로드·배치 경고/오류 경로 확장

  • [CORE] `02-admin-page.php` — Strava OAuth 실패, 수동 스트림 백필, 수동 업로드, 관리자 배치 수집 결과를 통합 로그에 연결. 업로드/백필은 시작·완료·실패/보류 맥락까지 기록.
  • [CORE] `06-cron.php` — `strava_run_backfill_streams()`가 cron/manual 모드별 `start / complete / pause / fail` 구조화 결과를 반환하고 통합 로그에 남기도록 확장.
  • [CORE] `04b-intervals-api.php` — Intervals.icu 스트림 조회의 WP_Error 및 비정상 HTTP 응답을 통합 로그에 기록.
  • [CORE] `14-batch-collector.php` — 배치 수집 엔진이 시작/재개, rate-limit 일시중지, max-months 일시중지, 완료를 공통 포맷으로 기록하도록 확장.
v 2.4.4.34
2026.06.26

RON 통합 로그 Phase 2 — 동기화·재생성·백업 시작/실패 이벤트 확장

  • [CORE] `02-admin-page.php` — 수동 동기화, 특정 월 재생성, 전체 페이지 재생성 경로에 `start / complete / fail` 통합 로그 추가. 예외 발생 시 관리자 notice도 `err`로 명시.
  • [CORE] `06-cron.php` — 자동 동기화 크론 경로에 `start / fail` 통합 로그 추가. 완료는 기존 `strava_log_sync('auto')` wrapper를 통해 유지.
  • [CORE] `17-backup.php` — 자동 백업과 수동 백업 다운로드 경로에 `start / fail` 통합 로그 추가. 기존 완료 기록과 개별 로그 파일 저장은 유지.
v 2.4.4.33
2026.06.26

RON 통합 로그 Phase 1 — 공통 logger 계층 도입

  • [CORE] `strava-personal/includes/19-logging.php` 신규 — `strava_log_event()` 공통 logger 추가. 최근 200건을 `ron_event_log` 옵션에 보관하고, `strava-personal/logs/ron.log`에 plain text append 저장.
  • [CORE] `strava_personal.php` — 공통 logger를 초기 로드 체인에 추가해 크론/관리자/백업 wrapper에서 공용 사용 가능하게 정리.
  • [CORE] `06-cron.php` — 기존 `strava_log_sync()`가 레거시 `strava_sync_log`/`sync.log` 유지와 함께 공통 통합 로그에도 동기화 완료 이벤트를 기록하도록 재배선.
  • [CORE] `17-backup.php` — 기존 `strava_log_backup()`가 레거시 `backup.log`/`strava_backup_log` 유지와 함께 공통 통합 로그에도 백업 완료·다운로드·실패 이벤트를 기록하도록 재배선. 로그 경로 상수는 공통 logger 계층으로 이관.
v 2.4.4.32
2026.06.25

RON 메인 Walk 바 반응형 재배치 + 카드 토글 모바일 가로 전환

  • [UI/UX] `05-page-builder.php` + `frontend-script.js` — Walk 카드 상태 토글에 `role="group"`/`aria-label`/`aria-pressed` 적용. 기존 `full / nomemo / min` 상태 구조는 유지.
  • [UI/UX] `frontend-style.css` — Walk 바 반응형 브레이크포인트 재설계. `<=1024px`에서 차트를 하단 독립 행으로 분리하고, `<=640px`에서는 토글/메트릭/연간 누적/차트를 모바일 단일 컬럼 흐름으로 재배치.
  • [UI/UX] `frontend-style.css` — O/△/✕ 카드 토글을 모바일에서 세로 스위치 대신 가로 segmented control로 전환. thumb 이동축도 `translateY` → `translateX`로 분기.
  • [UI/UX] `frontend-style.css` — Walk INTENSITY 헤더/레전드 줄바꿈 허용, 초소형 화면에서 레전드 압축 및 월간 보조 지표 1열 전환 추가.
  • [UI/UX] `05-page-builder.php` + `frontend-style.css` — 모바일에서 `WALK` 헤더를 상단 토글 행으로 이동시키고, `THIS MONTH / 4항목 박스 / YEAR TOTAL`을 명확한 1열 흐름으로 재배치. 4항목 박스 폭도 모바일에서 소폭 축소.
  • [UI/UX] `frontend-style.css` — Walk 바 반응형 규칙을 `기본형 / 767px 이하 / 420px 이하` 3단계로 단순화. 상위 `768px` 보정 규칙과 하위 `640px` 규칙 충돌을 제거해 모바일 1열 배치 디버깅 기반 정리.
  • [UI/UX] `05-page-builder.php` + `frontend-style.css` — 모바일 전용 `swb-mobile-summary` 신규 추가. `THIS MONTH / COUNT / TIME / AVG HR / LOAD / YEAR TOTAL`를 텍스트형 스택 레이아웃으로 별도 렌더하고, `767px 이하`에서는 기존 데스크톱 메트릭 그리드를 숨기도록 전환.
  • [UI/UX] `frontend-style.css` — BOX1 `Monthly Trend` 스파크 섹션의 수동 `translateY` 보정 제거. `stbc-spark-section` / `stbc-spark-stack`을 세로 중앙 정렬 구조로 재정의해 구분선에 붙는 현상 완화.
  • [UI/UX] `frontend-style.css` — BOX1 스파크 헤더를 가로 정렬로 전환. `Monthly Trend`와 `월별 거리 추이`를 같은 행에 배치해 스파크 차트와의 간격 확보.
v 2.4.4.31
2026.06.25

RON 전체 페이지 재생성 박스 재정렬 + Strava 아코디언 문구 정리

  • [UI/UX] `02-admin-page.php` — 재생성 본문을 외부 `2:1:1` 3슬롯으로 재구성. 첫 슬롯 안에서만 진행 상태·연도 선택 재생성·전체 재생성을 `1:1:1`로 배치하고, 나머지 2슬롯은 `Empty Box` 예약 영역으로 유지.
  • [UI/UX] `admin-style.css` — 재생성 박스 세로 구분선 전부 제거. 연도 셀렉터와 '해당 연도 재생성' 버튼 폭을 동일하게 통일하고, 재생성 버튼 색상을 제어판 공통 `--sa-icu` 톤으로 정리.
  • [UI/UX] `02-admin-page.php` — 재생성 헤더 우측 상태 배지(`완료/진행 중/일시정지`) 제거. 진행 상태 표시는 본문 상태 텍스트만 사용하도록 단순화.
  • [UI/UX] `02-admin-page.php` — Strava 아코디언 요약문 `API · OAuth · 배치 · 멤버십 · Rate Limit 4종 — 보조 수단 (평소 접힘)` 삭제.
v 2.4.4.30
2026.06.25

RON 전체 페이지 재생성 박스 본문 레이아웃 리뉴얼

  • [UI/UX] `02-admin-page.php` — 재생성 박스 본문을 3:2 분할 레이아웃으로 재구성. 좌측에 진행 상태·연도 재생성·전체 재생성만 재배치하고, 우측은 `Empty Box` 예약 영역으로 분리.
  • [UI/UX] `02-admin-page.php` — 초기화 버튼 제거. 전체 재생성 버튼의 잠금 해제 후 확인창 실행 흐름은 기존 로직 그대로 유지.
  • [UI/UX] `admin-style.css` — 짧은 음각 세로 구분선, inset 패널, 124px 연도 셀렉터, `#fa5252` 기반 재생성 버튼 톤, 잠금 오버레이 스타일 신규 적용. 태블릿/모바일 반응형 재배치 추가.
v 2.4.4.28
2026.06.24

RON TSB 박스 — 무릎 부상 위험도 인디케이터 (3-slot LED)

  • [AI] feat: `10-training-load.php` — `strava_calc_injury_risk()` 신규 추가. RAMP·ACWR·Monotony band + TSB 수치를 조합해 0~8점 스코어 산출, 4단계(safe/watch/warn/danger) 레벨과 컨텍스트 맞춤 메시지 반환.
  • [UI/UX] feat: `topbar.php` — TSB 박스 하단 Acute·Mono 2행 프로그레스 바 제거 → 3-slot vertical LED 인디케이터로 교체 (R=RAMP / A=ACWR / M=MONO 개별 색상 + 종합 판정 텍스트).
  • [UI/UX] `frontend-style.css` — `.tsb-inj-*` / `.tsb-led-*` 신규 CSS 블록. LED 슬롯 9×32px, border-radius 4px, inset 음영+glow. 다크모드 대응 포함.
  • [UI/UX] docs: `doc/strava/ron-injury-risk.md` 신규 — 도입 배경·학술 근거(Gabbett 2016)·스코어링 로직·UI 구조·향후 조정 항목 상세 기술.
v 2.4.4.29
2026.06.24

RON STATUS 밴드 요약 pill + 무결성 체크

  • [UI/UX] feat: `02-admin-page.php` — STATUS 밴드 우측에 요약 pill 추가. 자동동기화 예정 시각·백업 경과일·Strava D-day·Rate Limit 상태를 ok/warn/err 색상 badge로 표시.
  • [UI/UX] feat: `02-admin-page.php` + `11-db-tables.php` — DB 현황 컬럼에 무결성 체크 버튼 추가 (돋보기 아이콘). AJAX로 스트림 누락 건수·중복 strava_id·최신 활동 경과일 검사 결과를 인라인 badge로 표시. `strava_check_integrity()` 신규 추가.
  • [UI/UX] `assets/admin-style.css` — `.sa-status-band__summary`, `.sa-summary-pill--*`, `.sa-integrity-result`, `.sa-intg-*` CSS 신규 추가.
v 2.4.4.27
2026.06.24

RON TCX 고도·칼로리 계산 알고리즘 개선

  • [CORE] `15-manual-upload.php` — `manual_elev_gain()` raw 합산 → 0.5m 임계값 필터 교체. GPS 노이즈 제거, 가민 커넥트 대비 고도 오차 90% → 6~18%로 개선.
  • [SYS] feat: `15-manual-upload.php` — `manual_calc_calories()` 신규 추가. 1순위 파워 기반(3초 슬라이딩 평균 kJ × 1.2, 대사효율 20%), 2순위 HR 기반 폴백(%HRmax × weight × time_min × 0.12). TCX·GPX 파서 모두 적용.
  • [CORE] docs: `doc/strava/` — 낙동강·2번 라이딩 TCX 파일 + 가민 커넥트 스크린샷 2종 추가 (알고리즘 검증 데이터).
v 2.4.4.26
2026.06.24

RON Strava 아코디언 — API 정보 버튼 정렬·백필 통합

  • [UI/UX] `02-admin-page.php` — API 정보 카드 저장 버튼을 `sa-card-actions--mt-auto`로 감싸 다른 카드 버튼들과 바닥선 통일.
  • [UI/UX] `02-admin-page.php` — 스트림 백필 버튼을 Rate Limit 섹션 하단에서 '과거 데이터 재수집' 카드로 통합. 배치 상태 배지·시작 연도 입력 복원.
  • [UI/UX] `admin-style.css` — `.sa-batch-year-form` 재정의, `.sa-batch-year-row`, `.sa-fl-sm`, `.sa-num-input` 신규 추가.
v 2.4.4.24
2026.06.24

RON 제어판 종합 로그창 정렬 수정 — ghost 제거·toggle margin 제거

  • [UI/UX] fix: `02-admin-page.php` — `sa-log-col` 내 `sa-section-bar--ghost` 더미 엘리먼트 제거. 구 레이아웃 섹션바 높이 맞춤용으로 넣었던 것, 신 레이아웃에서 로그창을 아래로 밀던 원인.
  • [UI/UX] fix: `admin-style.css` — `.sa-toggle-shell margin-bottom` 16px → 0. 토글바 하단과 로그창 하단 정렬 일치.
  • [UI/UX] fix: `02-admin-page.php` — `saMatchLogColHeight()` JS 제거. CSS grid stretch + flex 체인으로 충분히 처리되며, JS가 오히려 script/style 로드 순서 문제로 루프를 유발하던 근본 원인.
v 2.4.4.23
2026.06.24

RON STATUS 단일 패널 전환 + 음각 박스 + DB현황 하이라이트 강화

  • [UI/UX] `02-admin-page.php` — STATUS 4개 개별 카드 → 단일 `sa-status-block` 패널 전환. 상단 단일 STATUS 헤더 밴드, 내부 `sa-status-cols` 4컬럼 구분선 레이아웃.
  • [UI/UX] `02-admin-page.php` — 연결·DB현황·동기화현황 컬럼에 `sa-col-body--inset` 음각 박스 적용 (rgba 배경 + inset box-shadow). 복구: 클래스 제거만으로 즉시 원상복구 가능.
  • [UI/UX] `admin-style.css` — `.sa-status-source.is-active` 하이라이트 강화: `var(--sa-icu)` 단색 배경, 흰색 텍스트, 좌측 액센트 보더, 아이콘 invert.
  • [UI/UX] `02-admin-page.php` — 백업 버튼 2종 `sa-backup-btn` 신규 디자인: 30px, 아이콘+텍스트, `#343a40`/`#868e96` 톤.
  • [UI/UX] `admin-style.css` — `.sa-status-cols` 그리드, `.sa-status-col`, `.sa-status-col-hd`, `.sa-col-body--inset`, `.sa-col-refresh-btn` 스타일 신규 추가.
v 2.4.4.22
2026.06.24

RON 제어판 색상 톤 변경 + 헤더 칩 제거 + 엔진칩 이중 애니메이션

  • [UI/UX] `admin-style.css` — `--sa-icu` #2f6fde → #495057(다크 그레이), `--sa-icu-2` → #343a40. breathing 키프레임 색상 갱신.
  • [UI/UX] `admin-style.css` — `sa-status-band` 헤더 배경 `var(--sa-icu)` 단색 + 흰색 텍스트. refresh 버튼 흰색 테두리.
  • [UI/UX] `02-admin-page.php` — 헤더 우측 엔진 칩(`sa-header-engine`) 삭제.
  • [UI/UX] `admin-style.css` — `.sa-status-inline-chip` 브리딩 + shimmer 이중 애니메이션 적용. `sa-chip-shimmer` 키프레임 추가.
v 2.4.4.21
2026.06.24

RON STATUS 컬럼 비율·버튼 색상 수정

  • [UI/UX] `admin-style.css` — STATUS 컬럼 비율 `0.85fr 0.95fr 1.1fr 1fr` (백업 박스 확대). 버튼 `.sa-btn-coral` #fa5252, `.sa-btn-green` #58a000 적용.
v 2.4.4.20
2026.06.24

백업 다운로드 스트리밍 수정 + 실전 검증 완료

  • [UI/UX] fix: `17-backup.php` — 다운로드 핸들러에 `ob_end_clean()` 루프 추가(WP 중첩 버퍼 제거). `readfile()` → 64KB 청크 `fread()+flush()` 스트리밍 전환. `X-Accel-Buffering: no` 헤더로 Nginx 버퍼링 차단. `no-gzip` 환경변수로 Apache mod_deflate 중복 압축 방지.
  • [SYS] 실전 백업 검증 완료 (2026-06-24) — `ron-db-backup-20260624-152813.sql.gz` 59MB. gzip 무결성 OK, activities 81블록(~4050건) + streams 81블록(~4050건), `SET FOREIGN_KEY_CHECKS=1;` 정상 종료 확인. 복원 절차 `doc/strava/backup-restore.md` 작성.
v 2.4.4.19
2026.06.24

백업 OOM 긴급 수정 — 스트리밍 덤프 전환·자동 백업 기본 비활성화

  • [SYS] fix: `17-backup.php` — SQL 덤프 메모리 누적(`$sql .=`) 방식 제거. `gzwrite()` 청크 직접 파일 기록으로 전환 (50행 단위, `$wpdb->flush()`). 다운로드도 임시파일 기록 후 `readfile()` 스트리밍으로 교체. OOM(256MB 초과) 해소.
  • [SYS] fix: `06-cron.php` — 자동 백업 크론 기본값 비활성화(`strava_auto_backup_enabled = 0`). 과거 시각 등록 시 +1일 처리 추가. 비활성 시 기존 크론 언스케줄.
v 2.4.4.18
2026.06.24

RON 제어판 — 자동 동기화 시간 설정

  • [UI/UX] `02-admin-page.php` — 토글바 자동 동기화 항목에 시간 입력창(HH:MM) + 적용 버튼 추가. 메타 텍스트 제거, 시간 폼 좌측 배치.
  • [CORE] `06-cron.php` — `strava_auto_sync_time` option 기반으로 크론 등록 시간 결정 (기본 14:00). 시간 변경 시 기존 크론 언스케줄 후 재등록.
  • [UI/UX] `admin-style.css` — `.sa-autosync-time-form`, `.sa-time-input` (105px) 스타일 추가.
v 2.4.4.17
2026.06.24

RON 제어판 DB 백업 박스 — 아이콘·비율·버튼 색상·확인창

  • [UI/UX] `02-admin-page.php` — DB 백업 밴드 아이콘 database → archive (중복 해소). archive lucide SVG 추가.
  • [UI/UX] `admin-style.css` — STATUS 그리드 비율 `1fr 1.1fr 1.1fr 0.75fr` (백업 박스 최소폭). `.sa-btn-coral` #fa5252, `.sa-btn-green` #58a000 버튼 스타일 추가.
  • [UI/UX] `02-admin-page.php` — 백업 버튼 2종에 confirm 확인창 추가.
v 2.4.4.16
2026.06.24

RON 제어판 — DB 백업 기능 전체 구현

  • [SYS] `strava-personal/includes/17-backup.php` 신규 — DB 백업 전체 구현: SQL 덤프 생성, 롤링 3파일 서버 보관(`ron-db-0/1/2.sql.gz`), 수동 다운로드(admin-post), 자동 백업 크론 핸들러, 백업/동기화 로그 파일 기록, AJAX 로그 다운로드.
  • [SYS] `strava_personal.php` — 17-backup.php require_once 추가.
  • [CORE] `06-cron.php` — `strava_log_sync()` 파일 로그 기록 확장(`logs/sync.log`). `strava_auto_backup` WP-Cron 등록 (기본 13:30 KST, 주기 조절 가능).
  • [UI/UX] `02-admin-page.php` — STATUS 4열 그리드 전환. DB 백업 박스 신규(마지막 백업 정보·자동 주기 선택·다운로드·로그 버튼). "동기화 로그" → "종합 로그". 로그 헤더 다운로드 버튼 추가. 백업 빈도/시간 POST 핸들러.
  • [UI/UX] `admin-style.css` — 4열 그리드, 백업 박스 스타일, 버튼 색상 변수.
  • [SYS] `strava-personal/logs/.htaccess` 신규 — `.sql.gz`, `.log` 직접 URL 접근 차단.
v 2.4.4.15
2026.06.24

RON 제어판 — refresh 아이콘·토글·STATUS 헤더 후속 정리

  • [UI/UX] `02-admin-page.php` — DB 현황 refresh 버튼 아이콘 sync → rotate-cw 변경. 토글바 스트림 백필 자동 항목 제거. archive/rotate-cw 아이콘 추가.
  • [UI/UX] `admin-style.css` — STATUS 3카드 밴드 높이 min-height:46px 통일.
v 2.4.4.14
2026.06.24

RON 제어판 아이콘·토글·헤더 정렬 정리

  • [UI/UX] `02-admin-page.php` — DB 현황 refresh 버튼 아이콘 sync → rotate-cw 변경 (동기화 현황 밴드 아이콘과 시각적 구분).
  • [UI/UX] `02-admin-page.php` — 토글바 스트림 백필 자동 항목 제거 (GitHub Actions 워크플로로 대체).
  • [UI/UX] `admin-style.css` — STATUS 3카드 밴드 높이 불일치 수정: `padding: 11px 15px` → `padding: 0 15px; min-height: 46px` 통일.
v 2.4.4.13
2026.06.24

RON 제어판 키 입력 잠금 — 오버레이 보호장치 추가

  • [UI/UX] `02-admin-page.php` — ICU API Key·Strava Client ID·Client Secret 3개 필드에 `.sa-key-guard` 오버레이 잠금 적용. 기본 `readonly`+`tabindex="-1"`, [수정] 버튼 클릭 시 해제+포커스. Bitwarden 자동입력 차단 (`autocomplete="new-password"`, `readonly`).
  • [UI/UX] `02-admin-page.php` — `lock`/`unlock` lucide SVG 아이콘 추가.
  • [UI/UX] `admin-style.css` — `.sa-key-guard`, `.sa-key-guard-btn` 오버레이 스타일 추가.
v 2.4.4.12
2026.06.24

RON 제어판 UX 개선 — DB 현황 새로고침·아코디언 상태유지·타이틀 정리

  • [UI/UX] `02-admin-page.php` — DB 현황 헤더 refresh 버튼 추가. 클릭 시 AJAX로 소스별 활동수·스트림률 즉시 갱신, 아이콘 스핀 애니메이션.
  • [CORE] `02-admin-page.php` — `wp_ajax_strava_db_refresh` AJAX 핸들러 추가 (`strava_get_source_stats()` 반환).
  • [UI/UX] `02-admin-page.php` — Strava 아코디언 열림 상태 localStorage 유지 (`sa_acc_open`). 폼 저장 후에도 열림/닫힘 상태 그대로 복원.
  • [UI/UX] `02-admin-page.php` — 히스토리 배치 카드 타이틀 '히스토리 배치' → '과거 데이터 재수집'.
  • [UI/UX] `02-admin-page.php` — Rate Limit 섹션 하단 WP-CLI 로컬 경로 하드코딩 블록 제거.
  • [UI/UX] `admin-style.css` — `.sa-band-refresh-btn` 신규 스타일, `sa-spin` 키프레임 추가.
v 2.4.4.11
2026.06.24

Strava 스트림 백필 — WP-CLI 커맨드 및 GitHub Actions 워크플로 추가

  • [SYS] `strava-personal/includes/06-cron.php` — `wp strava backfill-streams --batch=N` WP-CLI 커맨드 추가. 실행 전 일간/15분 리밋 선확인, 루프 내 매 활동마다 재확인(eff_15m<10, eff_day<50 기준). 배치 후 잔여수 출력.
  • [SYS] `.github/workflows/stream-backfill.yml` 신규 — 스트림 백필 전용 GitHub Actions 워크플로. 일간 한도 도달 시 종료+텔레그램 알림, 15분 한도 시 900초 대기 자동 재개, 배치 완료(잔여 있음) 시 즉시 다음 라운드.
v 2.4.4.10
2026.06.24

RON 제어판 마무리 정합 — Strava 오렌지 버튼 확정·폰트 적용·타이틀 스타일

  • [UI/UX] `02-admin-page.php` — Strava 아코디언 저장 버튼 오렌지 확정: button-primary 제거 후 sa-btn-orange 단독 적용(API 정보 저장, 히스토리 이어서, 멤버십 저장). WP admin 스타일 간섭 완전 차단.
  • [UI/UX] `02-admin-page.php` — 계정 연동 재인증 버튼: sa-card-actions--mt-auto로 감싸 바닥선 정렬 + sa-btn-orange 오렌지 적용.
  • [UI/UX] `02-admin-page.php` — STATUS 섹션 바 '항상 노출 · 실시간' 핀 텍스트 삭제.
  • [SYS] `01-admin-menu.php` — admin_enqueue_scripts 훅으로 RON 제어판 전용 fonts.css enqueue(get_stylesheet_directory_uri 사용). Pretendard 전 weight admin 페이지 적용.
  • [UI/UX] `admin-style.css` — .sa-wrap font-family Pretendard 적용. .sa-header-title font-family Rockstar-ExtraBold 적용, font-size 40px.
v 2.4.4.9
2026.06.24

RON 제어판 레이아웃 정밀 교정 — 버튼 바닥선 통일·드롭다운 폭·힌트 텍스트 제거

  • [UI/UX] `02-admin-page.php` — 동기화 액션 카드 '실행 결과와 최근...' 힌트 텍스트 삭제.
  • [UI/UX] `admin-style.css` — 동기화 액션 재생성 드롭다운(연도/월) flex:1 적용, 재생성 실행 버튼과 동일 폭.
  • [UI/UX] `admin-style.css` — 엔진&연결 카드 sa-control-form flex:1, sa-engine-actions margin-top:auto — 저장/테스트 버튼 다른 카드와 같은 바닥선 정렬.
  • [UI/UX] `admin-style.css` — Strava 4카드(sa-strava-card) flex column 구조 추가, control-form flex:1, card-actions margin-top:auto — API 정보/계정 연동/히스토리 배치/멤버십 만료 버튼 바닥선 통일.
  • [UI/UX] `admin-style.css` — sa-inline-alert margin-bottom:10px 추가 — ICU 경고 박스와 히스토리 배치 버튼 간격 확보.
v 2.4.4.8
2026.06.24

RON 제어판 3차 정합 — 버튼 색상 통일·엔진폼 통합·히스토리/멤버십 시안 재작성

  • [UI/UX] `admin-style.css` — 지금 동기화 버튼 linear-gradient 제거, var(--sa-icu) 단색으로 통일. 4개 박스 모든 파란 버튼 동일 색상.
  • [UI/UX] `02-admin-page.php` — 엔진&연결 폼 2개(icu_engine_set+icu_api_key_save) → 1개(icu_engine_and_key_save) 통합. 저장 버튼 1개+테스트 버튼 1개로 시안 일치.
  • [UI/UX] `02-admin-page.php` — 히스토리 배치 카드: sa-mini-status 구형 구조 제거 → sa-hint + card-actions [이어서(grow)] [초기화(sm)] 시안 구조로 재작성.
  • [UI/UX] `02-admin-page.php` — 멤버십 만료 카드: sa-mini-status 구형 구조 제거 → sa-kv-simple(만료일) + sa-hint(잔여일) + form[date-grow + 저장sm] 시안 구조로 재작성.
  • [UI/UX] `admin-style.css` — sa-hint, sa-kv-simple, sa-date-grow, sa-engine-actions 신규 스타일 추가.
v 2.4.4.7
2026.06.24

RON 제어판 시안 2차 정합 — 아이콘 보완·버튼 통일·히스토리배치 재배치·스트림백필 토글 복원

  • [UI/UX] `02-admin-page.php` — 누락 아이콘 5개 추가(plug/settings/list/search/wrench). STATUS 섹션 바 chart 아이콘, 연결 카드 plug, 로그헤더 list, 입력/설정 섹션 바 settings 기어로 교체.
  • [UI/UX] `02-admin-page.php` — 버튼 디자인 통일: 저장 버튼(primary 파란, 전체너비), 테스트/재생성실행 ghost-icon(search/wrench 아이콘). 버튼 텍스트: '엔진 적용'→'저장', 'TSB 저장'→'저장', '업로드 및 저장'→'업로드(아이콘+텍스트)'.
  • [UI/UX] `02-admin-page.php` — 토글행 2번째: '설명 수집 고정' → '스트림 백필 자동' 실제 토글로 복원(strava_backfill_auto 옵션, 핸들러 추가).
  • [UI/UX] `02-admin-page.php` — Strava 히스토리 배치 카드: 기존 혼잡한 레이아웃 → hint 텍스트 + '이어서(오렌지 grow)'+'초기화(ghost sm)' + 시작 연도 행 분리.
  • [UI/UX] `admin-style.css` — ico-o/ico-g에 color 추가(오렌지/그린). Strava accordion chi에 orange color 추가. ghost-icon 버튼·card-actions·batch hint/year-form 스타일 신규.
v 2.4.4.6
2026.06.24

RON 제어판 시안 정합 수정 — 이모지 제거·헤더 단순화·카드 비율·DB현황·아코디언 배지

  • [UI/UX] `02-admin-page.php` — 헤더 박스 제거(단순 flex row로). STATUS 연결 카드 레이블 시안 일치(ICU 연결/Strava 인증). DB현황 카드 메트릭 박스 제거, 소스 테이블만 유지. 동기화 액션 버튼 화살표(chevron-right) 추가. 로그 레일 헤더 서브텍스트 '메시지 · 이력 통합' 추가. 토글행 3번째 칸 '향후 토글 자리' placeholder로 변경. Strava 아코디언 헤더에 '보조' 오렌지 배지 추가 및 텍스트 chevron 제거.
  • [UI/UX] `02-admin-page.php` — 이모지 전면 제거. 입력/설정 4카드(엔진/번개/차트/업로드) SVG 교체. Strava 4카드(key/link/package/credit-card) SVG 교체. 아코디언 chevron SVG 교체. 10개 신규 lucide SVG 케이스를 `strava_admin_render_panel_icon()`에 추가.
  • [UI/UX] `admin-style.css` — 헤더 border/background/shadow 제거. `.sa-chi` 22px→30px, border-radius 6→8px, `.sa-ic` 17px 지정. `.sa-step` 7.5px→9px·ICU 블루 컬러·letter-spacing 1.5px. `.sa-ctitle` 11.5px→14px. `.sa-ch` padding 13px 16px 조정. `.sa-strava-badge`, `.sa-log-head__sub`, `.sa-action-btn-arrow`, `.sa-toggle-item--ph` 신규 스타일 추가.
v 2.4.4.5
2026.06.23

RON 제어판 UI/UX 리뉴얼 P1~P6 반영 — 헤더·STATUS·로그레일·입력 4박스·Strava 아코디언

  • [UI/UX] `strava-personal/includes/02-admin-page.php` — RON 제어판 상단 헤더를 `RIDE OR NOT Dual Engine Control Panel v3.0` 구조로 교체하고, STATUS 3카드(연결/DB 현황/동기화 현황), 우측 동기화 로그 레일, 입력/설정 4박스(엔진&연결/동기화 액션/훈련 설정/수동 업로드), Strava 전용 설정 아코디언(API/OAuth/히스토리 배치/멤버십/Rate Limit)으로 재구성. 기존 우측 상태 카드, ICU 개별 패널, 수동 업로드 개별 패널, 상단 notice 출력, 구형 안내/로고 블록 제거.
  • [UI/UX] `strava-personal/assets/admin-style.css` — 관리자 컬러스킴 대응 토큰 보강, RON 헤더/엔진 칩/STATUS 카드/로그 타임라인/입력 4박스/토글행/Strava 아코디언 스타일 추가. 완료 메시지 애니메이션을 로그 레일 상단으로 이관.
  • [CORE] `strava-personal/includes/02-admin-page.php` — Description 수집 토글 UI 제거, `strava_fetch_description` 옵션을 Strava 경로 상시 ON 기준으로 고정. 자동 동기화는 풀폭 토글행으로 이동, 스트림 백필은 Strava 아코디언 내부 수동 액션으로 정리.
v 2.4.4.4
2026.06.23

RON 제어판 UI/UX 리뉴얼 — 레이아웃 확정 및 Codex 인계 사양서 작성

  • [AI] `doc/plans/ron-panel-renewal.md` 신규 작성 — RON 제어판 전면 개편 Codex 인계 사양서. 방안 C(단일 페이지 + Strava 아코디언 비대칭 분리) 확정. 컴포넌트-기존코드 매핑표, 디자인 시스템, 결정사항(다크모드=admin 컬러스킴 대응, 엔진칩 현행유지), P1~P7 분할 작업계획, 회귀주의 포함.
  • [UI/UX] `html_codes/ron-panel-skeleton.html` 신규 작성 — 실제 WP admin 폭 기준 레이아웃 시각 SSOT. 상단 풀폭 STATUS(연결/DB현황/동기화현황 3카드, ICU 틴트 띠지 헤더) + 우측 동기화 로그 세로 레일 + 하단 입력/설정 4박스(엔진연결/동기화액션/TSB/수동업로드) + 풀폭 토글행 + Strava 전용 아코디언(4컬럼 2스택). 이모지 전면 제거, lucide 스타일 인라인 SVG 아이콘 채용. 완료 메시지 3단계 애니메이션(등장+체크그리기+글로우 펄스 3회), 엔진 칩 브레싱 글로우, 로그 음각 처리, 타임라인 레일.
  • [AI] `doc/TODO.md` — RON 제어판 UI/UX 전면 개편 계획 상세 내용 추가.
v 2.4.4.3
2026.06.23

TSB 리스크 스택 추가 + BOX1 중단/하단 정렬 재구성

  • [UI/UX] `strava-personal/includes/05-page-builder.php` + `strava-personal/includes/10-training-load.php` + `strava-personal/templates/topbar.php` — TSB 하단 해설 문단을 리스크 메트릭(`ACUTE / MONO`) 스택으로 대체하고, `RAMP`는 `훈련 부하 포커스` 박스 상단으로 이동. 최근 7일 CTL 변화량, 최근 7일/28일 부하비, 7일 단조로움 계산값을 각 박스에 시각화.
  • [UI/UX] `strava-personal/assets/frontend-style.css` — TLF 상단 `RAMP` 행을 음각 박스형 미니 카드로 추가. 배지 폭 통일, 단위 표시는 hover 툴팁으로 전환, TSB 하단 스택은 초저높이 2행(`ACUTE / MONO`) 기준으로 압축.
  • [UI/UX] `strava-personal/templates/topbar.php` + `strava-personal/assets/frontend-style.css` — BOX1(`Monthly Trend`) 중단 영역 구조를 재정리. 스파크 섹션을 독립 스택 래퍼로 분리해 타이틀 2줄과 그래프 위치를 별도 제어 가능하게 정리하고, 하단 3개 통계(`ELEVATION / RIDES / YTD TSS`)는 카드 하단 기준으로 재정렬.
v 2.4.4.2
2026.06.22

Walk 바 토글 세로화 + 메트릭 위계/가독성 재정비

  • [UI/UX] `strava-personal/assets/frontend-style.css` — Walk 바 CARD 토글을 좌측 세로 슬라이더 형태로 재배치. 다크모드 활성 아이콘 대비를 어둡게 조정하고, 토글 본체는 플랫 톤 유지.
  • [UI/UX] `strava-personal/includes/05-page-builder.php` + `strava-personal/assets/frontend-style.css` — Walk 메트릭을 `THIS MONTH / 월간 4개 / YEAR TOTAL` 3영역 구조로 재편. 중앙 4개(`COUNT`, `TIME`, `AVG HR`, `LOAD`)는 음각 패널 안에 묶고, 캡션을 숫자 위 가운데 정렬로 통일.
  • [UI/UX] `strava-personal/includes/05-page-builder.php` + `strava-personal/assets/frontend-style.css` — 시간 표기 위계 조정: `14h` 메인 유지, 뒤 `11m`은 축소·저투명 처리. `TIME | AVG HR` 사이 짧은 세로 양각 구분자 추가로 시선 분할 강화.
v 2.4.4.1
2026.06.22

월 네비 버튼 다크모드 미생성 페이지 배경 수정

  • [UI/UX] fix: `assets/frontend-style.css` — 다크모드 `.strava-month-btn` 기본 상태 배경 오버라이드 누락으로 미생성 페이지 버튼이 거의 검정으로 표시되던 문제 수정. `rgba(255,255,255,0.05)` 배경·`rgba(255,255,255,0.07)` 테두리·`rgba(255,255,255,0.3)` 글자 추가 (라이트모드 `#f5f5f5` 뉘앙스 대응). 호버 배경 `0.06→0.12` 강화. 미생성 dot `rgba(255,255,255,0.18)` 추가.
v 2.4.4.0
2026.06.22

RON UI 전면 정비 v2 — TSB 리뉴얼 + 색상 팔레트 통일 + Walk 위계

  • [UI/UX] `templates/topbar.php` + `assets/frontend-style.css` — TSB 박스 전면 리뉴얼. 헤더 아래 가로선·세로 구분선으로 BOX1형 3단 레이아웃 구성. 좌 셀: TSB 수치(Bebas 60px, 상하좌우 가운데), 우 셀: ATL/CTL 가로 바 + 엔드캡 도트 + 스케일 `max(CTL, ATL)→85%` 로 바 길이 확대. 하단 셀: TSB 개념 해설 텍스트(9.5px). 훈련균형 칩 헤더 복귀. 구 TSB 수직 대칭 게이지·양방향 게이지 삭제.
  • [UI/UX] `assets/frontend-style.css` — 색상 팔레트 전면 통일. 무산소/위험 `#c92a2a`, 중강도/앰버 `#fab005`, 저강도/균형 `#82c91e`, 체력/블루 `#1864ab`. TLF 존 바·도트·퍼센트, TSB CTL/ATL 바·캡·수치, VO2Max 아크·카테고리, EF 임계강도, Walk 강도 HR존, TSB 상태 색상(`$tsb_color`) 전부 통일. 구 `#ef4444`·`#f97316`·`#22c55e`·`#3b82f6` 계열 잔존 0건.
  • [UI/UX] `includes/05-page-builder.php` — Walk 바 3단 시각 위계. 이번달 거리(`swb-item--primary`): 오렌지·22px, 횟수·시간·부하(`swb-item--secondary`): 회색·16px, 평균 심박(`swb-item--hr`): `#c92a2a`, 연간 누적(`swb-item--yearly`): `#1864ab`·좌측 구분선.
  • [UI/UX] `includes/05-page-builder.php` — Walk 강도 차트 날짜 라벨 `$d % 7 === 1` 조건 제거 → 1~31일 전체 표시.
  • [UI/UX] `templates/topbar.php` + `assets/frontend-style.css` — 전광판(`strava-scoreboard`) 최종 레이아웃: 훈련상태·메시지 1행 나열(`:` 구분), LAST/RIDE 세로 스택 + 경과일 32px, eyebrow `var(--orange)`, 상태 라벨 `#82c91e`(라이트)/`var(--dropcap-color)`(다크).
  • [UI/UX] `templates/topbar.php` TLF·TSB 툴팁 도트 색상 팔레트 통일 적용.
  • [UI/UX] `templates/analysis-row.php` — VO2Max 아크 세그먼트·카테고리 색상·FTP diff·EF 추세 방향 색상 팔레트 통일.
v 2.4.2.0
2026.06.22

GitHub Actions 온라인 배치 수집 workflow 추가

  • [SYS] `.github/workflows/batch-collect.yml` 신규 — `workflow_dispatch`로 라이브 서버에서 Strava 배치 수집 실행. 기존 `deploy.yml` SSH 인프라(SFTP_SSH_KEY·FTP_USERNAME·FTP_SERVER) 재활용. rate_limited 15분 대기 자동 처리, 일간 한도 도달 시 Telegram 알림 후 종료(다음 날 재실행). 2014년부터 전체 히스토리 수집 지원. PHP 코드 변경 없음.
v 2.4.1.0
2026.06.22

푸시 전 보안 점검 — 어드민 에러 메시지 안전화 + ICU 스트림 에러 로깅

  • [SYS] fix: `02-admin-page.php` — OAuth 실패 시 API 응답 전체 노출 제거. 민감 정보를 PHP 에러 로그로 이동, 화면에는 안전한 메시지만 표시.
  • [SYS] fix: `04b-intervals-api.php` — `icu_fetch_activity_streams()` 비정상 HTTP 응답(non-200) 시 `error_log` 추가. 422(STRAVA source 정상 케이스)는 기존 동작 유지.
v 2.4.0.0
2026.06.22

RON UI 전면 리뉴얼 — 다크모드 통합 + 탈오렌지 팔레트 + Walk 강도 차트 + RIDE OR NOT v3.0

  • [UI/UX] `assets/frontend-style.css` — `.ct-dark` 셀렉터 전량 `body.dark-theme` 교체 완료. 기술 부채 해소.
  • [UI/UX] `assets/frontend-style.css` — RON 다크모드 전체 박스 통합. Topbar 4박스(`.strava-top-card`), 캘린더, 월 스트립, 분석 박스 전부 `body.dark-theme` 대응. TSS 뱃지·TSB 폼로우·VO2MAX 수치·EF 수치·Power Analysis 등 세부 요소 다크 처리.
  • [UI/UX] `assets/frontend-style.css` — BOX1 구분선 `--stbc-div` 변수 통합. `.stbc-top`, `.stbc-left`, `.stbc-year-block`(기존 누락), `.stbc-bottom`, `.stbc-stat--mid::before/::after` 전부 단일 변수 구동. 라이트 `rgba(0,0,0,0.10)` / 다크 `rgba(255,255,255,0.22)`.
  • [UI/UX] `assets/frontend-style.css` — 라이트모드 탈스트라바 팔레트 전면 교체. `--orange: #ff8787` (코랄), 스파크·THIS MONTH `#1864ab` (네이비 블루), 달력 라이딩 셀 `#82c91e` (라임), 오늘 셀 `#fa5252`, 월 네비 활성 `#356d00` (다크 그린), CARD 토글 `#fa5252`. 하드코딩 `#FC4C02` 잔존 0개.
  • [UI/UX] `assets/frontend-style.css` — BOX1·BOX3/4 등 각종 다크모드 미처리 텍스트 수정. `.strd-title`, `.strd-zone-name`, `.strd-tsb-name`, `.cal-heading`, 존별 % 색상(`:has()` 선택자), TSB CTL/ATL 레이블 색상 등.
  • [UI/UX] `templates/topbar.php` — BOX2 RIDE OR NOT v3.0 리뉴얼. 타이틀 Rockstar Extra Bold 48px 확대. Strava 로고 제거. `version 3.0` 풀네임을 달력 하단 우측에 Rockstar Extra Bold · `#5c940d` 배치.
  • [UI/UX] `includes/05-page-builder.php` + `assets/frontend-style.css` — Walk 박스 재구성. Quick Metrics 섹션 삭제. 연간누적 구분선 오른쪽 이동. 우측 영역에 일별 Walk 강도 차트 신규(속도 막대 높이 + HR 색상 인코딩 4존). 레전드(bpm 구간 색상표) 타이틀 행 우측 배치.
  • [UI/UX] `assets/frontend-style.css` — 다크모드 월 네비 `.is-current`/`.has-data` 라임(`#82c91e`) 별도 오버라이드. 다크 배경에서 `#356d00` 대비 보완.
  • [SYS] `includes/11-db-tables.php` — DB v2.3 스키마. `description TEXT`, `suffer_score INT` 컬럼 추가 마이그레이션.
  • [SYS] `includes/02-admin-page.php` — 관리자 Rate Limit 카드에 Read 15분·일간 카운트다운 타이머 스팬 추가.
  • [SYS] `run-batch-safe.sh` — 일간 limit 도달 시 UTC 자정까지 자동 대기 후 재개 로직 추가.
v 2.3.1.0
2026.06.21

RON 카드 UI 완성 — 피크파워·심박존 세로 바 차트 + CARD MAX/MIN 토글 + 다크모드 정비

  • [UI/UX] `templates/card.php` — 피크파워 가로 바를 **세로 바 차트**로 전환. 심박존 5존 세로 바 추가. 두 차트를 동일 섹션에 세로 스택(피크파워 상단, 심박존 하단). 6열/5열 `repeat(N, 1fr)` 그리드로 카드 전폭 활용. 바 위에 수치(W / %), 아래에 레이블. 바 색상 Coggan 7존/Friel 5존 연동.
  • [UI/UX] `templates/card.php` — sc-row에 `--r1` / `--r2` / `--r3` 식별 클래스 추가 (CARD MIN 접기 기준).
  • [UI/UX] `templates/topbar.php` — DESC 토글 레이블 `DESC` → `CARD`, title 텍스트 수정.
  • [SYS] `assets/frontend-script.js` — DESC 토글 리팩터. localStorage 키 `strava_card_min`, body 클래스 `strava-card-min`으로 변경. 기존 `strava-desc-hidden` → `strava-card-min`.
  • [UI/UX] `assets/frontend-style.css` — 토글 상태 텍스트 `ON`/`OFF` → `MAX`/`MIN`. CARD MIN 숨김 대상 변경: 기존 `.card-description` → `.card-analysis` + `.card-stream-unavailable` + `.sc-row--r1` + `.sc-row--r2`. MIN 결과: 헤더 + 하단 3셀(NP/칼로리/회복시간)만 잔존.
  • [UI/UX] `assets/frontend-style.css` — 세로 바 차트 CSS 신규 (`.cvb-chart`, `.cvb-col`, `.cvb-bar-area`, `.cvb-bar`, `.cvb-val`, `.cvb-lbl`). 다크모드 대응 포함.
  • [UI/UX] `assets/frontend-style.css` — 라이드 타입 뱃지 색상 Road→라임, Virtual→바이올렛으로 단순화 (2종만 유지). 나머지 타입 기본 폴백.
  • [CORE] fix: 피크파워 `czb-header--peak` 컬러 오렌지 → 레드(#fa5252). 거리 숫자 `var(--orange)` → `var(--text)`.
  • [UI/UX] fix: 카드 전체 `body.dark-theme` 다크모드 대응. `.strava-card` 배경, 타입 뱃지, 고통지수·훈련강도 배지, 분석 섹션 전부 반응. `.sc-cell` 다크모드 배경 transparent 처리.
  • [CORE] fix: `body.dark-theme` 변수 오버라이드 — `--text` / `--gray-1~4` 재정의로 카드 측정값 텍스트 다크모드 반응. 기존 `.ct-dark` 셀렉터(무효) 대체 시작.
v 2.3.0.0
2026.06.21

RON 카드 리뉴얼 + 탈 스트라바 Phase 1·2 — 라이덕 대체 분석 + Walk 바 + ICU 엔진 안정화

  • [SYS] `04b-intervals-api.php` — `icu_is_duplicate()` 보완. strava_id NULL일 때 `start_date_local + moving_time + sport_type` 조합 fallback 추가로 MyWoosh 등 중복 감지 강화. `icu_sync_month()` 호출 시 정규화 객체 전달하도록 수정.
  • [SYS] `12-analysis.php` — 신규 분석 함수 3개 추가. `strava_calc_power_zones($id, $ftp)` Coggan 7존 초당 분포(%, 초), `strava_calc_hr_zones($id, $max_hr)` Friel 5존 분포, `strava_calc_anaerobic_kj($id, $ftp)` 무산소 운동량(kJ) + 지속시간. 피크파워 구간 5→6개로 확장(15s/1m/2m/5m/10m/20m, 라이덕 동일). 전 함수 6h transient 캐싱.
  • [UI/UX] `templates/card.php` 전면 리뉴얼. 라이덕 description 텍스트 영역 제거 → 파워존 7색 바 + 무산소(지속시간/kJ) + 피크파워 6구간으로 교체. 헤더 도전과제 제거 → 해골 SVG + 고통지수 배지 + IF 기반 훈련강도 레이블(6단계) 추가. 하단 셀 고통지수 → 회복시간(TSS×0.3h)으로 교체. 셀 헤더 컬러 1안 적용(아이콘+라벨 텍스트 컬러 구분: 파워·인디고, 심박·레드, 틸·케이던스, 올리브·고도, 슬레이트·시간, 시안·속도, 오렌지·칼로리, 바이올렛·회복).
  • [UI/UX] `05-page-builder.php` — Walk 타입 카드 그리드에서 제외. Walk 월간/연간 통계 확장(횟수·시간·평균HR·TSS 추가). Walk 와이드 바 신규 추가(topbar 하단, 분석행 상단): 좌측 Walk 집계 5항목 + 연간누적, 우측 Quick Metrics(FTP 설정·W/kg·이번달 IF평균·4주 EF). 월간 평균 IF, EF 4주 계산 추가.
  • [UI/UX] `assets/frontend-style.css` — 카드 분석 섹션 스타일 신규(파워존 바·피크파워 그리드·무산소 라인·stream-unavailable). Walk 바 스타일 신규. 고통지수·훈련강도 배지 스타일. 셀 헤더 컬러 1안 CSS.
  • [UI/UX] fix: `assets/frontend-style.css` — `body.dark-theme { --text / --gray-* }` 변수 오버라이드 추가. 기존 `:root`의 `--text: #1a1a1a`가 다크모드에서 재정의되지 않아 sc-val 등 측정값 텍스트가 검정으로 고정되던 문제 해결.
  • [CORE] fix: DB — MyWoosh 2026-06-01 ICU 중복 활동(`i153059358`) 삭제. Strava 엔진 수집본(`18736807109`)만 유지(description 보존).
  • [UI/UX] `frontend-style.css` 내 `.ct-dark` 셀렉터 20개가 실제 다크모드 클래스(`body.dark-theme`)와 불일치하여 전부 무효 상태. 추후 일괄 교체 필요.
v 2.2.2.0
2026.06.17

Strava 배치 수집 Rate Limit 버그 수정 — Read 버킷 감지 + 안전 배치 추가

  • [SYS] `16-batch-collector-safe.php` 신규 (Codex 작성) — `X-ReadRateLimit-*` (read/non-upload 전용, 100/15분·1000/일) 까지 추적. overall과 read 중 더 빡빡한 버킷 기준으로 중단 판단. 실패 월을 성공 처리하지 않음 (`$processed++` 실제 성공 시만). WP-CLI `wp strava batch-collect-safe` 등록.
  • [SYS] `00-rate-limit.php` — `X-ReadRateLimit-Limit/Usage` 헤더 파싱 추가. `read_limit_15m/day`, `read_used_15m/day` 필드 저장. 429 무헤더 fallback 시 read 15분 사용량도 강제 소진 처리.
  • [SYS] `02-admin-page.php` — Rate Limit 상태 카드에 Overall / Read 두 그룹 게이지 추가. 기존 overall 2000/일뿐 아니라 read 1000/일 소진 여부까지 표시.
  • [SYS] `14-batch-collector.php` — 월 처리 후 rate limit 사후 재확인 추가. 429 무헤더 시 `used_15m = limit_15m` 강제 마킹.
  • [SYS] `03-oauth.php` — `strava_get_access_token()` 토큰 캐싱 추가. 만료 5분 전까지 저장된 토큰 재사용 → 배치 중 매번 `/oauth/token` POST 호출하던 구조 해소 (OAuth rate limit 원인). `expires_at` 저장.
  • [SYS] fix: Strava API Base URL `www.api-v3.strava.com` → `www.strava.com/api/v3` 복원 — DNS 미등록 도메인으로 전체 API 호출이 묵음 실패하던 버그 수정 (00/04/05 파일).
  • [SYS] `doc/batch-rate-limit-bug.md` 신규 — 배치 Rate Limit 버그 원인 분석 요청 문서. 코덱스 분석 결과 문서 `doc/2026-06-17-batch-safe-patch.md` 추가.
v 2.2.1.0
2026.06.17

DB v2.1 — 전체 API 응답 raw_json 보존 + 스트림 11종 수집

  • [SYS] `11-db-tables.php` — DB 스키마 v2.0 → v2.1. `wp_strava_activities`에 `raw_json MEDIUMTEXT` 추가 (Strava/ICU/Manual 전체 API 응답 JSON 보존). `wp_strava_streams`에 7종 추가: `stream_latlng`, `stream_altitude`, `stream_velocity`, `stream_distance`, `stream_grade`, `stream_temp`, `stream_moving`. MySQL 호환 마이그레이션 (`ADD COLUMN IF NOT EXISTS` → INFORMATION_SCHEMA 체크 방식).
  • [SYS] `04-api-functions.php` — 스트림 keys 확장: `time,watts,heartrate,cadence` → `+latlng,altitude,velocity_smooth,distance,grade_smooth,temp,moving`.
  • [SYS] `05-page-builder.php` — Strava 상세 API 병합 데이터를 `raw_json`으로 보존.
  • [SYS] `04b-intervals-api.php` — ICU 스트림 types 확장. 정규화 전 원본 ICU 응답 `raw_json` 저장.
  • [SYS] `15-manual-upload.php` — 파싱 결과 + 파일명/시각/포맷을 `raw_json`으로 저장.
v 2.2.0.0
2026.06.17

Strava → Intervals.icu 마이그레이션 완료 — Phase 6 통합 제어판

  • [SYS] `11-db-tables.php` — `strava_get_source_stats()` 추가. SOURCE별(STRAVA/INTERVALS_ICU/MANUAL) 활동 건수·스트림 커버리지·기간 집계 반환.
  • [SYS] `02-admin-page.php` — Phase 6 엔진 현황 대시보드 패널 추가. 활성 엔진 배지, Strava 멤버십 잔여일(설정 가능), 마지막 동기화 시각, 소스별 통계 테이블 표시.
  • [SYS] Strava → Intervals.icu 마이그레이션 Phase 0~6 전체 완료. DB v2.0, 듀얼 엔진(Strava/ICU), TCX/GPX 수동 업로드, 배치 수집, 통합 제어판까지 구현.
v 2.1.9.0
2026.06.17

Strava → Intervals.icu 마이그레이션 Phase 3 — 전체 히스토리 배치 수집

  • [SYS] `14-batch-collector.php` 신규 추가 — `strava_batch_collect($start_year, $end_year, $max_months)`. Rate limit 감지(15분 잔여<30 또는 일 잔여<50 시 자동 중단), `strava_batch_progress` WP 옵션에 재개 지점 저장.
  • [SYS] WP-CLI `wp strava batch-collect [--start-year=2019] [--reset]` 커맨드 등록 — 무제한 수집, 타임아웃 없음.
  • [SYS] `02-admin-page.php` — 배치 수집 패널 추가. 1회 클릭 = 5개월 처리, 시작 연도 설정, 진행 상태 표시, WP-CLI 명령어 안내.
  • [SYS] `strava_personal.php` — `14-batch-collector.php` 로더 등록.
v 2.1.8.0
2026.06.17

Strava → Intervals.icu 마이그레이션 Phase 2 — 렌더링 DB 기반 전환

  • [SYS] `11-db-tables.php` — `strava_get_activities_from_db($year, $month)` 신규 추가. DB 행을 API 응답과 동일한 필드명으로 정규화 반환 (`distance`: km → m 복원으로 기존 `/1000` 계산 호환).
  • [SYS] `05-page-builder.php` — `strava_sync_month_from_api($year, $month)` 신규 추가 (Strava API→DB 동기화 전담). `strava_update_monthly_page()`에서 API 호출 전면 제거 — `strava_get_activities_from_db()` 기반 완전 DB 렌더링으로 전환. Walk 활동도 DB 저장 대상에 포함.
  • [SYS] `06-cron.php` — `strava_run_sync_as_admin()`이 `strava_sync_month_from_api()` 후 `strava_update_monthly_page()` 순서로 분리 호출. sync↔render 역할 분리 완성.
v 2.1.7.0
2026.06.17

Strava → Intervals.icu 마이그레이션 Phase 1 — DB 스키마 v2.0 적용

  • [SYS] `11-db-tables.php` — DB 스키마 v1.1 → v2.0 업그레이드. `activity_id` BIGINT → VARCHAR(32) (activities + streams 양쪽), `source_type VARCHAR(20) DEFAULT 'STRAVA'` 컬럼 추가, `strava_id BIGINT NULL` 컬럼 추가 (중복 감지용). v1.1 테이블 대상 ALTER TABLE 마이그레이션 블록 내장.
  • [SYS] `11-db-tables.php` — `strava_save_activity_meta()`, `strava_save_activity_streams()`: `intval($id)` → `(string)$id` 전환, format 배열 `%d` → `%s` (activity_id 위치).
  • [SYS] `12-analysis.php` — `strava_calc_mmp()` L29: `WHERE activity_id = %d` → `%s` 전환. Intervals.icu ID(`i154719518`) 수용으로 위험도 R1(쿼리 파괴) 해소.
v 2.1.6.0
2026.06.17

Intervals.icu 마이그레이션 Phase 0 검증 완료 + 연구 문서화

  • [SYS] Strava → Intervals.icu 듀얼 엔진 마이그레이션 사전 조사 완료. 실제 API 호출 기반 검증 #1~#6 전체 통과. 페이지네이션 방식, 파워 수치 신뢰성, 스트림 타입, rate limit, STRAVA source 스트림 차단 동작(422) 확인.
  • [SYS] `doc/strava-intervals-migration.md` 신규 작성 — 배경, API 실증 결과, 필드 비교, 위험도 평가(R1~R9), 듀얼 엔진 아키텍처, Phase 0~6 플랜 포함.
  • [SYS] Phase 0 검증 스크립트 6종 추가 (`strava-personal/verify_01~04_05_06.py`, `check_intervals_*.py`).
  • [SYS] Strava API Base URL 변경 (`www.strava.com/api/v3` → `www.api-v3.strava.com`) — 6개 파일 커밋 `aa0ef7c`. DNS 미해결로 라이브 미푸시 상태. 2027-06-01 이전까지 DNS 전파 예상.
v 2.1.5.4
2026.06.07

now-timeline 본문 정렬 — 좌/우 교차 정렬을 양끝 정렬로 통일

  • [UI/UX] now-timeline 항목별 본문(`.now-text-box`) 정렬 방식을 타임라인 좌/우 위치에 따라 `text-align: right`/`left`로 교차 적용하던 기존 방식에서, 양쪽 모두 `text-align: justify`(양끝 정렬)로 통일 (`now-timeline.css:748, 752`). 문단이 더 정돈되어 보이도록 사용자 요청으로 변경, 적용 후 만족하여 확정.
v 2.1.5.2
2026.06.07

LocalWP 의도치 않은 코어 7.0 자동업데이트 사고 분석 및 차단 상수 추가

  • [SYS] **사고 개요** — 2026.06.02 19:05 `3rdvault-devtools/sync-3rdvault.sh` 동기화 직후, 분명히 꺼두었던 LocalWP 사이트가 자동으로 6.x → 7.0 메이저 업데이트됨. `wp-includes/version.php` 수정시각이 동기화 6단계(캐시/퍼머링크 초기화) 완료 시각(19:05:52)으로부터 단 63초 후인 19:06:55로 확인 — 동기화 직후 페이지 로드로 깨어난 WP-Cron(`wp_version_check` → `wp_maybe_auto_update`)이 즉시 메이저 코어 업데이트를 적용한 것으로 결론.
  • [SYS] **근본 원인** — ① 라이브 사이트 `wp_options`에는 `auto_update_core_major/minor/dev = enabled`가 저장돼 있음(최근 두 차례 DB 백업 모두 확인). ② 그러나 라이브는 `wp-config.php`의 `define('WP_AUTO_UPDATE_CORE', 'minor')` 상수가 DB 옵션값보다 우선 적용되어 메이저 업데이트가 차단된 상태로 6.x를 유지 — 즉 라이브가 안전한 이유는 DB 옵션이 아니라 이 상수 덕분. ③ 로컬에는 이 보호 상수가 없었고, 사용자가 지난 롤백 사고 이후 UI로 꺼둔 자동업데이트 설정은 로컬 `wp_options`에만 저장되어 있었음. ④ `sync-3rdvault.sh` 4단계(`wp db import`)가 라이브 DB 덤프를 통째로 임포트하면서 로컬 `wp_options`이 라이브 값(`enabled`)으로 전부 덮어써짐 — 사용자가 꺼둔 설정이 매 동기화마다 리셋되는 구조였던 것. 결과적으로 "켜진 옵션 + 차단 상수 부재" 상태가 되어 cron이 즉시 업데이트를 실행.
  • [UI/UX] fix: 로컬 `wp-config.php`에 `define('WP_AUTO_UPDATE_CORE', false);` 추가 (wp-config.php:97 직후) — 이 상수는 DB 옵션값보다 항상 우선 적용되므로, 이후 DB 동기화로 `wp_options`이 어떤 값으로 덮어써지더라도 코드 레벨에서 전체 자동업데이트(메이저/마이너/개발판)가 영구 차단됨. UI 토글에 의존하던 기존 방식의 구조적 결함을 해소.
  • [AI] fix: 7.0 → 6.9.4 코어 다운그레이드 진행 — WP-CLI 정석 절차(`wp maintenance-mode activate` → `wp db export` 사전 백업 → `wp core update --version=6.9.4 --force` → `wp core verify-checksums` → `wp cache flush` / `wp rewrite flush` → `wp maintenance-mode deactivate`)로 처리. 다운그레이드 후 `wp core version --extra` 결과 `6.9.4 / db revision 60717`로 라이브 사이트와 일치 확인, `verify-checksums` 무결성 검증 통과. 다운그레이드 직전 DB 스냅샷은 `~/Desktop/before_downgrade_20260607_152330.sql`에 보관.
v 2.1.5.3
2026.06.07

now-timeline 관리자 패널 미디어 버튼 — 코어 CSS 의존 비표준 코드 제거

  • [UI/UX] fix: 7.0 임시 적용 중 now-timeline 관리자 패널의 "이미지 선택"/"갤러리 추가" 버튼 레이아웃이 깨지는 현상 발견 → 6.9.4 롤백 후에도 아이콘·텍스트 정렬이 미세하게 어긋나는 것을 확인. 원인은 `inc/now-timeline.php`의 아이콘 `<span>`에 인라인 `vertical-align:middle`이 들어있었는데, 부모 `.vault-media-btn`이 `display:flex`라 **flex 자식에는 vertical-align이 전혀 적용되지 않는 죽은 코드**였던 것 — 코어 `.button`/`.dashicons` 의 우연한 메트릭 정합에 기대어 맞춰져 있던 취약한 구조.
  • [UI/UX] fix: 근본적으로 정리하기 위해 두 버튼을 아이콘+커스텀 flex 정렬 방식에서 **워드프레스 코어 `.button` 클래스만 사용하는 순수 텍스트 버튼**으로 교체 (`inc/now-timeline.php`). dashicons span과 인라인 스타일을 모두 제거하고 `now-timeline.css`의 `.vault-media-btn`/아이콘 크기 규칙도 삭제 — 아이콘 정렬이라는 문제 영역 자체를 없애 코어 CSS가 어떻게 바뀌어도 깨지지 않는 구조로 변경. JS 핸들러는 `#vault_upload_btn`/`#vault_gallery_add` ID 기반이라 기능 변화 없음.
v 2.1.5.1
2026.06.05

뉴스룸 자동화 아키텍처 전환 — GitHub Actions + Gemini → Cowork + Claude

  • [SYS] 뉴스룸 스크립트를 `Newsroom/` 디렉토리에서 독립 레포(`github.com/coolwarp/newsroom`)로 분리
  • [SYS] 기존 구조(GitHub Actions 크론 → curator2.py Gemini 큐레이션 → WP 발행)에서 Cowork 스케줄 기반으로 전환 — RSS 수집(`rss_collector.py`)과 WP 발행(`wp_poster.py`)은 cowork-terminal-mcp를 통해 호스트 Mac에서 직접 실행, 큐레이션은 Cowork 네이티브 Claude AI가 담당
  • [SYS] Azure IP 기반 GitHub Actions 환경에서 발생하던 LiteSpeed rate limit(429) 문제가 로컬 Mac 직접 실행으로 구조적 해소
v 2.1.5.0
2026.06.03

뉴스룸 GitHub Actions 크론 피크 타임 회피 및 403 재시도 로직 추가

  • [SYS] daily_report.yml 크론 `0 22` → `7 22` (UTC) 변경 — GitHub Actions 정각 피크 타임 혼잡으로 Cloudflare/LiteSpeed가 공유 IP 일시 차단하던 문제 회피
  • [SYS] rerun_newsroom.yml 크론 `0 0` → `17 0` (UTC) 변경 — 동일 피크 타임 회피, 메인 실행 후 약 70분 간격 유지
  • [SYS] curator2.py `_wp_request()` — 403 응답 시 120초 대기 후 최대 2회 재시도 추가 (일시적 IP 차단 대비 벨트-멜빵)
v 2.1.4.9
2026.06.02

notice 티커 활성 시 Article 드롭다운 클릭 불가 버그 수정

  • [UI/UX] fix: notice-ticker.css — `.vault-notice-ticker` 및 자식 요소 전체에 `pointer-events: none` 적용, `.vault-ticker-link`만 `auto` 복원 (ticker가 마우스 이벤트를 가로채 dropdown hover를 끊던 문제 해결)
v 2.1.4.8
2026.05.25

Strava 동기화 로그 기능 추가 및 Hostinger 크론잡 시각 수정

  • [SYS] Hostinger 서버 크론잡 시각 수정 — `0 4`/`0 7` (UTC) → `5 5`/`15 5` (UTC)로 교체 (v2.1.4.7 WP cron UTC 05:00 변경 후 `0 4` 트리거가 예정 시각보다 이전이어서 자동 동기화 미실행되던 문제 해결)
  • [SYS] strava_log_sync() 함수 추가 — 자동/수동 동기화 실행 시 wp_options에 최근 10개 로그 저장 (06-cron.php)
  • [UI/UX] BOX05에 최근 동기화 로그 2개 표시 — 자동(초록)/수동(파랑) 뱃지 + 실행 시각 (02-admin-page.php)
  • [UI/UX] 동기화 로그 표시용 CSS 추가 (assets/admin-style.css)
v 2.1.4.7
2026.05.21

Strava 자동 동기화 시각 수정 및 타임존 정확도 개선

  • [SYS] strava-personal 자동 동기화 시각 03:00 → 14:00 (한국시 오후 2시)로 변경
  • [SYS] 백필 스트림 스케줄 13:10 → 14:10으로 변경
  • [CORE] fix: 크론 등록 시 strtotime() 대신 wp_timezone() 기준 DateTime 사용 — 서버 타임존 불일치 문제 해결
  • [CORE] fix: 관리자 페이지 시각 표시 date() → wp_date() 교체 — 다음 실행 시각이 WP 사이트 타임존 기준으로 정확히 표시됨
  • [UI/UX] BOX04 자동 동기화 레이블 하드코딩 제거 — wp_next_scheduled() 실제 시각을 동적으로 표시
v 2.1.4.6
2026.05.21

seen_links 자동 커밋 제거 — GitHub Actions Cache로 일원화

  • [SYS] daily_report.yml, rerun_newsroom.yml의 'Commit seen_links.json' git 커밋 스텝 삭제
  • [SYS] .gitignore에 Newsroom/seen_links.json 추가, git 추적 해제
  • [SYS] seen_links.json은 이미 actions/cache로 영속 보관 중이었으나 git 커밋 스텝이 중복으로 남아 main 브랜치에 매일 자동 커밋을 생성하던 문제 해결 — 로컬 push 시 diverge 반복 발생의 원인이었음
v 2.1.4.5
2026.05.21

Now 타임라인 관리자 에디터 전면 개선 (now_v3)

  • [UI/UX] 에디터 폼 레이아웃 전면 개편 — 날짜·내용·미디어·캡션·YouTube 필드 구조화, 실시간 미리보기 패널(550px) 추가 (inc/now-timeline.php)
  • [UI/UX] 미리보기 패널 정렬 토글(좌/우) 추가 — 홀수/짝수 항목 레이아웃 사전 확인 가능
  • [UI/UX] 에디터 리스트 월별 탭 필터 추가 — 진입 시 최신 월 자동 활성, 탭 클릭으로 즉시 JS 필터링(리로드 없음), 각 탭에 항목 수 배지 표시
  • [UI/UX] 리스트 상단 검색창 추가 — 탭 무시하고 전체 날짜+내용 실시간 검색, N건 카운트 표시
  • [CORE] fix: 월별 네비게이션 첫 진입 시 최신 월 active 표시 누락 버그 수정
v 2.0.4.4
2026.05.19

newsroom 리다이렉트 Cloudflare 캐싱 버그 수정

  • [SYS] /newsroom/ 302 리다이렉트 전 Cache-Control no-store 헤더 추가 — Cloudflare가 리다이렉트 응답을 캐싱해 발행 후 ~1시간 동안 전날 포스트가 표시되던 문제 수정 (functions.php)
v 2.0.4.3
2026.05.19

release-tracker 게이지 마커 디자인 개선

  • [UI/UX] v2.0·v3.0 endpoint 마커 — 라벨+세로 라인+도트 구조로 바 위쪽에 표시
  • [UI/UX] current/filled 마커 — 바 아래 버전 라벨 제거, 도트만 표시 (STATUS 영역과 중복 제거)
  • [UI/UX] .vrt-gauge-wrapper 상단 마진 2.5rem → 3.5rem (라벨 공간 확보)
v 2.0.4.2
2026.05.18

changelog-v1.html v1.0·v1.1 섹션 — git 히스토리 기반 엔트리 복원

  • [SYS] changelog-v1.html v1.0 섹션 "0 entries" 플레이스홀더 → 9개 엔트리로 교체 (2026-03-01 ~ 2026-03-10)
  • [SYS] changelog-v1.html v1.1 섹션 "0 entries" 플레이스홀더 → 2개 엔트리로 교체 (2026-03-11 ~ 2026-03-12)
  • [SYS] 3rdvault_v1.0 아카이브 저장소 git 히스토리 분석으로 복원 — 자식 테마 초기 구축부터 라이트박스·뉴스룸 첫 구현까지
v 2.0.4.1
2026.05.18

changelog v1.x 페이지 다크모드 적용 — 전역 변수 체계 준수

  • [UI/UX] changelog-v1.css 자체 변수 시스템 제거, 전역 변수(--bg-main, --bg-panel, --text-main 등) 직접 참조로 전환
  • [UI/UX] gold 계열 색상 --link-entry / --link-hover 차용 (케이스 A, body.dark-theme 블록 없음)
  • [SYS] page-changelog-v1.php HTML style 블록 주입 롤백 — 전역 CSS 오염 제거
  • [UI/UX] changelog-v1.html dark mode 트리거 `@media prefers-color-scheme` → `body.dark-theme` 교체
v 2.0.4
2026.05.18

뉴스룸 공지 방식 리뉴얼 — PHP 자동 감지로 전환 + 검색 태그 fix

  • [SYS] notice-ticker.php에 vault_get_newsroom_notice_entry() 추가 — 오늘 YYYYmmdd_newsroom 포스트가 6시간 이내 발행됐으면 WP 포스트 생성 없이 티커 항목 자동 삽입
  • [SYS] vault_get_notice_posts()에 뉴스룸 항목 맨 앞 삽입 로직 추가 (array_unshift)
  • [SYS] curator2.py의 post_newsroom_notice() 호출 제거 및 함수 본체 deprecated 처리
  • [SYS] 로컬 DB의 기존 누적 _newsroom_notice 포스트 21개 일괄 삭제 (WP-CLI)
  • [UI/UX] 홈화면 사이드 태그 검색창 마우스 호버 액션 추가.
v 2.0.3.4
2026.05.18

mini-panel TOC 1열 수평 스크롤 + 포스트 제목 마키 스크롤

  • [UI/UX] floating-toc 항목 1열 고정 (white-space: nowrap + overflow: hidden + text-overflow: ellipsis)
  • [UI/UX] TOC 항목 호버 시 transition으로 수평 슬라이드, active 항목 4초 왕복 루프 애니메이션
  • [UI/UX] TOC 항목 초과 시 floating-toc 내부 수직 스크롤 (flex: 1 + min-height: 0 + overflow-y: auto)
  • [UI/UX] floating-title-inner max-height: calc(100vh - 220px) + flex column 전환 — to Top 버튼 겹침 방지
  • [UI/UX] f-title 포스트 제목 1열 고정 + 무한 마키 스크롤 (24s linear, 클론 복사본으로 끊김 없는 루프)
  • [SYS] measureOverflows() 패널 visible 시점 실행 — DPR 서브픽셀 오측정 방지, CSS animation 재시작으로 keyframe var 캐시 초기화
v 2.0.3.3
2026.05.18

changelog-v1 WordPress 페이지 통합 + mini-panel TOC 지원

  • [SYS] page-changelog-v1.php 커스텀 템플릿 신규 생성 — changelog-v1.html body를 WP 헤더/푸터로 래핑, 링크 PHP 동적 생성
  • [SYS] css/changelog-v1.css 분리 — '.changelog-v1-wrap' 스코프 제한으로 글로벌 충돌 차단, 다크모드 'body.dark-theme' 연동
  • [SYS] WP 페이지 /changelog/v1/ 생성 (로컬 WP-CLI + 라이브 REST API) — sitemap 자동 포함, SEO 클린 URL 확보
  • [SYS] .htaccess에 기존 테마 경로 URL → /changelog/v1/ 301 리다이렉트 추가
  • [CORE] inc/release-tracker.php "상세 →" 링크를 home_url('/changelog/v1/')로 교체
  • [UI/UX] js/mini-panel.js에 changelog-v1 분기 추가 — 'page-template-page-changelog-v1' body 클래스 감지, TOC 소스를 section.major[id] 10개로 교체
  • [SYS] mini-panel.js 버전을 filemtime 기반으로 교체 — Cloudflare 캐시 자동 무효화
v 2.0.3.1
2026.05.18

changelog-v1.html 양식 통일 & 레이아웃 1열 평탄화

  • [UI/UX] v1.x 아카이브 23개 엔트리 자동 타이틀 부여 — 04-13 이전 엔트리 양식을 04-14+와 통일
  • [UI/UX] 단일 item + sub-bullets 구조 3개 평탄화 — item을 entry-title로 승급, sub-bullets는 평면 items로 전환 (부모 태그 상속)
  • [UI/UX] .entry-items > li 레이아웃 flex → grid 전환 — sub-bullets가 다음 행 전체폭으로 자연스럽게 wrap되도록 처리
  • [UI/UX] .entry-sub grid-column: 1 / -1 적용 — 들여쓰기 + 좌측 border 유지하면서 1열 흐름 확보
  • [UI/UX] filetime 기반 트랜지언트 자동 무효화 코드 추가
v 2.0.3
2026.05.17

릴리즈 로그 입력 방식 변경 — changelog.md 단일 소스

  • [SYS] changelog.md YAML frontmatter 단일 소스 워크플로 전환 — 신규 버전 추가 시 PHP 수정 불필요
  • [CORE] vrt_parse_changelog() 재작성 — date/version/title/progress 필드 자동 파싱
  • [CORE] $vrt_versions 배열 제거, v1.x 메이저 10개는 $vrt_v1_archive 상수로 박제
  • [SYS] vrt_auto_progress() 도입 — progress 필드 미지정 시 minor*10 + patch 공식 자동 계산
  • [UI/UX] 트로피 그리드에 "상세 →" 링크 추가 — doc/changelog-v1.html 아카이브 연결 (같은 탭)
  • [UI/UX] changelog-v1.html 돌아가기 버튼 — history.back() 처리 (직접 접속 시 사이트 루트로 폴백)
  • [CORE] delete_transient 무조건 호출 버그 수정 (트랜지언트 1시간 캐시 실제 작동)
  • [UI/UX] 게이지 마커 단순화 — v2.0 시작 / 현재 / v3.0 종료 3개만 표시
  • [SYS] VRT_CURRENT_VERSION 상수 → vrt_current_version() 함수 전환 (custom-footer.php 호출 교체)
v 2.0.2.2
2026.05.16

다크모드 코어 정리 & 게임 리뷰 트로피 보정

  • [UI/UX] 다크모드 코어 CSS 정리 — 불필요한 빈줄 제거 (css/dark-mode-core.css 2,129줄 → 1,538줄)
  • [CORE] dark-mode/page-colors dark_sample.webp 경로 하드코딩 → 첨부파일 동적 조회로 변경
  • [UI/UX] 게임 리뷰 트로피 4개 교체 — 중복/빈껍데기 제거 후 신규 항목으로 대체
  • [CORE] 본문 양쪽 공백 관련 버그 수정
v 2.0.2.1
2026.05.15

다크모드 프리셋 재정비 & 릴리즈 트래커 마무리

  • [UI/UX] 다크모드 프리셋 3종 신규 추가 — Urban Nocturne, Lapis Velvet, Fireside
  • [SYS] 다크모드 프리셋 7종 폐기 — doc/deprecated-presets.md로 아카이브 이전
  • [CORE] 릴리즈 트래커 버전 키 x.x.x 표기 수정 + 게이지 마커 로직 개선
  • [SYS] v2.0-beta 브랜치 main 머지 완료 — 15개 커밋 통합 (대규모 정비 + v2.1/v2.2 준비)
  • [SYS] docs — v2.0-beta 머지 완료 체크 + changelog 버전 키 수정
v 2.0.2
2026.05.14

Strava Phase 2 — PHP 템플릿 분리

  • [SYS] strava-personal/includes/13-helpers.php 신설 — 헬퍼 함수 4개 (zone status, render zone row, calendar cell, spark bar class)
  • [SYS] strava-personal/templates/topbar.php 신설 — Topbar 4박스 (통합 스파크+스탯·캘린더·훈련부하·TSB) 240줄
  • [SYS] strava-personal/templates/analysis-row.php 신설 — BOX5 심박효율·BOX6 VO2Max·BOX7 PMC 분석 행 221줄
  • [SYS] strava-personal/templates/card.php 신설 — 활동 카드 1개 빌드 (필드 추출 + 타입 라벨 + HTML) 119줄
  • [CORE] 05-page-builder.php god function 분리 — 920줄 → 331줄 (-589, 64% 감소)
  • [CORE] HTML 동일성 검증 — 2026-04 페이지 diff 시각 동일 (Step 3·4 완전 동일)
v 2.0.1
2026.05.14

Release Tracker Milestone Transition

  • [UI/UX] 진행률 게이지 범위 전환 v1.0~v2.0 → v2.0~v3.0 (마일스톤 라벨 갱신)
  • [UI/UX] v1.x 메이저 10개 RPG 트로피 그리드 신설 (메달 이모지 + 카드 그리드, 게이지 직후 노출)
  • [UI/UX] 상세 리스트에 v2.0 Era 가로선 구분자 추가 (역순 출력에서 era 전환점 감지)
  • [SYS] 버전 era 추론 헬퍼 vrt_get_era() + 메이저 버전 글로벌 배열 $vrt_major_versions 신설
  • [CORE] vrt_calc_marker_positions() 재작성 — era v2/v3 만 게이지 마커로 사용
  • [UI/UX] 트로피·era 다크모드 변수 셋 신규 추가 (라이트/다크 자동 대응)
v 2.0.0
2026.05.14

Massive Restructure & Optimization

  • [CORE] Phase 1 PHP 보안 정비 — Strava SQL Injection 8건 wpdb prepare, 02-admin-page nonce 통합 (8개 폼), 03-oauth 응답 3중 가드
  • [CORE] CRITICAL — inc/release-tracker.php 배열 키 중복 v1.9.1.1 해소 (v1.9.1.0 분리, 데이터 손실 방지)
  • [SYS] dark-mode/ajax-handler darkmode_verify_request 헬퍼 통일, 06-cron 백필 13:10 변경
  • [UI/UX] inc/custom-header get_category_by_slug 5건 nullsafe 연산자 적용 (PHP 8.4 안전성)
  • [UI/UX] Phase 2 다크모드 자기참조 변수 수정 (css/dark-mode-core.css --theme-text-color → --text-main)
  • [SYS] Phase 3.5 doc/ 폴더 신설 — 흩어진 .md 10개 git mv 통합, CLAUDE.md 참조 경로 갱신
  • [SYS] Phase 4 old_things/ 폴더 신설 — 레거시 24개 (구버전 PHP/CSS, .bak, 데드 JS 3개, 일회용 스크립트) git mv 통합
  • [SYS] Phase 5 Claude 메타 헤더 일괄 삽입 (60 파일, 이중 레이어 주석) — PHP 35 + CSS 17 + JS 8