Skip to content

[Template+Agent] 첫 CODE 스텝 템플릿 씨딩 [ #318 ] - #321

Merged
dldnsgkr merged 1 commit into
developfrom
unhak/template-seeding
Sep 10, 2026
Merged

[Template+Agent] 첫 CODE 스텝 템플릿 씨딩 [ #318 ]#321
dldnsgkr merged 1 commit into
developfrom
unhak/template-seeding

Conversation

@dldnsgkr

Copy link
Copy Markdown
Collaborator

#320 까지는 없는 템플릿을 거절하는 데까지였다. 통과한 뒤의 동작은 여전히 백지 생성이라, 사용자가 고른 템플릿은 아직 아무 데도 반영되지 않았다. 이게 #318 의 마지막 조각이다.

무엇

첫 CODE 스텝에서 씨앗 tarball 을 /workspace/app 에 푼다. 그러면 CODE 프롬프트가 "만들어라" → "고쳐라" 로 바뀌고, 그 수정분이 #317 의 diff API 로 그대로 보인다.

previewSessionService.acquire            컨테이너 확보
→ previewWorkspaceService.prepareProject 저장소가 있으면 clone/pull
→ TemplateSeedingService.seedIfNeeded    비어 있을 때만 씨앗을 푼다
→ 씨딩됐으면 지시문 앞에 템플릿 맥락을 붙인다
→ LLM 루프

판단이 갈릴 만한 곳

clone 이 씨딩보다 먼저다. 반대면 clone 이 씨앗을 덮거나, 비어 있지 않은 디렉터리에 clone 하려다 실패한다. 씨딩 조건을 "작업 디렉터리가 비어 있음" 으로 잡아서, 저장소가 있는 프로젝트나 두 번째 요청에서는 자연히 건너뛴다 — 덮는 순간 사용자 작업물이 사라지는 자리다.

실패하면 태스크를 실패로 닫는다. 씨딩에 실패했는데 그냥 진행하면 고른 템플릿과 다른 결과물이 "성공" 으로 나온다. 고치려던 그 버그를 형태만 바꿔 재현하는 셈이다. tar 종료코드만 믿지 않고 푼 결과도 확인한다 — 빈 입력에 0 이 나올 수 있고, "성공했는데 아무것도 없는" 상태가 가장 나쁘다.

지시문에 템플릿 맥락을 직접 싣는다. 시스템 프롬프트가 "프로젝트가 없으면 스캐폴드" 로 시작한다. 파일이 있으니 모델이 알아서 수정 경로를 타는 게 정상이지만 그 판단을 추측에 맡기지 않는다 — 스캐폴더가 한 번이라도 돌면 고른 템플릿이 통째로 덮인다. contentHints 를 함께 넘기는 것도 같은 이유로, 없으면 "내용만 바꾸기" 요청에도 레이아웃을 건드린다.

sourceUrl 을 셸에 넘기기 전에 검증한다. 카탈로그는 우리 저장소가 발행하지만, 거기 실린 값을 그대로 셸에 넘기는 구조 자체를 두지 않는다 — 카탈로그가 오염되면 컨테이너 안 임의 명령 실행이 된다.

실측

dev 서버에서 확인한 것:

  • node:20-alpinewget·tar 존재, https 로 받아 압축 해제까지 성공(curl 은 없다)
  • 프리뷰 네트워크는 enable_icc=falsebridge — 컨테이너 간만 차단이고 외부 통신은 된다

검증

  • 전체 테스트 1350건 통과
  • 신규 7건: 빈 작업공간 씨딩 / blank 건너뜀 / 비어있지 않으면 건너뜀 / 다운로드 실패 / 종료코드 0 인데 파일 없음 / 안전하지 않은 URL 거절 / 카탈로그에서 사라진 템플릿
  • 프롬프트 계약 1건: 씨딩되면 지시문에 템플릿명·DO NOT scaffold·contentHints·원래 요청이 모두 실린다
  • 마이그레이션 없음

남은 것

실 사용자 e2e 는 아직입니다 — 템플릿 선택 → 생성 → 프리뷰까지 실제로 밟아보는 건 머지 후 dev 에서 하겠습니다. state.md §4.22 에 그대로 적어뒀습니다.

🤖 Generated with Claude Code

https://claude.ai/code/session_013y8USoCXTsRTATAhy88M93

카탈로그 검증(#320)까지는 "없는 템플릿을 거절" 하는 데까지였고, 통과한 뒤의 동작은
여전히 백지 생성이었다. 이 커밋이 그 마지막 조각이다.

첫 CODE 스텝에서 씨앗 tarball 을 /workspace/app 에 푼다. 그러면 CODE 프롬프트가
"만들어라" 에서 "고쳐라" 로 바뀌고, 그 수정분이 diff API(#317)로 그대로 보인다.

순서가 중요하다. 저장소 clone 이 씨딩보다 먼저다 — 반대면 clone 이 씨앗을 덮거나
비어 있지 않은 디렉터리에 clone 하려다 실패한다. 씨딩은 작업 디렉터리가 비었을
때만 일어나므로, 저장소가 있는 프로젝트나 두 번째 요청에서는 자연히 건너뛴다.
덮는 순간 사용자 작업물이 사라지는 자리라 조건을 파일 존재 여부로 잡았다.

실패하면 조용히 넘어가지 않는다. 씨딩에 실패했는데 그냥 진행하면 사용자가 고른
템플릿과 전혀 다른 결과물이 "성공" 으로 나온다 — 고치려던 그 버그를 형태만 바꿔
재현하는 셈이다. tar 종료코드만 믿지 않고 푼 결과도 확인한다(빈 입력에 0 이 나올 수
있다). "성공했는데 아무것도 없는" 상태가 가장 나쁘다.

지시문 앞에 템플릿 맥락을 붙인다. 시스템 프롬프트가 "프로젝트가 없으면 스캐폴드" 로
시작하므로 모델이 알아서 수정 경로를 타는 것이 정상이지만, 그 판단을 추측에 맡기지
않는다 — 스캐폴더가 한 번이라도 돌면 고른 템플릿이 통째로 덮인다. contentHints 를
함께 넘기는 것도 같은 이유다. 어디가 내용이고 어디가 구조인지 모델이 스스로 판단하면
"내용만 바꾸기" 요청에도 레이아웃을 건드린다.

sourceUrl 은 셸 명령에 들어간다. 카탈로그는 우리 저장소가 발행하지만 거기 실린 값을
그대로 셸에 넘기는 구조 자체를 두지 않는다 — 형식을 먼저 검증한다.

컨테이너 이미지(node:20-alpine)에 wget·tar 가 있고 https 로 받아 풀리는 것,
프리뷰 네트워크가 외부 통신 가능한 bridge 라는 것은 dev 서버에서 실측했다.

테스트 1350건 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013y8USoCXTsRTATAhy88M93
@dldnsgkr
dldnsgkr merged commit 62db91e into develop Sep 10, 2026
1 check passed
@dldnsgkr
dldnsgkr deleted the unhak/template-seeding branch September 10, 2026 03:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant