B["요청 컨텍스트 초기화
request_id, session_id"] B --> C{"금지질문 필터
(ForbiddenQueryFilter)"} C -->|"FORBIDDEN_BOTH"| C1["차단 응답 반환"] C -->|"FORBIDDEN_RAG"| C2["RAG 스킵 플래그"] C -->|"FORBIDDEN_BACKEND"| C3["Backend 스킵 플래그"] C -->|"ALLOWED"| D["PII 마스킹
(INPUT 단계)"] C2 --> D C3 --> D end subgraph PRIVACY["2. 프라이버시 게이트"] direction LR D --> E{"Privacy Query Gate
명단 요청 감지"} E -->|"타인+명단+민감속성"| E1["차단 응답 반환"] E -->|"1인칭 or 허용"| F["라우팅 오케스트레이션"] end subgraph ROUTING["3. 의도 분류 & 라우팅"] direction LR F --> G["Rule Router
(키워드 기반 1차)"] G --> G1["Smalltalk Gate"] G --> G2["절차 AND 조건"] G --> G3["애매한 경계 감지"] G --> G4["치명 액션 확인"] G --> G5["키워드 매칭"] G1 --> H{"confidence >= 0.85?"} G2 --> H G"> B["요청 컨텍스트 초기화
request_id, session_id"] B --> C{"금지질문 필터
(ForbiddenQueryFilter)"} C -->|"FORBIDDEN_BOTH"| C1["차단 응답 반환"] C -->|"FORBIDDEN_RAG"| C2["RAG 스킵 플래그"] C -->|"FORBIDDEN_BACKEND"| C3["Backend 스킵 플래그"] C -->|"ALLOWED"| D["PII 마스킹
(INPUT 단계)"] C2 --> D C3 --> D end subgraph PRIVACY["2. 프라이버시 게이트"] direction LR D --> E{"Privacy Query Gate
명단 요청 감지"} E -->|"타인+명단+민감속성"| E1["차단 응답 반환"] E -->|"1인칭 or 허용"| F["라우팅 오케스트레이션"] end subgraph ROUTING["3. 의도 분류 & 라우팅"] direction LR F --> G["Rule Router
(키워드 기반 1차)"] G --> G1["Smalltalk Gate"] G --> G2["절차 AND 조건"] G --> G3["애매한 경계 감지"] G --> G4["치명 액션 확인"] G --> G5["키워드 매칭"] G1 --> H{"confidence >= 0.85?"} G2 --> H G"> B["요청 컨텍스트 초기화
request_id, session_id"] B --> C{"금지질문 필터
(ForbiddenQueryFilter)"} C -->|"FORBIDDEN_BOTH"| C1["차단 응답 반환"] C -->|"FORBIDDEN_RAG"| C2["RAG 스킵 플래그"] C -->|"FORBIDDEN_BACKEND"| C3["Backend 스킵 플래그"] C -->|"ALLOWED"| D["PII 마스킹
(INPUT 단계)"] C2 --> D C3 --> D end subgraph PRIVACY["2. 프라이버시 게이트"] direction LR D --> E{"Privacy Query Gate
명단 요청 감지"} E -->|"타인+명단+민감속성"| E1["차단 응답 반환"] E -->|"1인칭 or 허용"| F["라우팅 오케스트레이션"] end subgraph ROUTING["3. 의도 분류 & 라우팅"] direction LR F --> G["Rule Router
(키워드 기반 1차)"] G --> G1["Smalltalk Gate"] G --> G2["절차 AND 조건"] G --> G3["애매한 경계 감지"] G --> G4["치명 액션 확인"] G --> G5["키워드 매칭"] G1 --> H{"confidence >= 0.85?"} G2 --> H G">
flowchart LR
    %% 1) 메인 플로우 (End-to-End) - 가로형
    subgraph INPUT["1. 입력 처리"]
        direction LR
        A["사용자 질문"] --> B["요청 컨텍스트 초기화<br/>request_id, session_id"]
        B --> C{"금지질문 필터<br/>(ForbiddenQueryFilter)"}
        C -->|"FORBIDDEN_BOTH"| C1["차단 응답 반환"]
        C -->|"FORBIDDEN_RAG"| C2["RAG 스킵 플래그"]
        C -->|"FORBIDDEN_BACKEND"| C3["Backend 스킵 플래그"]
        C -->|"ALLOWED"| D["PII 마스킹<br/>(INPUT 단계)"]
        C2 --> D
        C3 --> D
    end

    subgraph PRIVACY["2. 프라이버시 게이트"]
        direction LR
        D --> E{"Privacy Query Gate<br/>명단 요청 감지"}
        E -->|"타인+명단+민감속성"| E1["차단 응답 반환"]
        E -->|"1인칭 or 허용"| F["라우팅 오케스트레이션"]
    end

    subgraph ROUTING["3. 의도 분류 & 라우팅"]
        direction LR
        F --> G["Rule Router<br/>(키워드 기반 1차)"]
        G --> G1["Smalltalk Gate"]
        G --> G2["절차 AND 조건"]
        G --> G3["애매한 경계 감지"]
        G --> G4["치명 액션 확인"]
        G --> G5["키워드 매칭"]

        G1 --> H{"confidence >= 0.85?"}
        G2 --> H
        G3 --> H
        G4 --> H
        G5 --> H

        H -->|"YES"| I["Rule 결과 확정"]
        H -->|"NO"| J["LLM Router<br/>(LLM 기반 2차)"]
        J --> I

        I --> K{"needs_clarify?"}
        K -->|"YES"| K1["되묻기 응답<br/>PendingAction 저장"]
        K -->|"NO"| L{"requires_confirmation?"}
        L -->|"YES"| L1["확인 요청<br/>PendingAction 저장"]
        L -->|"NO"| M["라우트 실행"]
    end

    subgraph EXECUTION["4. 라우트 실행"]
        direction LR
        M --> N{"RouteType?"}
        N -->|"RAG_INTERNAL"| O["RAG 검색<br/>(Policy/Education QA)"]
        N -->|"BACKEND_API"| P["Backend 조회<br/>(개인화 데이터)"]
        N -->|"MIXED_BACKEND_RAG"| Q["RAG + Backend<br/>(병렬 조회)"]
        N -->|"LLM_ONLY"| R["LLM 직접 호출<br/>(일반 대화)"]
        N -->|"ROUTE_SYSTEM_HELP"| S["시스템 도움말<br/>(템플릿)"]
    end

    subgraph RAG["5. RAG 파이프라인"]
        direction LR
        O --> O1["Query 정규화"]
        O1 --> O2["Query Expansion<br/>(YAML 규칙 기반)"]
        O2 --> O3["Milvus 검색<br/>(원문 쿼리)"]
        O3 --> O4{"결과 0건?"}
        O4 -->|"YES"| O5["2nd-chance<br/>top_k=15 재검색"]
        O4 -->|"NO"| O6["RRF Fusion"]
        O5 --> O6
        O6 --> O7["Low-Relevance Gate<br/>(anchor 키워드)"]
        O7 --> O8["Quality Gate<br/>(L2 거리 평가)"]
        O8 --> O9{"Quality Action?"}
        O9 -->|"REJECT"| O10["INSUFFICIENT<br/>명확화 응답"]
        O9 -->|"PROCEED"| T["LLM 프롬프트 구성"]
        O9 -->|"PROCEED_WITH_WARNING"| T
    end

    P --> T
    Q --> T
    R --> T
    S --> T

    subgraph LLM["6. LLM 처리"]
        direction LR
        T --> T1["System Prompt<br/>(route type별)"]
        T1 --> T2["RAG/Backend<br/>컨텍스트 추가"]
        T2 --> T3["대화 이력<br/>(멀티턴)"]
        T3 --> T4["사용자 질문"]
        T4 --> U["LLM 호출<br/>(Timeout 정책)"]
        U --> U1{"성공?"}
        U1 -->|"NO"| U2["에러 응답"]
        U1 -->|"YES"| V["Answer Guard"]
    end

    subgraph GUARD["7. 응답 검증"]
        direction LR
        V --> V1["Answerability Gate<br/>(RAG 근거 확인)"]
        V1 --> V2["Citation Guard<br/>(가짜 조항 검증)"]
        V2 --> V3["Statistical Guard<br/>(통계 주장 검증)"]
        V3 --> V4["Korean Output<br/>(한국어 검증)"]
    end

    subgraph OUTPUT["8. 출력 처리"]
        direction LR
        V4 --> W["PII 마스킹<br/>(OUTPUT 단계)"]
        W --> X["응답 조립<br/>answer + sources + meta"]
        X --> Y["AI 로그 생성<br/>(백그라운드)"]
        Y --> Z["ChatResponse 반환"]
    end

    C1 --> Z
    E1 --> Z
    K1 --> Z
    L1 --> Z
    O10 --> Z
    U2 --> Z

    style A fill:#e3f2fd
    style Z fill:#c8e6c9
    style C1 fill:#ffcdd2
    style E1 fill:#ffcdd2
    style O10 fill:#fff3e0
    style U2 fill:#ffcdd2

flowchart LR
    %% 2) 라우팅 오케스트레이션 상세 - 가로형
    subgraph RULE["Rule Router (1차 분류)"]
        direction LR
        A["마스킹된 쿼리"] --> B{"Smalltalk Gate<br/>길이 2~10자?"}
        B -->|"YES"| B1{"업무 도메인<br/>힌트 없음?"}
        B1 -->|"YES"| B2["GENERAL_CHAT<br/>confidence=0.95"]
        B1 -->|"NO"| C
        B -->|"NO"| C

        C{"절차 AND 조건<br/>(최우선)"}
        C -->|"절차+보안/사고"| C1["POLICY_QA<br/>confidence=0.92"]
        C -->|"절차+교육"| C2["EDUCATION_QA<br/>confidence=0.92"]
        C -->|"NO"| D

        D{"애매한 경계?"}
        D -->|"교육+애매동사"| D1["needs_clarify=true<br/>clarify_group=EDU_CONTENT_VS_STATUS"]
        D -->|"연차/휴가+애매동사"| D2["needs_clarify=true<br/>clarify_group=POLICY_VS_PERSONAL"]
        D -->|"NO"| E

        E{"치명 액션?"}
        E -->|"QUIZ_START"| E1["requires_confirmation=true<br/>sub_intent_id=QUIZ_START"]
        E -->|"QUIZ_SUBMIT"| E2["requires_confirmation=true<br/>sub_intent_id=QUIZ_SUBMIT"]
        E -->|"QUIZ_GENERATION"| E3["requires_confirmation=true<br/>sub_intent_id=QUIZ_GENERATION"]
        E -->|"NO"| F

        F["키워드 매칭"]
        F --> F1{"HR 개인화?<br/>연차/근태/복지"}
        F1 -->|"YES"| F2["BACKEND_STATUS"]
        F1 -->|"NO"| F3{"정책/규정?"}
        F3 -->|"YES"| F4["POLICY_QA"]
        F3 -->|"NO"| F5{"교육 내용?"}
        F5 -->|"YES"| F6["EDUCATION_QA"]
        F5 -->|"NO"| F7{"시스템 도움말?"}
        F7 -->|"YES"| F8["SYSTEM_HELP"]
        F7 -->|"NO"| F9["POLICY_QA<br/>(기본값)"]
    end

    B2 --> G{"confidence >= 0.85?"}
    C1 --> G
    C2 --> G
    D1 --> G
    D2 --> G
    E1 --> G
    E2 --> G
    E3 --> G
    F2 --> G
    F4 --> G
    F6 --> G
    F8 --> G
    F9 --> G

    subgraph LLM["LLM Router (2차 분류)"]
        direction LR
        G -->|"NO"| H["LLM Router 호출"]
        H --> H1["System Prompt<br/>+ Few-shot Examples"]
        H1 --> H2["JSON 응답 파싱"]
        H2 --> H3{"유효한 JSON?"}
        H3 -->|"NO"| H4["Rule 결과 유지"]
        H3 -->|"YES"| H5["LLM 결과 적용"]

        H5 --> I{"BACKEND_STATUS +<br/>빈 sub_intent_id?"}
        I -->|"YES"| I1["Fallback Gate<br/>(절차 키워드 확인)"]
        I1 -->|"절차+보안"| I2["POLICY_QA로 변경"]
        I1 -->|"절차+교육"| I3["EDUCATION_QA로 변경"]
        I1 -->|"그 외"| I4["clarify 처리"]
        I -->|"NO"| J
    end

    G -->|"YES"| J["최종 결과"]
    H4 --> J
    I2 --> J
    I3 --> J
    I4 --> J
    H5 --> J

    subgraph POST["Post-Process"]
        direction LR
        J --> K{"needs_clarify?"}
        K -->|"YES"| K1["PendingAction 저장<br/>TTL=5분"]
        K1 --> K2["clarify_question 반환"]
        K -->|"NO"| L{"requires_confirmation?"}
        L -->|"YES"| L1["PendingAction 저장"]
        L1 --> L2["confirmation_prompt 반환"]
        L -->|"NO"| M["can_execute=true<br/>즉시 실행"]
    end

    style B2 fill:#e8f5e9
    style C1 fill:#e3f2fd
    style C2 fill:#e3f2fd
    style F2 fill:#fff3e0
    style D1 fill:#fce4ec
    style D2 fill:#fce4ec
    style E1 fill:#f3e5f5
    style E2 fill:#f3e5f5
    style E3 fill:#f3e5f5

flowchart LR
    %% 3) RAG 파이프라인 상세 - 가로형
    subgraph PREP["쿼리 전처리"]
        direction LR
        A["마스킹된 쿼리"] --> B["정규화<br/>마스킹 토큰 제거"]
        B --> C{"길이 < 40자?"}
        C -->|"YES"| D["Query Expansion"]
        C -->|"NO"| E["원문 그대로"]

        D --> D1["YAML 규칙 로드<br/>20개 핵심 키워드"]
        D1 --> D2{"키워드 매칭?"}
        D2 -->|"YES"| D3["동의어 + 관련어<br/>최대 8개 확장"]
        D2 -->|"NO"| E
        D3 --> F["확장된 쿼리"]
    end

    subgraph SEARCH["Milvus 검색"]
        direction LR
        E --> G["원문 쿼리 검색<br/>top_k=5"]
        F --> G
        G --> H{"결과 0건?"}
        H -->|"YES"| I["2nd-chance<br/>top_k=15 재검색"]
        H -->|"NO"| J["원문 결과"]
        I --> I1{"여전히 0건?"}
        I1 -->|"YES"| K["빈 결과"]
        I1 -->|"NO"| J

        F --> L["확장 쿼리 검색<br/>top_k=5"]
        L --> M["확장 결과"]
    end

    subgraph RRF["RRF Fusion"]
        direction LR
        J --> N{"확장 결과<br/>존재?"}
        M --> N
        N -->|"NO"| O["원문 결과만 사용"]
        N -->|"YES"| P["RRF 병합<br/>score = Σ 1/(k+rank)"]
        P --> P1["양쪽 등장 문서<br/>= 높은 점수"]
        P1 --> Q["재정렬된 결과"]
        O --> Q
    end

    subgraph QUALITY["품질 평가"]
        direction LR
        K --> R["sources = []"]
        Q --> S["Low-Relevance Gate"]
        S --> S1["anchor 키워드 추출<br/>(명사, 순환형)"]
        S1 --> S2["source별 anchor 매칭"]
        S2 --> S3{"매칭 실패?"}
        S3 -->|"YES"| S4["순위 강등<br/>(최소 1개 유지)"]
        S3 -->|"NO"| T
        S4 --> T

        T["Quality Gate<br/>L2 거리 평가"]
        R --> T

        T --> U["거리 통계 계산<br/>min, avg, max"]
        U --> V{"min_L2?"}
        V -->|"<= 1.4"| W1["OK<br/>action=PROCEED"]
        V -->|"1.4 ~ 1.6"| W2["LOW<br/>action=PROCEED_WITH_WARNING"]
        V -->|"> 1.6"| W3["INSUFFICIENT<br/>action=REJECT"]
        V -->|"sources=0"| W3
    end

    subgraph RESULT["결과 반환"]
        direction LR
        W1 --> X["RagRetrievalResult"]
        W2 --> X
        W3 --> Y["명확화 응답 생성"]

        X --> X1["sources: ChatSource[]"]
        X --> X2["retriever_used: MILVUS"]
        X --> X3["quality_action: PROCEED"]

        Y --> Y1["insufficient_evidence: true"]
        Y --> Y2["clarify_message: 안내 메시지"]
    end

    style D3 fill:#e8f5e9
    style P fill:#e3f2fd
    style W1 fill:#c8e6c9
    style W2 fill:#fff3e0
    style W3 fill:#ffcdd2

