이 문서는 진입점이다. 상세는 미결 항목에 있고 여기는 “다음 한 걸음”만 적는다. 어긋나면 미결 항목이 정본이다.

라벨을 확보하러 나가는 사람은 정확도 확보 단계를 본다. 이 문서는 정답 없이 할 수 있는 일의 순서이고, 그쪽은 정답이 생긴다는 전제에서 무엇을 몇 건, 어떤 조건으로 받아야 하는지다.

작성 2026.09.04 · 담당 구역 ho(정상호, agent/)


1. 무엇을 만드는가

생활체육 영상에서 선수의 자세를 재고 실력을 판단하는 에이전트다. 영상 → 프레임 샘플링 → RT-DETR로 사람 검출 → ViTPose로 키포인트 → 지표 추출 → 루브릭 채점 → LLM 리포트.

   
코드 agent/ (Python, uv, FastAPI). 소유자 정상호
이웃 fastapi/(정어진, 백엔드) · www/(백성검, Next.js) · flutter/(백성검)
실행 로컬 GPU 또는 AWS g4dn.xlarge. 절차는 agent/deploy/README.md
평가 자산 agent/eval/. 원본 데이터는 /mnt/d/supersub-phaseA/, 캐시 사본은 저장소
문서 사이트 저장소 루트가 Jekyll 소스. 규칙은 루트 CLAUDE.md

2. 작업 방식 — 반드시 지킬 것

이 프로젝트는 정답(라벨)이 거의 없는 영역에서 일한다. 아래는 그 조건에서 “고쳤다”고 잘못 말하지 않으려고 생긴 규칙이다.

   
구현 전 사전 등록 합격/불합격을 수치로 먼저 고정하고, 결과를 보고 바꾸지 않는다. 예: agent/eval/pending7_fps/PREREGISTRATION.md, pending6_side/labeling/AFTER_LABELS.md
조사와 구현의 분리 조사 회차에는 agent/src/를 고치지 않는다. 평가 스크립트는 production을 import만 하거나 규칙을 복제한다
닫힌 경로는 재조사하지 않는다 아래 4절. 이유가 남아 있으면 같은 벽에 다시 부딪히지 않는다
보존 감사 agent/eval/phaseA/PRESERVED_ASSETS.md와 phaseA/README.md의 「수정 금지」를 착수 전에 읽는다. eval_b2/eval_b2.py의 selector 가중치를 고치면 B-2~B-5 결과 전체가 무효다
push는 사람이 시킬 때만 commit은 자유, push는 지시가 있을 때만
AI 단독 판독은 정답으로 승격하지 않는다 B-3·B-4·B-5의 라벨은 전부 Claude 판독이다. 부정적 결론(“갈리지 않는다”)의 근거로는 쓰고, 정답으로는 쓰지 않는다
“정확해졌다”고 쓰지 않는다 정답이 없으면 달라진 것이지 나아진 것이 아니다
🔴 “종목을 넘어 유효하다”를 뭉뚱그리지 않는다 평가 자산 39편은 야구인데 제품은 축구다(미결 39번). 넘는 것은 대수·자료 구조의 성질(「재가중은 후보 1개 프레임의 argmax 를 못 바꾼다」)과 계기의 성질(「고정 IoU 는 구간 길이를 잰다」)뿐이다. 장면의 물리(공이 발치에 있다 · 카메라 구도 · 인원 수)와 수치로 고른 상수는 안 넘는다 — 2026.09.14 에 「야구는 공이 발치에 없다」가 0.4%(39편 중 1편) 로 측정됐다. 적을 때 어느 쪽인지 밝힌다(미결 18번의 정정 절). 🔴 2026.09.16 결정 — 앞으로의 회차는 축구 표본으로 연다(사용자 지시, 미결 39번). 야구 39편은 기록으로 남고 지우지 않는다(판독 라벨은 다시 못 받는다). 🔴 지금 축구 표본은 둘 다 반쪽이다: 1인 19편(관절·등급은 되고 선택 질문 불가) · SoccerNet 방송 100편(박스 선택은 되고 키 28px라 등급 불가). 둘 다 되는 표본이 아직 없다
야구 표본을 대조군으로 쓰는 것은 다르다 재는 대상이 도구이면 종목과 무관하다(eval/sample_gate/ 가 그 예다). 🔴 성능·등급을 야구로 말하지 않는다

왜 이 규칙이 생겼는지가 규칙보다 오래 간다. 두 사례:

  • A-1 되돌림 (미결 5번). np.gradient 오염 제거를 구현했다가 되돌렸다. 오염은 실재한다 — 제거 대상 프레임의 잔차가 자연 변동의 약 85배다. 그런데 결측이 정답 창에 몰려(축구 참조 10/10이 접촉 ±10프레임, p=0.0017) 임팩트가 84.3% 이동하는 것의 정당성을 검증할 독립 정답이 없었다. 두 문장이 다 필요하다 — “되돌렸다”만 남기면 오염이 없는 줄 알고, “오염이 있다”만 남기면 왜 안 고쳤는지 모른다.
  • target 30 전환 (미결 7번). 밴드 적중이 31.8% → 49.8%로 올랐지만 동작점을 옮긴 것이지 정확해진 것이 아니다. 다른 프레임을 고르게 됐을 뿐이고, 어느 쪽이 실제 임팩트에 가까운지는 정답이 있어야 말할 수 있다. 얻은 것은 정확도가 아니라 측정 타당성이다(15fps에서는 임팩트 프레임이 격자에 아예 없는 경우가 많아 측정이 성립하지 않았다).

3. 남은 작업 — 순서

① 미결 6번 마무리 — 스윙 측

2026.09.04 진행. 서식 결함 정리 ✅(review_packet2/) · 12건 계산 ✅(RESULTS.md). 남은 것은 27건 판독 하나이고, 그건 사람이 해야 한다 — AI가 채우면 정답으로 승격이 안 된다.

나온 값: 다리 4/11 = 36.4% [15.2%, 64.6%] · 팔은 분모 8건이라 정확도를 내지 않았다(6/8) · both 4/12 · top_hand 일치 5/12.

   
무엇을 판독이 들어온 12건으로 사전 등록 명세를 돌리고, 뺀 27건을 사유별로 분류하고, 서식 결함을 정리한다
왜 지금 라벨이 이미 도착해 있다. 물어 놓고 안 쓰는 상태가 가장 나쁘다
확정 사실 평가셋 39클립은 전부 야구 타격 = 두 손 스윙이다. 이 항목의 원래 근거 클립(투구·레이업)은 한 손 동작이라 “팔 종목에서 약한가”는 이 39건으로 답이 안 나온다. 대조표는 정규화 좌표로 이미 고쳤다(원 픽셀로 재던 것이 틀렸다)
정답 필요 불필요 — 라벨이 곧 정답이고 이미 있다
무효화 없다. GPU 불필요, 재추출 불필요
완료 조건 labeled_stats.py 결과를 신뢰구간과 함께 항목에 적는다. 유효 분모가 한 자릿수면 정확도를 내지 말고 분모만 보고한다(사전 등록 6절). both는 분자·분모 양쪽에서 뺀다

🔴 AFTER_LABELS.md를 먼저 읽는다. 계산 규칙은 라벨을 보기 전에 고정됐고 (159355f), 결과를 보고 고치면 그 순간 근거가 아니게 된다.

착수 전 확인:

wc -l agent/eval/pending6_side/labeling/review_packet/side_form.csv   # 13 = 머리줄 + 12건
cat agent/eval/pending6_side/labeling/EXCLUDED.md

② E-3 — 프레임 단위 값의 물리 시간 표기 ✅ (2026.09.04)

끝났다. 결과 봉투에 timebase(원본·실효·목표 fps, step, 분석 길이, 프레임 지표의 초 환산)를 붙였고, 화면은 「임팩트(2.07초 · 62프레임)」로 적는다. 격자를 모르는 합성 경로는 🔴 초를 지어내지 않고 known: false 를 낸다.

  • 🔴 features를 바꾸지 않았다 — 시간은 형제 블록이다. 판정 입력이 그대로라 B-6 재실행을 부르지 않는다. 미결 11번이 그렇게 적어 둔 것은 이 형태의 수정에는 해당하지 않는다(같은 항목에 근거를 적었다)
  • 새 프레임 단위 지표가 선언을 빠뜨리면 테스트가 걸린다 — test_every_frame_valued_metric_is_declared. 결함을 조용히 되살릴 수 없다
  • 테스트 161 → 169

남은 인접 결함: 정수배 아닌 소스의 격자 어긋남 · max_frames fps별 커버리지 → 쟀다(2026.09.07, 미결 9번): 30.5~44.5fps에서 가드가 창을 먹어 최악 6.74초(10초의 67%). 평가셋은 0건이라 고쳐도 B-6를 안 부른다. 지금은 timebase.limited_by로 드러내는 데까지 했고, RSS 실측은 끝났다(2026.09.08, EC2: 4K 300장 9.06GB · 기준 A ✅ B 🔴 C ✅ D ✅ · base 1.6GB · k 0.98). 남은 것은 가드를 바이트로 옮기는 별도 회차다 — 예산에서 동거 vLLM 몫을 빼는 방법을 거기서 정한다 · 🔴 루브릭 앵커의 프레임 수(다른 동작점에서 매긴 값이다 — 등급은 안 바뀌고 근거 문장만 흔들린다. 고치면 이쪽은 진짜로 B-6 재실행을 부른다).

