novel-toon · skill architecture

Novel Builder × Memory-Bank

장편소설 한 권을 웹툰 빌더의 영속 컨텍스트로 결정화한다. 원본 매뉴스크립트는 추적 밖에 두고, canon · persona · world · visual seed만 memory-bank MCP project-scoped facts로 동기화하여 회차·패널·이미지가 연속성을 잃지 않도록 한다.

매뉴스크립트 · 컨텍스트 · 런타임의 3계층 분리

소설을 그대로 컨텍스트 윈도우에 밀어 넣지 않는다. 분석에서 추출한 구조화된 사실만 폴더에 적고, 그것을 MCP project-scoped facts로 sync하여 생성 시점에 search_facts로 필요한 만큼만 회수한다. 원본은 외부에 남는다.

Layer 01 · external

매뉴스크립트는 외부에

raw 소설 파일은 --source 인자로 절대경로만 전달. 레포 안 source/·uploads/·private/는 git-ignore. MCP에도 동기화 금지.

Layer 02 · authoring

컨텍스트는 폴더에

novel당 한 폴더(memory-bank/novels/{novel_id}/). canon, persona, world, visual seed가 사람이 읽고 수정 가능한 JSON/MD로 누적. ledger로 변경 추적.

Layer 03 · runtime

런타임은 MCP에

sync 스크립트가 폴더를 project-scoped facts로 upsert. 생성·스토리보드·렌더링 시점에 search_facts / trace_fact로 회수.

소스 → 빌더 → 메모리뱅크 → MCP → 소비자

novel-builder.py가 매뉴스크립트를 분해하고, memory-bank/novels/{novel_id}/를 작성한 뒤 novel-memory-bank-mcp-sync.mjs가 MCP에 facts를 upsert한다. 소비자는 storyboard, lettering, visual seed 매칭, continuity 검증.

