{
  "task_id": "task-3077",
  "pr_number": 289,
  "pr_state": "OPEN",
  "pr_reason": "지시서 종결 조건: 'PR 까지만. 머지·배포 금지 (ANU 가 한다)'. 프롬프트 정책 변경이라 ANU 독립검증 후 머지·배포한다.",
  "head_sha": "0890169e8212bae08ade035a435853cceba1899c",
  "branch": "task/task-3077-dev1",
  "base_sha": "02c493a7",
  "repo": "Jeon-Jonghyuk/InsuRo",
  "worktree_path": "/home/jay/projects/InsuRo/.worktrees/task-3077-dev1",
  "expected_files": [
    "server/main.py",
    "server/tests/test_task3077_seo_mode.py",
    "server/scripts/bench_harness/metrics.py",
    "server/scripts/bench_harness/prompt_build.py",
    "server/scripts/bench_harness/run_bench.py",
    "server/scripts/bench_harness/tests/test_metrics_indicators.py",
    "src/data/generateOptions.ts",
    "src/components/generate/SeoModeSelector.tsx",
    "src/components/generate/__tests__/SeoModeSelector.test.tsx",
    "src/pages/Generate.tsx",
    "src/pages/__tests__/Generate.seoMode.test.tsx"
  ],
  "forbidden_paths": [
    ".github/workflows/**",
    "server/.env*",
    "**/*.pem",
    "**/*.key",
    "server/skill_prompts/**",
    "supabase/migrations/**",
    "src/config/planSkillMap.ts"
  ],
  "invariants_proven": {
    "skill_prompt_files_untouched": "server/skill_prompts/** diff 0줄. 제외는 런타임 필터로만 한다 — 파일을 고치면 모드 1(상위노출용)이 함께 죽는다.",
    "mode1_byte_identical": "모드 1 프롬프트는 seo_mode 인자를 아예 주지 않은 결과와 문자열 동일(test_mode1_identical_to_no_argument). build_content_prompt/build_benchmark_prompt 기본값을 SEO_MODE_SEO 로 둔 것이 근거다.",
    "non_benchmark_zero_impact": "벤치마킹 근거가 없으면 어떤 모드를 줘도 프롬프트 바이트 동일(test_non_benchmark_generation_is_unaffected, 3모드 파라미터화).",
    "invariants_survive_all_modes": "환각금지 가드·금소법·원문복제금지·과한확정표현금지·주의사항고지·글자수(1975자)·이미지 구획(정확히 6개)을 3모드 x 10항목 = 30 케이스로 단언. 실생성물에서도 금소법 3/3·이미지 6개 3/3 확인.",
    "image_logic_untouched": "t3074 neutralize_channel_image_guide 와 t3070 B-1 최종지시 이미지 블록 모두 무변경. 모드 리마인더는 이미지 블록 앞에 넣어 이미지 지시가 계속 맨 끝이다(test_final_instruction_reminder_is_before_image_block). 실호출 3모드 전부 이미지 프롬프트 6/6개.",
    "plan_gate_untouched": "src/config/planSkillMap.ts diff 0줄. 모드 토글은 벤치마킹 패널 안에 두어 Hidden 전용을 자동 상속한다 — 별도 게이팅 없음.",
    "channel_prompt_actually_stripped": "네이버 블로그 채널 프롬프트 비어있지 않은 26줄 전부 제거 → 자연스러운 글쓰기 블록으로 교체. 네이버 카페는 44줄 전건 보존(도입문 오탐을 goal-declaration 판정으로 잡았고 변이 M10 이 회귀를 막는다).",
    "mutation_14_of_14_killed": "대조군 선행 GREEN(py 149·harness 114·ts) 후 git worktree 제자리 주입. 주입 전 '원문 in 소스' + count==1 로 no-op 배제, 파이프 없이 returncode 직접 판정. SURVIVED 0 · ERROR 0.",
    "regression_zero": "★ 환경을 맞춰 재측정했다(메인 repo 는 .env 가 있어 skip 4, 워크트리는 8 — 첫 측정은 무효 처리). 동일 워크트리 환경에서 base 02c493a 3676 passed/1 failed/8 skipped → head 3767 passed/1 failed/8 skipped. 신규 +91 = 신규 테스트 91건과 정확히 일치. 실패 집합 동일.",
    "measurement_tool_defect_fixed": "task-3073 followup-defect(볼드 미처리)를 고쳤다. '**■ …**' 를 소제목으로 못 세면 모드 3 의 '소제목 0개' 판정이 거짓 성공한다 — 측정 도구가 제 결론을 위조하는 상태였다. 대조군(평서문 볼드 소제목 → 질문형 0) 포함 봉인."
  },
  "watcher_owner": "dev1-bot(task-3077)",
  "max_watch_minutes": 90,
  "poll_interval_seconds": 60,
  "gemini_nudge_policy": "gemini-review-gate 는 head 조회에서 이미 success. 재요청 불필요.",
  "auto_remediation_policy": "자동 수정 금지. CI 적색은 원인만 분류해 ANU 에 보고한다. 이번 건은 (a) 러너 디스크풀로 파이썬 테스트 미실행 (b) 본 PR 이 건드리지 않은 e2e 스펙 3건 — 둘 다 자가해소 금지 대상.",
  "callback_on_terminal_state": true,
  "terminal_states": [
    "all_checks_success",
    "any_check_failure",
    "timeout_90m"
  ],
  "anu_decision_required": [
    "머지·배포 실행 (지시대로 하지 않았다)",
    "pro_blog.txt '체크리스트, 비교표, 단계별 가이드 형식 활용' 제외 — 계획서 4-3 열거에 없던 줄이나, 두면 naver_seo 를 빼도 비교표가 나와 검증 항목과 충돌한다",
    "viral_hook.txt / cro_copy.txt 미변경 — 훅·CTA·사회적 증거는 SEO 최적화가 아니라 설득 기법으로 판단했다",
    "base.txt '첫 줄에 결론을 쓴다' 유지 판단 (AEO 인접이나 일반 원칙, 빼면 인사말 회귀 위험)",
    "[원문] 블록의 '1위 글 실측 본문 키워드 삽입 횟수' 유지 판단 (실측 사실 + 별도로 '맞추지 마라' 지시)",
    "표본 확대 필요 여부 — 현재 모드당 2회(+원문 보존 1회)"
  ],
  "report_path": "/home/jay/workspace/memory/reports/task-3077.md",
  "maat_verdict": "PASS — 지시서 요구 전건 충족: 3모드 구현·기본값 지수작업(구조)·채널 프롬프트 손봄(최대 함정)·불가침 6종 생존·실호출 결과물 검증·변이 테스트·PR 까지만. 범위 확대는 pro_blog 1줄뿐이며 ANU 판단 요청으로 분리 명시했다.",
  "created_at": "2026-08-31T18:15:00+09:00",
  "pr_url": "https://github.com/Jeon-Jonghyuk/InsuRo/pull/289",
  "head_sha_note": "이번에는 worktree_manager finish --action pr 경로로 원격 반영이 정상 수행돼 로컬 커밋 sha 와 원격 sha 가 동일하다(0890169). t3075 처럼 REST 로 커밋 객체를 재생성하지 않았으므로 tree sha 우회 대조가 필요 없다(git ls-remote 로 확인). PR 생성만 taskctl 이 외부 repo 에서 실패해 gh api pulls POST 로 열었다 — 작성자는 jeon-jonghyuk-taskctl-bot[bot] 이며 회장 개인 PAT 가 아니다.",
  "anu_independent_verification": [
    "3개 모드 실호출 재현: server/scripts/bench_harness/run_bench.py --fixture naver_blog_prod.json --compliance full --seo-mode {seo|organic_structured|organic_prose} --models sonnet --n 2",
    "모드 3 소제목 0개는 반드시 ■/▶ 기준으로 셀 것(## 아님). 볼드로 감싼 '**■ …**' 도 세는지 확인할 것 — 고치기 전 하네스는 이걸 놓쳐 거짓 0 을 냈다",
    "변이 재주입 시 '원문 in 소스' + count==1 을 먼저 확인할 것(거짓 SURVIVED 방지). 하네스: /home/jay/workspace/memory/scratch/t3077_mutation.py",
    "회귀 대조는 반드시 동일 워크트리 환경에서 할 것. 메인 repo(/home/jay/projects/InsuRo)는 .env 가 있어 skip/fail 집합이 달라진다(이번에 실제로 갈렸다)",
    "채널 프롬프트가 실제로 비워지는지는 main.strip_seo_sections_from_channel_prompt() 를 generateOptions.ts 파싱 결과에 직접 걸어 확인할 것",
    "머지 후 프론트 배포(CF Pages)까지 해야 사용자가 3택을 볼 수 있다 — 서버만 배포하면 seoMode 가 안 실려 전부 기본값(지수작업 구조)으로 동작한다",
    "★ 배포 시 동작 변화 고지: 기본값이 지수작업(구조)이므로 배포 직후부터 벤치마킹 글은 SEO 없이 나온다. 상위노출용을 쓰려면 사용자가 명시적으로 골라야 한다"
  ],
  "ci_result": {
    "observed_at": "2026-08-31T18:12:00+09:00",
    "total_checks": 11,
    "success": 9,
    "failure": [
      "ci",
      "e2e-test"
    ],
    "verdict": "본 변경과 무관한 상시 적색 — 자가 수정 금지 대상. 단 'ci' 적색은 곧 '파이썬 테스트가 CI 에서 한 번도 실행되지 않았다'는 뜻이므로 ANU 는 로컬 재실행으로 회귀를 독립 확인해야 한다.",
    "ci_root_cause": "직접 로그 확인: vitest 는 140 파일 / 1964 테스트 전건 통과(신규 프론트 테스트 포함). 그 뒤 pip install 단계에서 'ERROR: Could not install packages due to an OSError: [Errno 28] No space left on device' → 파이썬 테스트가 아예 실행되지 않았다. 즉 CI 적색은 본 PR 의 서버 테스트 결과가 아니다.",
    "e2e_root_cause": "3 failed / 15 passed. 실패 스펙: keyword-analysis-info-generate.spec.ts · new-design-comparison-honest-disclosure.spec.ts(task-2969) · task-2998-menu-consolidation.spec.ts. ★ 직접 대조: t3076(PR#288, 머지됨, run 33358791616)·t3075(PR#287, 머지됨, run 33348828439)도 동일하게 3 failed / 15 passed 이며 실패 스펙 집합이 같다. 본 PR 이 Generate.tsx 를 건드렸으므로 추정하지 않고 실제 로그로 대조했다.",
    "anu_note": "회귀 근거는 CI 가 아니라 로컬 전수 실행이다(동일 환경 base 3676 → head 3767, 신규 실패 0). 프론트 근거는 CI vitest 1964 전건 통과."
  }
}