flowchart LR
    %% 4) LLM 프롬프트 구성 상세 - 가로형
    subgraph SYSTEM["System Prompt 선택"]
        direction LR
        A["RouteType"] --> B{"타입?"}
        B -->|"RAG_INTERNAL"| C1["SYSTEM_PROMPT_WITH_RAG<br/>근거 제시 강조"]
        B -->|"BACKEND_API"| C2["SYSTEM_PROMPT_BACKEND_API<br/>데이터 기반 응답"]
        B -->|"MIXED_BACKEND_RAG"| C3["SYSTEM_PROMPT_MIXED<br/>RAG+Backend 통합"]
        B -->|"LLM_ONLY"| C4["SYSTEM_PROMPT_NO_RAG<br/>일반 지식"]
    end

    subgraph RAG_CTX["RAG 컨텍스트"]
        direction LR
        C1 --> D{"sources 존재?"}
        D -->|"YES"| E["source 포맷팅"]
        E --> E1["출처 1: [제목]<br/>내용..."]
        E1 --> E2["출처 2: [제목]<br/>내용..."]
        E2 --> F{"컨텍스트<br/>길이 초과?"}
        F -->|"YES"| G["하위 source 제거"]
        F -->|"NO"| H["RAG 컨텍스트 완성"]
        G --> H
        D -->|"NO"| I["Soft Guardrail<br/>확정 표현 금지 지시"]
    end

    subgraph BACKEND_CTX["Backend 컨텍스트"]
        direction LR
        C2 --> J["BackendContextFormatter"]
        C3 --> J
        J --> J1["개인화 데이터<br/>테이블 포맷"]
        J --> J2["통계 데이터<br/>(관리자용)"]
        J1 --> K["Backend 컨텍스트 완성"]
        J2 --> K
    end

    subgraph HISTORY["대화 이력"]
        direction LR
        H --> L["ChatContextHandler"]
        I --> L
        K --> L
        L --> L1["이전 대화 로드<br/>최대 10턴"]
        L1 --> L2["토큰 버짓 체크"]
        L2 --> L3{"초과?"}
        L3 -->|"YES"| L4["오래된 턴 제거"]
        L3 -->|"NO"| M["대화 이력 완성"]
        L4 --> M
    end

    subgraph FINAL["최종 메시지 조립"]
        direction LR
        M --> N["사용자 질문<br/>(마스킹된)"]
        N --> O["messages 배열"]
        O --> O1["role: system<br/>content: system_prompt"]
        O --> O2["role: user<br/>content: 이전 질문"]
        O --> O3["role: assistant<br/>content: 이전 응답"]
        O --> O4["role: user<br/>content: 현재 질문"]
    end

    subgraph LLM_CALL["LLM 호출"]
        direction LR
        O4 --> P["Timeout 계산<br/>route_type별"]
        P --> Q["LLM API 호출"]
        Q --> R{"스트리밍?"}
        R -->|"YES"| S1["chunk별 yield"]
        R -->|"NO"| S2["전체 응답 반환"]
    end

    style C1 fill:#e3f2fd
    style C2 fill:#fff3e0
    style C3 fill:#f3e5f5
    style C4 fill:#e8f5e9
    style I fill:#ffcdd2

