작업 계획 — 무엇을 고칠 것인가
2026-08-01 · 배경 씨드 / 배경 생성 계보 · 이 문서가 남은 일의 단일 목록이다
왜 이 순서인가. 그림이 이상할 때 원인은 세 군데 중 하나다 —
①지시가 전달이 안 됨 ②지시 문구가 나쁨 ③심사가 나쁜 것을 고름.
지난 며칠 이 셋을 헷갈려 헛돌았다. 4층으로 그린 그림이 있었는데 심사가 3층을
골랐고("모델이 못 그린다"고 두 번 오진), 간판에 글자만 덜렁 나온 것도
문구가 아니라 전달이 안 되고 있었다.
그래서 전달(돈 0) → 심사(돈 조금) → 그림(돈 듦) 순서로 간다.
1단계 · 전달배선이 맞는지 자동 검사. 비용 0
2단계 · 심사그림은 안 그리고 판정만 재측정. 소액
3단계 · 그림1곳 → 4곳 → 전체, 매번 육안. 비용 발생
완료 이미 끝난 것 — 다시 하지 말 것
| 항목 | 결과 | 커밋 |
| 정책 SOT — 불가능한 조합을 실행 전에 거부 | 완료 유닛 9건 | 4e20f0f4 |
| 어휘 ratchet — 금지 어휘가 더 늘지 못하게 잠금 | 완료 유닛 5건, 주입 검증 | 1a5d58d7 |
| 전체 파이프라인 문서(84스텝·12탭·CP 계약) | 완료 | 71242870 |
| 테스팅 플랜 | 완료 | b590363d |
| 실험 하네스 25건 백업 | 완료 artifact/20260801_실험_하네스/ | — |
1단계 · 전달 결함 Codex가 찾은 것 — 지금 이걸 잡는 테스트가 하나도 없다
중요. 아래 5건은 지금 production 경로에 있는 결함이다.
그리고 현재 테스트가 하나도 잡지 못한다 — 그 사실 자체가 커버리지 구멍이다.
| № | 무엇이 잘못됐나 | 고치면 | 상태 |
| A1 |
선행 단계와 계약이 열려 있다. 검색 참조를 만드는 단계와 씨드를 만드는 단계 사이에
의존 관계가 없다. 게다가 "선행 미실행"과 "대상 0건"을 구분 못 해, 정상 판정을 뒤집거나
반대로 15그룹을 조용히 참조 없이 내려보낸다. 양방향 결함 |
실패 6건 함께 해소 · 계약 유닛 11건 신규 · 구 CP default-deny 흡수 |
완료 a6394a78 |
| A2 |
지시문이 실제 그림 요청에 안 실린다. 밑그림용 프롬프트에만 붙고 정작 3장을
그릴 때는 빠진다. 카나리 A/B로 확인 — 각 장에 넣으니 기관 표장이 0/2 → 2/2 |
전 롤 주입 · 테스트가 결함을 먼저 재현 |
완료 26556758 |
| A3 |
씨드 이미지의 출처가 기록되지 않는다. 참조 사진을 썼는데 input_image_ids가 비어 있어
계보가 끊긴다 | form_ref 자산을 입력 간선으로 영속 |
완료 26556758 |
| A4 |
다시 돌리면 과거 기록이 소급해서 바뀐다. 후보 파일 이름이 고정이라 재실행이
이전 후보를 덮어쓴다. 그런데 더 큰 것은 계보였다 — 참조 자산 한 줄의 경로를 계속
갱신해 왔고 씨드가 그 자산을 입력으로 가리키므로, 재검색 한 번이 과거 씨드의 입력
기록을 다른 이미지로 바꾼다. 기록이 조용히 거짓이 된다 |
라운드마다 새 자산 · 기존 줄은 고치지 않고 검증만(어긋나면 정지) ·
이전 라운드는 옮기지도 덮지도 않음 · 중간에 끊긴 실행은 유료 호출 0으로 이어받음 ·
회귀 106건 + 위반 주입 56건 · 실제 DB 로 계보 불변 확인
★리뷰에서 더 깊은 결함이 다섯 번 나왔다. ①기록(파일)과 자산(DB)이 서로 다른
곳에 저장되는데 기록을 먼저 확정해서, 뒤 그룹이 실패하면 앞 그룹 자산만
사라지고 기록은 "완료"로 남았다 → 순서를 뒤집어 자산을 확정한 뒤에 기록한다.
②"표시가 없으면 옛 방식"으로 판단해서, 현재 기록이 손상돼 표시만 사라져도 옛
방식으로 내려가 검사가 통째로 면제됐다 → 옛 방식 여부는 기록 버전으로만.
③기록의 머리말과 본문이 서로 같은 회차의 것인지를 안 봐서, 머리말의 자산 번호만
바꾸면 재개가 자산을 하나 더 만들었다 → 머리말과 본문을 묶고, 그 검사를
읽는 함수 자체에 걸었다. ④목록 파일이 없으면 회차 폴더를 아예 보지 않아
같은 번호를 다시 열고 자산 번호를 갈아치웠다 → 목록이 없어도 폴더를 본다.
⑤기록을 검사하기 전에 먼저 저장해서, 잘못된 값 한 번이 그 회차를 영영 이어갈 수
없게 만들었다 → 저장 전에 검사하고 읽기·쓰기가 같은 검사기를 쓴다.
★내가 넣은 검사 하나는 방향이 틀려 정상 경로를 막았다 — "지금 쓰는 팩과
같아야 한다"고 검사했더니 이름만 바뀐 경우까지 거부했다. 무효화 판단은 지문이
하고, 팩·정책은 회차를 열 때 그때의 기록으로 고정해 대조만 한다 |
✅ 완료 e7d5ffb9 · Codex APPROVED(리뷰 8회) |
| A4+ |
참조 검색이 이미 통째로 죽어 있었다. 재사용 판단에 쓰는 함수가 호출되자마자
멈춰(이름 하나가 빠져 있었다) 모든 그룹이 조용히 실패로 떨어진다. 그 함수를
실행해 보는 테스트가 하나도 없어 드러나지 않았다. A4 를 다 해도 유료 실행은 못 했을
자리다 |
봉합 + 같은 종류를 전체 코드에서 훑어 2건 더 발견·수정(현재 0건) ·
실행 경로를 실제로 태워 "유료 호출 0회 · 전 그룹 실패"를 재현한 뒤 고침 |
완료 4429f10f |
| A7 |
"편집으로 못 고친다"고 판정된 결함을 편집으로 고치려 든다. 검사 단계가
층수·규모처럼 다시 그려야만 되는 결함을 따로 표시하는데, 다시 그리는 경로가
아무 데도 연결돼 있지 않아 그 결함이 그대로 수정 지시에 실렸다. 게다가 씨드는
수정본을 재판정 없이 원본과 바꿔치운다.
★휴면이 아니라 이미 난 손해 — 25그룹 중 8그룹에서 구조 결함
11건이 수정 지시에 실렸고, 그중 3그룹은 고칠 수 있는 결함이 하나도
없어 못 고칠 것만으로 유료 호출을 태웠다 |
"꺼짐"을 동작으로 정의 — 그 결함은 손대지 않고 기록만 · 편집 대상 0이면
유료 호출 0 + 원본 유지 · 공용 기본값은 그대로 두고 씨드만 명시 전환 ·
켤 때 재판정·브리프 결손은 첫 유료 호출 전 차단 · 정책을 지문·CP 양쪽에 |
완료 · 유닛 25 · 위반 주입 13 |
| A5 |
키 예비 전환이 동시 호출에서 요청 하나를 버린다. 실패한 호출이 쓴 슬롯이 아니라
"그 시점의 전역 슬롯"을 기준으로 바꾼다 — 실측 재현됨 |
실패 슬롯 기준 전환 · 슬롯·키 원자 읽기 · Router 도 생성 슬롯과 짝으로 ·
소비 경로 17곳 전부 이행(Router 4 + litellm 직접 13) · 소스 잠금 3종 · 유닛 +23 |
완료 00f00e10 → a5fb9471 → b0d6582c → 1dfad83e |
| A6 |
두 심판 점수를 검증 없이 평균낸다. 한 심판이 후보를 빠뜨려도 그냥 넘어가,
후보마다 심판 수가 다른 평균을 비교한다. 지금 테스트는 오히려 이 무시를 정상으로 잠그고 있다 |
심판 응답 원자 검증(1..N 정확한 순열) · 하나라도 깨지면 그 심판 전체 제외 ·
전 후보 동일 분모 · valid 0명 fail-closed · 제외 사유 기록 · 판정 계약과 물리 모델을 hash 축에 |
완료 74f2b04e + 19fb2e65 |
1단계 부록 · 재리뷰 이행 A1~A3 를 고친 뒤 세 차례 재리뷰에서 나온 것
고쳤다고 끝이 아니었다. A1~A3 이후 재리뷰가 세 번 돌았고 매번
새 결함이 나왔다. 특히 3차는 내 수정 자체가 만든 결함이었다 — 계보 검증이
경로를 상대로 바꿔 비교하는데 DB 는 절대로 돌려주므로, 유료 실행에서 정상 참조가
전부 막혔을 상태였다. 내 유닛이 이를 못 잡은 이유는 fake 를 구현과 같은 함수로
만들었기 때문이다 — 구현이 아니라 mock 을 검증하고 있었다.
| 회차 | 무엇이 잘못됐나 | 고침 | 상태 |
| 1차 | config_hash 불변 · 구 CP 키만 검사 · 계보 optional 등 7건 |
계약 유닛 27건 | 완료 e18a776e·cc5f12ac |
| 2차 | 구 CP 의 stale no_spec 이 순수 T2I 하강을 다시 열었다(소비자가
producer 분할을 그대로 믿음) · 존재하지 않는 UUID 가 정상 계보로 기록 · 소비 기록 미영속 ·
critique 공유 문안 빈 문자열의 기록↔실행 불일치 |
분할 공유 helper · 현재 spec 기준 재계산 exact 비교 · 자산 실존·소유·경로
검증 · CP typed 영속 · 소비 계약 v2 로 hash 갱신 · 유닛 27→46 |
완료 777f9da8 |
| 3차 | 정상 DB 자산이 전부 거부됨(ORM 은 절대, 비교는 상대) ·
계약 검증이 _execute 에서 .get 연쇄에 막혀 도달조차 못 함(422 대신 500) |
양쪽 절대 정규화 · 검증 순서 교정 · ImagePathType round-trip 회귀 ·
_execute 경로 테스트 |
완료 663f528e |
A5 는 "동시성" 한 건인 줄 알았는데 실제로는 도달 범위 문제였고 층이 셋이었다.
①동시성 ②Router 가 생성 슬롯을 안 기억함 ③소비자가 helper 를 안 씀.
③이 가장 컸다 — Router 직접 호출 4곳(Codex 지적)에 더해, litellm 직접 호출 13곳(10파일)이
전부 OpenAI 모델인데 api_key= 를 안 넘겨 환경변수로 해석됐고, 브로커는 그 변수를
한 번도 건드리지 않았다. 즉 키가 죽으면 그 13곳은 보조 키를 못 써 보고 죽는다.
★교훈 = "고쳤다"는 helper 를 고친 것이지 경로가 그것을 쓴다는 뜻이 아니다.
helper 를 만들었으면 누가 안 쓰는지 전수로 세어라.
2단계 · 심사 신뢰도 그림은 안 그린다 — 이미 있는 것으로 판정만 다시
| № | 무엇을 | 왜 | 상태 |
| B1 | 같은 이미지에 판정을 5회 돌려 답이 일치하는지 |
여기서 표시면 재작화(간판) 편입 가부가 갈린다. 지금 회차마다 답이 다르다
("고칠 가치 있음"↔"없음", 크기 medium↔small) | 다음 |
| B2 | 층수 계수 절차가 실제로 작동하는지 표본 확대 |
이미 2회 역전 확인 — 표본을 늘려 확정 | 대기 |
| B3 | 탈락 후보까지 갤러리에 걸어 육안 대조 |
선정본만 보면 원인을 오진한다(두 번 겪음) | 대기 |
어휘 이행 부채 13건 — ratchet이 이미 잠가 뒀으니 하나씩 지우면 된다
장소를 알리는 표시물의 통칭 자체를 코드·프롬프트에서 뺀다.
일반화된 표현은 "장소를 알리는 활자나 표시가 들어가는 면"이고 판정은 VLM이 한다.
업종명·작품 고유명사도 마찬가지. 팩은 덮어쓰지 않고 새 버전으로 발행한다.
| 대상 | 건수 | 방법 | 상태 |
| 활성 팩 (저작·판정·결함·표시면 절) | 6 | 중립 어휘로 새 버전 발행 | 대기 |
| 활성 모듈 (씨드·배경 렌더·항공뷰·프롬프트 서비스·포즈·연속성) | 7 | 스키마 필드 개명 + 호출부 이행 | 대기 |
테스트 정리 배경·씨드 영역 95파일 1439건 중 22 실패
| 실패 | 건수 | 성격 | 처리 |
| 옛 실험 슬라이스 | 10 | 미분류 | 열어보고 실험 잔재면 격리 |
| 씨드 스텝 계약 | 6 | 실제 결함 | A1이 함께 해결 |
| 기타 (스모크·hygiene·determinism·팩 v7) | 5 | 미분류 | 열어보고 분류 |
| 팩 membership stale | 1 | 낡은 단언 | 즉시 수정 |
★22건 중 실제 결함으로 확인된 것은 6건뿐이고 16건은 아직 성격을 모른다.
"전부 기존 실패"로 뭉뚱그리지 않는다.
3단계 · 새 기능 위가 끝난 뒤 — 지금은 설계만 있고 코드가 없다
| 항목 | 내용 | 상태 |
| 사전조사 배선 | 입지→규모→구성→작명 4축을 실제 단계로 연결. 모듈은 있는데 아무도 부르지 않는다 | 미구현 |
| 표면 기준 선택 | 재질·분위기용 참조를 형태용과 따로 고른다 | 미구현 |
| 새 단계 3개 | 저작·전략 판정 / 선 스케치 + 구조 게이트 / 표시면 재작화 | 미구현 |
표시면 재작화는 B1을 통과해야 넣는다. 심사가 회차마다 다른
답을 내는 상태로 넣으면 운에 맡기는 셈이다.
절대 제약 전 항목 공통
- 하드코딩·하드프롬프팅 금지 — 작품 고유명사, 업종명, 표시물 통칭, 대상 그룹 상수 배열 전부
- 자동 테스트는 결정론 영역만 — 이미지 품질은 실험 반복 + 육안이고 최종 판정자는 사용자다.
통과 건수를 품질 근거로 쓰지 않는다
- 재생성이 개선을 보장하지 않는다 — "통과할 때까지 다시 그리기" 금지.
자격 미달이면 fail-closed, "가장 덜 나쁜 후보" 채택 금지
- 프롬프트 팩은 덮어쓰지 않는다 — 새 버전 디렉토리로만
- 산출물은
artifact/ 아래, 웹서버는 포트 8940 하나 — 새 포트를 띄우지 않고 서브패스만 추가