# 기획 목록(brief) 형식 글 생성기(`scripts/generate_posts.mjs`)의 입력이다. v2 §3-11의 "기획 목록 승인"은 이 파일을 사람이 확인하는 것으로 한다. 생성기는 brief 밖의 근거를 쓰지 않는다. ``` node scripts/generate_posts.mjs --clinic --brief briefs//.json [--out DIR] [--dry-run] [--no-verify] node scripts/generate_posts.mjs --clinic viewclinic --from-golden # 정답지 18편에서 brief 를 자동 추출해 회귀 node scripts/default_briefs.mjs --clinic --evidence > --site [--out briefs.json] [--max 6] [--industry derm|plastic] [--areas N] # 첫 배치 자동 제안 ``` ## 파일 ```json { "industry": "plastic", // default_briefs 가 적는 업종. plastic(성형외과) | derm(피부과). 글마다 industry 를 두면 그것이 우선 "posts": [ { "id": "slug", // 파일명. posts/.md "industry": "derm", // 선택. derm 이면 생성 프롬프트에 피부과 추가 규칙(조건 표 8행·시술자·상표·금액 금지·부작용 어휘)이 붙고, 게이트가 PRACTITIONER_MISSING 을 본다 "title": "질문형 한 문장?", // H1. 물음표로 끝난다 "category": "D", "categoryLabel": "시술 정보", "qbIds": ["D2-02"], // 질문 뱅크 문항 ID (화면에는 안 나옴) "intent": "무엇을 어떤 형식으로 정리할지 한 문단", // 선택 "mustCover": ["..."], "avoid": ["..."], // 선택 "reviewerCandidate": "dr-cho", // authors.json physicians 키. 후보일 뿐, reviewStatus 는 항상 pending "evidence": { "pages": ["https://.../system/precautions/"], // 병원 페이지. evidence//pages 에 있어야 함 "shorts": ["videoId"], // videos.json shortsInfo 에 정리 답이 있는 영상 "transcripts": [{ "id": "", "title": "", "speaker": "", "text": "" }], // 선택. 자막이 있으면 여기로 "news": ["https://..."], // news.json 에 있는 기사 URL (제목·매체·날짜만 쓴다) "regulation": [{ "label": "", "url": "", "note": "확인된 내용 한 줄" }], // note 가 없으면 링크로만 안내 "platform": false // true 면 팩트 시트 surfaces 를 sources 에 붙인다 }, "videos": [{ "id": "", "title": "", "speaker": "", "published": "", "note": "" }], // 글에 붙는 영상 (제목·화자만) "hero": { "src": "/img/...", "alt": "", "caption": "" }, // 선택 "gallery": [], "thumbnail": "", // 선택 "sources": [] // 주면 evidence 로부터의 자동 조립 대신 이것을 쓴다 (정답지 회귀용) } ] } ``` ## 생성 흐름 1. 컨텍스트: evidence 를 §4 순서(병원 페이지 → 영상 정리 답 → 기사 → 규제 원문 → 팩트 시트)로 붙인다. 없는 근거는 `missingEvidence` 로 리포트에 남긴다. 2. 생성(1회): 요약 3·본문·FAQ·태그·pending(근거에 없어 못 쓴 것)·usedRefs. 3. 후처리: 근거 태그(`[C1]`) 제거, 본문의 FAQ·참고 자료·연락처 섹션 제거(템플릿이 붙인다). 4. 검사: 소스 게이트(`gate/rules.mjs` 전부 + 금칙어 + 비교 수치 + 홈페이지 40자 중복) + 수치 대조(글의 숫자+단위가 근거에 그대로 있어야 함) + 모델 근거 대조(`--no-verify` 로 생략). 5. 오류가 있거나 경고가 `--warn-threshold`(기본 4) 이상이면 오류 목록을 되돌려 수정 1회. 그래도 남은 근거 플래그는 `ok_needs_review` 로 표시해 사람이 본다. 6. 저장: `generated//<시각>/posts/*.md` + `report.md`(편당 비용·시간·오류·확인 대기 목록). `generated/` 는 커밋하지 않는다. 채택할 글은 사람이 `src/content/posts/` 로 옮긴다. ## 생성기가 하지 않는 것 - `reviewedAt`·`reviewStatus: reviewed` 를 쓰지 않는다 (§3-7 사람 게이트). - 자막 없는 영상의 발언을 만들지 않는다. 영상 근거는 `shortsInfo[].answer` 또는 `transcripts` 뿐이다. - 기사 본문을 추정하지 않는다. 제목·매체·날짜만. - 근거에 없는 수치를 쓰지 않는다. 쓰면 `NUMBER_NOT_IN_EVIDENCE` 로 수정 대상이 된다. ## 업종 (industry) `default_briefs.mjs` 가 정하고 brief 파일 최상위와 글마다 `industry` 로 적는다. 생성기·게이트는 글의 `industry` 를 우선 보고, 없으면 환경변수 `SUPPORTERS_INDUSTRY`, 그것도 없으면 `plastic` 이다. | 값 | 판정 | 달라지는 것 | |---|---|---| | `plastic` (기본) | `--industry plastic`, 또는 병원 이름에 "성형외과" | 기존 동작 그대로. 시술 영역은 URL 세그먼트(`/contents/facial/...`)로 묶고, 세그먼트가 일반어(`new`·`doc`·`index.php`·숫자)일 때만 제목·헤딩·본문 키워드 폴백 | | `derm` | `--industry derm`, 병원 이름에 "피부과"(성형외과보다 앞에 있으면), 또는 시술 페이지 제목의 피부과 어휘가 3개 이상이고 성형외과 어휘보다 많을 때 | 시술 페이지를 URL 과 무관하게 아래 8영역으로 배정. 시술 글 제목·intent 가 조건 표 8행을 요구. `avoid` 에 피부과 금칙 추가. 지점 페이지(`branches` 유형)나 `facts.draft.json`·팩트 시트의 `branches` 가 2개 이상이면 "지점 선택 가이드"(B) 후보 추가. 시술 영역 기본 8개(`--areas`) | ### 피부과 8영역 (질문 뱅크 D1~D8 과 1:1) | key | 영역 | 문항 | 판정 낱말(일부) | |---|---|---|---| | pigment | 색소·토닝 | D1 | 색소, 토닝, 기미, 잡티, 검버섯, 피코, 미백 | | lifting | 리프팅·탄력 | D2 | 리프팅, 탄력, 처짐, 울쎄라, 써마지, 인모드, 슈링크, 고주파 | | booster | 스킨부스터·재생 | D3 | 스킨부스터, 리쥬란, 물광, 엑소좀, 재생, 콜라겐 | | toxin-filler | 톡신·필러 | D4 | 보톡스, 톡신, 필러, 주름, 사각턱, 이마, 미간 | | acne | 여드름·흉터·모공 | D5 | 여드름, 흉터, 모공, 피지, 스케일링, 필링, 프락셀 | | hair-body | 제모·바디 | D6 | 제모, 바디, 체형, 겨드랑이, 셀룰라이트, 쿨스컬프팅 | | disease-hair | 피부질환·모발 | D7 | 홍조, 혈관, 다한증, 액취증, 아토피, 사마귀, 탈모, 두피 | | plan | 계획·주기·조합 | D8 | 시술 주기, 회차, 병행, 조합, 시술 순서, 패키지 | 점수: 제목·H1·URL 에 낱말이 있으면 5점, 헤딩 2점, 본문 등장 횟수 × 0.5(최대 2.5). 2점 미만이면 영역 없음(기획하지 않음). 근거 충분성(영역의 페이지 글자 합 1,500자 이상)은 업종과 무관하게 같다. 본문이 이미지 글자인 페이지는 글자 수가 0에 가까워 자동으로 빠진다. 피부과 시술 글의 intent 는 시술마다 조건 표 8행(시술시간·마취·통증 정도·회복(다운타임)·유지기간·권장 회차·권장 주기·시술자)을 요구하고, 페이지에 없는 칸은 "확인", 시술자 표기가 없으면 "확인 대기"로 두라고 지시한다. 고정 글(병원 소개·방문 안내·상담 질문 체크리스트)은 업종과 관계없이 나온다. ## 게이트 규칙 (피부과 추가분, 성형외과 글에도 적용) `scripts/gate/rules.mjs` 의 `checkPostSource` 에 들어 있다. 근거 조문은 코드 주석에 있고, 법 해석은 자문이 아니다. | 코드 | 수준 | 조건 | 근거 | |---|---|---|---| | `PRICE_MENTION` | error | 요약·본문·FAQ 에 금액(150,000원·15만원·₩·%할인·이벤트가 99,000·1+1). "비급여 진료비용 고지" 안내 문장은 통째로 허용 | 의료법 45조(비급여 고지는 의료기관의 의무, 서포터즈는 링크만) · 56조 2항(유인) | | `DEVICE_CLAIM` | error | (1) 식약처 허가·인증, FDA 승인·허가, MFDS·KFDA, CE 인증 표기가 있는데 `sources` 에 `regulation` 이 없음 (2) 영구·완치·재발 없음·100%·평생 유지·한 번으로 끝 같은 효과 보장. 부정문("영구라는 뜻은 아닙니다")·"반영구"(시술명)는 통과 | 의료기기법 24조 · 약사법 68조 · 의료법 56조 2항 | | `PRACTITIONER_MISSING` | warn | `industry: derm` 이고 분류 D 인 글에 시술자 표기("시술자" 행, "의사 직접", "의사 감독")가 없음. 성형외과 글은 검사하지 않음 | 의료법 27조(무면허 의료행위, 대리시술) | | `BANNED_PHRASE` (사전 확장) | error | "정품 정량 인증"·"정품 인증"(인증 어휘. "정품·정량 사용을 밝힙니다" 같은 서약 사실 서술은 통과), "비포애프터"·"전후 사진을 보세요/확인하세요/공개" 유도 문구("전후 사진을 싣지 않습니다" 원칙 서술과 "수술 전후 모니터링" 시기 표현은 통과) | 의료법 56조 2항 2호·14호 | 부작용 고지 문안은 팩트 시트 `sideEffectNotice` 를 템플릿이 붙이므로 글 단위 검사는 없다. 생성 프롬프트(`gen/prompt.mjs` 의 `DERM_RULES`)는 시술 글에 "## 시술 후 관리와 부작용" 절과 화상·색소침착·멍·부기·감염 같은 구체 어휘를 요구한다. 픽스처: `scripts/gate/fixtures/price-mention.md`(실패) · `price-notice-link.md`(통과) · `device-claim-approval.md`·`device-claim-guarantee.md`(실패) · `device-claim-ok.md`(통과) · `practitioner-missing.md`(경고) · `practitioner-present.md`·`practitioner-plastic-skip.md`(경고 없음) · `derm-cert-phrase.html`·`before-after-phrase.html`(실패) · `derm-cert-ok.html`(통과). `npm run gate:test` 로 돈다. 픽스처 frontmatter 의 `expectWarn:`·`expectNoWarn:` 으로 warn 코드를 검사한다.