flowchart LR
    %% 5) Answer Guard 상세 - 가로형
    subgraph INPUT["LLM 응답 입력"]
        direction LR
        A["raw_answer<br/>(LLM 생성 응답)"] --> B["sources<br/>(RAG 검색 결과)"]
    end

    subgraph ANSWERABILITY["1. Answerability Gate"]
        direction LR
        B --> C{"sources 존재?"}
        C -->|"NO"| D{"intent가<br/>POLICY_QA or<br/>EDUCATION_QA?"}
        D -->|"YES"| E["고정 템플릿 반환<br/>LLM 응답 무시"]
        D -->|"NO"| F["LLM 응답 유지"]
        C -->|"YES"| F
    end

    subgraph CITATION["2. Citation Hallucination Guard"]
        direction LR
        F --> G["조항 패턴 추출<br/>제N조, 제N항, 별표..."]
        G --> H{"조항 인용<br/>존재?"}
        H -->|"NO"| I["통과"]
        H -->|"YES"| J["source 텍스트에서<br/>조항 존재 확인"]
        J --> K{"모든 조항<br/>검증 통과?"}
        K -->|"NO"| L["차단 응답 반환<br/>가짜 인용 감지"]
        K -->|"YES"| I
    end

    subgraph STATS["3. Statistical Claim Guard"]
        direction LR
        I --> M["통계 패턴 감지"]
        M --> M1["TOP N"]
        M --> M2["N위"]
        M --> M3["N%"]
        M --> M4["가장 많이"]
        M --> M5["대부분"]

        M1 --> N{"패턴 매칭?"}
        M2 --> N
        M3 --> N
        M4 --> N
        M5 --> N

        N -->|"NO"| O["통과"]
        N -->|"YES"| P{"sources에<br/>해당 통계?"}
        P -->|"NO"| Q["차단 응답 반환<br/>근거 없는 통계"]
        P -->|"YES"| O
    end

    subgraph KOREAN["4. Korean Output Enforcement"]
        direction LR
        O --> R["영어 시작 패턴 체크"]
        R --> R1["I'd be happy to..."]
        R --> R2["I can help..."]
        R --> R3["According to..."]
        R --> R4["Based on..."]

        R1 --> S{"영어로 시작?"}
        R2 --> S
        R3 --> S
        R4 --> S

        S -->|"YES"| T["한국어 재생성 요청<br/>또는 강제 변환"]
        S -->|"NO"| U["최종 응답 확정"]
        T --> U
    end

    subgraph OUTPUT["검증 완료"]
        direction LR
        E --> V["guard_result"]
        L --> V
        Q --> V
        U --> V

        V --> W["blocked: bool"]
        V --> X["reason: str"]
        V --> Y["final_answer: str"]
    end

    style E fill:#fff3e0
    style L fill:#ffcdd2
    style Q fill:#ffcdd2
    style U fill:#c8e6c9

