---
title: 작업보고 — 근력 리포트 재개편 v0.1 구현 (신호3종·온보딩·태깅스키마·뷰M3교정)
category: workreport
document_type: 작업보고
source_status: published
knowledge_group: 03_history
priority: Normal
purpose: 근력 리포트 v0.1 전체 구현 기록 — DB 마이그레이션·신호 엔진·온보딩·Codex 검수 7라운드
read_when: 근력 리포트·strength 계산엔진·태깅 스키마 관련 작업 시
updated: 2026-06-13
work_timestamp: 20260613_013309
source_of_truth: dallog-tools
---

# 작업보고 — 근력 리포트 재개편 v0.1 구현

> 명세서: `docs/go_work/260612/dallog_strength_spec_b_260612.md`(기능) + `dallog_strength_design_spec_260612.md`(디자인).
> 브랜치: `feat/brief-viewer-260612` · 커밋 `22c2485` · 빌드 그린(npm run build ✓, TS에러 0).

## 1. 한 줄 요약
근력 리포트를 "추정 신호 3종 + 온보딩 프로필 + 종목 태깅 스키마 + 서버뷰 버그(M3) 교정 + 계산엔진 단일화"로 v0.1 완성했다. DB 마이그레이션 3종 적용·실측 검증 완료, 프론트/워커 코드 빌드 그린, Codex 적대검수 7라운드 반영.

## 2. 무엇을 왜 했나 (비개발자 설명 병기)
- **서버뷰 버그(M3) 교정**: 근력 집계 뷰(strength_daily_summary)가 '바벨/덤벨/케이블' 같은 옛 분류를 기대해서, 실제 앱이 쓰는 '웨이트' 종목의 볼륨(운동량)이 0으로 나오던 버그를 교정. 이제 '웨이트·머신=중량×횟수', '맨몸=(체중×비율+추가중량)×횟수'로 프론트 계산과 1:1 일치.
- **태깅 스키마**: 종목마다 '어떤 관절·부위·움직임 패턴인지' 13개 속성을 붙일 수 있게 DB 컬럼을 확장하고, 기본 38종목에 분류값을 채움(백필). 값 오염을 막는 검증 제약(CHECK) 8종 동봉.
- **추정 신호 3종**: 기록만으로 ①관절 부하 ②회복 여유 ③움직임 균형을 추정해 '신호등(초록/노랑/빨강/회색)'으로 보여줌. 생체측정이 아니라 '추정'임을 항상 고지. 데이터가 부족(14일 미만·기록 공백)하면 회색('데이터 쌓는 중').
- **온보딩 프로필**: 6문항 선택 + 자유기재(선택). 자유기재가 있을 때만 AI(OpenAI)가 정리하고, 없으면 규칙으로 처리해 비용 0. 사용자가 확인·수정 후 저장(버전 이력 보관).
- **계산엔진 단일화**: 볼륨 공식이 3곳(기록입력·요약·종합브리프)에 복붙돼 있던 것을 한 모듈(computeStrength.ts)로 합쳐 어긋날 위험 제거. 기존 화면 출력은 숫자 그대로(회귀 0).

## 3. 산출물 (구현 파일)
**DB 마이그레이션(migrations/, MCP로 적용·검증 완료)**
- `2026-06-13_strength_v01_schema.sql` — exercise_configs 13컬럼+CHECK 8종 + user_training_profiles(부분unique·RLS 4정책·save_training_profile RPC, advisory lock)
- `2026-06-13_strength_v01_backfill_38.sql` — 38종목 태깅 백필(source='built_in'·tagging_status='confirmed' 명시)
- `2026-06-13_strength_v01_view_fix.sql` — strength_daily_summary M3 교정(security_invoker=true 보존, 6컬럼 시그니처 불변)
- 골든셋 `docs/sql/golden_set/260529_기록스키마_필수보존.sql` §12 뷰 동기 갱신

**프론트(신규)**
- `src/lib/strength/computeStrength.ts` — canonical 계산(setVolume·aggregateStrength·computeSignals·computeRunningWeekly·effective/derivePolicy·5톤)
- `src/lib/strength/trainingProfile.ts` — active 조회·RPC 저장·AI정규화·규칙매핑·정규화 캡
- `src/hooks/useTrainingProfileGate.ts` — 온보딩 게이트(fail-open)
- `src/pages/OnboardingProfile.tsx` · `src/pages/StrengthReport.tsx`
- `src/components/strength/UnclassifiedBadge.tsx` · `StrengthTagEditor.tsx`
- `src/styles/strength.css`