③ 사용자 지정 분석 대상 (신규 기능)

   
무엇을 프론트가 드래그로 찍은 대상 박스를 백엔드가 받아 그 사람을 분석한다
왜 이 순서 받아 갈 곳이 아직 없다. → 🔴 줄이 이어졌다 (2026.09.09). 정어진 님이 POST /videos → 작업 행 → claim 응답까지 실었고(paik 6번, ee401d6), 워커 배선(claim → analyze_s3.py 인자)을 내가 붙였다. 화면에서 찍은 박스가 분석까지 끊기지 않고 간다
확정 사실 프론트 UI는 있고(www/.../AnalysisStage.tsx), 좌표는 이미 레터박스를 걷어낸 정규화 0~1이며, 서버로는 하나도 안 나간다
정답 필요 기능 자체는 불필요. 다만 “찍은 사람이 실제로 분석됐는가”를 확인하려면 선택 박스가 결과에 남아야 하는데 지금은 안 남는다
무효화 지정이 없을 때 결과는 비트 동일해야 한다. 그렇지 않으면 기존 평가가 전부 무효다
완료 조건 상세는 미결 18번. 에이전트 쪽은 2026.09.04에 열었고(입구·닻·결과 봉투·관측) 워커 배선까지 2026.09.09에 끝났다. 🔴 남은 것은 배선이 아니라 처방이다 — 닻은 다인 10건 전수에서 10/10 맞았는데 이어가기가 3건에서 다른 사람으로 갈아탄다(눈으로 확인). 못 고쳤고, 대신 source를 specified_uncertain으로 낮춰 안 한 일을 했다고 말하지 않게 했다. 외양 모델이 유력하다. → 🔴 재 봤고 불합격이다 (2026.09.09, eval/pending18_appearance/). 외양을 재가중으로 넣는 형태는 원리적으로 안 된다 — 점프 프레임에 겹치는 후보가 1개뿐이라(나머지는 IoU 정확히 0) 무엇을 곱해도 argmax 가 안 바뀐다. 🔴 기전도 고쳐 적었다: 「IoU 흡인원」이 아니라 「검출 구멍 → 유일한 후보로 강제 이동 → 되돌아오지 못함」이다. 외양 신호 자체는 갈린다(깨끗 0.81~0.98 대 갈아탐 0.26~0.72). 2회차로 거부·재획득을 쟀다 (eval/pending18_reacquire/) — 🔴 1/3 로 불합격이지만 되긴 된다(3R1kvNrGJK0 엉뚱 프레임 190 → 49, 커버리지 58% 유지). 나머지 둘이 0%인 것은 처방이 아니라 보정 규칙 탓이다: 깨끗한 클립을 안 깨뜨리는 K 가 41프레임이라 그보다 짧게 어긋나는 둘은 거부가 발동조차 안 했다. 🔴 진짜 병목은 정지 히스토그램의 딜레마다 — 갱신하면 갈아탄 뒤 외양을 배우고, 안 하면 옳은 트랙도 닻에서 멀어진다. 3회차로 보수적 갱신을 쟀다 (eval/pending18_conservative/) — 🔴 사전 예측대로 K 가 41 → 1 로 떨어져 2회차 진단이 확인됐고, 세 클립이 전부 좋아졌다(99%·53%·54%, 앞 회차엔 둘이 0%). 그래도 불합격이다: 53·54%가 70% 바 아래이고(C 1/3), 3R1kvNrGJK0 은 커버리지가 42%로 떨어져 D 가 걸렸다 — 엉뚱한 사람을 안 보는 대신 아무도 안 보게 된 것이라 기준이 제대로 일한 것이다. 뿌리는 보정 규칙이 하한을 고른다는 점이고(2회차 41 · 3회차 1, 같은 규칙이 양극단), 🔴 4회차에서 표본을 25건으로 늘리다 진짜 원인을 찾았다 (eval/pending18_scale/) — 갈아타는 프레임에서 대상은 사라진 것이 아니라 버려졌다. sGKeqfxwq5E f169 에서 IoU 0.76 짜리 검출이 점수 0.48 로 PERSON_ELIGIBLE_THRESHOLD=0.5 에 0.02 차이로 걸렸고, 트랙은 IoU 0.12 인 남을 골랐다. 43/5,641 프레임(0.8%)이지만 11/25 클립에서 나고, 그 한 프레임이 나머지를 다 정한다. 🔴 5회차에서 그 상류를 열었다 (eval/pending18_rescue/) — 이어가기에 한해 밴드 [0.3, 0.5) 을 구제한다(새 상수 0개, 자동 경로 비트 동일). X6dC9pu5H3k 이 엉뚱 57 → 0, 커버 손실 0 으로 네 회차 만에 첫 무상 개선이다. 🔴 그런데 진단이 절반 틀렸다: 커버리지가 무너진 넷 중 셋은 구제가 0~1회뿐이고, 잃은 173·184·196프레임 중 밴드에 되찾을 것이 각각 1·0·0개다. 갈아탐과 커버리지 붕괴는 원인이 다른 두 사건이고 후자는 대상이 후보에 있는데 거부되는 것이다. 4회차 표제 사례도 정정했다 — f169 를 실제로 되찾았는데 클립은 엉뚱 35 → 36 이었다. 🔴 6회차로 구제에 외양 문턱을 걸었다 (eval/pending18_gate/) — 재획득이 이미 요구하는 app(닻) ≥ 0.6 을 구제에도 건다(불일치 제거, 새 상수 0개). 대가가 없었다(10%p+ 후퇴 0건). 그리고 1~5회차가 한 번도 안 쓴 8건을 처음 열었더니 커버리지 붕괴가 3/8 에서 재현됐다(하나는 커버 1%) — 25건에 맞춰진 현상이 아니라 설계의 성질이다. 🔴 7회차로 커버리지 붕괴를 정면으로 쟀다 (2026.09.10, eval/pending18_coverage/) — 세 후보 중 「거부해도 자동 박스로 떨어지되 source 를 낮추기」를 골랐다. 🔴 먼저 진단을 정정했다: 뿌리는 K = 1 이 아니다. K 는 얼마나 쉽게 거부하는가를 정하고, 거부한 뒤에 무엇을 내놓는가(chosen[t] = None)는 따로다 — 커버리지를 0으로 만드는 것은 출력 형태다. 결과는 불합격이고, 그 방식이 값이다: 과녁 7건이 전부 커버 100% 로 올라왔는데(기준 C 7/7) 채운 1,731프레임 중 닻과 닮은 것이 16개(1%) 다. YNMHMKb5Md4 는 커버 1% → 100% 인데 엉뚱률이 0% → 99% — 아무도 안 보던 것을 엉뚱한 사람을 보는 것으로 바꿨을 뿐이다. ✅ 「채울 것이 없어서」가 아니다 — 잃은 프레임의 93% 에 auto[t] 가 있었다. 있는데 남이다. 🔴 사후 관찰이 두 사유를 갈랐다: 채운 프레임의 app 이 중앙 0.28(1사분 0.15), 문턱 근처(0.5~0.6)는 11% 뿐이라 「거의 맞았는데 문턱에 걸린 것」이 아니다 — 문턱을 0.5 로 낮추는 곁길도 함께 닫힌다. ✅ 기준이 이번엔 제대로 일했다 — D·F 를 짝으로 박아 C 의 7/7 을 개선으로 적지 못하게 막았다(5회차 E·6회차 D 가 연달아 저지른 결함이 안 났다). 🔴 다음 한 걸음은 한 칸 위다 — 「잃은 구간에 대상이 있기는 한가」: (가) 가림·이탈이면 커버리지 붕괴는 결함이 아니고 None 이 정직한 답이다 · (나) 있는데 못 알아보는 것이면 뿌리는 정지 히스토그램의 표류(3회차)다. 라벨 없이 가를 수 있다 — 잃은 구간의 후보 수(0개면 (가))와, 후보가 있는데 전부 app 이 낮으면 후보끼리의 app·닻 시점부터의 시간 거리를 본다. 🔴 8회차로 그 한 칸 위를 쟀고, 판정은 났는데 계기가 틀렸다 (2026.09.10, eval/pending18_presence/) — 사전 등록대로면 (가) 대상이 없다 77% 이고 자기 검사 셋(궤적 비트 동일 · 1,267프레임 전수 분류 · auto 보유율 93→99% 재현)도 다 통과했다. 🔴 그런데 사후 관찰이 잡았다: cont_iou 는 잃은 구간 내내 고정된 previous 와의 IoU라 구간이 길면 대상이 있어도 떨어진다(≤10프레임 구간 중앙 0.76 대 >40프레임 0.07, 구간 길이 중앙 38). 「없다」가 아니라 「멀어졌다」를 쟀다. 시작 3프레임만 보면 시작부터 후보가 없는 것 27% 대 있었던 것 73%로 거의 뒤집힌다 — drifted_away 8구간 중 5구간(프레임 가중 51%)이 시작 시점엔 IoU 0.74~0.98 짜리 후보를 갖고 있었다. 진짜 (가)는 3R1kvNrGJK0·YNMHMKb5Md4 둘뿐이다. ✅ 그래도 대조군은 진짜로 통과했다 — 깨끗한 프레임의 app(닻) 이 여섯 클립에서 0.62~0.88 로 전부 TAU 이상이라 외양 기술자는 추적이 깨끗할 때 작동한다. 그래서 7회차의 「채운 프레임 0.28」은 진짜로 낮고 F 불합격은 계기 탓이 아니었다. 🔴 다만 YNMHMKb5Md4 는 깨끗한 프레임이 닻 한 장뿐이라 관문이 공허하게 통과했다 — 최소 장수를 안 걸었다. 🔴 배운 것이 이 회차의 값이다: 사전 등록은 「결과를 보고 기준을 바꾸는 것」을 막지만, 계기가 재려던 것을 재는지는 막지 못한다. cont_iou 의 정의는 사전 등록에 정확히 적혀 있었고 규격대로 구현했는데도 다른 양을 쟀다 — 필요했던 것은 짝 기준이 아니라 계기 검사(길이로 층화해 보는 한 줄)였다. 🔴 (가)/(나) 갈래는 안 닫혔다. 9회차는 시작 IoU 기반으로 사전 등록을 다시 세우고, ① 대조군 관문에 최소 깨끗 장수 ② 계기 검사를 넣고, 안 쓴 표본을 확보하고 시작한다. 🔴 사후 값(27/73)을 사전으로 승격하지 않는다 — 같은 표본에서 다시 재면 순환이다. ✅ 9회차로 물음을 「왜 거부했는가」로 바꿨고 기준 다섯이 다 섰다 (2026.09.10, eval/pending18_drift/) — 거부는 app(ref, pick) < TAU 한 줄에서 일어나고 ref 는 흘러가고 닻은 고정이라, 그 프레임에서 둘을 나란히 보면 원인이 나온다. 🔴 거부 24건 중 23건에서 닻도 TAU 미만이다 — anchor_app − ref_app 이 중앙 −0.06 · 최대 +0.05 로, 닻에서 거부까지 중앙 70프레임이 걸렸는데도 두 의견이 사실상 같다. 표류 진단을 닫는다(4절). ✅ 계기가 이번엔 살았다 — 거부를 「한 프레임의 사건」으로 잡은 것이 8회차를 망친 길이 축을 없앴다(ρ −0.05 대 8회차의 0.76/0.07 갈림). 층 A(과녁 7건, 8회차에 쓴 것) 100% 와 층 B(과녁 밖 19구간 593프레임, 이 질문에 처음) 92% 가 같은 쪽이라 선택 편향도 아니다. MIN_CLEAN = 20(유일한 새 상수)이 8회차에 공허하게 통과했던 YNMHMKb5Md4(깨끗 0장)를 뺐다. 🔴 내 8회차 예측이 틀렸다 — 「사후 27/73 이라 (나) 쪽이 유력」이라 적었는데 (나)는 24건 중 1건이다. 8회차의 사후 「정정」이 그 자체로 틀린 방향이었고, 사전 등록 판정을 안 고치고 옆에 붙여 둔 것이 옳았다 — 고쳐 썼으면 틀린 값이 정본으로 남았다. 🔴 안 닫힌 것 둘: 「닻도 못 알아본다」가 (i) 후보가 진짜 남이다(→ None 이 정직한 답이고 커버리지 붕괴는 결함이 아니다) 와 (ii) 대상인데 그동안 안 닮아 보인다(→ 뿌리는 닻 기술자, 처방은 더 강한 외양 표현) 를 아직 안 가른다. 대조군이 깨끗한 프레임에서 0.60~0.93 을 내고 재획득이 23/37(62%)에서 일어나므로 기술자가 통째로 못 쓰는 것은 아니다. 10회차: 재획득 상자가 잃기 직전 상자와 이어지는가 — 이어지면 (ii), 딴 데서 나타나면 (i)다. 🔴 거기도 IoU 라 구간 길이로 층화하고 짧은 구간(≤10프레임)을 주 지표로 삼고, 🔴 층 B·C 를 이번에 처음 썼으니 「안 쓴 표본」이 없다는 것을 사전 등록에 적고 시작한다. 🔴 10회차를 돌렸고 판별불가다 — 그리고 계기가 현상의 2.6%만 본다 (2026.09.10, eval/pending18_link/): 사전 등록 기준 A·B·D ✅ · C·E 🔴, 주 층 9구간에서 이어짐 44% 대 안이어짐 56% 로 70% 폭에 어느 쪽도 못 닿는다 — (i)도 (ii)도 아니고 둘 다 일어난다. 🔴 이 회차의 값은 판정이 아니라 계기가 닿는 자리다: 관문 통과 클립의 잃은 프레임 1,309 중 69%(901)가 재획득으로 끝나지 않는 구간(중앙 147프레임 대 재획득 구간 중앙 10프레임)이고 주 층이 설명하는 몫은 2.6%(34프레임) 뿐이다. 재획득으로 끝난 구간은 쉬운 경우이고, 이 계기는 트래커가 스스로 「돌아왔다」고 말한 구간만 보므로 커버리지 붕괴에 원리적으로 못 닿는다 — 9회차가 규격을 쓸 때 그 간극을 못 봤다. 🔴 8회차와 다른 결함이다: 8회차는 무엇을 재는가(길이 오염), 10회차는 누구를 재는가(재는 양은 맞았다, ρ +0.11). 계기 검사는 두 개다(5절에 남겼다). ✅ 문턱을 미리 못 박은 것이 일했다 — LINK_IOU 0.1/0.2/0.3/0.5 에서 이어짐이 67/56/44/22% 라, 0.5 로 그었으면 「(i) 대상이 없었다」가 78%로 결론이 됐다. 0.3 은 production MIN_ANCHOR_IOU 라 결과를 보기 전에 정해져 있었다. 사후: reach(프레임당 상자폭 이동)가 두 덩어리로 갈리고 사이가 비었다(≤0.41 여섯 = 제자리 · ≥1.83 셋 = 자리 이동) — 9건이고 금을 값을 보고 그었으므로 판정에 안 쓰고 옆에 붙였다. 🔴 기하로 가르는 길과 라벨 없이 가르는 길이 함께 닫혔다(4절). 남은 둘: (A) 사람 판독 70장(안 끝난 7구간 × 10프레임, 「대상이 보이는가」 예/아니오 — 권함, 어느 쪽이 나와도 갈래가 닫힌다) · (B) 더 강한 외양으로 되짚기(새 의존을 부르고 실패해도 (i) 을 증명 못 한다). 화면에서 두 버튼을 잇는 것(백성검)도 남아 있다. 🔴 11회차는 (A)/(B) 가 아니라 「공 근접」이라는 제3의 축으로 열었고, 판정은 판별 불가다 (2026.09.14, eval/pending18_ball_proximity/) — 계기는 섰는데(ρ 0.835, ViTPose 없이 후보 전부를 잰다) 축구 19편이 전부 1인 영상이라 주 층이 1프레임이었다. 다음은 처방이 아니라 표본이고(미결 46번), (A) 사람 판독 70장은 그대로 열려 있다. ✅ 표본을 그날 확보했다 — SoccerNet 방송 40편, 관문 다인률 98%(eval/sample_gate/). 🔴 12회차도 판별불가인데 이번엔 이유가 다르다 (2026.09.14, eval/pending18_broadcast/) — 회차는 성립했다(주 층 198프레임 · 9클립). M 17.7% · 불일치 margin 중앙 1.687 키높이(문턱의 6.7배)로 (나)의 두 조건이 다 섰는데 G 가 깨졌다: 내가 박아 둔 기전이 원근이었는데 불일치 높이비가 1.19(p25 1.04)로 거의 같은 크기다. 사전 등록이 그 경우를 판별불가로 내린다고 미리 적어 두었고 그대로 했다. ✅ 사후 관찰이 진짜 기전을 찾았다 — 「면적이 폭에 끌린다」: 면적비 1.71 대 높이비 1.19, 고른 박스 w/h 0.61 대 0.50, 그 프레임에서 가장 넓은 박스인 비율 64%. 동률은 부차적이다(10% 안 2명 이상 32%, 중앙 1명). 🔴 M·margin 만 봤으면 「선택이 틀린다」로 결론 내고 원근 때문이라고 적었을 것이다 — 둘 다 틀렸을 뻔했다. 🔴 처방은 비싸다: 면적 → 높이는 selector 동작 기준이라 B-1~B-6 이 전부 무효다. ✅ 13회차가 갈랐다 — 「자세」다 (2026.09.14, eval/pending18_wide/): 고른 넓은 박스가 다른 후보를 삼키는 비율 S 12.3%(IoA 기준 — 🔴 IoU 는 큰 박스와 작은 박스 사이에서 구조적으로 낮게 나와 삼킨 경우를 못 잡는다), 문턱 0.5까지 내려도 27.6%, 계기 사각지대 36프레임을 전부 겹침으로 쳐도 34.4% 로 자세가 다수다. 뿌리는 검출 후처리가 아니라 선택 규칙이다. 🔴 내 예측이 두 회차 연속 틀렸다(「둘 다」를 예측, 실제 12.3%) — 집계값 하나로 기전을 추정하는 습관이 원인이고, 앞으로 예측에 그 예측이 어떤 분포에서 나왔는지를 함께 적는다. 사후(판정 밖): 가장 넓은 6개 중 셋이 땅에 눕거나 엎드린 선수였다(w/h 3.39 = 슬라이딩) — 면적으로 고르면 누운 사람이 이긴다. 🔴 14회차 사전 등록을 세우며 내 말을 정정했다 — 「면적 → 높이」는 B-1~B-6 이 전부 무효 는 과장이었다. eval_b2.py:94·eval_selectors.py:93 의 baseline 이 argmax(area) 라 production 과 같은 규칙이고, 바뀌는 것은 「baseline 이 곧 제품이다」라는 대응 하나다. ✅ A vs B 결론과 B-3~B-5 판독 라벨은 안 죽는다(다시 못 받는 유일한 자산인데 이 변경에 안 걸린다). 🔴 다시 돌릴 것은 B-6 244초 + B-2 6분 = 10분 남짓이다. 그래도 순서는 안 바꾼다 — 이유가 「비싸서」에서 「어느 규칙이 나은지 아직 모르기 때문」으로 바뀔 뿐이다. 14회차는 구현이 아니라 오프라인 비교다(eval/pending18_rule/): src/ 무변경으로 R0(면적)·R1(높이)·R2(누운 박스 제외)를 견주고, 🔴 보지 않은 층(SoccerNet 41~100) 을 확보해 확인에만 쓴다. 🔴 짝 기준: M 이 올라도 키포인트 신뢰도가 10%p 넘게 떨어지면 「이겼다」고 안 적는다. 🔴 14회차를 돌렸고 아무 후보도 못 넘었다 (2026.09.14) — R0 17.7%/12.1% · R1(높이) 9.1%/8.3% 로 더 나쁘다(절반 넘는 프레임에서 다른 박스를 고르는 큰 변화인데 살린 것 8·9 대 죽인 것 25·19 로 3:1 손해, 두 층 같은 방향) · R2 는 R0 와 95~96% 같은 박스라 아무것도 안 바꾼다. 🔴 그래서 13회차 진단을 다시 읽어야 한다: 「고른 박스가 넓고 그 폭은 자세에서 온다」는 그대로 서지만 「면적이 나쁜 기준이라 바꾸면 낫다」는 안 따라온다. ✅ 보지 않은 층이 실제로 일했다 — R2 가 층 A +2.0%p 에서 층 B −0.8%p 로 부호가 뒤집혔다. ✅ 현상도 재현됐다(안 본 16클립 264프레임에서 M(R0) 12.1%). 🔴 내 예측이 절반 틀렸다(R1 의 방향) — 「높이로 보면 대등해진다」와 「우리 쪽이 뒤집힌다」는 다른 말이었다. 사후(판정 밖): 키포인트 신뢰도는 R1 이 더 높다(0.771 대 0.755) — 「포즈가 잘 잡힌다」와 「맞는 사람이다」는 다른 축이다. 15회차(구현)는 열지 않는다 — 구현할 것이 없다. 📋 그래서 판독 ① 을 준비했다 (2026.09.14, eval/pending18_subject/) — 「이 프레임의 분석 대상은 누구인가」를 사람이 고르는 70장(25클립·층 A 27·층 B 43). 🔴 이것은 10회차의 「사람 판독 70장」이 아니다 — 그쪽은 야구에서 「대상이 보이는가」를 묻고 그대로 열려 있다(14회차에 둘을 같은 것처럼 적은 것을 정정했다). 명세(AFTER_LABELS.md)를 라벨 받기 전에 커밋했고 채점 스크립트가 같은 커밋에 있다. 앵커링을 막으려고 공을 안 그리고 · 박스를 전부 같은 색으로 하고 · 번호를 화면 왼쪽부터 붙였다. 🔴 AI 가 채우면 정답이 아니다 — 사람 판독자가 병목이고 그게 미결 2번이다

④ 연결 뒤 기능 여섯 (2026.09.11 신설 — 미결 ho 43번이 정본)

에이전트가 프론트·백엔드와 이어진 뒤 사용자가 여섯을 요청했다. 순서와 근거는 미결 43번에 있고 여기는 상태만 적는다.

  기능 상태
