vignette/AGENTS.md
Yun Chan a0311c5957
Some checks failed
API contract / OpenAPI type drift (push) Failing after 3m27s
회기 무발화 0턴 분리, 자기예측 락 불변식 및 TDD 회귀 검증 완료
2026-09-08 23:28:06 +09:00

30 KiB
Raw Permalink Blame History

AGENTS.md — Vignette 프로젝트 작업 지침

Vignette = AI 심리상담 시뮬레이션 훈련 플랫폼 (한신대 산학협력). 모노레포: apps/api(FastAPI/Python), apps/web(React 19/Vite/Playwright), docs, infra, scripts.

📚 문서 맵 — 작업 전 해당 가이드를 먼저 읽어라

목적 문서
⚖️ 오케스트레이션 바이블(절대 규칙) 이 파일 B절 — 고급 모델은 설계·평가, 하위 모델은 조사·구현·검증 실행. 양식 docs/ops/agent-work-packet-template.md
문서 인덱스(먼저 여기서 시작) docs/README.md
할 일(안된 것들 통합 TODO) docs/TODO.md
저장소 개요·빠른 시작 README.md
로컬 서버 띄우기·테스트 docs/guides/local-development.md
시스템 아키텍처·데이터 흐름 docs/guides/architecture.md
테스트·검증 실행 docs/guides/testing.md
원천문서·갭 로드맵 docs/guides/source-docs-and-gaps.md
SSOT 상태판 docs/dev_dashboard.html
백로그(열린 항목만·얇은 현행본) docs/ops/backlog-2026-06-26.md
서연 아바타 핸드오프 docs/ops/handoff-avatar-seoyeon-2026-06-27.md
냉동 보관소(읽지 않는다) docs/archive/

작업 결과로 동작/구조가 바뀌면 해당 가이드와 SSOT 대시보드를 함께 갱신한다.

docs/archive/는 평상시 작업에서 읽지 않는다. 완료·검증된 작업의 변경 로그, 실행이 끝난 구현/리팩터 계획, 일회성 smoke·PoC·리서치 스냅샷, 완료된 재설계 프롬프트만 냉동 보관한 이력이다. 현재 상태의 근거로 삼지 마라. 열린 작업은 얇은 현행 백로그와 SSOT 대시보드가 소유한다. 완료된 작업 기록이 다시 쌓이면 docs/archive/로 옮겨 활성 문서를 얇게 유지한다.


⚖️ B. AI 에이전트 오케스트레이션 바이블 (절대 규칙 · 모든 절보다 우선)

이 절은 이 저장소의 모든 지침 중 최우선이며 절대 규칙이다. 다른 절·스킬·편의·속도와 충돌하면 이 절이 이긴다. 글로벌 지침(~/.codex/AGENTS.md, ~/.claude/CLAUDE.md)에도 같은 내용이 있으며, 프로젝트 안에서의 원본은 이 파일이다. 한쪽을 고치면 다른 쪽도 같은 내용으로 고친다. 진입점 CLAUDE.md·AGENT.md와 워커 정의(.claude/agents/)도 함께 맞춘다. 한 줄 요약: 고급 모델은 생각하고, 설계하고, 배정하고, 평가한다. 손은 하위 모델이 움직인다. 단, 설계와 평가는 절대 넘기지 않는다.

B.0 적용 대상

  • 오케스트레이터: 사용자와 직접 대화하는 최상위 세션이 고급 모델일 때. 이 절 전체가 적용된다.
    • Codex: Astra(gpt-6-astra), Sol(gpt-5.6-sol)
    • Claude Code: Fable 5.1(claude-fable-5-1), Opus 5(claude-opus-5)
  • 워커: 오케스트레이터가 하위 모델로 스폰한 에이전트(explorer / researcher / worker·implementer / verifier 등). 워커에게는 이 절의 "위임" 규칙이 적용되지 않는다. 워커는 받은 작업 패킷을 직접 수행하고, 설계를 바꾸지 않고, 다른 에이전트를 스폰하지 않고, 결과와 증거를 보고한다. 워커도 이 파일의 §0·§0.1·§2·§3은 그대로 따른다.
  • 최상위 세션이 하위 모델(Sonnet, Haiku, Terra, Luna 등)이면 이 절의 위임 규칙은 적용하지 않고 직접 수행한다. 대신 설계 결정이 필요하면 고급 모델 세션으로 넘기라고 사용자에게 알린다.

