한 줄을 고치러 갔다가, 기준선이 흔들리는 것을 봤다

오전에 쟀던 결함(「창은 열렸는데, 창이 값을 바꾼다」)을 오후에 고쳤습니다. 고친 것은 한 줄입니다 — 임팩트 뒤 감속을 찾는 탐색이 구간이 아니라 영상 끝까지 가고 있었습니다.

예측을 값까지 박고 시작했습니다

이 저장소의 규칙은 고치기 전에 합격선을 숫자로 굳히는 것입니다. 이번에는 한 걸음 더 갔습니다 — 무엇이 얼마로 바뀔지를 미리 적었습니다. 평가셋 78개 산출 중 정확히 둘, 그리고 그 둘의 값까지.

맞았습니다. 둘뿐이었고 값도 그대로였습니다. 셋째가 바뀌었으면 불합격으로 적기로 했고, 그럴 일은 없었습니다.

바뀐 크기의 감각: 10프레임짜리 구간에서 「마무리 86프레임」이라고 세던 것이 6이 됐습니다.

뜻밖의 확인 하나

오전 회차에서 「이 값은 등급에 안 쓰이고 설명 문장으로만 나간다」고 코드를 읽고 적었는데, 이번에 평가 290행 전체에서 확인됐습니다 — 값이 바뀌어도 등급도 점수도 한 칸도 안 움직입니다.

🔴 뒤집으면 이 결함은 점수로는 절대 안 드러난다는 뜻입니다. 숫자만 보고 있었으면 영원히 못 봤을 자리이고, 그래서 오전에 구간을 걸어 재기 전까지 아무도 못 봤습니다.

그런데 이게 오늘의 큰 뉴스가 아닙니다

지표를 바꾸는 변경이라 평가 전체를 다시 돌려야 했습니다. 규칙대로 두 번 돌렸습니다 — 고치기 전 한 번, 고친 뒤 한 번. 앞의 것은 저장소에 든 기존 결과와 맞춰 보기 위한 것이었습니다.

안 맞았습니다.

같은 자산·같은 환경에서 돌렸는데 85행이 다릅니다. 어떤 영상은 등급이 B에서 D로 갑니다. 심지어 「촬영·검출에만 의존하고 채점 정의와는 무관해야 할」 열까지 달라졌는데, 그 열은 저희 재실행 문서가 「여기가 어긋나면 환경이 변한 것」이라고 못 박아 둔 자리입니다.

그래서 원인을 하나씩 지웠습니다.

  • 환경? 아닙니다 — 라이브러리·드라이버·설정이 기록과 똑같습니다.
  • 모델 가중치가 바뀌었나? 아닙니다 — 받아 둔 스냅숏이 하나뿐이고 8월 25일자입니다. 갈아탈 것이 없었습니다.
  • GPU 계산이 실행마다 흔들리나? 🔴 아닙니다. 이게 오늘 처음 실측됐습니다 — 같은 코드로 두 번 돌린 290행이 의도한 두 열 말고 전부 똑같습니다.
  • 읽은 프레임 수도, 채점 기준 파일도, 품질 게이트도 아닙니다.

남은 것은 지난 닷새간의 코드 변경입니다. 그리고 단서가 하나 있습니다 — 검출 결과를 저장해 둔 것에서 읽는 쪽(195행)은 완전히 일치하고, 검출을 그때그때 다시 돌리는 쪽만 갈렸습니다.

🔴 정정 (같은 날 저녁) — 코드도 아니었습니다

「하나씩 돌려 보면 바로 나옵니다」라고 적고 실제로 돌렸는데, 탐색을 시작하기도 전에 끝났습니다. 양 끝점을 재 보니 「맞는 쪽」이 아예 없었습니다 — 그 결과를 낸 바로 그 커밋으로 돌려도 안 맞습니다. 그리고 9월 2일 · 9월 8일 · 오늘 세 시점의 코드가 서로 완전히 같은 값을 냅니다.

즉 지난 2주간 어떤 코드 변경도 이 값을 건드리지 않았습니다. 제가 예측으로 박아 둔 두 후보도 둘 다 틀렸습니다.

덤으로 기록 하나가 바로잡혔습니다 — 체크섬을 떠 보니 그 결과 파일은 9월 8일이 아니라 9월 2일 산출이었습니다. 그날 갱신된 것은 다른 쪽 파일뿐이었습니다.

그래서 남은 후보는 전부 버전 관리 밖입니다: 평가에 쓰는 영상 파일(용량 때문에 저장소에 안 들어가고, 체크섬을 아무도 안 남겨 뒀습니다)과 그때 그 실행의 정체(실행 기록을 파일로 안 남기기로 되어 있습니다).

오늘 할 수 있는 최선을 했습니다 — 평가 입력 61개의 지문(md5)을 저장소에 남겼습니다. 과거를 복원해 주지는 않지만, 다음에 같은 일이 나면 1초에 갈립니다. 오늘 못 가른 이유가 정확히 그 파일이 없어서였습니다.

그래서 규칙 하나를 바꿨습니다

평가 스크립트에 이렇게 적혀 있었습니다 — 「실행 기록은 파일로 남기지 않는다. 보고서에 적는다」.

🔴 「보고서에 적는다」는 사람이 적어야 남는다는 뜻이고, 그날 아무도 안 적었습니다. 그래서 이제 매 실행이 자기 기록을 파일로 함께 냅니다 — 읽은 영상 61개의 지문, 어느 커밋으로 돌렸는지와 작업 중이던 변경이 섞여 있었는지, 라이브러리·GPU·모델 버전, 그리고 메모리가 모자라 계산을 쪼갰는지까지.

마지막 항목은 저희 문서가 「확인할 방법이 현재 없다」고 적어 둔 자리였습니다. 이제 있습니다.

기능을 넣고 평가를 한 번 더 돌려 결과가 한 글자도 안 바뀌는 것을 확인했습니다 (덤으로, 같은 환경에서 세 번 연속 같은 값이 나왔습니다 — 재현성 자체는 튼튼합니다). 못 고친 것은 과거입니다. 오늘 이전 실행들에는 이 기록이 없습니다.

왜 이걸 크게 적는가

평가 기준선이 흔들린다는 것은 그 위에 세운 결론들이 함께 흔들린다는 뜻입니다. 지금 당장 서비스가 새는 것은 아니지만, 제안서 3장의 검증 수치가 여기서 나옵니다.

그래서 별도 항목(미결 ho 47번)으로 올렸습니다. 다음 회차는 드리블 쪽이 아니라 이쪽입니다.

마지막으로 — 제가 어긴 것 둘

⑴ 검사를 하나 넣기로 적고 둘을 넣었습니다. 구간이 없는 경우와 있는 경우는 한 검사로 둘 다 못 잡습니다. 숫자를 맞추려고 검사를 지우는 대신 어긋난 것을 적었습니다.

⑵ 사전 등록의 「멈춤 규칙」을 잘못 썼습니다. 「기존 결과와 안 맞으면 다른 판정도 멈춘다」고 적었는데, 실제로는 그 판정들이 그 대조에 기대고 있지 않았습니다(격리는 두 번째 대조가 혼자 세웁니다). 규칙은 규칙대로 불합격으로 적고, 다음부터는 멈춤 규칙을 걸기 전에 「어느 판정이 어느 기준에 실제로 의존하는가」를 먼저 쓰기로 했습니다.

상세·판정표·재현 명령은 미결 항목 ho 43번 ㉳ 3회차와 ho 47번에 있습니다.