㉮ 축구 아닌 영상 거르기 ✅ 1회차 합격 (2026.09.11). 축구 19편 오거절 0건 · 야구 39편 거절 69%. 🔴 31%는 통과한다 — 벽이 아니라 걸름망이고 농구는 원리적으로 못 거른다(COCO 에 구별되는 도구가 없다). 종료 코드를 품질 게이트(2)와 나눴다(3) — 뭉뚱그리면 사용자가 같은 파일을 다시 올린다(41번). eval/pending43_sport_gate/
㉱ 리포트 문구 ✅ 1회차 끝. build_prompt 가 지표 코드를 JSON 그대로 넣어 모델이 베끼던 것을 라벨로 바꿨다. 🔴 단위는 안 붙였다 → ✅ 2회차가 붙였고 실측했다 (2026.09.16, eval/pending43_evidence_plain/): 맨 숫자를 주면 모델이 단위를 지어낸다 — 값을 언급한 문장의 71%(15/21) 가 7프레임을 「7초」라고 적었다. 계약의 emitted_from 이 이미 「환산해야 초가 된다」를 말하므로 새 선언 0개로 참인 단위를 붙였더니 0/23 이 됐고, 프레임 표기가 0 → 23 이다(줄어든 것이 침묵이 아니라 참인 말로 갔다). 🔴 초로 환산하지는 않았다 — 프롬프트의 앵커가 프레임이라 한쪽만 바꾸면 두 다른 자가 되고, 앵커의 격자는 미결 7번이 아직 안 닫았다. 🔴 계기를 네 번 고쳤다(반복이 결정론이라 비어 있었다 · 밴드가 루브릭마다 다르다 · 정규식이 조사에 걸려 분자를 0으로 셌다 · 소수점 앞자리를 분모로 셌다) — 첫 집계는 분모 7 · 분자 0 이라 그대로 믿었으면 「재현 안 됨」으로 닫을 뻔했다. 🔴 구간 숫자(「140~165도」)는 남아 있다 — 미결 23번이고 지도자 검수에 묶여 있다
㉯ 사람 목록 ✅ 에이전트 몫 완료 (pose.detect_candidates · scripts/detect_subjects.py). 🔴 좌표가 정규화 0~1 이고 낸 박스가 그대로 --subject-box 로 돌아간다(실물 확인). 남은 것은 내주는 자리(미결 44번, 정어진) → ✅ 줄이 이어졌다 (2026.09.16). 정어진 님이 큐 기반 detect 작업(같은 큐·job_type·detection_result)을 냈고(09-15), 워커 배선을 붙였다 — claim 의 job_type 이 detect 면 detect_subjects.py 를 부르고 후보 JSON 을 무변환으로 보고한다. 🔴 분석 경로는 한 줄도 안 바뀌었다(job_type 없으면 분석 — 구 백엔드 호환). 🔴 autostop 의 BUSY_PATTERN 에 detect_subjects 가 없었다 — 검출 도중에 인스턴스가 꺼질 수 있었고 함께 고쳤다(배포된 /etc/.../autostop.conf 는 자동으로 안 바뀐다). 🔴 실물 확인은 GPU 인스턴스가 필요해 아직이다 — 남은 것은 화면(백성검)과 그 확인이다. 🔴 GPU 인스턴스가 잠들어서 동기 API 가 안 된다는 것이 그 항목의 출발점이었고, 큐로 간 이유가 그것이다
㉲ 한 영상에 리포트 둘 🔴 진행 중 — 4회차에서 「막는 것 ⑴」을 치웠다 (2026.09.14, eval/pending45_multi_event/). 1~3회차가 전부 찾는 쪽이었는데, 찾는 것이 완벽해져도 실어 나를 칸이 없었다. segment_phases·extract_features 가 구간(window=[a,b))을 받는다 — 구간 밖을 「검출 실패」와 같게 다루는 로직 다섯 줄이고, 임팩트 탐색·경계 검사·구간 분할은 한 줄도 안 고쳤다(이미 usable 위에서만 돌아서다). 그래서 window=None 비트 동일이 검사가 아니라 구조로 보장된다 — 기준 A 0/117, B-6 재실행 없음. 🔴 argmax 를 「상위 N개」로 바꾸지 않았다 — 그러면 「몇 개인가」와 「어디인가」가 한 함수에 섞이고 새 상수가 붙는다. 바깥이 구간을 정하고 안은 하나씩 받는다. 기준 A~G 7/7, 새 상수 0개, 테스트 410 → 413. 🔴 G(짝 기준)가 이 회차의 값이다 — A·B 는 「안 바뀌었다」를 재므로 한 줄도 안 고치면 만점이라, 결과 전에 예측을 박았다(반으로 자르면 전체 argmax 가 둘 중 정확히 한 구간에, 다른 구간은 다른 프레임). 92/92. 🔴 D 의 22건이 다음 자리를 가리킨다 — 반으로만 잘랐는데도 창 22개가 경계 검사에 걸렸다(성립한 것 92쌍). 이벤트가 촘촘하면 구간 분할 자체가 성립 안 한다는 뜻이고 ㉳ 가 정확히 그런 동작이다. ㉳ 를 연 것은 맞지만 「열렸다」가 「된다」는 아니다. 🔴 5회차가 그 「촘촘하면」을 쟀고 판별불가다 (2026.09.18, eval/pending45_window_floor/) — 🔴 먼저 4회차의 인과를 정정한다: 그 22건은 반 클립(50~150프레임)에서 났고 경계 검사가 요구하는 것은 5프레임이라 길이일 수가 없다. 타일 15,710개로 이벤트를 담은 창(층 E) 과 안 담은 창(층 N) 을 견줬더니 차이가 −1.8 ~ +7.5%p 로 겹친다 — 「창에 이벤트가 있느냐」가 성립률을 거의 안 정한다(→ 「경계 검사가 이벤트 없음을 잡는 계기다」는 안 섰다). 층 N 이 산수 (L-4)/L 보다 낮은 폭이 최대 18.7%p 로 문턱 20%p 에 1.3%p 못 미쳐 판별불가이고, 🔴 문턱을 안 옮겼다(옮기면 표본이 훈련셋이 된다). 🔴 이 회차의 알맹이는 계기 쪽이다 — 내가 「산수」라고 못 박은 (L-4)/L 이 사실은 가설이었다: 그 식은 argmax 자리가 균등하다를 몰래 전제하는데 균등성은 산수가 아니라 신호의 성질이고 재 보니 아니었다(기준 B 가 그래서 깨졌다). 8회차(무엇을)·10회차(누구를)에 이은 세 번째 형태 — 계기 검사의 기준선 자체가 검증 안 된 모형이었다. 사후(판정 밖): 가장자리 쏠림은 실재하고(배율 최대 2.4 · z +12.9) 두 층에서 같다. ㉳ 가 가정한 간격 10~15프레임에서 진짜 터치를 담은 창의 50.0%·58.2%만 산다 — 이벤트가 없어서가 아니라 창 경계가 옆에 그어져서다. 🔴 그래서 처방이 2 를 낮추는 쪽이 아니라 「바깥이 창을 넓게 잡는 쪽」일 수 있다(파이프라인에 새 상수가 안 붙는다) — 사후 읽기라 처방으로 안 적는다. 🔴 6회차가 그 둘을 붙였고, 기준은 전부 통과했는데 값은 사후에 있다 (2026.09.18, eval/pending45_margin/) — 🔴 표본을 축구로 바꿨다(52번 2회차가 뜬 포즈 캐시 38편, 키포인트와 공 궤적이 함께. 🔴 52번을 다시 여는 것이 아니라 이미 뜬 자산만 읽었다). 바깥 규칙은 1회차에서 import(새 상수 0개). 관문 통과 17/38(🔴 다리 가시성에서 14편 — 52번 1회차의 10편과 같은 현상). |δ| 중앙 10프레임 · 평균 82.6 · 범위 0~906, 무작위 대조 중앙 14 로 C 통과. 🔴 그런데 사후가 그 통계를 무너뜨린다 — 클립 단위로는 9/17 로 동전 던지기다. 집계가 이긴 것은 δ 가 작아서가 아니라 무작위 대조군 중앙값이 클립마다 5~322 로 흩어져서다(후보 ≤5 층은 δ 13.5 인데 무작위 95 라 이기고, 후보 ≥10 층은 δ 7.0 인데 무작위 11.0 이라 절반만 이긴다). 🔴 계기가 미끄러진 네 번째 형태 — 대조군을 클립마다 따로 만들어 놓고 비교는 전체 중앙값끼리 했다(8회차 무엇을 · 10회차 누구를 · 5회차 기준선이 가설 · 6회차 요약 통계가 비교 불가능한 것을 묶었다). 그래서 여백 m*(50·80·90% 커버에 12·27·41)를 처방으로 안 낸다. ✅ P3 은 거짓이고 방향이 좋다 — 실효 여백 손실 5.9% 라 m ≥ |δ|+2 의 전제가 이 표본에서는 대체로 선다. 🔴 e 가 정답이 아니라 안쪽의 자기 답이라, δ 가 크면 바깥이 틀린 건지 안쪽이 틀린 건지 못 가른다 — 그 자리가 52번 2회차의 diagnose_impact.py 인데 보류다(파국 두 클립: δ +906·−325, 여백으로 덮을 수 없다). 🔴 7회차가 그 계기를 고쳤고, 6회차의 C 를 뒤집었다 (2026.09.18, eval/pending45_pointing/) — 새 측정 없이(0.8초) 6회차 원자료를 클립별 분위로 다시 요약했다. 평균 분위 0.422 > 0.35 로 불합격 — 「공-발 거리 극소점이 신전 각속도 임팩트를 가리킨다」가 이 표본에서 안 선다. ✅ 계기가 이번엔 제 일을 했다: 가짜 바깥(후보를 같은 개수의 무작위 프레임으로 갈아 끼운 것)의 평균 분위가 0.499 라 통계가 귀무 아래에서 교정돼 있다 — 🔴 이 확인이 없었으면 0.422 를 「0.5보다 작으니 가리킨다」로 읽을 수 있었다(mid-p 보정과 그 교정 확인을 사전 등록에 미리 적어 둔 것이 값을 했다). ✅ 사전 등록 P2 로 불합격을 예측하며 열었고 그대로 됐다 — 🔴 맞은 예측은 틀린 예측만큼 값이 없고, 새로 알려 준 것은 뒤집힌 6회차 쪽이다. 🔴 6회차의 사전 등록 판정은 고쳐 쓰지 않았다 — 인용할 때 둘을 함께 인용한다. 🔴 「안 섰다」는 「없다」가 아니다(n=17 에 바가 2.1 표준오차 · 분위 ≤0.10 인 클립이 4편으로 귀무 기댓값 1.7보다는 많다). 사후: 후보 ≤5 층은 양극단이다(6편 중 3편 <0.1 · 2편 >0.9 — 맞히거나 완전히 딴 데를 본다) · 파국 두 클립은 자기 귀무보다도 나쁘다(0.979·0.961, 체계적으로 다른 자리다) · 잘 맞힌 4편은 δ 가 0~8프레임이라 문제는 정밀도가 아니라 맞히느냐다. 🔴 그래서 여백 처방을 닫는다 — m*(12·27·41)을 쓰지 않는다. 남는 갈래 둘은 둘 다 정답이 있어야 갈린다: (가) 바깥이 틀렸다(1회차가 67%에서 멈춰 있다) · (나) 안쪽의 e 가 진짜 킥이 아니다(52번 2회차 diagnose_impact.py 자리인데 52번이 보류) — 가르려면 사람이 「이 프레임이 킥인가」를 봐야 하고 그게 미결 2번이다. 🔴 표본에 반복 터치가 0편이라 「드리블이 된다/안 된다」는 여전히 못 말한다 🔴 「㉲-a 가 됐다」고 적지 않는다 — 된 것은 칸이고, 넣을 것(67%, 박민호 제품 판단)과 내보낼 곳(schema 2.0, 정어진 A/B/C)이 둘 다 남의 결정이다. 🔴 표본이 야구 39클립이라 검출 성능·등급은 이 표본으로 말하지 않는다(재는 성질이 종목 무관해서 회차만 성립한다). 아래는 그 앞 기록: 미결 45번. 계약이 「영상 1 : 리포트 1」이라 schema 2.0 이고, 분석 창 10초(30번)가 이것 때문에 급해진다 — 「앞 10초만 본다」가 「두 번째 동작이 통째로 사라진다」로 증상이 바뀐다. ㉲-a(같은 동작 여러 번, 정답 불필요)와 ㉲-b(슛+패스 섞임, 🔴 분류라 정답 필요)로 갈랐다
㉳ 드리블 루브릭 🔴 ㉲ 뒤다 — 내가 순서를 틀렸다. 파이프라인이 「클립당 임팩트 한 번」을 전제하는데(IMPACT_EVENTS 둘 다 단일 순간, impact 는 int 하나, 지표가 전부 _at_impact) 드리블은 반복 동작이다. ㉲ 와 같은 빈틈이다. ✅ 그 빈틈의 절반이 2026.09.14 에 메워졌다 — ㉲ 4회차가 window 를 넣어 구간마다 한 번씩 돌릴 수 있게 했다. 🔴 그런데 「열렸다」가 「된다」는 아니고, 1회차가 그 크기를 쟀다 (2026.09.14, eval/pending43_dribble_spacing/) — 기준 A~G 7/7, src/ 무변경(조사 회차), GPU 안 씀. 유효 구간을 길이 L 로 타일링한 성립률: L=5 13% · 10 42% · 15 53% · 30 70% · 60 83%(🔴 10·15 는 드리블 간격이라고 가정한 값이다 — 드리블 클립이 없어 재 보지 않았다). 🔴 D 가 뜻밖이다 — 90% 에 닿는 L 이 없다. 2초짜리 창에서도 83%라 「구간을 넉넉히 잡으면 된다」가 닫혔다(타일에 봉우리가 없으면 어떤 L 이어도 걸리고, L 을 키우면 실패 비율만 낮아진다). G(짝 기준) 77.5 < 97.7 예측대로 — 다만 🔴 크기가 틀렸다: 50(아무 데나)까지 안 내려가고 77.5 에 멈춘다. 사후 설명 — 경계 검사가 「가운데에 봉우리가 있는가」 필터로 일하고 있다(L=5 면 허용 위치가 하나뿐이다). 🔴 정정 — 바로 위에 적었던 「2 를 낮추는 것은 새 상수라 답이 아니다」의 이유가 틀렸다. 낮춰 보니 성립률이 42% → 89% 로 배 넘게 오르는데 백분위는 86.9 → 87.0 으로 안 움직인다. 🔴 계기가 대가를 볼 자리가 아니었다 — 백분위는 임팩트 한 프레임만 보는데 m 이 지키는 것은 「준비·마무리 구간이 비지 않는 것」이다. m=0 이 추가로 살리는 891구간을 세니 takeback 길이 0 35% · follow_through 길이 0 33% · 한쪽 1프레임 39% 로 사실상 전부 퇴화했고, 그 위에서 follow_through_duration_frames·swing_hip_flexion_after_impact_deg 가 계산된다. 그래서 결론은 같고 이유가 바뀐다: 「새 상수라서」가 아니라 「지표가 뜻을 잃어서」다. ✅ 짝 기준이 없었으면 「낮춰도 백분위가 안 떨어지니 낮추자」로 적을 뻔했다(8·10회차와 같은 형태 — 사전 등록은 계기가 재려던 것을 재는지까지는 못 막는다). 🔴 남은 길은 하나다: 「성립」이 「터치」인지는 각속도로 못 말한다(「봉우리다」까지고 정답이 필요하다). 구간을 쪼개는 쪽은 더 갈 곳이 없고, 필요한 것은 이 표의 위 칸이 이미 적은 터치 빈도·거리 유지·제어 반경이다 — 그건 features 를 바꿔 B-6 재실행을 부르고 임계값 unverified 를 늘리므로 제품 판단 대기다. 지금 넣을 수 있는 것은 롱패스·크로스(새 지표 0개)뿐이고 트래핑은 「공을 어디에 뒀는가」가 없어 절반, 헤딩은 impact_limb 이 leg·arm 뿐이라 안 된다. 🔴 2회차를 돌렸다 (2026.09.15, eval/pending43_dribble_metrics/) — 1회차의 「기다리는 동안 할 수 있는 것은 다 했다」가 틀렸다. 1·4회차는 전부 「구간이 서는가」까지였고, 선 다음 값이 쓸 수 있는 값인지를 안 물었다. 같은 임팩트를 같은 정의로 잡은 짝(창 없음 vs 창 안)을 대 봤다 — 기준 A 불일치 0, 짝 예측 C-1·C-2 둘 다 예측대로, src/ 무변경, 테스트 413. ⑴ 누수는 결함이다: follow_through_duration_frames 가 ankle_speed[t:] 라 창 밖을 읽는다(L=10 에서 35%). 🔴 extract_features docstring 이 「창 안에서 끊긴다」고 적은 것과 어긋난다 — 문서가 코드보다 앞서 있다. 이 값은 밴드가 아니라 근거 문장으로 나가 점수에는 안 보인다. ⑵ 축소는 결함이 아니다: 창에 묶인 지표가 작아져(중앙 −87%·−57%) 등급이 한 방향으로만 내려간다 — L=10 에서 44%(18/41), 올라간 것 0, L=60(2초)에서도 17%. 커진 것이 0 인 이유는 대수(부분집합의 ptp)라 결론이 아니라 계기 검사다. 🔴 틀린 것은 값이 아니라 밴드다 — 25/15도·30/15도는 단일 동작 한 번을 통째로 본 클립에서 매긴 눈금이다(로드맵 5절 「앵커는 다른 동작점의 값」과 같은 형태. 그때는 fps, 이번엔 구간 길이). 그래서 새 지표보다 먼저 서는 것이 「반복 동작용 밴드」다. 🔴 누수 수정은 공짜가 아니다 — window=None 에서도 2/78 이 바뀌어 B-6 재실행을 부른다(별도 사전 등록). 남은 길 셋: (가) 누수 수정 → (나) 반복 동작용 밴드(제품·검수 판단) · (다) 드리블 표본(간격 10~15 는 여전히 가정). (가)가 (나)보다 먼저다 — 누수가 낀 값 위에 눈금을 매기면 안 된다. ✅ (가) 를 3회차에서 했다 (2026.09.15, eval/pending43_leak_fix/) — post = ankle_speed[t:ft_end] 한 줄 + 회귀 검사 둘(테스트 413 → 415. 사전 등록엔 414 로 적었고 줄이지 않았다). 🔴 값까지 박은 예측이 맞았다: 78산출 중 정확히 2개(109→104 · 56→47), 다른 지표·임팩트·구간 불일치 0. 창 밖 읽기 35/31/15/15% → 전부 0%, L=10 창의 「마무리 86프레임」이 6 이 됐다. ✅ D 가 2회차 결론을 실물에서 확인했다 — B-6 290행에서 등급·점수 불일치 0, 즉 이 결함은 점수로는 안 드러나고 근거 문장에만 실린다. 🔴 밴드 문제(축소·강등 44%)는 그대로다 — 2회차 재측정에서 한 숫자도 안 바뀌었다. 🔴 그리고 B-6 재실행이 더 큰 것을 드러냈다 — 기준선이 재현되지 않는다(290행 중 85행, 전부 Track 2). 환경·가중치·비결정성(같은 코드 두 번이 비트 동일)·프레임 수·루브릭·품질 게이트를 전부 배제했다 → 미결 47번(그쪽이 (나)·(다)보다 먼저다). 🔴 그리고 47번 1회차가 같은 날 「남은 것은 코드 변경」도 지웠다 (eval/pending47_baseline_audit/) — 이분 탐색을 시작하기 전에 양 끝점이 답했다: 4626870(그 CSV 를 낸 커밋 자체)에서 돌려도 85/95행 다르고, 09-02 · 09-08 · 오늘 세 시점 재실행끼리는 불일치 0 이다. 어떤 커밋도 Track 2 값을 바꾸지 않았다. 예측 P-1(read_frames)·P-2(3b05436) 둘 다 틀렸다. md5 가 기준선 출처도 바로잡았다 — Track 2 CSV 는 09-08 에 한 바이트도 안 바뀌었고 09-02 산출이다. 추가 배제: uv.lock 무변경 · 드라이버 560.94 동일 · N-2 배치 폴백은 Track 2 에서 구조적으로 불가능(박스 1~3개 < MAX_BATCH 24). 🔴 남은 후보 둘은 전부 버전 관리 밖이다 — 입력 클립(agent/data/ 는 gitignore·체크섬 없음)과 그 실행의 정체(실행 메타를 파일로 안 남긴다). 그래서 입력 61개의 md5(input_fingerprints.csv)를 남겼다 — 오늘부터의 기준선이고 과거를 복원해 주지는 않는다. 🔴 ㉳ 를 뒤로 미뤘다 (2026.09.15) — 남은 (나)는 지도자 검수(2번), (다)는 드리블 클립이 없다, 그리고 47번이 그 둘보다 먼저다. 즉 지금 붙어도 진도가 안 나간다. 대신 paik 30번(비교 화면의 관절·세 순간) 을 앞당겨 에이전트 몫을 끝냈다 — 사용자가 「비교를 켜니 분석 시간이 2배」라 했고 원인이 그것이다(브라우저가 영상 두 편의 관절을 다시 뽑는다). 🔴 ㉳ 를 닫은 것이 아니다. ✅ 그리고 47번이 2026.09.16 에 규명됐다 — 커밋이 아니라 torchvision 이었다(4·5회차). 09-08 17:48 에 extra 없이 uv sync 가 돌아 torchvision 이 빠졌고, 그러면 transformers 가 다른 이미지 전처리기를 고른다. 되살리니 09-08 기준선이 95행 × 40열 불일치 0 으로 재현됐다. B-2~B-5 는 무효가 아니다 — 같은 전처리 경로의 산출이고 오늘 비트 단위로 재현된다. 🔴 대신 더 큰 것이 나왔다: 평가(torchvision)와 EC2 서비스(--extra aws 라 Pil)가 다른 전처리를 쓴다 → 미결 49번. 기준선 재선언 (나)는 그것이 정해진 뒤다
㉰ 가림 추적 🔴 11회차를 돌렸고 판별 불가다 (2026.09.14, eval/pending18_ball_proximity/) — 공을 새 축으로 세웠는데 주 층이 19편에서 1프레임이라 분모가 0편이다. 🔴 문턱도 자도 아니었다: 검출 바닥 0.3 까지 풀어도 사람 후보 수가 중앙 1이고, 눈으로 보니 19/19 가 1인 훈련 영상에 OpenPose 스켈레톤이 픽셀에 구워져 있다. ✅ 계기 하나는 섰다 — 「박스 하단 중앙↔공」이 「발목↔공」의 대리로 서고(ρ 0.835) ViTPose 없이 후보 전부에 잰다(클립당 13초 → 5초). 🔴 45번 1회차 진단을 정정했다: 「중계 영상이라 골키퍼·수비벽을 골랐을 수 있다」가 틀렸다 — 다른 사람이 화면에 없다. 그 회차의 어깨너비 절대 크기도 배율이 0.8~7.6 으로 흩어져 크기로 읽으면 안 된다(측면 촬영, 미결 37번과 같은 뿌리). 🔴 A 가 제 일을 했다 — 발치 프레임 58 중 57(98%)이 단일후보였고 A 가 없었으면 「일치율 98%」가 결론이 될 뻔했다(B-1 의 40.2% 오염과 같은 형태). ✅ 표본은 그날 확보했다(미결 46번 — SoccerNet 방송 40편, 다인률 98%) 🔴 그리고 12회차도 판별불가다 — 회차는 성립했는데(주 층 198프레임) M 17.7% 로 (나) 쪽인 채 G 가 깨졌다. 내가 박아 둔 기전(원근)이 틀렸고 진짜는 「면적이 폭에 끌린다」(면적비 1.71 대 높이비 1.19 · 가장 넓은 박스인 비율 64%). ✅ 13회차가 갈랐다 — 겹침이 아니라 「자세」(S 12.3%, 최악으로 쳐도 34.4%)라 뿌리는 선택 규칙이다. 🔴 14회차까지 돌렸고 처방을 못 골랐다 (2026.09.14, eval/pending18_rule/) — R0(면적·현행) 17.7%/12.1% · R1(높이) 9.1%/8.3% 로 오히려 더 나쁘고 · R2(누운 박스 제외) 19.7%/11.4% 로 못 넘는다(층 A/층 B). 기하로 고치는 길을 닫는다. 🔴 배운 것: 「계기가 재려던 것을 재는가」 위에 「표본에 그 현상이 있는가」가 있다 — 8회차는 다른 양을, 10회차는 현상의 2.6%를, 11회차는 맞게 쟀는데 현상이 없었다. 그 관문(후보 2명 이상 프레임 비율, 여기서 8%)은 GPU 100초면 나온다

