--state-align leadup 보정slot=0.00, action=0.00으로 붕괴. 항상 정답 place 대신 그 다음 동작 close door를 예측(over-advance).chunk[tfi-1]로 한 칸 당기는 --state-align leadup 추가(토글, 캐시 격리).estimated_cost → COST $X 출력.m3=control(텍스트 무효과), m2<control(시각 keyframe 해로움) → 메모리는 control을 못 이기고, "M2 best"는 chunk 착시였음.벤치는 "로봇이 긴 영상으로 여러 task를 수행한 뒤, 메모리를 반영해 다음 fine sub-task를 내보내는 능력"을 측정한다. oracle 세그먼트를 순회하다 타깃 세그먼트에서 fine-step을 walk하고, target_fine_idx(tfi) 스텝의 예측만 GT와 slot match(action∧object∧place)로 채점한다.
1·2차 측정에서 메모리 메서드(control / m1 / m2 / m3)를 한꺼번에 돌렸더니, 강모델일수록 M3(텍스트 running-notes)가 slot=0으로 붕괴했다. 사용자 직관은 "M3 메모리가 ...Now closing the freezer처럼 다음 동작을 미리 적어버려서 계속 틀린다"였다. 이번엔 메서드를 하나씩 손보기로 했고, M3(TEXT)부터 들어갔다.
place인데 control·m3 둘 다 place를 단 한 번도 예측하지 않음. 항상 Close the door 류를 출력. place_acc≈0.59는 살아있는데 action_acc≈0.00.같은 (scenario, test_id)끼리 control(메모리 0)과 m3(텍스트 메모리)의 예측을 맞대어 비교했다. 메모리가 원인이라면 m3가 control보다 더 심하게 over-advance해야 한다.
| gemini-3.5-flash (n=298) | 값 | 해석 |
|---|---|---|
| control도 close 예측 (both) | 182 | 메모리 0인데도 over-advance |
| control만 close | 6 | — |
| m3만 close (메모리가 민 것) | 13 | 순효과 +7 (≈2.3%) |
| control과 글자까지 동일 예측 | 239 / 298 (80%) | 메모리가 답을 바꾸는 일 자체가 드뭄 |
"Now closing the freezer"는 모델이 잘못된 STATE를 보고 쓴 증상일 뿐 — 예측과 노트가 같은 STATE에서 파생된 쌍둥이라 상관은 높지만 인과는 아니다. control이 이 교란을 끊어준다(메모리 0, 같은 STATE, 같은 오류).데이터에는 세그먼트 경계만 있고 fine-subtask별 프레임 경계는 없다. 그래서 runner가 타깃 세그먼트를 fine 개수 K로 균등 비율분할한다. 예: combo_002_..._0006의 seg0=[0,724), K=4, tfi=1:
채점 스텝에서 chunk 모드는 chunk[tfi]=[181,362)를 STATE로 보여준다. 이 윈도의 마지막 프레임(~362)은 place가 이미 끝난 장면이다. "다음에 뭘 할까?"를 물으면서 행동 완료 장면을 주니, 모델은 정상적으로 그 다음 fine인 Close the freezer door(=실제 tfi+1)를 답한다. leadup 모드는 윈도를 한 칸 당겨 chunk[tfi-1]=[0,181)을 보여준다 — 마지막 프레임이 place 직전이라 "다음 행동"이 곧 타깃 Place the steak가 된다.
over-advance는 fixture(freezer)는 그대로 두고 action만 한 칸 앞서간다. 그래서 place_ok(freezer 일치)는 살아남고 action_ok(place→close)만 죽는다. 측정에서 본 place_acc≈0.59 / action_acc≈0.00 패턴이 정확히 "딱 +1칸 over-advance"의 지문이다.
runner.run_test의 타깃 walk를 _walk_chunk(기존 보존) / _walk_leadup(보정)로 분리. --state-align {chunk,leadup} 토글, RunConfig.state_align. leadup 캐시는 cache/.../align_leadup/ 별도 subdir로 라우팅해 기존 chunk 결과(수백 $ 든 측정)를 보존하고 A/B를 가능하게 함.estimated_cost.amount(USD, Letsur 실청구 기준)를 반환 → OpenAIClient._accumulate가 콜마다 누적, runner summary usage + COST $X 출력. 로컬 단가표 추측 불필요.| method | slot | action | place | leadup 비용 |
|---|---|---|---|---|
| control (메모리 없음) | 0.00 → 0.80 | 0.00 → 0.80 | 0.60 → 1.00 | $0.23* |
| m3 (텍스트 메모리) | 0.00 → 0.80 | 0.00 → 0.80 | 0.67 → 1.00 | $1.13 |
| m2 (시각 keyframe) | 0.20 → 0.33 | 0.33 → 0.33 | 0.60 → 0.73 | $1.59 |
*control은 캐시된 증분 측정만 $0.23. 풀 5셀(60 calls)은 ~$1.15. per-call ≈ $0.0192, prompt ≈ 9.1k tok/call(이미지가 초기 추정의 2배), per-scenario(3 tests) ≈ $0.23.
slot 0.00→0.80으로 회복 → STATE 윈도 off-by-one이 1차 원인임이 실측 확정. Close the freezer door(action❌) → Place the steak(slot✅).Navigate to the oven, Pick up the bowl) — 주입된 과거 keyframe 이미지가 모델을 이전 상태로 끌어당긴다. 기존 "M2 best"는 모두가 over-advance하던 깨진 측정 하의 착시였을 가능성이 크다.combo_002_L29_S48_* 같은 템플릿 변종 — 사실상 3개 test 타입 × 거의 동일한 1개 구조. OvenBroilFish는 m2에서 5/5 전부 Navigate to the oven으로 동일 실패(구조적이지만 다양성 0). 결론 확정 전 다른 시나리오 패밀리 + 큰 n 필요.Close the cabinet door로 틀린다 — context의 알려진 데이터 tfi 버그 클래스로, 윈도 보정과 별개로 데이터 수정이 필요하다.estimated_cost를 ground truth로 매 run이 출력하므로 본런 전 단가가 사전확인된다."API를 너무 자주/드물게 부르는가?"를 데이터로 확인했다(다양한 셋 111개 타깃 세그먼트, 소스 20fps, 영상 디코딩 없이 세그먼트 경계 + fine 개수만 사용).
| 항목 | median | 범위 (min–max) |
|---|---|---|
| 세그먼트 길이 | 43초 | 12 – 164초 |
| K (세그먼트당 fine 수) | 5 | 2 – 8 |
| fine-subtask 1개 실시간 (평균) | 11.8초 | 3.3 – 82초 |
| API call 1개가 커버하는 윈도 span | 11.8초 | 3.3 – 82초 |
| 윈도당 보여주는 프레임 수 (cap 8) | 8 | 6 – 8 |
| 윈도 내 프레임 간격 dt | 1.5초 | 0.5 – 10초 |
1 API call = 1 fine-subtask로 강제하므로, 연속 call의 video-time 간격(≈11.8초) = fine-subtask 평균 길이(≈11.8초). 한 fine를 8프레임(≈1.5초 간격)으로 보여줘 해상도도 합리적. 정정: 181프레임은 20fps에서 9초지 90초가 아님§5의 5셀은 전부 combo_002 단일 템플릿이었다. 서로 다른 12개 패밀리(각 1 시나리오, --val-list)로 control/m3/m2를 전부 leadup으로 측정해 일반화를 확인했다. (chunk 베이스라인은 비용상 생략 → 메서드 간 비교.) gemini-3.5-flash, n=39.
| method | slot | action | place | exact |
|---|---|---|---|---|
| control (메모리 없음) | 0.333 | 0.385 | 0.718 | 0.128 |
| m3 (텍스트 메모리) | 0.333 | 0.385 | 0.718 | 0.103 |
| m2 (시각 keyframe) | 0.128 | 0.308 | 0.564 | 0.000 |
chunk 모드에서 M2가 1등이던 건, 모두가 over-advance하던 상황에서 keyframe이 우연히 덜 틀린 것이었다. 윈도를 고치자 메모리는 둘 다 control을 못 이기고, 시각 메모리는 오히려 net-negative다. 또한 combo_002의 0.80은 비대표적 — 다양한 패밀리 절대정확도는 control도 0.333으로, over-advance를 고쳐도 다른 실패모드(fine 경계 어긋남)가 남는다. 현재 결론: next-subtask 단일 프롬프트 + 약모델 조합에선 메모리 이득이 없다.
비용: control $3.31 + m3 $3.36 + m2 실제 ~$4.5 ≈ $11. (m2는 병렬 실행 중 게이트웨이 일시오류로 1셀 크래시 → 순차 재실행 복구; 코드 버그 아님(오프라인 정상). 교훈: 비싼 sweep은 순차로.)
소스 로그: claude/260623/analysis-m3_overadvance_leadup_fix.md · 커밋 4641d99 · 결과 results/gemini-3.5-flash__{control,m3,m2}__full__align_leadup.json