flowchart LR
    %% 6) PII 마스킹 플로우 - 가로형
    subgraph INPUT_STAGE["INPUT 단계"]
        direction LR
        A["사용자 질문<br/>(원문)"] --> B["PII 서비스 호출<br/>POST /mask"]
        B --> C{"서비스 정상?"}
        C -->|"YES"| D["PII 검출 & 마스킹"]
        C -->|"NO"| E["Fail-Closed 발동"]

        D --> D1["이름 → [NAME]"]
        D --> D2["전화번호 → [PHONE]"]
        D --> D3["이메일 → [EMAIL]"]
        D --> D4["주민번호 → [RRN]"]

        D1 --> F["마스킹된 쿼리"]
        D2 --> F
        D3 --> F
        D4 --> F

        E --> G["안전 메시지 반환<br/>원문 전송 차단"]
    end

    subgraph OUTPUT_STAGE["OUTPUT 단계"]
        direction LR
        H["LLM 응답<br/>(원문)"] --> I["PII 서비스 호출<br/>POST /mask"]
        I --> J{"서비스 정상?"}
        J -->|"YES"| K["PII 검출 & 마스킹"]
        J -->|"NO"| L["Fail-Closed 발동"]

        K --> K1["응답 내 PII 마스킹"]
        K1 --> M["마스킹된 응답"]
        L --> N["안전 메시지 반환<br/>원문 전송 차단"]
    end

    subgraph LOG_STAGE["LOG 단계"]
        direction LR
        O["질문 + 응답"] --> P["PII 서비스 호출<br/>stage=LOG"]
        P --> Q["마스킹된 Q&A"]
        Q --> R["Elasticsearch<br/>마스킹된 데이터만 저장"]
    end

    subgraph PRIVACY_GATE["Privacy Query Gate"]
        direction LR
        S["마스킹된 쿼리"] --> T["조합 규칙 체크"]
        T --> T1["대상: 직원, 팀원, 누가<br/>(+2점)"]
        T --> T2["행위: 명단, 리스트, 뽑아<br/>(+3점)"]
        T --> T3["속성: 교육, 점수, 평가<br/>(+3점)"]

        T1 --> U{"총점 >= 6?"}
        T2 --> U
        T3 --> U

        U -->|"YES"| V["BLOCK_PII_LIST<br/>차단 응답"]
        U -->|"NO"| W{"1인칭?<br/>내/저"}
        W -->|"YES"| X["ALLOW<br/>개인화 조회 허용"]
        W -->|"NO"| X
    end

    style E fill:#ffcdd2
    style G fill:#ffcdd2
    style L fill:#ffcdd2
    style N fill:#ffcdd2
    style V fill:#ffcdd2
    style F fill:#c8e6c9
    style M fill:#c8e6c9
    style X fill:#c8e6c9