🔴 ㉲-a 1회차가 뜻밖에 18번을 쟀다 (eval/pending45_touch_events/). 공-발 거리로 터치를 찾으려다 불합격했는데, 원인이 문턱도 공 검출도 아니라 추적 대상이 공 가진 사람이 아니었던 것이다(최근접 4.82 어깨너비 ≈ 2m 인 클립까지 있었다. 못 잡은 쪽의 공 커버리지가 오히려 높다 — 0.76 대 0.69). 문턱 0.8 은 사후 분포의 빈 구간에 정확히 앉았다(잡힘 ≤0.662 · 못 잡음 ≥0.862)라 문턱을 돌리는 회차는 열지 않는다.

18번에 주는 것: 「공을 다루는 사람의 발과 공은 가깝다」는 라벨이 아니라 물리다. 열 회차가 전부 IoU·외양이었고 공은 닫힌 경로 목록에 없다.

🔴 정정 (같은 날) — 이 단서는 18번의 표본에는 안 통한다. 18번의 근거는 phaseA 골든셋 39편 전부 야구인데, ⑴ 공 궤적이 12/39(31%) 만 남고 (축구는 19/19) ⑵ 더 근본적으로 야구는 공이 발치에 없다 — 저 물리는 축구의 것이다. 열 회차의 결론(닫힌 경로)은 알고리즘의 성질이라 그대로 유효하지만 이 단서를 그 표본으로 검증할 수는 없다.

🔴 그리고 이것이 18번 자체의 문제를 드러낸다 — 제품은 축구 단일 종목(39번)인데 18번의 증거 기반은 야구 39편이고 난이도 성격도 다르다 (관중 많은 중계 야구 대 휴대폰 축구). 11회차는 표본부터 다시 정해야 한다.

🔴 계기 검사가 세 줄로 늘었다 (5절도 함께 볼 것). 1회차에서 배운 것은 「내 앞 단계가 맞게 돌고 있는가」다 — 표본도 공도 맞았는데 어긋난 것은 파이프라인 앞단이 고른 사람이었고, 그래서 묻고 싶던 질문에 닿지도 못했다.

순서 미정 — 열린 항목

정답이 필요 없는 것 (측정·확인으로 끝난다):