**프론트(수정·회귀0)**
- `src/lib/brief/computeBrief.ts` · `src/components/SummaryBrief.tsx` · `src/pages/LogEntry.tsx` — setVolume canonical 위임
- `src/components/dashboard/StrengthSection.tsx` — 상세리포트 링크 + 미분류 배지
- `src/pages/Settings.tsx` — 수동 태깅 통합 + INSERT source='built_in'
- `src/lib/coachChat/settingsTools.ts` — 코치AI INSERT source='ai_import'
- `src/App.tsx` — 온보딩 게이트·라우트(/strength-report, /onboarding/profile)
- `workers/brief-proxy/index.js` — /onboarding-profile-normalize 라우트(OpenAI gpt-4o-mini, JSON강제·500자캡·화이트리스트)

## 4. 실행한 SQL / 검증
- migration1·2·3 MCP `apply_migration` 적용 성공.
- STEP0(백필 전 38종 이름 일치): 0행 ✓.
- STEP3(백필 후): 미태깅 built_in 0 / isolation 모순 0 / 잘못된 traits 0행 / isolation built_in 11 / built_in confirmed 38 — 전부 기대값 일치 ✓.
- 뷰: reloptions=security_invoker=true 보존, 컬럼 6개 시그니처 불변, 볼륨>0 세션 52건(웨이트 종목 0 버그 해소) ✓.

## 5. Codex 협업 검수 결과 (§7-1)
- **사전 공유**: 명세 b·디자인명세·실DB 검증사실·구현계획을 Codex에 전달, 적대 검수 의뢰.
- **검수 차수: 1차(계획) + 구현 2~7차 = 총 7라운드.**
- **차수별 신규 기능성 지적 → 반영**:
  - 1차(계획): 4건 — 수동태깅 confirmed 승격경로·온보딩 게이트·신호 confirmed 필터·워커 분기. 전부 구현 전 반영.
  - 2차: 3건 — (3일공백 trailing 한정)·(컨펌칩 원답표시)·(캡초과 parse_status). 반영.
  - 3차: 2건 — (fallback injury_notes 누락)·(recordDays 윈도우밖 포함→거짓과부하). 반영.
  - 4차: 1건 — (미분류-only 세션이 firstRecord에 잔존). 반영.
  - 5차: 2건 — confirmed 필터를 볼륨/활동량 집계로 확대 요구. **[반려]**(§4-9 "기존 출력 동일/회귀금지" 위반 + §4-12 필터범위='신호·커버리지'). 6차에서 Codex가 [반려 인정](명세 인용 못 함).
  - 7차: 1건 — (StrengthReport 초기 fetch try/catch 누락→무한로딩) + 죽은코드 3건. 반영.
- **종료 상태**: 기능성 지적 추이 3→2→1→0(반려)→0→1 로 수렴. 8차(최종 2번째 클린 확인)는 **Codex 사용량 한도 도달로 보류**(2026-06-13 02:06 KST 이후 재개 가능). 7차 수정은 trivial·빌드그린이라 저위험.
- **미반영 사유**: 5차 2건 = 명세 §4-9 회귀금지·§4-12 범위한정과 충돌하는 잘못된 지적(6차 Codex 인정).

## 6. 남은 일 (핸드오프 참조)
1. **Codex 8차 최종 확인**(연속 2차수 클린 충족) — 사용량 한도 리셋 후 1라운드.
2. **워커 배포** — `workers/brief-proxy` 에 onboarding 라우트 추가분 `wrangler deploy` 필요(OPENAI_API_KEY 기설정·추가 시크릿 불요, 미배포 시 자유기재 AI정리만 fallback 동작).
3. **PR/머지 판단** — 사장님 확인 후. (대형 기능이라 머지는 보류, 브랜치 push 완료)

## 7. 결정·트레이드오프 노트
- "3일+ 연속 공백" 해석: 명세가 정상 휴식과 기록누락을 구분하는 정의가 모호 → 28일 윈도우의 선두·내부·trailing 연속 무기록 스캔으로 보수적 미산정(거짓 과부하 차단 의도 충실). 결과적으로 주2회 이하 저빈도는 신호3종 중 관절·회복이 회색이 될 수 있으나(움직임 균형은 즉시 집계), 이는 "데이터 없이 신호 안 냄" 철학과 일치.
- coaching_policy 회복형은 저장값이 아니라 런타임(회복 여유 빨강) 오버라이드 — 저장 톤 불변.