flowchart LR
    %% 7) 전체 보안 게이트 요약 - 가로형
    subgraph LAYER1["Layer 1: 입력 필터"]
        direction LR
        A["금지질문 필터"] --> B["PII 마스킹<br/>(INPUT)"]
        B --> C["Privacy Query Gate"]
    end

    subgraph LAYER2["Layer 2: 의도 분류"]
        direction LR
        D["Smalltalk Gate"] --> E["절차 AND 조건"]
        E --> F["애매한 경계 감지"]
        F --> G["치명 액션 확인"]
    end

    subgraph LAYER3["Layer 3: 검색 품질"]
        direction LR
        H["Low-Relevance Gate<br/>(anchor 매칭)"] --> I["Quality Gate<br/>(L2 거리)"]
    end

    subgraph LAYER4["Layer 4: 응답 검증"]
        direction LR
        J["Answerability Gate"] --> K["Citation Guard"]
        K --> L["Statistical Guard"]
        L --> M["Korean Output"]
    end

    subgraph LAYER5["Layer 5: 출력 보호"]
        direction LR
        N["PII 마스킹<br/>(OUTPUT)"] --> O["Fail-Closed"]
    end

    C --> D
    G --> H
    I --> J
    M --> N

    style A fill:#ffcdd2
    style C fill:#ffcdd2
    style I fill:#fff3e0
    style K fill:#f3e5f5
    style L fill:#f3e5f5
    style O fill:#ffcdd2