항목 남은 것
⏸ 52. 영상만 보고 슛인지 패스인지 🔴 보류 (2026-09-17) — 남은 개발 기간에 2회차를 열지 않는다(사용자 결정, 이유는 시간). 제품 경로가 이 항목에 안 걸려 있어서 잃는 것이 거의 없다 — 아래가 이미 「유효한 답은 동작을 사용자가 고르게 하는 것」(jin 17번)이다. 🔴 다만 패스 영상이 슈팅 루브릭으로 채점되는 것은 그대로고 그건 jin 17번이 풀려야 없어진다. 재개하면 표본을 제품 입력에 맞추는 것부터 (포즈 캐시는 이미 서 있다). 🔴 보류 중에도 아래 「하지 말 것」 둘은 유효하다 — 특히 루브릭 자동 전환. 아래는 그 앞 기록: 1회차 불합격 (2026.09.16, eval/pending52_motion_id/). 🔴 막힌 곳이 분류기가 아니다 — 31편 중 판정까지 간 것이 5편이라 일치율 75%(3/4)는 잡음이지 측정이 아니다. 26편이 빠진 이유가 전부 앞 단계다: 다리 가시성 게이트 10편(실제값 15~67%, 표본이 강의 영상이라 상반신 컷이 섞였다) · AV1 디코딩 4편(표본이 아니라 이 기계의 한계 — 2회차에서 yt-dlp 포맷 제약으로 고쳤다) · 각속도/경계 4편 · 대상 선택 실패 8편(공-발 거리 최대 20.04 어깨너비 ≈ 8m). ✅ 계기 검사가 두 번째로 값을 했다 — 미결 45번 1회차가 「터치 검출이 아니라 대상 선택을 쟀던」 것을 사전 등록에 「내 앞 단계가 맞게 돌고 있는가」로 넣어 두었고 그것이 걸렸다. 없었으면 8편이 「분류기가 틀렸다」로 기록될 뻔했다. 🔴 대상 선택 문제가 중계에서만 나는 것이 아니라는 새 정보(미결 18번). 🔴 정정 둘 — 사전 등록의 기대가 둘 다 안 섰다: ⑴ S3′(팔로스루)이 2/5(40%)로 우연보다 낮다. 문턱 25/30은 내가 고른 것이 아니라 두 루브릭이 먼저 적어 둔 2등급 경계였는데 「여기서 갈린다」가 안 섰다(값도 겹친다 — 패스 13~91 · 슛 0~119) ⑵ ball_speed 는 값 자체를 못 믿는다. 집계가 「안 겹친다」로 내지만 슛 표본이 1편이라 그렇고, 통과분 전체는 슛 1.86~138.16이다 — 어깨너비 0.4m 환산으로 138=초속 55m(세계기록 초과) · 1.86=초속 0.7m(걷기보다 느림), 슛 6편 중 4편이 패스 문턱 아래. 🔴 패스 라벨이 우리에게 0편이었다 — 골든셋 19·3DSP 200·SoccerNet Shots 100이 전부 슛이고, PASS 라벨이 있는 SoccerNet Ball Action Spotting 은 암호로 잠긴 NDA 배포라 쓰지 않았다. 그래서 표본을 YouTube 드릴로 새로 만들었고 라벨은 제목에서 온다(약한 라벨). 🔴 하지 말 것: 분포를 보고 문턱을 돌리는 회차 — 이 표본이 훈련셋이 되고 합격이 뜻을 잃는다. 🔴 하지 말 것: 분류 결과로 루브릭을 자동 전환 — 틀리면 엉뚱한 루브릭으로 채점되고 그 사실이 결과에 안 남는다(jin 17번의 「기본값으로 채우지 않기」와 같은 형태). 2회차 착수 (2026.09.16): ✅ 포즈를 캐시한다(cache_poses.py → paths.motion_id_cache()) — 1회차의 진짜 병목은 분류기가 아니라 확인 한 번에 GPU 30분이었다. 실패도 캐시한다(안 그러면 못 여는 영상을 또 연다). 다음은 임팩트가 진짜 킥인가(diagnose_impact.py, 판정 회차 아님) → 표본을 제품 입력에 맞추기. 지금 유효한 답은 동작을 사용자가 고르게 하는 것(미결 jin 17번)
21. 지어낸 0.0 ✅ 해소 (2026.09.08). 못 쟀으면 키를 안 넣는다. 사전 등록을 코드 변경 전에 커밋하고 B-6 전 구간을 다시 돌렸다(Track1 330초·Track2 142초) — 기준 A~F 전 항목 합격. Track 1 의 10행(2클립 × 5 selector)만 바뀌었다. 🔴 등급 변동 0건은 공허하다 — Track 1 은 애초에 채점을 안 하고 Track 2 는 0.0 인 행이 0개였다. 축구 경로는 실측 위 반사실로 따로 쟀다: 15편 중 14편 점수 하락, 10편은 등급 문자까지 (eval/pending21_hip_rotation/)
36. 루브릭 근거 수준 ✅ 4축 정본을 냈다 (2026.09.10) — agent/contracts/rubric_evidence.yaml + tests/test_rubric_evidence.py. 🔴 평면으로 안 적었다 — 측정 타당성은 지표(11개)의 성질이고 이벤트 타당성은 루브릭(6개)의 성질이다. 복사하면 한쪽만 낡는다. 🔴 닫힌 어휘에 verified 가 없다 — 그렇게 말할 수 있는 축이 하나도 없어서다. 지금 분포: 임계값 30/30 unverified(예외 없음) · 이벤트 6종 중 3종 refuted_internal(레이업만 measured_internal) · 측정 11지표 중 4개 refuted_internal. 새로 드러난 것 둘: trunk_forward_lean 을 타격만 「크기」로, 나머지는 「부호」로 읽고 있다(어느 쪽이 옳은지 안 쟀다) · guide_hand 는 근거·측정 두 축이 한 자리에서 겹친다. 🔴 인용은 하나도 안 넣었다 → ✅ 34번이 붙였다 (2026.09.14) — 아래 34번 행. 지금 cited_verified 3건이고, 나머지는 왜 못 올렸는지가 note 에 있다
🔴 34. 임계값 출처 ✅ 결정 3 완료 (2026.09.14, eval/pending34_thresholds/) — 사전 등록을 찾기 전에 걸고(b8dd698) 돌려 기준 A~E 5/5. 축구 인스텝 6개 중 5개에서 수치를 찾았고 3개가 인용 조건을 채웠다(원 논문 1 · 리뷰 본문 2). 🔴 값은 「출처가 붙었다」가 아니라 「붙여 보니 어긋난다」다 — 차는 다리(엘리트 내각 125~145 대 우리 2등급 140~165, 대부분이 우리 0등급) · 팔로스루(엘리트 추가 69~91도 대 우리 문턱 30도, 1/3) · 디딤발 위치(엘리트 27~33cm 대 우리 2등급 ≈20cm, 엘리트가 1등급). 🔴 밴드를 하나도 안 옮겼다 — 문헌은 공 접촉 시점이고 우리는 extension_peak 라 둘이 같다는 근거가 없다(event_validity: unverified). rubrics/·src/ 무변경 → B-6 재실행 없음. 🔴 인사이드 패스 5/5 는 문헌을 못 찾았다 — draft 를 여는 날 인스텝보다 근거가 한 칸 얕다. 🔴 공개 지도 자료가 이 수치화 자체를 「권하지 않는다」고 명시한다(디딤발 위치) — 지도자 검수(2번) 첫 질문으로 올렸다. 🔴 정정 둘: 조사(09-12)와 정본 반영(09-14)이 갈라져 RESULTS.md 가 안 된 일을 됐다고 적고 있었다 · 판정 B 를 5 → 3 으로 내렸다(둘은 리뷰 근거표에만 있어 사전 등록 조건 1의 「2차 요약(리뷰의 표 포함) 불가」에 걸린다). 🔴 그 조건이 값을 했다 — 같은 리뷰에서 본문(「굴곡 21.4도」)과 근거표(「굴곡 ROM −21.4도」)가 어긋난 것을 잡아, 없는 근거를 만들 뻔한 것을 막았다
🔴 37. 상체 기울기가 촬영 방향을 함께 채점한다 36번 4축 표가 찾아냈고 크기를 쟀다 (2026.09.10, eval/pending37_trunk_mirror/). trunk_lean = arctan2(trunk[0], -trunk[1]) 이고 normalize() 가 방향을 정규화하지 않아 좌우 반전 시 정확히 -θ 다 — 「앞으로 기울었나」가 아니라 「이미지 오른쪽으로 기울었나」를 잰다. 축구 인스텝(active) 18클립에서 항목 등급 18/18(100%) · 최종 등급 8/18(44%) 변동, 총점 평균 12.7점으로 3장 허용치 3점의 4.2배다. 🔴 가정이 아니라 이미 나고 있다 — 원 실측의 부호가 인스텝 8:10, 타격 20:24 로 갈려 있고, 인스텝 0등급 구간이 ≤0 이라 음수 8클립이 지금 「뒤로 젖혀졌다」로 0등급을 받고 있다. 18클립 중 9클립이 |θ| < 5도 로 경계에 붙어 있다. ✅ 야구 타격은 밴드가 0 대칭이라 0/46 — 부호 분산이 더 큰데도 안 움직인다. 처방의 방향을 이미 보여 준 셈이다. 🔴 투구·인사이드 패스는 표본 0이라 못 쟀다(투구가 6종 중 가장 비대칭인데). 🔴 2회차로 「표본 메우기가 먼저」를 정정했다 (2026.09.10, eval/pending37_band_map/) — 지금 데이터로는 못 채운다(투구 클립은 이미 품질로 탈락한 그 하나뿐 · 축구 골든셋 19편은 전부 인스텝). 그래서 구조와 분포를 갈라 구조만 전수로 답했다. 정의역 [-90,90](PLAUSIBLE_RANGE 그대로) 전수 뒤집힘: 투구 61%(Δ=2 28%) · 인사이드 26% · 인스텝 33% · 레이업 33% · 점프슛 10% · 타격 0%. 🔴 투구의 Δ=2 구간 [15,40] 은 그 항목의 2등급 구간 그 자체다 — 지금 2등급을 받는 모든 투구가 반대편에서 찍혔으면 0등급이다. 🔴 가장 중요한 것은 해석이다: 정의역 비율은 발생률이 아니다 — 인스텝은 정의역 33%만 뒤집히는데 실측 18/18(100%) 이 그 구간에 있다(θ 가 0 근처에 몰리고 뒤집히는 구간이 거기라서). 그래서 투구 61%도 과소평가일 가능성이 크다(추론이지 측정이 아니다). 🔴 레이업이 숨어 있었다 — 뒤집힘은 인스텝과 같은데 가중치 0.25로 점수 영향이 최대(25~29점) 다. 3장 허용치 3점의 5~10배가 전 루브릭이다. 🔴 예측 하나가 틀렸다 — 「0등급 하한이 같으면 비슷할 것」이 아니라 2등급 구간의 폭이 정한다. 🔴 3회차로 처방 (나)의 전제를 쟀고 안 섰다 (2026.09.10, eval/pending37_facing/) — 방향 인식 지표를 쓰려면 어느 쪽을 보는지 알아내야 한다. 코 오프셋은 구조적 순환이라 사전에 배제했고(기울면 코도 같은 방향으로 간다 → trunk_lean 이 항상 양수가 된다), 남은 두 큐는 귀·눈 신뢰도 비대칭(좌표를 안 쓴다)과 골반중심 x 변위(위치의 변화다)다. 결과: 커버리지 97%(A ✅)인데 독립 큐와 일치 46%(B 🔴 — 우연이 50%다) · 시간 안정 66%(C 🔴). 사람은 한 스윙 안에 돌아서지 않는데 귀 큐는 3분의 1의 클립에서 부호가 뒤집힌다. 🔴 이동 큐도 기준이 못 된다 — 카메라 팬과 피사체 이동을 구분 못 하는데 표본이 방송 영상이다. 그래서 「귀가 틀렸다」가 아니라 「둘 다 근거가 없다」다. 🔴 판정 문장이 A 만 보던 구현 오류를 잡았다 — 안 잡았으면 정반대 결론으로 기록될 뻔했다. 🔴 커버리지를 성과로 읽는 실수가 같은 날 두 번째다(미결 18번 7회차: 93% 채우고 1% 맞음 / 여기: 97% 값 나오고 46% 일치) — 커버리지 단독 기준을 세우지 않는다. 선택지가 셋이다: (가) 밴드 0 대칭화(임계값 이동 · 앞뒤 구분 포기) · (나) 방향 인식(전제가 안 섰다. 투구·킥 표본이 생긴 뒤 다시) · 🆕 (다) 드러내기만(점수 그대로 두고 「촬영 방향에 의존한다」를 봉투에 싣기 — B-6 재실행도 임계값 이동도 없다, 20번 out_of_band·E-3 timebase 와 같은 형태). 🔴 (다)가 지금 유일하게 대가 없이 되는 길이고 다음 한 걸음이다. (나)에 대해 「이 둘로는 안 됐다」이지 「방향은 못 짚는다」가 아니다. 🔴 4회차 — 축구 슛 200클립(3DSP)이 생겨 「못 쟀다」던 분포를 채웠다 (2026.09.10, eval/dataset_3dsp/): trunk_lean 부호가 음수 100 / 양수 100, 중앙값 -0.1도, |θ|<5도 36%, 좌우 반전 시 등급 변동 192/200(96%) — 임팩트 프레임을 9~16 어디로 옮겨도 78~98%다. 2회차의 「정의역 33%는 과소평가」 추론과 같은 방향이다. 🔴 3D 리프팅이 생겼는데도 (나)의 전제는 안 선다(A 100% · B 83% · C 66~70% 🔴 · D 안 섬 🔴 — 어깨·골반 두 큐가 같은 모델 하나에서 나와 서로를 검증하지 못한다). 🔴 투구·인사이드 패스는 여전히 표본 0이다. 함정 셋: 깊이 축이 z가 아니라 y · 뼈 길이 CV로 등방성을 판정하면 정반대 결론(그건 리프팅 오차다) · 이미지가 SoccerNet 방송 크롭이라 연구용 한정 — 공개 저장소 커밋 금지. 무릎각은 못 본다(선수 63.5px · 지터 13~15도 대 구간 폭 20도). ✅ (다) 드러내기를 넣었다 (2026.09.10) — breakdown[] 에 view_dependent(""·"metric"·"grade"). features 를 안 바꿨고 점수는 한 비트도 안 바뀐다 (표시 전용 필드라 B-6 재실행·임계값 이동 없음). 🔴 선언이 실제와 갈라지지 못하게 묶었다 — test_features.py::test_the_mirror_declaration_matches_what_the_code_actually_does 가 「좌우 반전에 실제로 부호가 뒤집히는 지표」 = MIRROR_ANTISYMMETRIC_METRICS 를 강제한다(빠뜨리면 결함이 안 보이게 되고, (나)로 고친 뒤 안 지우면 고쳐진 결함을 계속 경고한다). 골반 회전(22번)은 축 기준이라 반전에 안 변해서 안 넣었다 — 다른 결함이다. 남은 것은 (가)/(나) 선택이고 각각 지도자 검수(2·34번)·표본에 막혀 있다. 계약 필드가 늘어 jin 적재 판단이 미결 38번이다
🔴 「impact_event 를 먼저」 권고 2차 외부 검토(2026.09.10)가 임계값보다 이벤트를 먼저 고치라고 했다. 원리적으로 맞고 저장소도 같은 판단인데 지금 못 한다 — 그 일이 미결 5번이고 보류다(정답 25~60클립, 외부 경로 전부 닫힘). 게다가 impact_event 를 바꾸면 features 가 바뀌어 B-6 재실행을 부르고, 정답이 없으면 새 이벤트가 낫다고 말할 수 없다(「target 30 전환」과 같은 형태). 🔴 재조사하지 말 것 — 권고가 다시 들어와도 답은 같다
23. 근거 문장이 등급과 반대 2회차까지 돌렸다(2026.09.07). 등급 표기는 없앴고(17/19 → 0/19) 역방향 문장은 6/19 → 1/19. 남은 R2 1건의 원인은 루브릭 grades[g] 문구가 구간 숫자를 품고 있는 것 — 처방(숫자 없는 수준 설명)은 스키마를 늘리므로 지도자 검수(2번)와 함께 간다. 🔴 같은 19문장으로 3회차를 바로 돌리지 않는다
1. EXAONE NC 라이선스 후보 조사·GPU 예산 실측 둘 다 끝났다(2026.09.08). Apache/MIT + 한국어로 셋이 다 살아 있다: Qwen3-1.7B · Kanana 1.5 2.1B · Mi:dm 2.0 Mini 2.3B. 🔴 포즈는 예산의 10분의 1도 안 쓴다 — 단독 피크 903MiB(4K도 905, 해상도가 VRAM을 안 올린다), 동시 6341MiB, 여유 9019MiB(eval/pending1_gpu_budget/). GPU_FRACTION을 0.70쯤으로 올리면 뒤 둘이 들어온다(env 한 줄, features 안 바뀜). 포즈 코드는 건드리지 않는다. 🔴 다만 2026.09.08에 박민호 님이 「지금 10주 개발 기간에는 급하지 않다」고 결정했다 — 기한이 「개발 착수 전」에서 「서비스 상업 오픈 전」으로 옮겨졌고 대체 모델 조사·문의는 보류다. 위 조사는 그때 바로 쓸 수 있게 남겨 둔 것이지 지금의 다음 한 걸음이 아니다. 🔴 같은 기한에 하나 더 붙었다 (2026.09.09) — 홈 챗봇(min 7번)이 Gemini 무료 등급으로 돈다. EXAONE 과 분리된 것은 맞지만(챗봇에 EXAONE 없음을 실물로 확인) 라이선스 축이 사라진 게 아니라 모델 가중치 → API 약관으로 옮겨간 것이다. 상업 오픈 전 확인 셋(무료 등급 데이터 취급·상업 이용 가부·요청 한도)을 그 항목에 남겼다
9. 4K host RAM ✅ 가드를 바이트로 옮겼다 (2026.09.08) — DEFAULT_MAX_FRAME_BYTES = 7,465MB(= 4K 300장). 1080p 상한이 300 → 1,200장이 되어 30.5~44.5fps 구간에서 창을 지킨다. 사전 등록 기준 A~E 5/5, 평가셋 39/39 장수 불변이라 B-6 재실행 없음(eval/pending9_budget/). 🔴 4K는 여전히 6.74초까지 줄어든다 — 고친 것이 아니다. 예산을 안 올린 이유는 올리면 4K 결과가 달라져 동작점 이동이 되기 때문. 🔴 런타임 메모리 조회를 배제했다 — 예산이 기계 상태에 의존하면 같은 클립의 점수가 흔들린다. 아래는 그 앞 회차 기록:
9. (경과) RSS 실측 D-1(재디코딩)은 됐다. RSS 실측 로컬 회차 완료(2026.09.08) — RSS ≈ base + k × frame_bytes, base 1.6~1.8GB · k 0.98(프레임을 한 벌만 든다). 기준 A ✅ · B는 불합격으로 뒀다(0.98 < 1.0 — 하한의 근거가 틀렸다는 것만 적고 기준은 안 고쳤다). 🔴 핵심 조합인 4K 300장은 로컬 RAM 9GB로 못 돈다 — EC2에서 --plan full 한 번이 남았다. 예측 9.1GB. 그 뒤에야 가드를 바이트로 옮기는 별도 회차다 (eval/pending9_rss/)
11. B-6 재실행 자산 급소를 옮겼다 (2026.09.08). labeling/targets.py(18개 스크립트가 import 한다)·eval_b6/selector_downstream.py·직접 읽던 4개가 저장소 사본을 본다. paths.default_target() 신설. RERUN.md 의 재실행 명령이 없는 파일을 가리키고 있어 고쳤다. ✅ 사본 하나 문제도 닫았다 (2026.09.16) — clips/·labeling/ 198개(168MB)를 ~/supersub-assets/phaseA/(ext4)에 두 번째로 두고, path·bytes·md5 매니페스트(eval/phaseA/preserved_manifest.csv, 15KB)를 저장소에 넣었다. 확인은 uv run python eval/phaseA/verify_preserved.py [--root <사본>] (두 사본 198/198 일치 · 없는 루트엔 198개 어긋남). 🔴 사본보다 지문이 먼저다 — 47번이 「그때 그 바이트인가」에 일주일을 썼다. 🔴 같은 기계라 디스크 고장은 못 막는다
13. np.gradient 끝단 사실 확인은 끝났다(끝단은 문제의 8%). 어느 처방이 옳은지는 미결 5번의 정답이 필요하다
14. /mnt/d 경로 하드코딩 ✅ 전부 옮겼다 (2026.09.11) — 코드에 박힌 기계별 경로 56곳 → 7곳(남은 7곳은 기본값 선언·WSL 번역·라벨 출처 기록이고 각각 이유가 있다). 🔴 앞서 「일부러 안 건드렸다 — 미리 다 고치면 검증 없이 바꾸는 것이 된다」고 적어 두었던 판단을 뒤집었다. 근거: external_root() 의 기본값이 옛 문자열과 같아 읽는 위치가 한 곳도 안 바뀌고, 경로 표현 23곳을 실제로 계산해 존재를 확인했고(맞음 23·틀림 0), 무거운 의존이 없는 22개는 import 까지 했고, 나머지는 이름 해석을 정적으로 봤다(그 과정에서 report_b1.py 의 sys 미import 를 잡았다). 🔴 남은 한계는 여전히 「돌려 보지 않았다」는 것이다 — 무거운 9개는 GPU·외부 자산이 있어야 돈다. 새 하드코딩은 tests/test_eval_paths.py 가 막는다. 옮기다 드러난 것: /mnt/d/cand_stats.csv 는 target 15 산출물이다
jin 11. 업로드 60초 vs 분석 창 회신(2026.09.07) 뒤 실측으로 다시 쟀다(2026.09.09). 🔴 「창을 60초로 넓히는 길은 없다」를 정정했다 — 720p 로 낮추면 닿는다(천장 115초). 못 닿는 것은 1080p 이상(51초)·4K(13초)다. 맞게 적으면 「모든 입력에 보장할 수는 없다」. 1080p 여유도 10초가 아니라 40초다 · 🔴 창을 60초까지 넓혀도 평가셋 39클립 장수 불변 — B-6 재실행을 안 부른다. 값을 옮길 수 있는 드문 자리다 · 권고는 여전히 상한을 10~15초로. ho 30번을 신설해 박민호 님 grep 에 걸리게 했다 — 담당이 정상호라 PM 에게 안 보이던 것이 스프린트 2를 넘긴 이유다 (eval/pending11_window/). ✅ 제 몫은 닫았다 (2026.09.09) — 담당을 박민호(제품 판단) → 정어진(MAX_DURATION_MS 한 줄)로 넘겼다. 🔴 결정 전에 값을 고치지 않는다 — 사용자에게 보이는 값이라 근거 없이 바꾸는 것이 된다
jin 9. agent/ 진입점 문서 ✅ agent/CLAUDE.md (2026.09.07). 이 로드맵을 가리키고 있으니 둘을 함께 갱신한다
jin 22. agent/ 인프라 식별자 ✅ 해소 (2026.09.09). 계정 ID·VPC/서브넷/IGW/라우팅/엔드포인트/보안그룹/인스턴스 ID·과거 공인 IP 를 자리표시자로. 콘솔 런북의 리소스 표를 「ID 나열」에서 「이름으로 찾는 법」으로 바꿨다(ID 를 지우면 표가 쓸모없어져서다). worker.py 의 SUPERSUB_API_BASE 하드코딩 fallback 을 없앴다 — 🔴 자리표시자를 기본값으로 두면 배포에서 잘못된 URL 로 조용히 붙는다. 루트 CLAUDE.md 커밋 전 grep 범위에 agent/·fastapi/ 를 넣었다
paik 11. 리포트 자리 ✅ 실었다 (2026.09.09). 완료 보고에 report_key(버킷 상대). 🔴 자리 규칙을 워커로 복사하지 않았다 — 아는 쪽(analyze_s3.py)이 --result-json 에 적고 워커는 읽기만 한다. stdout 을 긁지 않는 것은 로그 문구가 바뀌면 깨져서다. 못 실어도 보고는 정상으로 보낸다(작업이 running 으로 남는 것이 더 나쁘다). 🔴 이 판단을 정정했다 (2026.09.10, jin 27번) — 적재가 report_key 로 S3 를 읽기로 정해져서 키 없는 succeeded 는 영원히 빈 리포트다(작업은 닫히고 화면은 아무것도 못 찾는다). 이제 자리를 못 실으면 failed 로 보고한다. FinishJobSchema 는 extra="ignore" 라 받는 칸 없이도 지금 배포해도 된다. ✅ 받는 칸도 들어왔다 — analysis_job.report_key
jin 27. 리포트 스키마 계약 ✅ 고정했다 (2026.09.10). 정본이 agent/contracts/report_schema.yaml 이고 봉투에 schema_version("1.0")이 실린다. 🔴 「정본은 코드」를 정정한 것이다 — 그러면 조용히 바뀌고, 적재·읽기·화면 셋이 같은 JSON 을 읽어 백엔드 배포 뒤 실서버에서만 드러난다. tests/test_report_contract.py 가 production build_report 의 산출과 맞춰 본다(검사할 수 있게 analyze_one 에서 떼어냈다). 필드 추가는 1.1, 삭제·뜻 변경은 2.0 + 미리 알림. breakdown[] 11필드·skipped[] 3필드를 못박아 백엔드의 테이블 (b) 컬럼 기준으로 냈고, 🔴 margin·confident 는 HTTP 데모에만 있다(적재가 필수로 읽으면 실서버 KeyError — 계약이 http_only 로 적고 검사가 고정). 남은 것은 정어진의 적재 구현
paik 20. 「비슷한 팀」의 기준 (RAG) ✅ 기준을 냈다 (2026.09.11). 🔴 RAG 로 풀 문제가 아니다 — 찾는 것은 「닮은 팀」이 아니라 「경기가 될 팀」이고 성사는 유사도가 아니라 교집합이다(5:5 와 7:7 은 조금 안 맞는 게 아니라 안 된다). 임베딩을 배제한 이유 셋: ⑴ 거리는 한 축의 불일치를 다른 축이 보상한다(ho 32 의 스케일 섞임과 같은 형태) · ⑵ 🔴 근거를 못 낸다 — 코사인 0.87 은 이유가 아니고 사후 설명은 지어내기다(ho 23 에서 이미 덴 형태) · ⑶ 정답 라벨이 없어 나아졌다고 말할 수 없다. 🔴 이름의 출처도 짚었다: 요구사항의 유사도는 SFR-005(선수 성향 player_vector) 뿐이고 팀↔팀은 계약에도 요구사항에도 없다 — 여기에 RAG 를 붙일 근거가 없다(제안서 문구 문제면 고칠 자리는 ho 31번). 낸 기준: 하드(판 크기·자기 팀 제외·자리 찼는가)와 소프트(시간은 겹치는 분, 지역은 같은 구>같은 시>그 외, 최근 활동)를 가르고, 문턱은 없다(하드만 문턱 — 다 빼면 조건을 조금 잘못 적은 사람에게 빈 화면만 남는다는 백성검의 판단이 맞다). 🔴 정렬은 개수가 아니라 무게 — 지금 why.length 는 크기 알약이 항상 붙어 모두가 똑같이 1점이라 변별이 없다. 근거 문장은 「시간이 맞음」이 아니라 「토요일 10~12시 겹침」(구체적일수록 사람이 그 자리에서 검증한다). 🔴 실력·등급 배제에 동의하고 이유를 보탰다 — 지금 등급은 provisional 이라 대외 노출 자체가 금지이고(루브릭 머리말·미결 2·34번), 실력으로 고르면 약한 팀이 영영 경기를 못 잡는다. 정어진에게는 사실값만 요청했다(유사도 점수를 서버가 매겨 내리면 곧 ⑵ 다) · 🔴 지역은 paik 19 에서 시/구 계층으로 달라고 걸었다
jin 24. 리포트 키 정렬 (내 조각) ✅ 고칠 것이 없었다 (2026.09.11 확인). 착수 전에 봤더니 이미 계약 자리였다 — reports/<user_id>/<video_id>/report.json + 같은 폴더 미리보기(report_targets). paik 11 에 답하면서 함께 들어갔고 항목이 쓰인 시점의 코드가 아니었다. 🔴 report_slug 는 안 지웠다 — 형태는 요청과 다르지만 목적은 됐다: video_id 가 없을 때만 쓰는 폴백이고, 배치·평가는 video_id 가 없어 회차별 타임스탬프 자리가 맞다(계약 자리로 끌고 오면 앞 회차를 덮어 비교가 사라진다). 소유자는 파일명이 아니라 접두사에서 읽으므로(owner_from_key) 이 항목이 정한 새 파일명이 들어와도 안 깨진다. 확인 tests/test_s3_layout.py 14 통과
jin 28. player_vector 축 (ho 32 확인 요청) ✅ 회신 (2026.09.11, eval/pending32_vector_basis/). 「인스텝 7 vs 6」은 둘 다 맞다 — 7 은 쓰는 지표, 6 은 채점 항목이고 follow_through 한 항목이 지표 둘을 쓴다. 틀린 것은 숫자가 아니라 내 표가 「차원」의 뜻을 안 정한 것이다. 🔴 내 원래 근거 셋 중 둘이 약해졌다 — ⑶(종목 넘는 비교)은 39번으로 종목이 하나라 해당 없고, ⑴(대부분 결측)은 인사이드 패스가 인스텝의 진부분집합이라 늘 비는 칸이 1개뿐이다. (가)는 그대로 권하되 이유가 바뀌었다. 🔴 새로 나온 것이 더 세다: 결측이 한 루브릭 안에도 있다 — 인스텝 18편에서 plant_foot_to_ball_offset 0/18(공 검출이 있어야 나온다 → 매번 skipped[]), hip_rotation_range_deg 15/18. jin 28 설계의 「같은 rubric_code 안에서는 꼬리가 똑같이 0」이 안 선다 — 가끔 비는 칸에 0을 넣으면 ho 21번이 벡터에서 되살아난다. 축은 측정 지표값을 권했다: 같은 15편의 고유 벡터가 지표값 15/15 · 등급 12/15(3편이 구분 안 됨) · stat 15/15 이고, (A)와 (C)는 겹침이 아니라 방향에서 갈린다(stat 은 과·부족이 같은 값 → 수준 축이지 스타일 축이 아니다). 🔴 사전 등록이 아니라 descriptive 계수다 — 숫자를 보고 고른 것이 아니라 구조가 자료에 얼마나 나타나는지를 센 것이라 판정 문장이 없다
🔴 paik 26. 표시 등급 S~F 의 눈금·경계 ✅ 회신 (2026.09.14). 🔴 ⑵ 경계값과 ⑶ 최소 건수를 따로 고르지 않았다 — 숫자를 둘 고르면 둘 다 근거를 대야 하는데 없다. 하나를 정하고 나머지가 따라 나오게 세웠다. ⑴ 눈금이 서는 축은 하나뿐이다: repeat_yes ↔ caution_would_not_repeat 만 같은 축의 반대편이라 0.5 라는 원점이 생긴다. 🔴 매너 3 · 실력 3 을 개수로 세면 평가받은 사람이 아니라 「평가한 사람이 체크박스를 몇 개 눌렀는가」를 재게 된다(「이 양이 내가 묻는 것인가」의 또 한 사례). 🔴 caution_position_mismatch 는 신뢰가 아니라 적합도라 뺐고 27번(추천)으로 넘겼다 — 거기서는 가장 쓸모 있는 신호다. ⑵ 문턱은 0.5(과반) 하나, 판정은 95% 신뢰구간 하한 > 0.5 — 비율 축에서 임의적이지 않은 유일한 점이고, 0.7·0.8 을 쓰면 34번이 기각한 「분포에 맞춰 긋기」가 된다. ⑶ 최소 건수는 안 정했다 — 따라 나온다: 전원 긍정이어도 4건(하한 0.510), 부정 1건이면 8건, 2건이면 11건. 「한 건으로 S 가 갈리면 안 된다」가 규칙을 안 써도 만족된다(1건 하한 0.207). 🔴 S·F 를 같은 문턱의 양쪽으로 뒤집었다 — 「D 인데 리뷰가 없으면 F」를 그대로 두면 안 잰 것이 나쁨의 근거가 되어 ho 21번이 벡터·등급에서 되살아난다. 「A 인데 올려 줄 근거가 있다」/「D 인데 구해 줄 근거가 없다」로 읽으면 결과는 같고 뜻이 선다. 🔴 정정: 리뷰는 영상이 아니라 경기에 달린다(계약 3-9 reviewee_id) — 두 축의 단위가 다르고, 그 편이 분모가 커져 규칙에 유리하다. 🔴 가장 큰 것은 눈금이 아니라 노출이다 — S~F 가 얹히는 A~D 가 루브릭 머리말상 대외 노출 금지(review_required: true)이고, 34번이 같은 날 6개 중 3개가 문헌과 어긋난다를 냈다. 막지 않고 provisional 을 25번 경로에 같이 실어 달라고 걸었다(배선은 scoring.py → 봉투 → analysis_report → types.ts 까지 이미 이어져 있다). 저장은 0컬럼 — review_selection 위의 읽을 때 집계라 D.4(신뢰도 미저장)를 지킨다
🔴 paik 27. 「비슷한 선수」의 기준 ✅ 회신 (2026.09.14). 답은 ±1칸인데 🔴 그 「칸」을 S~F 여섯으로 세면 안 된다 — 두 축이 섞여 있다: S↔A 와 D↔F 는 실력이 아니라 리뷰 차이다(26번 규칙이 그렇게 만들었다). 🔴 실력 축 자체도 등간이 아니다 — grade_bands 가 A 15점 · B 15 · C 20 · D 50점 폭이라 D 한 칸이 A 세 칸보다 넓다. 그래서 gradeValue() 가 S~F 를 0~5 등간으로 놓고 낸 평균이 뜻을 못 갖는다(averageGrade([S, D]) → B, 리뷰 유무를 실력으로 환산한 셈). 고치는 법은 작다 — 평균은 실력 축 네 칸(D0·C1·B2·A3, F=D·S=A)에서 내고 S·F 는 배지로 다룬다. 🔴 ±1 을 고른 이유는 반올림이다 — averageGrade 가 최대 반 칸을 버리는데 그 뒤 정확 일치를 요구하면 버린 것이 손실로 남는다. 🔴 기본값은 거르지 말고 정렬하라 — 항목의 「확인」이 이미 “평균 근처가 위로 오는가” 인데 코드는 filter 이고 기본값이 평균 한 칸이다. 초기엔 분석 안 한 사람이 다수라 화면이 거의 빈다(20번의 「빈 화면」 판단과 같은 자리). 거르개 자체는 둔다 — 사용자가 직접 고른 칸은 추론이 아니라 요청이다. 🔴 등급 모름은 거리 축에 안 올린다 — 「F 로 치지 않기」만으로는 부족하고 거리 1·중간을 줘도 똑같이 지어내는 것이다(ho 21번). 「아직 분석 전」을 따로 그린다. 🔴 RAG·벡터는 필요 없지만 20번과 이유가 다르다 — 27번은 선수↔선수라 SFR-005 근거가 있다. 그래도 물은 것이 「비슷한 등급」이고 등급은 이미 스칼라다. player_vector 는 성향(스타일) 축이라 다른 기능이고, 섞으면 「왜 추천했나」에 코사인 0.87 말고 할 말이 없어진다. 게다가 ho 32번 실측상 같은 루브릭 안에서도 칸이 빈다(plant_foot_to_ball_offset 0/18)
paik 23. 「받은 호칭」의 기준 ✅ 해소 (2026.09.11). 🔴 title 은 절대 비지 않는다 — title_for() 에 항목명 폴백이 있어 0등급도 「무너지는 축」을 받는다. 그런데 report-contract.md 가 그 자리를 그냥 「받은 호칭」이라 적어 두었고 화면은 그대로 구현했다 — 0등급 항목에 부정적 문구를 수여하고 있었다(계약 4장의 정반대). 실측: 인스텝 6항목 × 3등급에서 title 18/18 존재. 🔴 뿌리가 내 문서였다. 응답만으로 가를 수 있게 title_earned(boolean) 를 냈다 — 봉투 1.1 → 1.2. 선은 최고 등급(2) + 루브릭이 그 등급 문구를 실제로 적었을 것이고, 앞의 절반은 summarize 가 「강점」을 부르는 선과 같은 것이라 새로 그은 판단이 아니다. 뒤의 절반이 없으면 칭호를 안 쓴 루브릭이 항목명을 호칭으로 띄운다. features 를 안 건드려 B-6 재실행 없음. 🔴 summary 는 부정적 칭호를 일부러 쓴다(「「젖혀진 상체」로 가장 아쉬웠습니다」) — 문장 안의 서술이지 수여가 아니라 같은 규칙으로 거르면 안 된다. 데모(api.py)에서 증상이 안 났던 것은 장점·단점 구획으로 나눠 그려서다. 적재 판단은 ho 40번
jin 27. 곁가지 — 신뢰도 ✅ 자리를 냈다 (2026.09.10). keypoint_quality.swing_side_valid_ratio(0~1) + gate_joints·threshold·min_keypoint_confidence. 게이트(check_quality)가 이미 재던 값인데 통과 여부만 남기고 버리고 있었다 — 71%로 겨우 통과한 클립과 여유 있게 통과한 클립이 구분되지 않았다. 🔴 키포인트 신뢰도 평균이 아니다(top-down 이라 엉뚱한 박스에도 자신 있다 — 「누구를」은 subject). 🔴 features 의 형제 블록이라 판정 입력이 그대로다(B-6 재실행 없음). 정규화가 안 되는 입력은 known: false 이고 0.0 으로 채우지 않는다
min 14. k3s 전용 빌드·구동 정책 ✅ agent/ 쪽 확인 회신 (2026.09.09). compose 도 Dockerfile 도 0건이라 치울 것이 없다 — 🔴 대신 agent/ 는 컨테이너를 아예 안 쓴다. 호스트 systemd 3개(vllm·worker·autostop.timer)로 돈다. 「compose 금지」로 읽으면 준수, 「k3s로만」으로 읽으면 미준수다. 옮기는 것을 지금은 권하지 않았다 — 막는 것은 GPU 입도다(T4 한 장을 vLLM 0.35 + 포즈가 나눠 쓰는데 nvidia.com/gpu: 1 은 장 단위다). 적용 범위는 박민호 판단
paik 8. 집중해서 볼 항목 ✅ A 안으로 답하고 받는 자리까지 냈다 (2026.09.09). --focus id,id → 리포트의 focus{requested,applied,unknown}. 🔴 B 안(고른 것만 채점 + 재정규화)을 배제했다 — 같은 영상이 고른 것에 따라 다른 점수를 내면 선수끼리 비교가 안 되고 스카우팅은 비교가 전부다. 이미 있는 재정규화(applicable_criteria)는 촬영 조건이 강제한 것이라 성질이 반대다. 채점 경로가 focus 를 모르는 채로 남는지를 검사가 지킨다. 근거 문장을 고른 항목 위주로 쓰게 하는 것은 안 했다 — 「더 나은 설명」은 정답이 없어 판정이 안 된다