B.1 역할 원칙

  • 고급 모델은 메타인지와 오케스트레이션에 집중한다: 문제 정의, 설계, 작업 분해, 작업 패킷 작성, 하위 모델 배정, 진행 감시, 결과 평가, 최종 결정, 사용자 보고.
  • 매 작업마다 먼저 경중을 따진다: "이건 내가 직접 해야만 하는 일인가(B.2), 아니면 시킬 일인가(B.3)". 본인이 진짜 직접 해야 하는 일이 아니면 직접 나서지 않고 하위 모델에게 시킨다. "내가 하는 게 빠르다", "컨텍스트에 이미 다 있다"는 직접 할 이유가 되지 못한다.
  • 대규모 조사, 인터넷 웹서핑 조사, 논문·문서 스위핑, 코드베이스 탐색, 빌드·테스트 실행과 로그 수집처럼 컨텍스트를 많이 먹거나 양이 많은 일은 하위 모델 여러 개에 나눠 **멀티에이전틱(병렬)**으로 돌린다. 하나씩 순서대로 돌리지 않는다.
  • 오케스트레이터의 컨텍스트는 설계와 판단에 쓰는 자원이다. 로그 원문, 검색 결과 원문, 대량 파일 내용으로 채우지 않는다.

B.2 고급 모델이 절대 위임하지 않는 것 — 전면에서 직접 수행

  • 중요한 결정 전부. 특히 설계. 아키텍처, 모듈·계층 경계, 인터페이스/API/프로토콜 계약, 데이터 모델·스키마· 마이그레이션 방향, 상태 머신, 동시성·보안·성능·개인정보 전략, 기술·라이브러리 선택, 제품 방향에 영향을 주는 트레이드오프. 설계는 오케스트레이터가 직접 쓰고 직접 책임진다.
  • 요구사항 해석, 범위 확정, 작업 분해, 작업 패킷 작성, 완료 기준(DoD) 정의.
  • 개발 수행 결과 평가와 재개발 여부 판단. 워커가 낸 diff·보고·검증 증거를 오케스트레이터가 직접 읽고 판단한다(B.6). 평가와 리뷰의 결론을 하위 모델에게 맡기지 않는다. 하위 모델은 증거를 모아 올 뿐이다.
  • 최종 통합과 사용자 보고. 사용자에게 말하는 완료·수치·결론은 오케스트레이터가 직접 확인한 것만 쓴다.
  • 파괴적이거나 되돌리기 어려운 작업: 원격 push, 배포, 릴리스, DB 마이그레이션 실행, 대량 삭제, 비밀정보·자격증명 취급. 위임하지 않고 직접, 필요하면 사용자 확인 후 수행한다. (이 저장소의 구체 목록은 B.10.)

B.3 하위 모델에게 시키는 것

  • 조사: 웹 검색, 공식 문서·upstream 소스·이슈·PR 확인, 논문 스위핑, 레퍼런스·대안 비교표. 주제·출처·기간별로 쪼개 여러 researcher를 동시에 띄운다. 결과는 출처(URL, 문서 버전·날짜, 커밋·파일 경로)를 붙인 구조화된 보고로 받는다.
  • 탐색: 코드베이스 탐색, 호출 경로·영향 범위 추적, 재현 절차 확인, 관련 파일 목록화.
  • 개발: 설계와 작업 패킷이 확정된 구현, 리팩터, 테스트 작성, 버그 수정, 보일러플레이트, 마이그레이션 코드 작성. 워커는 설계를 바꿀 수 없다. 설계 변경이 필요하면 멈추고 보고하게 한다.
  • 검증 실행: 빌드·테스트·린트·재현 명령 실행, 로그 원문·스크린샷 등 증거 수집.
  • 순서는 항상 "하위 모델이 수집·수행 → 오케스트레이터가 판단·평가"다. 반대로 하지 않는다.

B.4 직접 수행이 허용되는 예외 (좁게 해석)

  • B.2 항목.
  • 위임 오버헤드가 작업보다 큰 사소한 일: 파일 한두 개의 몇 줄 수정, 단일 명령 실행, 사실 확인 한 번.
  • 워커가 같은 작업에서 2회 반려된 뒤에도 실패해, 오케스트레이터가 핵심 경로를 직접 구현해야만 할 때. 이때 왜 직접 하는지 한 줄로 남긴다.
  • 사용자가 "직접 하라"고 명시한 경우.
  • 위 경우가 아닌데 직접 하고 있다면 멈추고 위임으로 전환한다.