Source Manuscript external · /absolute/path/to/novel.md git-ignored · MCP sync 금지 --source flag novel-builder skill scripts/novel-builder.py · python3 · 1000 LOC · deterministic extract title · chars · chapters build manifest · persona · world seed image · photo · anchors write novels/{id}/* files sync → MCP facts (--sync) validate memory-bank/novels/{novel_id}/ authoring templates · Git tracked · one folder per novel manifest.json id · version analysis status context index context/ canon · timeline continuity-ledger unresolved-questions characters/ persona json per character · speech goals · wounds · secrets world/ eras · settings culture · politics technology · magic visual/ style-bible.md image-seeds.json prompt anchors · negs production/ episodes/*.md storyboard json panels/*.json research/ analysis-log.md source-notes.md speculation pending source · uploads private/ · references git-ignored MCP sync 금지 novel-memory-bank-mcp-sync.mjs structured summaries only · raw manuscripts skipped deterministic upsert · idempotent memory-bank MCP scope_type=project · scope_project=/Users/.../novel-toon namespace = novel-toon:{novel_id}:{area}:{entity_id} retrieval · search_facts · trace_fact · explore_graph · graph_stats storyboard episode planning lettering webtoon bubbles visual seed prompt anchors continuity ledger / retcon
manuscript → builder → folder → MCP facts → consumers (storyboard · lettering · visual · continuity)

novel-builder.py 내부 단계

extract_titleextract_charactersextract_chapters로 매뉴스크립트를 분해한 뒤, profile에 정의된 known persona/world 정보와 병합하여 build_* 단계가 deterministic seed를 포함한 구조체를 생성한다. 마지막으로 run_sync가 Node 스크립트를 호출해 MCP에 upsert.

01 · extract title · characters chapters · headings 02 · profile builder-profile.json + default fallback 03 · build manifest · persona eras · settings 04 · write novels/{id}/* deterministic 05 · sync MCP upsert --sync flag 03a · seed registry stable_seed(parts...) image · photo seeds validator validate-novel-builder.py .omx/specs/ result deterministic seed derivation post-write gate completion rule validate-novel-builder.py 통과 전에는 “완료” 선언 금지. autoresearch 런 → .omx/specs/ 에 JSON 결과 기록 → 최종 리포트에 cite 필수
five-stage deterministic pipeline · seed derivation in 03a · validator gate after stage 04

10개 컨텍스트 영역과 MCP 네임스페이스 매핑

각 영역은 한 가지 책임만 진다. 사실은 canon.md에, 변경 이력은 continuity-ledger.md에, 추측은 research/analysis-log.md에. 영역과 entity_id로 MCP 네임스페이스가 결정된다.

Area Path Role MCP namespace
manifestmanifest.jsonid · version · ownership · analysis 상태 · context indexnovel-toon:{id}:manifest:root
canoncontext/canon.md변경 불가 스토리 사실. 분석 증거 있을 때만 추가novel-toon:{id}:canon:{fact_id}
timelinecontext/timeline.mdchapter · episode · era · absolute date 단위 사건novel-toon:{id}:timeline:{event_id}
ledgercontext/continuity-ledger.md결정 · retcon · contradiction · fix 이력novel-toon:{id}:ledger:{decision_id}
unresolvedcontext/unresolved-questions.md미해결 연구 질문 · ambiguitynovel-toon:{id}:unresolved:{q_id}
characterscharacters/{char_id}.jsonpersona · goals · fears · speech · appearance anchor · 관계도novel-toon:{id}:character:{char_id}
worldworld/{eras,settings,culture}era · setting · culture · technology · magic · politicsnovel-toon:{id}:world:{entity_id}
visualvisual/style-bible.md + image-seeds.jsonstyle anchor · seed · photo seed · 음성 negative promptnovel-toon:{id}:visual:{seed_id}
productionproduction/episodes/* · panels/*episode 기획 · storyboard json · panel 메타데이터novel-toon:{id}:production:{ep_id}
researchresearch/{analysis-log,source-notes}분석 진행 로그 · 확증 전 speculationnovel-toon:{id}:research:{note_id}
source · uploads · privatesource/ · uploads/ · private/raw 매뉴스크립트 · binary references · 비공개— ignored · sync 금지 —

결정론적 sync, project-scoped retrieval

sync는 idempotent. 같은 폴더 상태로 두 번 실행해도 같은 facts. retrieval은 MCP의 4개 도구로 좁힌다 — 전체 컨텍스트를 끌어오지 않는다.

# 1) 매뉴스크립트 → 컨텍스트 폴더 + MCP 동기화
python3 scripts/novel-builder.py \
  --project-root . \
  --source /Users/me/blood-inheritance.md \
  --novel-id blood-inheritance \
  --sync --json

# 2) 완료 게이트 — 통과 못하면 “완료” 선언 금지
python3 scripts/validate-novel-builder.py \
  --project-root . \
  --source /Users/me/blood-inheritance.md \
  --novel-id blood-inheritance \
  --require-mcp-sync --json

# 3) 생성 시점 — MCP search_facts 로 좁혀 회수
project=/Users/jung-wankim/Project/novel-toon
query="novel_id=blood-inheritance character=han-seoyun visual seed"

컨텍스트 부패를 막는 운영 규칙

장기 연재에서 가장 비싼 실패는 페르소나·비주얼 시드의 미세한 drift다. 규칙은 단순하다 — 바뀌면 ledger에 적고, raw는 절대 들어오지 않는다.

persona / visual drift 방지

  • character persona 또는 image seed 변경 시 continuity-ledger.md에 entry 필수
  • seed는 stable_seed(parts...)로 결정론적 파생 → 재실행해도 동일 시드
  • seed 레코드에 locked=true 표시된 항목은 ledger entry 없이 변경 금지
  • style-bible 변경은 모든 후속 episode 재검토를 트리거

분석 신뢰도 분리

  • 확증된 사실 → canon.md
  • 분석 중 가설 → research/analysis-log.md
  • 답 안 나온 질문 → unresolved-questions.md
  • canon으로 승격하려면 evidence 인용 필수

privacy boundary (HARD)

  • memory-bank/novels/*/source/ · uploads/ · private/ · visual/references/*는 git-ignore
  • raw 매뉴스크립트 MCP sync 절대 금지 (sync_raw_manuscripts: false)
  • 구조화 요약(canon · persona · world · seed 메타)만 sync
  • private 이미지 reference는 ID로만 참조

scope 격리

  • novel 하나당 폴더 하나 — 글로벌 character/seed 파일 사용 금지
  • MCP scope_type은 project 고정 → cross-novel leak 차단
  • namespace에 novel_id를 강제로 포함
  • retrieval 쿼리에 novel_id= 명시 권장

렌더링 단계로 흘러가는 두 가지 계약

memory-bank에서 회수한 컨텍스트는 storyboard JSON으로 결정화되고, 그 다음 두 계약을 통과해야 이미지/영상으로 나간다.

webtoon lettering

한국 웹툰 핸드 레터링 규약

  1. 일반 문서/자막/UI/세리프 폰트 금지. 한국 웹툰 핸드 레터링 톤만.
  2. 말풍선 안에는 대사 텍스트만. 화자명·콜론·괄호·캡션·메타데이터 금지.
  3. JSON의 speaker는 메타데이터로만 유지, 풍선에는 text 값만 렌더링.
  4. 흰색 라운드 풍선 + 짧은 꼬리 + 충분한 패딩.
  5. 풍선은 네거티브 스페이스에 배치 — 얼굴·눈·중요한 손·증거 prop 위 금지.
  6. 짧은 자연스러운 한국어 라인 선호. 길면 한 풍선 안에서 두 줄로 분할.
  7. 한국어 최종 레터링은 Remotion / post-composition 텍스트 오버레이로 — 이미지 생성에 의존하지 않음.
visual diversity

패널 시각 다양성 규약

  1. 패널 2개 이상 생성 시 각각 고유한 visual_signature 필수.
  2. 인접 패널은 setting · camera distance · character set · core action · emotional beat 중 최소 1가지 이상 차이.
  3. 연속 패널에서 동일한 “앉은 사무실” 구도 재사용 금지.
  4. 한국어 대사는 Remotion 결정론적 풍선으로 — 이미지가 텍스트 렌더하지 않음.
  5. 영상 출력에는 텍스트 없는 배경 이미지 + 결정론적 오버레이 풍선 선호.