정답이 필요한 것 (사람 라벨 없이는 진행 불가):

항목 막고 있는 것
5. 임팩트 탐색 범위 보류. 재개 조건은 팔 종목 릴리스 프레임 정답 25~60클립이고, 유일하게 남은 경로는 자체 촬영(30fps 이상·릴리스가 화면에 남을 것)
7. fps 등급 불일치 원인 규명·1차 판정 완료. 근본 처방 E-6이 5번에 묶여 있다
8. selector A/B 필요 340건 대 데이터셋 상한 49건. 같은 39클립으로는 안 갈린다
20. 상한 초과가 0등급 크기를 전 루브릭으로 쟀다(2026.09.08): 0등급 117건 중 23건(20%)이 구간 위에서 왔고 6개 루브릭 30개 항목이 전부 상한이 닫혀 있다 — active 에서도 샌다. 🔴 항목의 서술보다 층이 하나 더 있다: 막 넘긴 값은 대개 1등급으로 가고(22개 중 13개) 0등급은 더 멀리 넘어야 걸린다. 처방 (다)만 넣었다 — breakdown[].out_of_band 로 표시만 하고 점수는 안 바꾼다(B-6 재실행 없음). (가)·(나)는 임계값 검수 대기. ✅ 아래쪽 끝도 쟀다 (2026.09.09, eval/pending20_band_floor/) — 🔴 팔꿈치 문제다(support_elbow 2.2도 · swing_elbow 6.8도). 항목이 적어 둔 5.4도보다 나쁘다. JHMDB 46편의 무릎은 95.6도 이상으로 깨끗하고, 무릎이 낮은 것은 항목이 인용한 실클립 4건뿐이다. 🔴 그런데 등급 문자가 바뀌는 것은 전부 baseball/batting(draft)이다 — active 는 어느 후보 하한에서도 안 움직인다(상한과 결론이 갈린다). 하한값은 고르지 않았다(검수 대상). 위·아래 크기는 이제 둘 다 쟀다
22. 골반 회전과 카메라 축 각도가 회전의 일부만 담는다(24%). 실클립 n=4로는 지표 문제인지 포즈 품질인지 못 가른다
2 · min 4. 골든셋 라벨링 주체 사람 검수자 미확보. 위 셋의 공통 병목이다. 회신했다(2026.09.08) — 🔴 「50~100건」이 한 덩어리가 아니다. (A) 임계값 검수는 지도자 1명이면 되고 적은 수로 지금 시작할 수 있다(20·22·23(나)·6번과 draft 루브릭 3개가 여기 걸린다). (B) 정답 라벨은 수가 안 차면 무의미하다(8번 340건·5번 25~60클립, 12건으로 해 보니 신뢰구간 [15.2%, 64.6%]). (A)만 먼저 여는 것을 권했다
jin 18. 분석 워커 폴링 루프 ✅ scripts/worker.py + deploy/supersub-worker.service (2026.09.07). 백엔드 큐를 폴링해 analyze_s3.py 를 돌리고 결과를 보고한다. 2026.09.08에 워커 방식을 이쪽 하나로 수렴(jin 20) — --skip-analyzed 를 지웠다. ✅ EC2 설치·토큰 주입도 끝냈다(같은 날) — 서비스가 enabled·active 이고 부팅에도 뜬다. 큐를 실제로 집는 것과 토큰 검증(401/404)은 백엔드를 켜는 날 한다 → ✅ 둘 다 했다 (2026.09.11, min 11번). 토큰은 켜기 전에 백엔드로 검증했고(없는 job id 에 PATCH → 새 토큰 404 · 대조군 틀린 토큰 401. claim 은 소비라 안 썼다), 새 값을 /etc/supersub/worker.env 에 넣은 뒤 밀린 큐 18건을 실제로 처리했다 — 성공 8 · 실패 10 · 진짜 401 0건 · NRestarts 0. 실패 10건은 전부 품질 게이트 미달로 설계된 거절이다. 🔴 성공 8건 모두 reports/<user_id>/<video_id>/report.json 로 갔다 — 계약 자리가 실서버에서 처음 확인됐다(jin 24번). 고치기 전 상태는 failed·종료 78/CONFIG 로 fail-closed 가 설계대로 멈춰 있었다. 🔴 집계하다 grep 이 두 번 틀렸다(파일명의 -0401- 이 「401」로 · 성공 로그가 완료 가 아니라 성공) — 센 수는 쓰기 전에 걸린 줄을 눈으로 볼 것. 곁가지로 ho 41번(같은 클립 9회 재업로드)이 나왔다
jin 1. 적재 규격 ✅ A안으로 결정했다 (2026.09.08) — metric_definition.sport_code 를 없앤다. 근거는 api-contract.md 3-1절. 🔴 항목별 등급(criteria.id)은 A안으로도 안 풀린다 — 같은 종목의 두 루브릭이 같은 id 를 다른 임계값으로 쓴다(축구 4개). 축이 종목이 아니라 루브릭이다. 스키마 반영은 끝났고(정어진, 5db18b239336) 부록 D.3 은 박민호(ho 25번). 🔴 「지표 11개 시드」를 정정한다 (2026.09.09) — 29개다 (jin 23번): 측정 12(루브릭 11 + impact_frame — 채점엔 안 쓰는데 features 에 실려 나간다) + total_score + 항목별 등급 16(계약 3-1 이 「총점과 항목별 등급도 metrics 에 넣는다」고 정했다). 11개만 시드하면 적재가 통째로 UNKNOWN_METRIC_CODE 다. 정본·내보내기·가드 검사를 냈다(contracts/metric_definitions.yaml). 🔴 다시 늘었다 (2026.09.09, jin 25번) — 레이더 축이 되는 항목별 stat 도 적재하기로 정해져서 항목마다 행이 둘이다. active 45행 · draft 포함 73행. 🔴 가장 긴 코드가 48자로 String(50) 여유가 2자뿐이다 — 넘은 채 적재하면 잘려서 다른 코드와 충돌하므로 검사로 고정했다(test_no_code_outgrows_the_backend_column)

남의 영역이라 기다리는 것: 1·15(라이선스, 박민호) · 4(GPU 조달, 정어진) · 17(S3 큐 소비자 — 양쪽 다 만들어졌다: 백엔드 claim/PATCH(정어진) + 워커 루프(위 jin 18). 🔴 접두사 스캔 형태는 없앴다 — 큐가 둘이 되어서다. --skip-analyzed 는 2026.09.08에 지웠고 test_there_is_only_one_queue 가 되살아나는 것을 막는다) · 18(계약, 정어진) · jin 1(적재 규격 — A안으로 정했고, POST /analyses 적재는 정어진 님의 스키마 반영을 기다린다. 그때까지 워커 산출물은 reports/ JSON 까지다).


4. 재조사 금지 — 닫힌 경로

🔴 ㉲-a 를 「창에 여백을 주어」 푸는 경로가 닫혔다 (2026.09.18, 45번 6·7회차). 바깥(공-발 거리 극소점)이 안쪽(e = 신전 각속도 argmax)을 가리킨다는 것 자체가 안 선다 — 클립별 분위 평균 0.422(귀무 0.5, 교정 확인 0.499). 가리키지 않으면 「여백 m 을 얼마나 줄까」는 답할 수 없는 질문이고, 6회차가 낸 m*(12·27·41)은 쓰지 않는다. 🔴 여백 크기를 다시 재는 회차를 열지 않는다 — 먼저 갈라야 할 것이 (가) 바깥이 틀렸나 (나) 안쪽이 틀렸나 이고, 둘 다 정답이 있어야 갈린다(52번 diagnose_impact.py 는 보류 · 사람 판독은 미결 2번). 🔴 「가리키지 않는다」를 증명한 것은 아니다 — n=17 에 바가 2.1 표준오차라 못 세운 것이고, 방향은 남아 있다.

🔴 야구·농구 종목 자체가 닫혔다 (2026.09.11, 미결 ho 39번). 팀 방향이 축구 단일 종목으로 정해져 루브릭 4개와 수집 어댑터를 지웠다. 아래 「팔 종목」 항목들은 그래서 더더욱 재조사 대상이 아니다 — 다만 이유가 「닫혔다」에서 「안 한다」로 바뀐 것이라, 종목이 되살아나면 아래 벽은 그대로 서 있다.

팔 종목 릴리스 정답을 외부에서 구하는 경로는 전부 막혔다 (미결 5번 「닫은 경로」).

경로 왜 닫혔나
PitcherMotion 81컬럼 이벤트 주석 없음
normalised_frame == 0 릴리스가 아니다 (표본 260 검증)
Statcast companion 프레임 인덱스·타임스탬프 없음
UCF101 클립 단위 라벨만, 공 검출 0건
외부 공개 데이터셋 Grade A 없음 — UPLIFT·MultiSports(CC BY-NC)·Penn Action·BBDB 전부
축구 표본 확대 필요 97~714 대비 상한 38. leg 종목이라 팔 종목 효과크기를 예측 못 함
offline 재분석 정답 없이 답할 수 있는 질문 소진