B.5 위임 절차 — 작업 패킷 없이는 위임하지 않는다

위임할 때는 워커에게 다음을 담은 작업 패킷을 넘긴다. 양식은 docs/ops/agent-work-packet-template.md.

  1. 목표와 비목표.
  2. 오케스트레이터가 확정한 설계·계약·불변량. 바꾸면 안 되는 것을 명시한다.
  3. 건드릴 파일·모듈 경계와 건드리면 안 되는 영역.
  4. 완료 기준과 검증 명령(테스트·빌드·린트·재현). 검증 명령은 B.10의 표준 세트에서 고른다.
  5. 보고 형식: 변경 파일, diff 요약, 실행한 명령과 결과 원문(통과/실패 수), 미해결·의문점, 설계 변경 요청 여부.
  6. 제약: 다른 에이전트 스폰 금지, fallback·silent catch·mock·테스트 스킵으로 통과 위장 금지, 임시 주석·디버그 코드 금지, 커밋·push는 허용된 경우만. 병렬 워커가 있으면 "다른 워커의 변경을 되돌리지 말 것"과 각자의 경계를 명시한다.

작업 패킷을 쓸 수 없을 만큼 설계가 불확실하면 그것은 위임할 때가 아니라 오케스트레이터가 설계를 먼저 끝내야 한다는 신호다.

B.6 결과 평가 게이트 — 시켜 놓고 방치하지 않는다

  • 워커가 끝나면 오케스트레이터가 즉시 평가한다. 다른 워커를 띄우고 잊거나, 워커의 보고를 사용자에게 그대로 전달하지 않는다.
  • 평가 항목:
    • (a) 작업 패킷·확정 설계 준수 여부, 범위 이탈 여부.
    • (b) 정확성과 회귀 위험 — diff를 직접 읽는다.
    • (c) 검증 증거의 진위 — 테스트·빌드가 실제로 통과했는지, 스킵·우회·완화·fallback·삼킨 오류가 없는지. 의심되면 verifier를 띄워 재실행 원문을 받는다.
    • (d) 노이즈 — 임시 주석, 디버그 출력, TODO, 무관한 변경.
    • (e) 워커가 올린 의문점·설계 변경 요청에 대한 답.
  • 판정은 셋 중 하나로 명시한다: 수용 / 반려 후 재작업(반려 사유와 수정 지시를 패킷에 추가) / 폐기 후 재배정 또는 직접 수행.
  • 워커의 "완료했습니다"는 증거가 아니다. 증거는 명령과 결과 원문이다. 확인하지 않은 결과를 사용자에게 완료라고 보고하지 않는다.
  • 같은 워커가 같은 이유로 2회 실패하면 워커 탓보다 패킷(설계·지시·완료 기준)을 먼저 의심하고 오케스트레이터가 설계를 재점검한다.
  • 사용자에게 보고할 때 무엇을 시켰고 무엇을 수용·반려했는지 짧게 남긴다.

B.7 금지

  • 설계를 하위 모델에게 맡기고 결과만 받아 쓰는 것.
  • 평가·리뷰를 하위 모델에게 위임하고 그 결론을 그대로 채택하는 것.
  • 조사 결과를 출처 확인 없이 사실로 채택하는 것.
  • 워커가 설계를 변경하거나 다른 워커를 스폰하는 것.
  • 위임이 귀찮다는 이유로 고급 모델이 대규모 조사·단순 구현·로그 읽기를 직접 다 하는 것.
  • 오케스트레이터 모델(Astra/Sol/Fable/Opus)을 워커 모델로 스폰하는 것(사용자 명시 요청 제외).

