← 목록으로
2026-05-19 · memer · progress

C2 Door Regrounding — 분해 파이프라인 배선 + P1/P2 정확성 수정

Sub-project A Task 4 구현 · commits ec635f1, 0709aba

TL;DR

421
Tests Passed
19
Auto rds tasks
11
Manual rds tasks
0
Baseline diff

1 배경/목적 (왜)

B1 eval 시각 뷰어에서 사용자가 직접 확인한 두 결함 중 "닫힌 fixture 앞 암묵 Open 누락"이 scene-mem v2 데이터 전체에 퍼져 있었다. 근본 원인은 fine-subtask 분해가 episode별 실제 초기 door 상태에 grounding되지 않고, robocasa-365 소스의 정적 AST에만 의존하기 때문이다. 즉 cabinet이 닫혀 있어도 열어 있어도 같은 분해 시퀀스를 emit했다.

Task 3에서 DoorStateMachine(scenario-scoped, 양방향, initial=closed→Open+Close / initial=open→suppress Open emit)을 구현했고, Task 4는 이것을 실제 분해 파이프라인에 연결하는 것이다. 두 가지 정확성 버그(P1/P2)가 독립 source-verification 과정에서 추가로 발견되어 함께 수정했다.

2 작업 내용 (어떻게)

C2 배선 (commit ec635f1)

스펙 deviation 2건: (1) resolve_subtasks_with_doors에서 is_target=False로 base resolve — eval_spec target answer는 final-query site(line 1119)에서 별도 처리(legacy 유지). (2) before_step_idx: k 삽입 위치가 base[max(0,k-1)] 앞 — 스펙 테스트가 before_step_idx:1을 base[0] 앞(맨 앞)에 기대해 legacy 해석 채택.

P1 수정: double-emission (commit 0709aba)

manual_subtasks.json 일부 task의 subtask_templates에 baked "Open/Close the … door" 스텝이 있거나 conditional_steps에 door 스텝이 있을 때, --emit-door-annotations 시 DoorStateMachine이 추가로 emit → duplicate. 영향 task: CoolBakedCake, FoodCleanup, LoadDishwasher, MakeFruitBowl, MicrowaveCorrectMeal, ReturnWashingSupplies, SpicyMarinade, SteamInMicrowave.

수정: build_task_subtasks의 strip pass를 manual entry에도 적용. re.match(r"(?i)^(open|close) the .+ door", s)로 baked door step 제거. keep_mask로 stripped list 생성, _reindex_before_step_idx(reqs, keep_mask)로 before_step_idx 재계산. 예외: close-only task(PrepareSoupServing)는 sole template이 door step이라 strip 시 빈 list → if new_tmpls: guard로 보존.

P2 수정: before:open 누락 (commit 0709aba)

derive_required_door_states_setup_skips_open gate가 setup에서 문을 여는 task 또는 setup이 없는 task(MakeFruitBowl)에 before:open을 emit하지 않았다. Cabinet이 실제로 닫혀 있는 episode에서 interior access 전 Open이 생략되는 silent-wrong.

수정: _setup_skips_open gate 완전 제거. 대신 baked_templates를 regex로 스캔 → from/in/inside/into/on/on a shelf in <fw> 패턴의 첫 match index가 before_step_idx. DoorStateMachine이 runtime에 emit(initial=closed)/suppress(initial=open) 결정 → 항상 before:open 선언해도 safe.

Manual required_door_states 재작성 (11개 tasks)

새 원칙(before_step_idx = baked list 기준, strip+reindex가 stripped list로 변환) 아래 11개 task required_door_states 재작성:

Taskbefore_step_idx근거
SteamInMicrowave4"Place the bowl inside the microwave"
MicrowaveCorrectMeal2"Place the {obj} inside the microwave"
FoodCleanup2"Place the {obj} in the cabinet"
LoadDishwasher2"Place the cup in the dishwasher"
MakeFruitBowl2"Pick up the {obj} from the cabinet"
ReturnWashingSupplies2"Place the {obj} in the cabinet"
CoolBakedCake1"Pick up the cake from the oven"
SpicyMarinade2baked idx=1 기준
PrepareCoffee, SetUpCuttingStation, YogurtDelightPrepas-is기존 correct

TDD 테스트 (총 6개)

3 결과 (수치)

421
passed, 1 skip
0
new failures
19
auto rds (non-empty)
11
manual rds tasks
TDD 단계별 검증: Step 2 red → ImportError: cannot import name 'resolve_subtasks_with_doors' 예상대로 fail. Step 5 green: 3/3 regrounding passed. 스펙 결함(존재하지 않는 parsed 키) 자동 탐지 — real ClassElements 신호로 adapt.

4 Takeaway

C2 door state machine이 분해에 실제로 연결됐다. 19 composite task가 scenario별 door re-grounding 대상이 됐고, manifest 없을 때는 legacy path byte-identical — baseline 재현 보장·비파괴.

P1/P2 두 silent-wrong 버그는 TDD red 단계가 아닌 별도 source-verification에서 발견됐다. "silent-wrong 절대 금지" 원칙이 구현 레벨(loud KeyError)에선 잘 작동하지만, 파이프라인 의미상 wrong(중복 emit / Open 누락)은 end-to-end spot-check가 필수임을 재확인.

설계 결정 기록: P2에서 _setup_skips_open을 gate로 유지하는 대신 완전 철거한 이유 — 실제 door state를 아는 DoorStateMachine이 runtime에 emit/suppress를 결정하는 게 더 정확하고, 정적 gate가 edge case(MakeFruitBowl)를 놓치는 패턴이 반복됐기 때문. "oracle-driven emit, static-gate 제거"가 Sub-project A의 핵심 원칙이다.

5 Next Steps