그 밖에:

  • A-1을 다시 구현하지 않는다. 되돌림이 1eb76ad로 확정됐다. 아카이브는 agent/eval/phaseA/eval_b7_a1_ground_truth/ — 거기서 KEEP/CHANGE 판단을 새로 내리지 않는다.
  • 대상 이어가기에 외양을 「재가중」으로 넣는 길은 닫혔다 (2026.09.09). IoU × f(app) 형태는 후보가 하나뿐인 프레임에서 argmax 를 못 바꾼다 — 그리고 갈아타는 자리가 정확히 그런 프레임이다(겹치는 후보 1개, 나머지는 IoU 0.00). 사전 등록 판정 C 가 0/3. 외양 신호가 쓸모없다는 뜻이 아니다 — 신호는 갈리고(깨끗 0.81~0.98 대 갈아탐 0.26~0.72) 쓸 자리가 없었을 뿐이라, 다음은 거부·재획득이다. agent/eval/pending18_appearance/.
  • 🔴 ref 표류가 거부의 원인이라는 진단은 닫혔다 (2026.09.10, 9회차). 거부 프레임에서 흘러간 ref 와 고정된 닻이 사실상 같은 답을 한다 — anchor_app − ref_app 이 중앙 −0.06, 최대 +0.05 다. 닻에서 거부까지 중앙 70프레임(최대 191)이 걸렸는데도 그렇다(ALPHA = 0.05 가 그 시간 동안 의미 있게 안 흘렀다). 거부 24건 중 23건은 닻도 TAU 미만이다. 기준 다섯이 다 섰고(층 A 100% · 층 B 92% 일치, 계기 검사 ρ −0.05), 3·6·7회차가 만졌던 축(갱신 규칙·구제 문턱·출력 형태)이 전부 뿌리가 아니었음이 이것으로 확인된다. agent/eval/pending18_drift/.
  • 🔴 「기하로 대상 유무를 가른다」는 길도 닫는다 (2026.09.10, 8→9회차). IoU 는 「상자가 있다」만 말하고 「그게 대상이냐」는 안 말한다. 8회차가 cont_iou 로 「없다 77%」, 사후 onset IoU 로 「있었다 73%」를 냈는데 9회차가 같은 상자에 닻을 대 보니 96%가 안 닮았다. 셋이 모순이 아니라 앞 둘이 정체성이 아니라 위치를 쟀을 뿐이다. 대상 유무는 외양으로 묻는다.
  • 🔴 「재획득 상자의 자리로 (i)/(ii)를 가른다」는 길도 닫혔다 (2026.09.10, 10회차). 재는 양은 맞았는데(길이 오염 ρ +0.11 — 8회차 결함은 안 났다) 닿는 표본이 현상이 아니다. 관문 통과 클립의 잃은 프레임 1,309 중 69%(901)가 재획득으로 끝나지 않는 구간(중앙 147프레임)이고, 이 계기가 볼 수 있는 몫은 2.6%(34프레임) 뿐이다 — 트래커가 스스로 「돌아왔다」고 말한 구간만 보이므로 커버리지 붕괴에 원리적으로 못 닿는다. 볼 수 있는 9구간 안에서도 44:56 으로 갈린다(판정 (다) 판별불가 — 섞여 있다). 🔴 표본을 늘려도 같은 벽이다. agent/eval/pending18_link/.
  • 🔴 라벨 없이 (i)/(ii)를 가르는 길이 사실상 소진됐다 (2026.09.10, 8~10회차). 기하(구간 중앙 IoU)·외양(닻 대비 app)·기하(끝점 IoU)로 세 번 물었고 셋 다 「대상인지 말해 줄 독립 근거가 없다」는 같은 자리에 닿았다. 다음은 (A) 사람 판독 70장(안 끝난 7구간 × 10프레임, 「대상이 보이는가」 예/아니오) 또는 (B) 더 강한 외양으로 되짚기(새 의존을 부르고, 실패해도 (i) 을 증명하지 못한다)뿐이다. (A)를 권한다 — 어느 쪽이 나와도 갈래가 닫힌다.
  • 🔴 축구 19편 표본으로 「여러 명 중 고르기」를 재지 않는다 (2026.09.14, 11회차). paths.soccer_clips_root() 의 19편은 전부 1인 훈련 영상이고 OpenPose 스켈레톤이 픽셀에 구워져 있다. 검출 바닥 0.3 까지 풀어도 사람 후보 수가 중앙 1 · 평균 1.44, 2명 이상인 프레임 24% 다. 공 근접 회차의 주 층이 19편에서 1프레임이었던 이유가 이것이고, 문턱도 자도 아니었다. 🔴 공 근접이라는 축 자체는 안 닫혔다 — 계기는 섰다(ρ 0.835). 막힌 것은 표본이고 미결 46번으로 올렸다. 그리고 이 표본을 쓴 회차들의 서술을 정정했다(45번 1회차 「중계 영상·골키퍼·수비벽」 · 43번 ㉮ 한계 「방송·데이터셋 영상」). agent/eval/pending18_ball_proximity/.
  • 🔴 대상 선택을 「다른 기하량」으로 바꾸는 길이 닫혔다 (2026.09.14, 14회차). argmax(area) 를 argmax(height) 로 바꾸면 공 근접 일치가 더 나빠진다 (층 A 17.7 → 9.1% · 층 B 12.1 → 8.3%, 두 층 같은 방향). 절반이 넘는 프레임에서 다른 박스를 고르는 큰 변화인데 살린 것 8·9 대 죽인 것 25·19 다. 「누운 박스 제외」(w/h 상한)도 R0 와 95~96% 같은 박스라 아무것도 안 바꾼다(LIE 0.9~1.5 전 구간). 🔴 13회차가 「폭의 뿌리는 자세」를 보인 것은 그대로 서지만, 거기서 「그러니 면적을 버리면 낫다」로 이어 적은 것은 틀렸다. 🔴 면적이 좋다는 뜻도 아니다 — M(R0) 가 12~18% 라 셋 다 대부분 틀리고 그중 면적이 덜 틀릴 뿐이다. 기하만으로는 안 된다. agent/eval/pending18_rule/.
  • 🔴 3DSP 로는 「여러 명 중 고르기」를 못 잰다 (2026.09.14). 영상이 없고 100×100 크롭 .jpg 뿐이라 이미 한 사람으로 잘려 있다. trunk_lean 같은 한 선수의 자세를 보는 데는 여전히 쓸 수 있다(미결 37번 4회차가 그렇게 썼다). 🔴 디스크에 남은 다른 후보도 없다 — sports_dataset/ 의 야구·농구는 클립 0편(수집 어댑터는 39번에서 지웠다)이고 축구는 그 19편뿐이다. ✅ 살아 있는 길은 하나다: SoccerNet 방송 클립(SoccerNet10s 어댑터가 scripts/dataset_pipeline/sources.py 에 이미 있다. Shots 5,456건. 목록은 익명으로 열리고 파일만 게이트라 허깅페이스 로그인이 필요하다). 받아도 224p 라 관문을 먼저 통과해야 한다 — 미결 46번. 🔴 「야구 39편으로 대신한다」도 측정으로 닫혔다 (2026.09.14, eval/sample_gate/). 다인률은 66% 로 충분한데 발치+다인이 0.4%(39편 중 1편) 다 — 공을 23% 나 보면서도 그렇다. 공이 안 잡혀서가 아니라 발치에 없어서이고, 45번 1회차가 원리로만 적어 둔 그것이 이제 숫자다.
  • 🔴 45번 1회차의 어깨너비 절대 거리를 인용하지 않는다 (2026.09.14, 11회차). 순위는 산다(키높이 기준과 ρ 0.835). 그런데 배율이 0.8~7.6(중앙 2.2) 으로 흩어져 단위 변환이 아니다 — 어깨너비는 촬영 방향에 따라 투영 폭이 달라지고(그 표본은 대부분 측면) 그것으로 나눈 거리가 부풀어 오른다. 미결 37번과 같은 뿌리다. 「4.82 어깨너비 ≈ 2m」 같은 크기 논증을 다시 쓰지 않는다. 그 회차의 판정 자체는 그대로다.
  • 재획득에까지 임계 미달 구제를 여는 길은 닫혔다 (2026.09.09, 5회차). 이어가기 한정 구제는 실재하는 것을 고친다(X6dC9pu5H3k 엉뚱 57 → 0, 커버 손실 0). 그런데 커버리지가 무너진 세 클립에서는 닿을 자리가 0~1프레임이다 — 잃은 173·184·196프레임 중 밴드 [0.3, 0.5) 에 잘 겹치는 검출이 각각 1·0·0개. 갈아탐과 커버리지 붕괴는 원인이 다른 두 사건이고, 후자는 대상이 후보에 있는데 외양 검사가 거부하는 것이라 구제로 안 닿는다. agent/eval/pending18_rescue/.
  • MIN_ANCHOR_IOU 를 구제가 깨끗한 클립에서 열린다는 이유로 올리지 않는다 (2026.09.09, 6회차). IYFifBJ9lH8 1프레임이 그 증상인데, 그 구제는 외양이 정당했다(app 0.64). 올리면 구제가 닿아야 할 자리도 함께 줄어든다 — production 상수이기도 하다. 증상 하나를 위해 손잡이를 돌리는 형태다.
  • 거부해도 자동 박스로 떨어지는 길은 닫혔다 (2026.09.10, 7회차). 커버리지는 되찾아진다 — 과녁 7건이 전부 100%가 됐다. 그런데 채운 1,731프레임 중 닻과 닮은 것이 16개(1%) 라, 「아무도 안 보는 것」을 「엉뚱한 사람을 보는 것」으로 바꾼 것이다. 🔴 「채울 것이 없어서」가 아니다 — 잃은 프레임의 93%에 auto[t] 가 있었고 그게 남이었다. agent/eval/pending18_coverage/.
  • 구제·채우기 문턱을 0.5로 낮추지 않는다 (2026.09.10, 7회차). 채운 프레임의 app 분포가 중앙 0.28 · 1사분 0.15 이고 문턱 근처(0.5~0.6)는 11%뿐이다. 분포가 거기 없어서 낮춰도 들어올 것이 없다.
  • PERSON_ELIGIBLE_THRESHOLD 자체를 낮추지 않는다. selector 동작 기준이라 B-1~B-6이 전부 무효가 된다. 상류가 필요하면 지정 경로 이어가기에서만 밴드를 연다 (자동 경로 비트 동일 → B-6 재실행 없음, 5회차 기준 A 만족).
  • E-1·E-2(시간축 처리)는 구현 전에 걸렀다. 사전 등록 기준으로 7개 명세가 전부 불합격. agent/eval/pending7_fps/에 판정 기준과 산정이 있다.
  • B-4/B-5 검수 60건은 표본으로서 무효다. 15fps 불일치 596건에서 뽑았는데 모집단이 1,333건으로 바뀌었다. 재검수하지 않기로 했다.
  • O2GSaYqH8JY는 selector 실패가 아니다. 라벨된 프레임의 후보가 전부 1개라 고를 것이 없었다.
  • w-AQcjcoDyA는 오진이었다 — 타자가 피사체가 맞다(ef2e3c7에서 정정).
  • 🔴 판정 프롬프트에서 「항목 취지」를 빼지 않는다 (2026.09.17, 미결 23번 C). 2×2 제거 실험에서 방향 오독이 30자리 중 5 → 9 로 거의 두 배가 됐다. 취지가 방향을 잡아 주고 있었다 — 「무엇을 하려는 동작인가」가 없으면 모델이 자세를 기준과의 거리로만 말하고 부호를 틀린다. 겨냥했던 어구 (「인사이드 면」)는 실제로 취지에서 오는 것이 맞았지만 — 어구의 출처와 방향 오류의 원인이 다르다는 것이 이 회차의 결과다(같은 어구를 쓰면서 방향은 맞는 팔이 있었다). agent/eval/pending23_evidence/RESULTS_source_trace.md.
  • 🔴 옆 등급 앵커를 끄지 않는다 (2026.09.17, 미결 23번 C). 방향 오독은 줄지만(5 → 3) 지어낸 수치가 2 → 5 → 8 로 늘고, 둘 다 끈 팔에서는 밴드 경계값까지 샜다(사전 등록 기준 R2′ 불합격). 앵커는 어투 본보기일 뿐 아니라 「말해도 되는 숫자」의 울타리다. 🔴 1회차의 대가(잘함 문장 붕괴)와 다른 축이 무너졌다 — 앞 회차에서 안 무너졌다고 안전한 것이 아니다. 좁히는 길(측정값은 남기고 문장만 줄이기)은 안 닫혔다. 🔴 2026.09.17 에 재 봤고 그것도 닫혔다 (E 회차, RESULTS_anchor_values.md). 가설은 맞았다 — 측정값이 숫자를 가두고(R3 1건, C2 는 5) 문장이 방향을 끈다(감점 방향 오독 5 → 2, 85.8 도 고쳐졌다). 🔴 그런데 잘함 문장이 1 → 6/22 로 무너져 사전 등록 기준 F 불합격이고, 되돌렸다. 무너진 모양이 패스인데 공이 뜨는 것을 칭찬하는 것이다 (“공을 효과적으로 공중에 띄울 수 있어 좋았다”). 🔴 수준별 「값」만 남기고 「뜻」을 빼면 모델이 뜻을 지어낸다 — 감점 쪽은 「지나치다/부족하다」가 값에서 읽히는데 칭찬 쪽은 「왜 좋은가」가 값에 없다. 🔴 값만 남기는 것이 아예 없는 것보다 나빴다(C2 는 1/22) — 반쪽 단서가 없는 단서보다 해로울 수 있다. 남은 갈래는 어느 등급의 문장을 남길지이고 새 사전 등록이다.
  • ✅ 앵커를 「측정값 순」으로 나열하는 것은 섰다 (2026.09.17, F 회차, RESULTS_anchor_order.md). 1회차·C·E 가 전부 「덜 준다」였고 셋 다 무언가를 무너뜨렸는데, 아무것도 안 빼고 정렬 키만 바꾸니 지어낸 수치가 0건(지금까지 최선)이고 85.8 이 고쳐졌으며 E 가 무너뜨린 잘함 문장 둘이 회복됐다. 🔴 그래도 다음 셋을 함께 읽을 것: ⑴ 방향 오독은 E 보다 나쁘다(2 → 4)이고 악화 자리가 또 옮겨 다닌다 ⑵ 기준 F 가 한 문장 차이라 판독이 갈리면 결론이 뒤집힌다 ⑶ 🔴 얻은 것이 「사다리 덕」인지 안 갈렸다 — 예측과 달리 한 방향 항목도 64%가 바뀌었다 (값이 작을수록 좋은 항목은 등급 순과 값 순이 서로 뒤집힌다). 80문장 중 52개를 건드린 변경이므로 좁은 변경이라고 적지 않는다. 🔴 2026.09.17 G 회차가 ⑶을 갈랐다 (RESULTS_order_source.md, 관측): 방향 축은 사다리 설명이 선다 — 고쳐짐 3·악화 2 가 전부 양방향 자리다. 🔴 그런데 R3 0건은 한 방향 자리에서도 일어나 흩어졌다 — 출처 미상으로 남긴다. 그리고 F 에 적은 「잘함 회복」은 이득이 아니었다(정정): 그 둘은 C0 에서도 ok 였고 한 방향이라 사다리와 무관하다. 기준선 대비 잘함 축의 이득은 0 이다. 실험 회차(한쪽만 값 순)는 열지 않는다 — 실험을 부르던 「흩어짐」이 방향 축에서는 없었다.
  • 🔴 끝맺음에 「한 방향으로만 말하라」를 덧붙이는 길은 닫혔다 (2026.09.17, H 회차, RESULTS_one_way.md). 겨냥한 것은 맞혔다 — 감점 쪽 방향 오독이 4 → 2 로 반이 되고 새 악화도 없었다. 🔴 그런데 잘함 문장이 1 → 3 으로 늘어 정확히 상쇄했다: 틀린 문장의 총량이 5 → 5 다. 2등급에서 “짧은 스윙이 패스보다 슈팅에 가깝지만” 처럼 결함 어휘가 들어온다 — 금지가 감점 쪽에만 들었다. 「줄어도 자리를 옮긴다」가 이 항목에서 일곱 번째이고 이번엔 총량까지 같다. 되돌렸다.
  • ✅ 앵커의 「문장」만 고치는 것은 평가 기준선을 안 흔든다 (2026.09.17, H). 🔴 앞서 「앵커를 고치면 eval/ 채우는 값이 바뀌어 A 기준선이 흔들린다」고 적은 것을 정정한다 — filler() 가 쓰는 것은 앵커의 값(measured)이지 문장(evidence)이 아니다. 값을 고칠 때만 흔들린다. 앵커 문장에서 결함 어휘를 걷어내는 회차(“추가 굴곡” · “슈팅” · “기준 범위 내”)는 그래서 싸다 — B-6 도 A 기준선도 안 부른다. 🔴 다만 루브릭 문구는 원래 지도자 검수 대상이라, 검수 없이 가기로 한 결정(미결 2번) 아래에서 누가 고쳐도 되는지를 사전 등록에 적을 것. ✅ 2026.09.17 에 실제로 해 봤고 값은 안 흔들렸다(I 회차, 밴드값·등급 80/80 동일). 정정이 맞았다.
  • 🔴 앵커 문장에서 결함 어휘를 걷어내는 길은 닫혔다 (2026.09.17, I 회차, RESULTS_anchor_text.md). 앵커에만 있던 세 어구가 문장에서 20건 → 0건이 됐고 — 출처 추적이 처음으로 인과로 확인됐다 — 그런데 행동은 안 바뀌었다: “기준 범위 내” 가 사라진 자리에 “기준 수준 미달”·“보통 수준” 이 왔다. 🔴 판정 메타언어는 「어휘」가 아니라 「습관」이다. 그리고 새 대가가 드러났다 — 🔴 본보기를 좋게 만들수록 통째로 베낀다. 고치기 전 앵커는 답으로 쓸 수 없는 조각이었는데(“기준 범위 중앙”) 고친 뒤엔 완성된 답이라 값까지 함께 베꼈다(0등급 앵커 값 −8.7 이 1등급 문장에 그대로 나왔다). 방향 오독 4 → 6, R3 0 → 3 으로 두 관문이 떨어져 되돌렸다. 앵커를 다시 손대려면 「베끼기」를 세는 기준을 먼저 만들 것 — 앵커 값은 「지어낸 수치」가 아니라 「남의 측정값」이라 R3 가 반만 잡는다.
  • 🔴 기계적 계수가 판독을 대신하지 못한다 (2026.09.17, I 회차). 정확한 어구를 세는 기준을 두어 통과했는데, 그 기준이 재려던 것은 안 고쳐졌다. 판독이 싫어서 기계 기준을 두면 약속한 것만 정확히 재고 빗나간다. 🔴 J 에서 또 밟았다 — 「서로 다른 문장 수」로 템플릿의 되풀이를 재려 했는데 값이 문장에 들어가 자리마다 달라 80에 붙었다. 계수가 재려는 것을 재는지부터 볼 것.
  • 🔴 미결 23번은 「제품 판단 대기」에서 멈춰 있다 (2026.09.17). 아홉 회차 (가-2 ~ I) 뒤 제품은 F 상태(앵커 측정값 순 · 방향 오독 4/30 · 잘함 1/22 · R3 0). F 이후 E·H·I 세 번 연속으로 「한쪽을 조이면 다른 쪽이 무너진다」가 났고 틀린 문장의 총량이 5 언저리에서 안 움직인다. 그래서 문장을 코드가 조립하는 판(J, SIDE_BY_SIDE_template.md)을 만들어 놓았다 — 방향 오독·지어낸 수치가 구조적으로 0이고, 대가는 말의 가짓수 76 → 37이다. 채택 여부는 제품 판단이고 그것이 풀려야 다음이 정해진다. 남은 갈래(더 큰 모델 · 파인튜닝 · 계기 잔여)는 미결 23번 「남은 단계」에 표로 있다.
  • 🔴 회차를 건너서 D(방향 오독) 숫자를 나란히 놓지 않는다 (2026.09.17, 미결 23번 C). 같은 문장·같은 규칙·같은 판독자로 다시 읽으니 3/30 이 5/30 이었다(첫 절만 맞고 뒤 절이 반대인 문장을 앞 절만 보고 넘긴 자리). 한 판에 자리별로 나란히 읽은 대조만 성립한다. 🔴 2026.09.17 보강 — 계기를 고쳤고(D 회차), 틀린 쪽은 B 였다. 절 단위 판독(eval/pending23_evidence/split_clauses.py)으로 두 번 읽어 두 번 다 C 와 같은 5자리다. 새 계기가 과하게 잡지도 않는다(숫자가 안 움직였다). 🔴 그래도 이 줄은 그대로 유효하다 — 어느 회차가 빠뜨렸는지 미리 알 방법은 여전히 없고, B·C 를 가른 것은 계기가 생긴 뒤다. 앞 회차 숫자를 새 계기로 다시 재서 갈아 끼우지도 않는다. 🔴 판정 규칙에 구멍이 남아 있다 — 「반대 조각의 방향을 주장」이 「맞는 방향을 부정하는 제3의 주장」(“약간 뒤로 젖혀져”)과 「방향을 안 말하고 문제없다고 하는 것」(“기준 범위 내”)을 안 담는데, 그 둘을 관례로 세고 있다. 넓힐지가 판단이고 새 사전 등록이다.