B.8 Codex 실행 규격 (모델 계층과 도구)

  • 오케스트레이터: Astra(gpt-6-astra) 또는 Sol(gpt-5.6-sol). 설계·평가 단계에서는 reasoning effort를 high 이상으로 쓴다. Sol/Terra의 ultra는 "자동 작업 위임"이 붙은 최대 추론 단계다.
  • 워커 역할은 ~/.codex/agents/*.toml(글로벌)에 정의돼 있다. 스폰할 때 역할명을 지정한다. 참조 사본과 설치법은 docs/ops/codex-agents/. 프로젝트 스코프 .codex/agents/는 스폰 실패 이슈 (openai/codex#26408, 2026-09-06 기준 open)가 닫힐 때까지 쓰지 않는다. 프로젝트 .codex/config.toml도 두지 않는다.
역할 모델 샌드박스 용도
explorer gpt-5.6-luna read-only 코드베이스 탐색, 호출 경로·영향 범위, 근거(파일:줄) 수집
researcher gpt-5.6-luna read-only 웹·공식 문서·upstream·이슈/PR·논문 스위핑, 출처 포함 보고
worker gpt-5.6-terra 상위 상속 작업 패킷 기반 구현·리팩터·테스트 작성
verifier gpt-5.6-luna 상위 상속 빌드·테스트·린트·재현 실행, 결과 원문 보고(판정 없음)
  • 역할을 지정하지 않고 스폰하면 ~/.codex/config.toml[agents](enabled=true, default_subagent_model = "gpt-5.6-terra", default_subagent_reasoning_effort = "medium", max_concurrent_threads_per_session = 8)가 적용된다. 워커에 Astra/Sol을 쓰지 않는다.
  • 흐름: 작업 패킷 작성 → spawn_agent로 병렬 스폰(조사는 주제별로 researcher 여러 개) → wait_agent(타임아웃은 작업 규모에 맞게) → B.6 평가 → 반려 시 send_input으로 재작업 지시 → 끝나면 close_agent.
  • 스폰 메시지에 항상 포함: "너는 워커다. 다른 에이전트를 스폰하지 마라. 설계를 바꾸지 마라. 병렬 워커의 변경을 되돌리지 마라. 이 저장소의 AGENTS.md §0·§2·§3을 따르라."
  • 여러 워커가 같은 저장소를 만지면 파일·모듈 경계를 겹치지 않게 나누고, 겹치면 순차로 돌린다.
  • Orca 하네스 안에서는 orchestration 스킬(orca orchestration task-create / dispatch)로 다른 터미널의 Claude Code·Codex 워커에게 디스패치할 수 있다. 이때도 워커 모델은 하위 티어로 지정하고, 작업 패킷과 B.6 평가 게이트를 똑같이 적용한다. 디스패치한 뒤 worker_done을 기다려 결과를 직접 평가한다.

B.9 Claude Code 실행 규격 (모델 계층과 도구)

  • 오케스트레이터: Fable 5.1(claude-fable-5-1) 또는 Opus 5(claude-opus-5).
  • 워커 계층: Sonnet 5(sonnet) = 구현·검증 실행, Haiku 4.5(haiku) = 대량 조사·스위핑·탐색.
  • 워커 정의는 이 저장소의 .claude/agents/(프로젝트, 커밋됨)에 있고, ~/.claude/agents/(글로벌)와 같은 내용을 유지한다. 프로젝트 정의가 우선한다.
서브에이전트 모델 도구 제한 용도
researcher Haiku 4.5 읽기·웹만, 쓰기·Agent 금지 웹·공식 문서·upstream·이슈/PR·논문 스위핑, 출처 포함 보고. 주제별로 여러 개 병렬
implementer Sonnet 5 Agent 금지 작업 패킷 기반 구현·리팩터·테스트 작성
verifier Sonnet 5 (low) Bash·읽기만, 쓰기·Agent 금지 빌드·테스트·린트·재현 실행, 결과 원문 보고(판정 없음)
내장 Explore 기본 서브에이전트 모델 읽기 전용 코드베이스 탐색·파일 위치 찾기
  • 모델을 지정하지 않은 서브에이전트(내장 Explore 등)는 이 저장소의 .claude/settings.json subagentModel = "sonnet"에 따라 Sonnet으로 돈다(우선순위: frontmatter model > 환경변수 CLAUDE_CODE_SUBAGENT_MODEL > subagentModel). subagent_type: "fork"는 부모(고급) 모델을 상속하므로 대량 작업·조사에 쓰지 않는다.
  • 흐름: 작업 패킷 작성 → Agent 도구로 스폰(독립 작업은 한 메시지에 여러 Agent 호출로 병렬) → 완료 알림 수신 → B.6 평가 → 반려 시 SendMessage로 같은 에이전트에 재작업 지시 → 수용.
  • 내장 Plan 에이전트는 설계 대행이 아니다. 설계 결정은 오케스트레이터가 직접 한다. Plan은 자료 정리·후보 열거에만 쓴다.
  • 외부 레인: codex exec --full-auto를 구현 워커로 쓸 수 있다. 이 경우에도 작업 패킷과 B.6 평가 게이트를 똑같이 적용한다.
  • 사용자가 ultracode를 켰거나 워크플로를 요청한 세션에서는 Workflow로 대규모 팬아웃(조사·검증)을 한다. 그 외에는 Agent 병렬 호출이 기본이다.
  • Orca 하네스 디스패치 규칙은 B.8과 같다.

B.10 Vignette 바인딩 — 이 저장소에서의 구체 적용

  • 워커도 이 파일을 따른다: §0(OS 선파악)·§0.1(PowerShell 5.1)·§2(검증 기준)·§3(한글·커밋 문구). 패킷에 명시한다.
  • 표준 검증 명령 세트 (패킷의 검증 명령은 여기서 고른다. 상세는 docs/guides/testing.md):
대상 작업 디렉터리 명령 외부 의존
백엔드 단위 apps/api python -m pytest app/ -q 없음
엔진 게이트웨이 apps/api python -m pytest engine_gateway/ -q 없음
API 타입 동기화 apps/web npm run check:api-types 없음
웹 타입체크·빌드 apps/web npm run typecheck · npm run build 없음
레이아웃 E2E 게이트 apps/web §2의 layout-visual-gate(7/7)·session-layout(8/8) web+api+DB 스택(scripts\dev-up.ps1)
  • SSOT 반영은 오케스트레이터 판정 뒤에만: 워커 보고는 docs/dev_dashboard.html·docs/TODO.md·핸드오프 문서의 상태 변경 근거가 아니다. B.6 판정(수용)을 거친 결과만 반영한다. 대시보드 편집 작업 자체는 워커에게 시켜도 되지만 "무엇을 DONE으로 쓸지"는 오케스트레이터가 정하고, 편집 뒤 python -X utf8 scripts/check-dev-dashboard-ssot.py를 통과시킨다.
  • 이 저장소의 파괴적·직접 수행 목록(B.2): Forgejo/NAS 정식 배포와 compose 교체, DB 마이그레이션 적용, scripts/backup-vignette-db.ps1 복원 경로, data/·uploads/·운영 볼륨 삭제, .env*·OAuth secret·NAS 자격증명 취급, 원격 push. 오케스트레이터가 직접, 소유자 확인 후.
  • 병렬 경계 기본값: apps/apiapps/webdocs/scripts를 워커별로 나눈다. 같은 파일을 두 워커가 만지지 않는다. apps/web/src/lib/api.gen.ts는 생성물이므로 손으로 고치지 않고 check:api-types로 맞춘다.
  • 평가 기록: 판정(수용/반려/폐기)과 근거는 사용자 보고에 남긴다. 세션을 넘기는 장기 작업은 핸드오프 문서에 패킷 제목·판정·미해결을 요약한다.

⚠️ 0. 무조건 OS를 먼저 파악하고 시작한다 (최우선·필수)

어떤 작업이든 명령을 실행하기 전에 OS와 셸을 먼저 확정하라. 이걸 건너뛰면 경로/인코딩/도구 차이로 시간을 크게 낭비한다(실제로 그랬다).

작업 시작 시 반드시 확인할 것:

  1. OS / 셸: 이 저장소의 주 개발 환경은 Windows 11 + PowerShell이다. POSIX를 가정하지 마라. Bash 도구도 쓸 수 있으나 셸마다 문법이 다르다.
  2. 경로 규칙: Windows 절대경로(D:\..., C:\...). 한글·공백 포함 경로가 흔하다 (예: OneDrive 문서\카카오톡 받은 파일). -LiteralPath로 다루고, 외부 도구에 넘기기 전에 ASCII 이름으로 로컬 복사해 인코딩/공백 문제를 차단하라.
  3. PowerShell 판(5.1) 주의: 인라인 if(){}else{}를 식으로 못 쓴다(삼항 없음). 네이티브 exe stderr를 2>&1로 합치지 마라(ErrorRecord로 감싸짐). 기본 출력 인코딩은 UTF-16 — 다른 도구가 읽을 파일은 -Encoding utf8.
  4. 외부 CLI는 실제로 블로킹되는지 확인: GUI 런처(soffice.exe 등)는 즉시 detach되어 Start-Process -Wait가 변환을 안 기다린다. 실제 작업 프로세스 (soffice.bin)를 직접 호출하라. 좀비 프로세스가 락을 잡으면 정리부터 한다.
  5. 도구 가용성 먼저 탐지: 변환/처리 전에 LibreOffice·pandoc·python 라이브러리· Playwright 브라우저 등 무엇이 설치돼 있는지 먼저 확인하고 경로를 잡아라.

한 줄 요약: "먼저 OS·셸·경로·도구를 확정한 뒤 실행한다." 추정 금지.

0.1 PowerShell 5.1 실행 규칙 (Windows 기본 셸)

이 프로젝트의 기본 셸은 Windows PowerShell 5.1 Desktop이다. PowerShell 7 문법이나 Bash 문법을 섞으면 바로 지연된다. 명령을 작성할 때 아래 규칙을 기본값으로 삼아라.

  • 세션 시작 프리루드: 한글/UTF-8 출력이 필요한 명령 전에는 아래를 먼저 둔다.
    $ErrorActionPreference = 'Stop'
    [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
    $OutputEncoding = [System.Text.UTF8Encoding]::new($false)
    
    단, $ErrorActionPreference='Stop'은 PowerShell cmdlet용 안전장치다. 네이티브 exe의 실패는 자동으로 예외가 되지 않으므로 실행 후 $LASTEXITCODE를 반드시 확인한다.
  • 5.1 미지원 문법 금지: ? : 삼항, ??, ??=, &&, ||, ForEach-Object -Parallel, Bash heredoc(<<EOF), Bash식 환경변수 주입 (FOO=bar command)을 쓰지 않는다. 값 선택은 명시적 if/else와 변수 대입으로 쓴다.
  • 제어문은 파이프라인 값이 아니다: foreach (...) { ... } | Format-Table처럼 쓰면 5.1에서 파서 오류가 난다. 필요하면 & { foreach (...) { ... } } | Format-Table처럼 스크립트블록을 파이프라인 입력으로 감싼다.
  • 경로는 PowerShell 방식으로 다룬다: 파일/폴더에는 -LiteralPath, Resolve-Path -LiteralPath, Join-Path를 우선 사용한다. 한글·공백·괄호가 있는 경로를 외부 CLI에 직접 넘기기 전에는 ASCII 임시 경로로 복사하는 편이 낫다.
  • 파일 인코딩을 명시한다: Get-Content/Set-Content/Out-File에는 필요한 경우 -Encoding UTF8을 붙인다. 단, Windows PowerShell 5.1의 -Encoding UTF8은 BOM을 쓴다. Node/Python/TS 도구가 읽을 UTF-8 no BOM 파일은 .NET API로 쓴다.
    [IO.File]::WriteAllText($path, $text, [Text.UTF8Encoding]::new($false))
    
  • 한글 출력 깨짐은 파일 손상으로 단정하지 않는다: 먼저 OutputEncoding을 UTF-8로 맞추고, 필요하면 Format-Hex, Node/Python 읽기, 실제 빌드/타입체크로 확인한다.
  • 네이티브 exe stderr를 2>&1로 합치지 않는다: 5.1은 네이티브 stderr를 ErrorRecord로 감싸 파이프라인/문자열 처리와 순서를 흐릴 수 있다. 로그가 필요하면 stdout/stderr를 별도 파일로 리디렉션하거나 System.Diagnostics.Process로 분리 캡처한다.
  • 네이티브 명령은 문자열 조립보다 인자 배열로 호출한다:
    $exe = 'C:\path\tool.exe'
    $args = @('--flag', $value, '--out', $outPath)
    & $exe @args
    if ($LASTEXITCODE -ne 0) { throw "tool failed: $LASTEXITCODE" }
    
    PowerShell 파싱이 외부 도구 인자를 망가뜨릴 때만 네이티브 명령 뒤에 --%를 검토한다.
  • HTTP/JSON은 curl 별칭을 피한다: PowerShell의 curl은 별칭일 수 있다. JSON API는 Invoke-RestMethod/Invoke-WebRequestConvertTo-Json을 우선 사용하고, 진짜 curl이 필요하면 curl.exe를 명시한다.
  • 인라인 Python/Node는 짧고 결정적으로 실행한다: 여러 줄 코드를 stdin으로 밀어 넣다 BOM/인용 문제가 나면 python -c, UTF-8 no BOM 임시 파일, 또는 base64 전달을 쓴다. Python 검증에는 필요 시 $env:PYTHONUTF8='1'python -X utf8을 사용한다.
  • powershell.exe -EncodedCommand는 UTF-16LE base64다. UTF-8로 인코딩하면 깨진다.
  • 프로세스 대기는 검증한다: 단순 CLI는 직접 실행하고 $LASTEXITCODE를 본다. Start-Process가 필요하면 -Wait -PassThru로 ExitCode를 확인한다. GUI 런처가 즉시 detach되는 도구(예: LibreOffice soffice.exe)는 실제 작업 프로세스와 산출물 생성을 따로 검증한다.

1. 운영 원칙

  • 개발 체계는 B절(오케스트레이션 바이블)을 따른다. 고급 모델 오케스트레이터가 설계·작업 패킷·평가·보고를 직접 하고, 조사·탐색·구현·검증 실행은 하위 모델 워커에게 시킨다. 워커 보고는 증거가 아니다.
  • 에이전트 지침의 원본은 이 파일(AGENTS.md) 하나다. CLAUDE.md, AGENT.md처럼 도구별로 자동 탐지되는 파일은 호환성 진입점으로만 유지한다. 프로젝트 규칙을 바꿀 때는 이 파일만 수정하고, 진입점 파일에는 중복 규칙을 추가하지 않는다.
  • 가짜 증거로 DONE 표기 금지. 실증/외부 의존/소유자 결정이 필요한 항목은 docs/ops/backlog-*.md에 분류해 추적한다(B1 코스메틱 · B2 환경제약 · B3 소유자결정 · B4 외부거버넌스).
  • docs/dev_dashboard.html이 SSOT(단일 진실 공급원)다. 상태·검증 증거·결정 필요·로드맵의 권위 기준이며, 새 발견·작업 결과·상태 변경은 별도 문서로만 남기지 말고 대시보드에 반영/동기화한다. 백로그(docs/ops/backlog-*.md)는 대시보드와 일치시킨다(어긋나면 대시보드 기준).
  • 소유자(윤찬) 단독 결정 사안을 임의로 정하지 않는다(월권 금지).

2. 검증 기준 (프론트 변경 시)

  • cd apps/web && npm run typecheck
  • 레이아웃 변경은 e2e/layout-visual-gate.spec.ts(7/7) + 레이아웃 포커스 E2E + e2e/session-layout.spec.ts(8/8) 무회귀. E2E는 web+api(+DB) 스택이 떠 있어야 한다.

3. 커뮤니케이션

  • 모든 대화·주석·커밋 메시지는 한글.
  • git 커밋 메시지에 Co-Authored-By / Codex 관련 문구 추가 금지.

4. 이미지 생성(gpt-image-2 = imagegen2) · Live2D식 아바타

"이미지 생성해/만들어/그려줘" 요청 → ~/.Codex/skills/codex-image 스킬이 아래 래퍼를 자동 사용.

4.1 gpt-image-2 호출 (반드시 래퍼)

bash ~/.codex/imagegen-headless/codex_imagegen.sh \
  --out <경로.png> [--size WxH] [--quality low|medium|high|auto] \
  [-i <참조이미지> ...] [--all] "<프롬프트>"
  • 인증: ChatGPT 구독 OAuth(~/.codex/auth.jsonauth_mode=="chatgpt"). API 키 사용 금지(과금).
  • codex 0.140+는 생성 이미지를 세션 rollout JSONL에 base64로 인라인 반환 → 래퍼의 extract_imagegen.py 추출만 결정적. stdout의 "저장 경로"는 환각(직접 codex exec 금지).
  • 프롬프트는 stdin 파이프로(인자 전달 시 멈춤). 변주 생성 시 base를 -i 참조로 넘겨 아이덴티티·프레이밍 고정.
  • 투명배경 미지원 → 단색 평면 배경으로 생성 후 누끼. 한글 텍스트 렌더 가능(stdin 파이프라 인코딩 문제 없음).

4.2 누끼(컷아웃)

  • object-separation 스킬(BiRefNet): ~/.venvs/object-separation/Scripts/python.exe ~/.agents/skills/object-separation/scripts/separate_object.py <in> <out> --model birefnet-general
  • 알파 정제(잔류 헤이즈 제거): 임계치 <35→0, >205→255 + 페더(docs/avatar-art/seoyeon/publish.py 참조).

4.3 Live2D식 아바타(파츠 분리 리깅)

아바타는 기본 SVG 파라미터 리그 또는 래스터 파츠 분리 리깅(apps/web/src/components/avatar/RasterBust.tsx)으로 렌더. 후자는 persona.rasterArtSet 지정 시 활성.

  • 레이어(각각 독립 opacity/교체 → 표정 중에도 깜빡임·입술싱크가 따로 움직임): base(neutral 전신) + upperface-<표정>(눈썹+눈) + eyelid-closed(깜빡임, 표정 무관) + mouth-<표정> + mouth-open(립싱크).
  • 파이프라인(재현 스크립트는 docs/avatar-art/seoyeon/):
    1. codex_imagegen.sh로 base + 표정 변주(sad/tired/anxious/warm/startled/eyes-closed/speaking) 생성. 변주는 base를 -i 참조로, 동일 평면 배경.
    2. BiRefNet 누끼 → publish.py(표준 캔버스 900×1125 정규화 + 알파 정제)로 apps/web/public/avatar/<artSet>/ 게시.
    3. make-parts.py로 특징 영역(upperface/eyelid/mouth) 크롭+페더 파츠를 parts/ 생성(영역 상수 튜너 블럭).
  • 연결: persona.tsAvatarPersona.rasterArtSet / Session.tsxPERSONA_AVATAR_LOOKS[<code>].rasterArtSet / RasterBust.tsx(28표정→클러스터 매핑 포함).
  • dev 미리보기(인증 없음): /dev/avatar-preview(AvatarPreview.tsx). 스크린샷: node apps/web/scripts/avatar-shot.mjs(BASE_URL 환경변수로 포트 지정).
  • 실제 Live2D Cubism(.moc3)은 편집기 저작이 필요해 자동화 불가 → 위 레이어 합성이 실용적 대안.

4.4 진행 중인 아바타 작업 핸드오프

서연(P1) 아바타 작업은 별도 세션에서 진행. 현재 상태·남은 작업(Image #2=짧은 보브 기준 재생성 등)은 docs/ops/handoff-avatar-seoyeon-2026-06-27.md 참조.

4.5 페르소나별 Live2D 파츠 생성 규칙

P4~P7 등 다른 페르소나 파츠를 imagegen으로 만들 때는 docs/avatar-art/personas/README.md를 먼저 읽고 따른다.

  • 시트 금지: 여러 파츠를 한 이미지에 모으지 않는다. 파츠 하나당 생성 파일 하나다.
  • 입력 참조는 원본 파츠 crop: 900×1125 전체 캔버스가 아니라 원본 alphaBox 기준 tight crop을 imagegen 참조로 준다.
  • 최종 산출물은 900×1125 투명 PNG: 생성 결과에서 실제 파츠만 crop/resize한 뒤 원본 alphaBox 위치에 강제 paste한다.
  • 검증 필수: 최종 파츠 bbox drift는 원본 alphaBox 대비 2px 이내여야 한다. 검증 없는 DONE 표기 금지.
  • 시각 QA 필수: visual_qa.py로 앱 합성 순서의 neutral/sad preview와 contact sheet를 만들고 직접 본다. 눈 위치, 외계인 같은 비대칭, 초록 chroma-key 헤이즈, 엣지 블리딩, 여성/남성 페르소나 불일치를 잡기 전에는 앱에 연결하지 않는다.
  • 남성/엣지 보정: P5/P7처럼 남성 짧은 머리 페르소나는 긴 머리 슬롯을 그대로 채우면 안 된다. apply_visual_overrides.py로 긴 뒷머리·긴 사이드 슬롯을 비우고 리본형 outfit을 제거하며, 저알파 chroma-key 초록 엣지도 정리한 뒤 다시 visual QA를 통과시킨다.
  • 기본 러너: python -X utf8 docs/avatar-art/personas/run_part_imagegen.py ....