flowchart LR
    %% 9) 멀티턴 대화 플로우 - 가로형
    subgraph TURN1["1턴: 사용자 질문"]
        direction LR
        A["사용자: 연차 알려줘"] --> B["Rule Router"]
        B --> C{"애매한 경계?"}
        C -->|"YES"| D["needs_clarify=true"]
        D --> E["되묻기 응답<br/>규정 설명? 잔여일수 조회?"]
        E --> F["PendingAction 저장<br/>TTL=5분"]
    end

    subgraph TURN2["2턴: 사용자 응답"]
        direction LR
        G["사용자: 잔여일수"] --> H["PendingAction 확인"]
        H --> I{"PendingAction<br/>존재?"}
        I -->|"YES"| J["ClarifyAnswerHandler"]
        I -->|"NO"| K["새 질문으로 처리"]

        J --> L{"응답 길이?"}
        L -->|"<= 20자"| M["키워드 매핑<br/>sub_intent_id 결정"]
        L -->|"> 20자"| K

        M --> N["잔여일수 → BACKEND_STATUS"]
        N --> O["원본 쿼리 + sub_intent<br/>재라우팅"]
    end

    subgraph EXECUTION["실행"]
        direction LR
        O --> P["BACKEND_API 경로"]
        P --> Q["개인화 데이터 조회"]
        Q --> R["LLM 응답 생성"]
        R --> S["응답 반환"]
    end

    subgraph CONTEXT["컨텍스트 관리"]
        direction LR
        T["ChatContextHandler"] --> T1["대화 이력 저장"]
        T1 --> T2["다음 턴에서<br/>이력 참조"]
    end

    F --> G
    S --> T

    style D fill:#fce4ec
    style E fill:#fce4ec
    style N fill:#c8e6c9