5. 함정

  • 🔴 uv sync 를 extra 없이 치지 않는다 (2026.09.16, 미결 47번). 그러면 aws·tracking extra 가 조용히 제거되고, 그중 torchvision 이 빠지면 transformers 가 다른 이미지 전처리기를 고른다(...ImageProcessorPil). 픽셀이 달라져 관절각이 흔들리고 등급까지 바뀐다 — 축구 19편 중 2편이 그랬다. 🔴 경고가 안 난다. 2026-09-08 에 그렇게 빠져서 B-6 기준선이 일주일간 재현되지 않았고, 다섯 회차를 썼다.
    cd agent && uv sync --extra dev --extra aws --extra tracking   # 평가 기계
    uv run python -c "from transformers.utils.import_utils import is_torchvision_available as t; print(t())"   # True 여야 한다
    

    🔴 uv.lock 이 안 바뀌었다는 것은 「같은 환경」이 아니다. 잠금 파일은 깔 수 있는 것이고 결과를 정하는 것은 깔려 있는 것이다. 지금은 eval_b6/run_meta.json 의 packages 가 그것을 적는다.

  • 🔴 좌표계. production은 identify_limb(normalize(kps), ...)로 부른다. 원 픽셀로 재면 고르는 쪽 자체가 달라진다 — 39클립에서 arm 6·leg 13건이 반대였다. 프론트가 보내는 박스는 정규화 0~1이고 표시 해상도가 아니다.
  • 🔴 프레임 격자. 사용자가 본 프레임 ≠ 파이프라인 샘플 인덱스. step = max(1, round(src_fps/target_fps))로 솎으므로 환산이 필요하다 (labeling/targets.py:remap_label_frame). 목표 fps는 실효 fps가 아니다.
  • 🔴 코드는 저장소, 데이터는 /mnt/d. 2026-09-02에 스크립트가 /mnt/d의 낡은 targets.py를 import해 라벨 재매핑이 빠진 채 B-1/B-2가 돌았다. 예외도 경고도 없이 숫자만 달랐다.
  • 🔴 근거 문장에 등급이 없다 (2026.09.07 이후). evidence는 자세 서술만 담는다. 등급 맥락은 breakdown[]의 title(칭호)·band(구간)가 붙이고, 붙이는 자리는 scoring.aggregate 한 곳뿐이다 — api.py에서 또 붙이지 않는다. 문장에서 등급을 정규식으로 뽑으려 하지 말 것. band는 임계값이 검수 전이라 선수 화면에 내지 않는다(미결 24번).
  • 🔴 리포트 봉투는 계약이다 (2026.09.10 이후, jin 27번). report.json 의 키를 늘리거나 줄이면 agent/contracts/report_schema.yaml 과 schema_version 도 함께 고친다 — 안 고치면 tests/test_report_contract.py 가 빨개진다. 그 빨간불이 목적이다: 적재·읽기 경로·화면이 같은 JSON 을 읽어서, 조용히 바꾸면 백엔드는 배포 뒤 실서버에서만 안다. 값을 더할 때는 features 가 아니라 형제 블록으로 낸다(timebase·subject·keypoint_quality 가 그 형태다).
  • 🔴 총점은 breakdown[].stat의 평균이 아니다 (2026.09.08 이후). stat은 표시 전용 연속 점수(0~100, 「이상 구간에서 얼마나 떨어졌나」)로 레이더 차트 축에 쓴다. 총점·등급은 지금까지대로 등급(0/1/2)의 가중합이고 stat은 거기에 관여하지 않는다 — features를 안 주면 None일 뿐 나머지는 한 비트도 같다(out_of_band와 같은 성질, B-6 재실행 없음). 등급별 점수대가 겹치지 않게 잘라 두어(2등급 85~100 · 1등급 50~85 · 0등급 0~50) 차트가 리포트의 등급과 반대로 그려지지 않는다.
  • 🔴 캐시 이름에 동작점이 들어 있다. cache_target15/와 cache_target30/. 그냥 cache/로 부르면 섞어 쓰게 된다 — 그것이 미결 10번의 형태다.
  • 🔴 rubrics/ 에 루브릭 아닌 .yaml 을 두지 않는다. discover_rubrics 가 그 폴더의 *.yaml 을 전부 루브릭으로 읽어 「채점 항목이 하나도 없음」으로 죽고, 워커의 SUPERSUB_RUBRIC_DIR 도 그 폴더를 가리킨다 — 배포에서 터진다. 2026.09.09에 metric_definitions.yaml 을 거기 뒀다가 test_scoring 이 잡았다. 계약 산출물은 agent/contracts/ 다.
  • 🔴 agent/ 도 공개된다. 사이트 빌드에서 제외됐다고 안 보이는 것이 아니다 — 저장소가 공개라 GitHub 에 그대로 있다. 2026.09.09까지 deploy/ 문서에 계정 ID·리소스 ID·공인 IP 가 값으로 남아 있었다(jin 22번). 커밋 전 grep 범위에 agent/ 가 들어갔다(루트 CLAUDE.md). 단위는 이름에서 유추하지 말 것도 같은 계열이다 — swing_elbow_angle_at_impact 는 _deg 가 없는데 각도이고 plant_foot_to_ball_offset 은 픽셀이 아니라 어깨너비 배수다.
  • 이상치 클립: 8gmHKqDxXdg는 원본 10fps라 target 15·30이 원소까지 같다 (fps 갈림 분모에서 뺀다). 3R1kvNrGJK0은 심판/포수를 피사체로 잡는다. h_3LqD2Pl-E는 앞 33프레임이 타이틀 카드다.
  • 데이터셋 특성: 39클립은 Kinetics hitting baseball 전수 = 전부 두 손 타격이다. usable_for_phase_B는 yes 7 · maybe 6 · no 26이고 19클립은 camera_angle부터 미검증이다. 분모가 39라고 가정하지 말 것.
  • 🔴 주석의 수를 데이터의 수로 착각하지 말 것 (2026.09.09). 「다인 10건」은 single_or_multi 주석이 다인인 것의 수였고(다인 10·단일 10·미검증 19), 후보 캐시로 실제 검출을 세면 다인 프레임 100+ 인 클립이 25건이다. 미결 18번이 세 회차를 10건으로 돈 이유가 이것이다 — 데이터가 없어서가 아니라 주석이 없어서였다. 주석 컬럼으로 표본을 정하기 전에 캐시로 세어 볼 것(라벨이 필요 없다). 주석이 단일인 LhD_fnHt_xg 도 실제로는 242프레임이 다인이다.
  • 🔴 커버리지 100%는 좋은 신호가 아니다 — 세 번 데었다 (2026.09.11 추가). 「매 프레임 봤다」가 아니라 「매 프레임 무언가를 그것이라고 불렀다」일 수 있다. 진짜가 안 보일 때 없다고 말하지 않고 엉뚱한 것을 집는 계기는 커버리지가 높을수록 더 틀린다.

       
    미결 18번 7회차 잃은 프레임의 93% 를 채웠는데 닻과 닮은 것은 1%
    미결 37번 3회차 방향 큐 커버리지 97% 인데 독립 큐와 일치 46%
    미결 45번 2회차 공 커버리지 100% 인 클립이 가장 엉터리 가속을 낸다 (33.6 어깨너비/프레임² — 물리 상한의 16배)

    커버리지 단독 기준을 세우지 않는다. 세울 거면 짝 기준(맞는가)을 같이 박는다.

  • 🔴 궤적을 쓰는 계기는 「이 궤적이 한 물체의 것인가」를 먼저 묻는다 (2026.09.11, 45번 2회차). 미결 18번이 사람에 대해 열 회차를 쓴 그 질문인데, 공에는 안 물어서 검출기의 신원 바뀜을 「가속」으로 쟀다. 단위를 물리량으로 환산해 상한을 대 보면 바로 드러난다(찬 공 20m/s ≈ 2.1 어깨너비/프레임인데 33.6 이 나왔다).
  • 🔴 계기 검사는 두 개다 (2026.09.10, 8·10회차). 「이 양이 내가 묻는 것인가」와 「이 **표본이 내가 묻는 대상인가」.** 8회차는 앞의 것이 틀렸고(cont_iou 가 대상 유무 대신 구간 길이를 쟀다), 10회차는 뒤의 것이 틀렸다(재획득으로 끝난 구간만 보여 잃은 프레임의 2.6%). 사전 등록은 「결과를 보고 기준을 바꾸는 것」만 막고 둘 중 어느 것도 자동으로 막지 못한다 — 그래서 사전 등록에 층화 한 줄과 「이 표본이 현상의 몇 %인가」 한 줄을 같이 넣는다. 둘 다 한 줄이면 끝나는 검사다. 🔴 셋이 됐다 (2026.09.14, 11회차) — 세 번째는 「표본에 그 현상이 **있기는 한가」다. 11회차는 앞의 둘을 다 통과했는데(양도 맞고 표본도 축구였다) **후보가 2명 이상인 프레임이 8% 뿐이라 주 층이 1프레임으로 비었다. 그래서 사전 등록에 관문 한 줄을 더 넣는다 — 「착수 전에 이 표본에서 그 현상이 몇 %인가. 바닥 미만이면 재기 전에 표본을 바꾼다」. 11회차에서 그 값은 GPU 100초면 나왔다. ✅ 도구로 만들어 두었다 (2026.09.14) — agent/eval/sample_gate/. --sample <표본> 한 줄이면 다인률·공 검출률·발치+다인을 낸다. 🔴 바(다인률 10%)는 다음 표본을 보기 전에 정했다. 🔴 양성 대조군(--sample phasea, 야구 39편)을 함께 돈다 — 다인 10건이 있다고 알려진 표본에서도 낮게 나오면 표본이 아니라 관문이 고장 난 것이고, 그 대조 없이 「8% 라 표본이 나쁘다」고 적으면 10회차와 같은 형태의 결함이다. 🔴 넷이 됐다 — 그리고 넷째·다섯째는 「계기」가 아니라 「판정 기준 자신」이다 (2026.09.18, 45번 5·6회차). ⑷ 「산수다」라고 적은 것에 전제가 몇 개 들어갔는지 센다 — 5회차가 층 E 의 기댓값 (L-4)/L 을 계기 검사로 박았는데, 그 식은 argmax 자리가 균등하다를 몰래 전제했고 균등성은 산수가 아니라 신호의 성질이었다. 기준선이 가설이면 그 기준선으로 계기를 판정할 수 없다. ⑸ 대조군을 단위마다 따로 만들었으면 비교도 그 단위로 한다 — 6회차가 클립마다 무작위 대조군을 만들어 놓고 전체 중앙값끼리 견줬다. 클립별 대조군의 중앙값이 5~322 로 흩어져 있어서, 집계로는 이겼는데(10 < 14) 클립 단위로는 9/17 로 동전 던지기였다. 요약 통계가 비교 불가능한 것을 묶으면 합격이 뜻을 잃는다. 🔴 둘 다 사전 등록을 지켜서 난 결함이다 — 사전 등록은 「결과를 보고 기준을 바꾸는 것」을 막지, 기준이 옳은지는 안 막는다. 그래서 사전 등록에 「이 기준이 쓰는 통계가 무엇을 전제하는가」 한 줄을 더 넣는다. ✅ ⑸ 를 바로 적용했고 먹었다 (2026.09.18, 7회차) — 요약을 클립별 분위로 바꾸니 6회차의 합격이 뒤집혔다(평균 분위 0.422 > 0.35). 🔴 고친 계기가 옳은지도 확인했다: 가짜 입력(바깥을 무작위로 갈아 끼운 것)을 같은 절차에 넣어 평균 분위가 0.499 임을 봤다. 「교정 확인」이 ⑷·⑸ 를 실제로 막는 한 줄이다 — 그것 없이 0.422 를 봤으면 「0.5보다 작으니 가리킨다」로 읽을 수 있었다. 새 회차의 사전 등록에는 「내 통계를 가짜 입력으로 한 번 돌린다」를 넣는다.
  • 🔴 적어 두는 확인 명령을 적는 자리에서 한 번 돌린다 (2026.09.18). 위 「미완 산출물」의 review_packet2 확인이 2026.09.09에 적힌 뒤 한 번도 안 돌아 봤고, 돌려 보니 틀렸다 — awk 의 NR 은 파일을 건너뛰며 계속 세므로 2·3·4번째 파일의 머리줄이 기입으로 잡혀 늘 3 이 나온다. 라벨이 0건 인데 「3건 들어왔다」로 읽힌다(FNR 이 맞다). 🔴 그때 적은 결론(0/39)은 맞았다 — 사람이 파일을 직접 봤기 때문이고, 명령만 물려받은 다음 사람이 틀리게 된다. 같은 형태로 이미 세 번 당했다: 스냅샷 테스트 수가 세 번 낡았고, 44번의 「남은 것」 한 줄이 엿새 낡아 다시 할 뻔했다. 수치와 명령은 적는 순간이 가장 싸게 검증되는 때다.
  • side 지정은 반대쪽 사지에 전달되지 않는다 — 의도다. 오른손 투수의 디딤발은 왼발이다. 자동 판별된 팔 측과 다리 측은 46%(18/39)만 일치한다.

6. 현재 상태 스냅샷 (2026.09.18)

⚠️ 이 값들은 낡을 수 있다. 착수할 때 다시 확인할 것.

   
HEAD 브랜치 ho. 2026.09.10 에 origin/ho(= main 반영분 전부) 를 흡수하고 push 했다. 그 위에 회차들이 회차마다 사전 등록 → 결과 두 커밋으로 얹혀 있다 (10회차: 3f4a415 → e182279 · 18번 11회차: 9680a3b → 65099d3 · 12회차: 2a9373c → 3fb5b2d · 13회차: 205dd01 → ee7cd8b · 14회차: 97c37e7 → 6fc6ddf). 🔴 push 는 안 했다 — 사람이 시킬 때만
테스트 578 통과 (cd agent && uv run pytest -q, 2026.09.18 실측 — 45번 5회차 판정 기준 I 로 잰 값이다. 🔴 5회차가 올린 것이 아니다 — 조사 회차라 src/·tests/ 를 0줄 고쳤다. 555 → 578 의 23건 내역: 파인튜닝 격리 검사 3(test_finetune_stays_out_of_the_product.py, 32dfc9b2) · 47번 환경 가드 6(test_eval_env_guard.py, c84f078d) · 나머지 14 는 main 에서 흘러온 남의 커밋이다). 아래는 그 앞 기록: 555 통과 (2026.09.17 실측 — 49번 드러내기의 검사 6건이 더해졌다. 🔴 그 직전 실측이 549 라 아래 457 은 이 회차에 손대기 전에 이미 낡아 있었다 — main 에서 흘러온 커밋들(오늘 병합한 70개)이 올린 값이고 그 92건은 내 변경이 아니다. 낡는 형태가 바로 아래 줄과 똑같다 — 이 표가 낡는 이유는 내가 안 재서가 아니라 남의 커밋이 흘러들어와서이므로, 병합 직후에 한 번 재는 것이 맞다). 아래는 그 앞 기록: 457 통과 (2026.09.16 실측 — 44번 워커 배선의 검사 12건이 더해졌다. 🔴 그 직전 실측이 445 라 아래 437 은 이 회차에 손대기 전에 이미 낡아 있었다 — main 에서 흘러온 커밋들이 올린 값이고, 그 8건은 내 변경이 아니다). 아래는 그 앞 기록: 437 통과 (2026.09.15 실측 — paik 30번 skeleton 봉투의 검사 22건이 더해졌다). 그 앞 실측은 415(같은 날, 43번 ㉳ 3회차의 회귀 검사 2건). 그 앞 실측은 413(2026.09.14, 45번 4회차의 검사 3건). 그 앞 같은 날 실측은 410. 🔴 362 도 또 낡았다 — 세 번째다. 이번엔 이유가 분명하다: 그 뒤에 ho 43번 ㉱·㉮ 와 44번(고를 수 있는 사람 목록)이 얹혔고 그때마다 스냅샷을 안 다시 쟀다. 아래는 그 앞 기록: 362 통과 (2026.09.11 실측). 🔴 그 앞줄의 352 도 낡은 값이었다 — 종목 정리 직후를 재고 ho 14번 커밋(test_eval_paths.py 8건)을 안 다시 쟀다. 지금 값 = 360(14번까지) + 2(paik 23번). 🔴 스냅샷 숫자는 고칠 때마다 다시 재는 것이 규칙인데 두 번 연속 어겼다. 아래는 그 앞 기록: 352 통과. 🔴 앞서 적힌 358 은 낡은 값이었다 — 종목 정리 직전 실측은 390 이고, 줄어든 38 건은 전부 루브릭 수로 매개변수화된 케이스다(테스트 함수는 오히려 하나 늘었다). 🔴 저장소 루트에서 돌리면 수집 오류가 난다 — agent/ 에서 돌릴 것
루브릭 active 1(축구 인스텝) · draft 1(축구 인사이드). 🔴 2026.09.11 축구 단일 종목 전환 — 야구·농구 루브릭 4개와 수집 어댑터를 지웠다(미결 ho 39번). eval/ 은 남겼다 — 한 회차가 6종을 같은 문서에서 쟀어서 종목으로 잘리지 않고, test_observability 가 eval/phaseA/extract.py 를 직접 읽는다. 🔴 야구·농구 루브릭을 읽던 재실행 스크립트 11개는 지금 안 돈다(머리에 꺼내는 명령을 달아 뒀다)
축구 평가 표본 (다인) SoccerNet 방송 40편 (paths.soccernet_clips_root(), 2026.09.14 확보). 다인률 98% · 🔴 사람 키 중앙 28px 라 박스 질문만 물을 수 있다(관절각·등급 불가) · 🔴 방송이라 제품 성능을 말하지 않는다 · 저장소에 안 넣는다
축구 평가 표본 (1인) 19편 (paths.soccer_clips_root()). 🔴 전부 1인 훈련 영상이고 OpenPose 스켈레톤이 픽셀에 구워져 있다 (2026.09.14 확인) — 종목 게이트·공 궤적 회차에는 쓸 수 있지만 「여러 명 중 고르기」는 못 잰다(4절 · 미결 46번)
🔴 이미지 전처리 경로 torchvision 설치 여부가 정한다 (2026.09.16, 미결 47번). 평가 기계는 uv sync --extra dev --extra aws --extra tracking 으로 torchvision 경로를 써야 B-1~B-6 자산과 비교된다. EC2 는 --extra aws 뿐이라 Pil 경로다 — 둘을 같게 만드는 결정이 미결 49번(박민호 판단 대기). ✅ 그때까지 드러내기를 넣었다 (2026.09.17) — 봉투의 preprocessing(schema_version 1.6)이 전처리기의 실물 클래스 이름을 싣는다(RTDetrImageProcessor ↔ RTDetrImageProcessorPil). 🔴 설치 여부가 아니라 고른 결과다 — 업스트림이 고르는 규칙을 바꾸면 is_torchvision_available() 은 같은 값으로 다른 전처리기를 뜻하게 된다. 점수 불변·B-6 재실행 없음. 확인: 리포트의 preprocessing 을 보거나, 기계에서 uv run python -c "from transformers.utils.import_utils import is_torchvision_available as t; print(t())"
DEFAULT_TARGET_FPS 30 (2026-09-02에 15에서 올림)
DEFAULT_MAX_FRAME_BYTES 7,465MB (= 4K 세로 300장) — 이쪽이 지금의 메모리 가드다. 장수는 해상도에서 계산한다(frames_within_budget)
DEFAULT_MAX_FRAMES 300 — 🔴 이제 폴백이다. 해상도를 모르는 컨테이너에서만 쓴다
DEFAULT_MAX_SECONDS 10.0 — 이쪽이 분석 창이다. 예산이 허락하는 상한은 해상도마다 다르다(1080p 40초·720p 90초·4K 는 10초로 여유 없음)
PERSON_ELIGIBLE_THRESHOLD 0.5 — selector 동작 기준이라 바꾸지 않는다
업로드 상한(백엔드) 200MB · 60초 · 1920x1080 — 🔴 60초는 분석 창 10초와 안 맞는다(ho 30번, 박민호 판단 대기)
지표 코드 정본 agent/contracts/metric_definitions.yaml → scripts/export_metric_definitions.py. 🔴 rubrics/ 안에 두지 말 것 — discover_rubrics 가 죽는다

미완 산출물:

  상태
pending6_side/labeling/review_packet/side_form.csv 12건 기입 완료 (머리줄 포함 13행)
pending6_side/labeling/EXCLUDED.md 뺀 27건의 명단·사유 기록됨. 🔴 subject_ok = n과 na 두 사유가 합쳐졌고 되돌릴 수 없다
pending6_side/labeling/labeled_stats.py 라벨 보기 전에 굳혔고 2026.09.04에 실행했다 — 결과는 labeling/RESULTS.md
pending6_side/labeling/review_packet2/ 2차 판독 서식 4회차. 비어 있다 — 사람이 채워야 한다. 🔴 2026.09.18 재확인: 4개 회차 전부 0/39 기입(그 앞 재확인 2026.09.09). 그래서 위 ①이 아직 막혀 있다. 🔴 확인 명령을 고쳤다 (2026.09.18) — 앞서 적힌 것이 NR>1 이었는데 awk 의 NR 은 **파일을 건너뛰며 계속 센다. 그래서 2·3·4번째 파일의 머리줄이 기입으로 잡혀 늘 3 이 나왔다 — 라벨이 한 건도 없는데 「3건 들어왔다」로 읽힌다. 파일마다 다시 세는 FNR 이 맞다:
awk -F, 'FNR>1 && $4 ~ /[A-Za-z0-9]/ {n++} END {print n+0}' review_packet2/*.csv → 0
phaseA/ 캐시 사본 cache_target{15,30} · candidates_target{15,30} 저장소에 있음

← 미결 항목으로