← 목록으로
2026-02-25plans

title: content-orchestration 자체교정 설계서 (L1) date: 2026-02-25T19:30:00+09:00 type: design layer: L1 status: in-review tags: [content-orchestration, self-healing, L1, error-recovery] author: self-healing-pl project: content-orchestration reviewed_by: "jarvis" reviewed_at: "2026-02-25T19:45:00+09:00" approved_by: "" approved_at: ""

content-orchestration 자체교정(Self-Healing) 설계서 (L1)

Task ID: dc1d0d04-5bca-4d69-abc7-e0b4f3e40c79 작성일: 2026-02-25 작성자: self-healing-pl 근거 문서:

  • L1: content-orchestration-design-pipeline.md (파이프라인 설계서, 승인)
  • L1: content-orchestration-design-db.md (DB 설계서, 검수 완료)
  • L1: content-orchestration-design-external.md (외부 연동 설계서, 승인)

1. 자체교정 개요

1-1. 자체교정이란

자체교정(Self-Healing)은 파이프라인 실행 중 발생하는 오류를 사람 개입 없이 자동으로 탐지하고 복구하는 메커니즘이다. 파이프라인 설계서 섹션 3의 교정 등급(L1~L5)을 기반으로, 등급별로 자동 복구 범위와 에스컬레이션 판단 기준을 정의한다.

핵심 목표: 파이프라인 장애 시 CEO 개입을 최소화하고, 자동 교정 성공률 80%+ 달성 (Phase 3 목표)

1-2. L1~L5 등급 정의 (상세)

등급이름교정 행동자동화 수준판단 기준Phase
L1즉시 자동 수정동일 작업 재실행 (파라미터 변경 없음)완전 자동일시적 오류 (네트워크, DB 연결, 타임아웃)Phase 1
L2재시도 후 수정대기 후 재시도 또는 파라미터 미세 조정완전 자동Rate Limit, API 일시 과부하, QA 미달Phase 1
L3대체 전략Fallback 경로 전환 (다른 소스/모델/채널)자동 (설정 범위 내)특정 소스/채널 지속 실패, AI 모델 장애Phase 2
L4품질 강등콘텐츠 재생성 → 실패 시 holding 전환반자동 (자비스 검수)AI 생성 품질 반복 미달, QA 3회 연속 실패Phase 2
L5인간 에스컬레이션CEO/VP에게 알림, 수동 해결 대기수동인증 실패, 3회 연속 자동 교정 실패, 전체 채널 실패, 비용 영향Phase 1

1-3. 자체교정 적용 범위

파이프라인 단계적용 자체교정 등급외부 연동
Stage 1: 수집 (Collect)L1, L2, L3RSS 17개 피드
Stage 2: 생성 (Generate)L1, L2, L4Gemini Flash API
Stage 3: 승인 (Approve)— (자체교정 대상 아님, CEO 액션)
Stage 4: 배포 (Publish)L1, L2, L3Brevo, AppPro 블로그 DB, getlate.dev
외부 연동: BrevoL1, L2, L5Brevo API
외부 연동: getlate.devL1, L2, L3getlate REST API
외부 연동: 블로그 DBL1, L5Turso (apppro-kr)

1-4. 자체교정 vs 에스컬레이션 판단 기준

에러 발생
    │
    ├─ 인증 실패 (auth_fail)? ─→ 즉시 L5 에스컬레이션 (CEO 키 갱신 필요)
    │
    ├─ 동일 에러 3회 연속? ─→ L5 에스컬레이션 (자동 교정 한계)
    │
    ├─ 전체 채널/소스 실패? ─→ L5 에스컬레이션 (시스템 장애 의심)
    │
    ├─ 비용 영향 (Rate Limit 초과 등)? ─→ L2 자동 지연 후 재시도
    │
    ├─ 대체 경로 가능? ─→ L3 Fallback 전환
    │
    ├─ 품질 문제? ─→ L4 재생성 시도 (최대 2회)
    │
    └─ 일시적 오류? ─→ L1/L2 즉시 재시도

2. 등급별 자체교정 시나리오 (상세)

2-1. L1: 즉시 자동 수정

원칙: 동일 파라미터로 1회 재시도. 성공하면 auto_fix_result='success', 실패하면 L2로 에스컬레이트.

#시나리오감지 방법교정 행동대기 시간재시도 횟수
1RSS 피드 HTTP 5xxfetch 응답 코드 >= 500동일 URL 재요청5초1회
2DB 연결 일시 오류LibSQL 연결 예외재연결 후 동일 쿼리3초1회
3Brevo API 네트워크 에러fetch timeout 또는 네트워크 예외동일 요청 재전송5초1회
4getlate API 일시 에러HTTP 5xx 또는 timeout동일 요청 재전송5초1회
5slug 중복 (블로그)SQL ON CONFLICT 감지slug에 날짜+순번 자동 추가 ({slug}-2026-02-25-2)0초즉시
6RSS XML 파싱 부분 실패rss-parser 예외 (개별 피드)해당 피드 skip, 나머지 계속0초

L1 교정 코드 패턴:

try {
  result = await action()
} catch (error) {
  // L1: 즉시 재시도
  await sleep(waitMs)
  try {
    result = await action()
    logAutoFix(errorId, 'success', 'L1 즉시 재시도 성공')
  } catch (retryError) {
    logAutoFix(errorId, 'failed', 'L1 재시도 실패 → L2 전환')
    // L2로 에스컬레이트
  }
}

2-2. L2: 재시도 후 수정

원칙: 대기 시간을 늘리거나 파라미터를 미세 조정한 후 재시도. 최대 3회.

#시나리오감지 방법교정 행동재시도 전략
1Brevo Rate Limit (HTTP 429)응답 코드 42960초 대기 후 재시도 → 발송 시간을 다음 날 06:00 KST로 변경60초 → 120초 → 다음 날 재예약
2RSS 피드 타임아웃10초 초과타임아웃 15초로 확장 후 재시도10초 → 15초 → 20초
3AI API 타임아웃Gemini API fetch timeout30초 대기 후 재시도30초 → 60초 → 포기
4QA 미달 (score < 6/8)validateQuality 함수프롬프트 온도 0.7→0.5로 낮추어 재생성최대 2회 재생성
5JSON 파싱 실패JSON.parse 예외이스케이프 보정 → 필드별 추출 시도2단계 파싱 시도
6getlate 월간 한도 근접포스트 수 추적우선순위 낮은 플랫폼 skip즉시
7블로그 DB INSERT 실패SQL 예외 (non-auth)5초 대기 후 1회 재시도5초 대기 → 1회

L2 백오프 전략:

재시도 간격 = baseDelay * (2 ^ attemptNumber)
  - 1회: 5초 (또는 60초 for rate limit)
  - 2회: 10초 (또는 120초)
  - 3회: 20초 (또는 다음 날 재예약)
최대 재시도: 3회
3회 실패 시: error_logs에 기록 + L5 에스컬레이션

2-3. L3: 대체 전략

원칙: 원래 경로가 실패하면 사전 정의된 대체 경로로 전환. Phase 2에서 구현.

#시나리오감지 조건대체 전략Phase
1특정 RSS 소스 3회 연속 실패error_logs에서 동일 component + 동일 URL 3건 (24시간 내)해당 소스 자동 비활성화, 동일 카테고리의 대체 소스로 교체Phase 2
2SNS 특정 플랫폼 실패getlate 응답에서 플랫폼별 status='failed'해당 플랫폼만 skip, 나머지 정상 진행Phase 1 (부분)
3Gemini API 장기 장애연속 3회 AI API 실패 (1시간 내)Claude API로 모델 전환 (content_generation_config에서 model 변경)Phase 2
4Brevo 발송 한도 초과HTTP 402 또는 일일 300통 도달scheduledAt을 다음 날로 자동 재예약Phase 1 (부분)

L3 대체 소스 매핑 (Phase 2):

카테고리별 대체 소스 우선순위:
  news (영문): The Verge → TechCrunch → Ars Technica → Techmeme
  official: OpenAI Blog → Google AI Blog → DeepMind → Hugging Face → NVIDIA
  news (한국): AI타임스 → ZDNet Korea → 전자신문 → ITWorld Korea → 테크니들
  community: Hacker News Best → Hacker News Latest → Techmeme

2-4. L4: 품질 강등

원칙: AI 생성 콘텐츠 QA 점수 부족 시 재생성. 3회 실패 시 holding 전환. Phase 2에서 구현.

#시나리오감지 조건교정 행동
1QA 6/8 미만 (1차)validateQuality score < 6프롬프트 온도 0.7→0.5, 재생성 (2차 시도)
2QA 6/8 미만 (2차)2차 재생성도 score < 6프롬프트 길이 제한 완화 (max_tokens +500), 재생성 (3차 시도)
3QA 6/8 미만 (3차)3차 재생성도 score < 6content_queue.status='failed' + error_logs(error_type='quality_fail', escalated=1)
4특정 필라 반복 실패동일 pillar에서 3일 연속 QA 실패optimization_history에 기록 + 해당 필라 프롬프트 템플릿 검토 에스컬레이션

L4 품질 강등 플로우:

AI 생성 완료
    │
    ↓
QA 검증 (8항목)
    │
    ├─ score >= 6/8: PASS → content_queue(draft)
    │
    └─ score < 6/8: FAIL
        │
        ├─ 1차 실패: 온도 0.7→0.5, 재생성
        ├─ 2차 실패: max_tokens +500, 재생성
        └─ 3차 실패: error_logs + escalated=1
                     content_queue.status='failed'

2-5. L5: 인간 에스컬레이션

원칙: 자동 교정이 불가능하거나 3회 연속 실패한 경우. CEO/VP에게 알림 후 수동 해결 대기.

#시나리오에스컬레이션 트리거알림 대상알림 방법
1API 인증 실패 (auth_fail)HTTP 401/403 (모든 외부 연동)CEO즉시 텔레그램 (Phase 2) / 대시보드 에러 표시 (Phase 1)
23회 연속 자동 교정 실패error_logs에서 동일 component 3건 (auto_fix_result='failed')VP/자비스vice-reply.sh (Phase 2)
3전체 채널 배포 실패content_distributions에서 해당 content_id의 모든 레코드가 failedVP/자비스vice-reply.sh (Phase 2)
4전체 RSS 피드 실패collect 실행 시 모든 17개 피드 실패VP/자비스pipeline_logs status='failed' + error_logs escalated=1
5DB 인증 토큰 만료Turso 연결 auth 에러CEO즉시 에스컬레이션 (토큰 갱신 필요)

Phase 1 에스컬레이션 표시 방법 (Telegram 미연동):

  • error_logs.escalated = 1 설정
  • 대시보드 /api/pipeline/errors 엔드포인트에서 escalated=1 건 우선 표시
  • pipeline_logs metadata에 "escalated": true 기록

Phase 2 에스컬레이션 알림:

  • vice-reply.sh 또는 ceo-reply.sh를 통한 Telegram 자동 알림 (외부 연동 설계서 섹션 2-4 참조)

3. error_logs 기반 자동 교정 메커니즘

3-1. error_logs 스캔 주기 및 방법

스캔 시점방법목적
파이프라인 실행 전runSelfHealingCycle() 호출이전 실행에서 남은 미해결 에러 교정 시도
파이프라인 실행 중각 단계에서 에러 발생 즉시실시간 교정 (L1/L2)
Cron 실행 시/api/cron/pipeline 시작 시누적 미해결 에러 배치 교정

스캔 쿼리:

-- 미해결 + 자동 교정 미시도 에러 조회
SELECT * FROM error_logs
WHERE resolved_at IS NULL
  AND (auto_fix_attempted = 0 OR auto_fix_result = 'failed')
  AND escalated = 0
ORDER BY occurred_at ASC
LIMIT 20;

3-2. 자동 교정 실행 플로우

[1] error_logs 스캔 (미해결 건 조회)
     │
     ↓
[2] 에러별 교정 등급 판단
     │
     ├─ component + error_type 조합으로 등급 결정
     │   (아래 3-3 매핑 테이블 참조)
     │
     ↓
[3] 등급별 교정 실행
     │
     ├─ L1: 즉시 재실행
     │   ├─ auto_fix_attempted = 1
     │   ├─ 교정 실행
     │   └─ auto_fix_result = 'success' / 'failed'
     │
     ├─ L2: 대기 후 재시도 (백오프)
     │   ├─ retry_count 확인 (3 미만인 경우만)
     │   ├─ auto_fix_attempted = 1
     │   ├─ sleep(backoff) → 재실행
     │   └─ auto_fix_result = 'success' / 'failed'
     │
     ├─ L3: Fallback 전환 (Phase 2)
     │   ├─ 대체 경로 조회
     │   ├─ 대체 경로로 재실행
     │   └─ auto_fix_action에 전환 내용 기록
     │
     ├─ L4: 품질 재생성 (Phase 2)
     │   ├─ 파라미터 조정
     │   ├─ 재생성 실행
     │   └─ 3회 실패 시 escalated=1
     │
     └─ L5: 에스컬레이션
         ├─ escalated = 1
         ├─ auto_fix_result = 'skipped'
         └─ 알림 전송 (Phase 2: Telegram)
     │
     ↓
[4] 결과 기록
     │
     ├─ 성공: resolved_at = now, resolution_type = 'auto_fixed'
     └─ 실패: auto_fix_result = 'failed'
              (3회 실패 시 escalated = 1)

3-3. component + error_type → 교정 등급 매핑

componenterror_type교정 등급자동 교정 액션
rss_collectortimeoutL1→L2재시도 (timeout 확장)
rss_collectorapi_error (HTTP 5xx)L15초 후 재시도
rss_collectorapi_error (HTTP 4xx)L3대체 소스 전환 (Phase 2)
rss_collectorvalidation_failL1해당 피드 skip
ai_generatortimeoutL230초 후 재시도
ai_generatorapi_errorL2→L3재시도 → 모델 전환 (Phase 2)
ai_generatorauth_failL5즉시 에스컬레이션
qa_checkerquality_failL2→L4재생성 (온도 조정)
publishertimeoutL15초 후 재시도
publishervalidation_failL1slug 변경 후 재시도
publisherauth_failL5즉시 에스컬레이션
brevorate_limitL260초 대기 → 다음 날 재예약
brevoauth_failL5즉시 에스컬레이션
brevoapi_errorL1→L2재시도 → 파라미터 검증
brevovalidation_failL2요청 파라미터 검증 후 재시도
sns_publisherauth_fail (NO_ACCOUNTS)L3해당 플랫폼 skip
sns_publisherapi_errorL130초 후 재시도
sns_publishertimeoutL1재시도 → 해당 플랫폼 skip
schedulerapi_errorL2Cron 다음 실행 시 재시도

3-4. auto_fix 업데이트 플로우

-- 1단계: 교정 시도 시작
UPDATE error_logs
SET auto_fix_attempted = 1,
    auto_fix_action = '교정 액션 설명'
WHERE id = ?;

-- 2단계-A: 교정 성공
UPDATE error_logs
SET auto_fix_result = 'success',
    resolved_at = (unixepoch() * 1000),
    resolution_type = 'auto_fixed'
WHERE id = ?;

-- 2단계-B: 교정 실패
UPDATE error_logs
SET auto_fix_result = 'failed'
WHERE id = ?;

-- 2단계-C: 에스컬레이션 (교정 불가 또는 3회 실패)
UPDATE error_logs
SET auto_fix_result = 'skipped',
    escalated = 1
WHERE id = ?;

3-5. 에스컬레이션 트리거 조건

-- 동일 component에서 3회 연속 자동 교정 실패 확인
SELECT COUNT(*) as fail_count
FROM error_logs
WHERE component = ?
  AND auto_fix_result = 'failed'
  AND occurred_at > (unixepoch() * 1000 - 86400000)  -- 최근 24시간
  AND resolved_at IS NULL;

-- fail_count >= 3 → escalated = 1

4. 자체교정 코드 구조

4-1. 파일 구조

content-pipeline/src/lib/
└── self-healing.ts   ← 자체교정 핵심 로직
    ├── detectErrors()           — error_logs 미해결 에러 스캔
    ├── classifyError()          — 에러 등급 판단 (L1~L5)
    ├── attemptAutoFix()         — 등급별 자동 수정 실행
    ├── escalateIfNeeded()       — 에스컬레이션 판단 + 처리
    ├── logFixAttempt()          — 교정 시도/결과 error_logs 업데이트
    └── runSelfHealingCycle()    — 통합 실행 (Cron에서 호출)

4-2. 핵심 함수 명세

detectErrors(): Promise<ErrorLog[]>

미해결 에러를 error_logs에서 조회한다.

  • 입력: 없음
  • 출력: 미해결 ErrorLog 배열 (최대 20건)
  • 쿼리: resolved_at IS NULL AND escalated = 0 조건
  • 정렬: occurred_at ASC (오래된 에러부터 처리)

classifyError(error: ErrorLog): HealingLevel

에러의 component와 error_type 조합으로 교정 등급을 판단한다.

  • 입력: ErrorLog 객체
  • 출력: 'L1' | 'L2' | 'L3' | 'L4' | 'L5'
  • 로직: 섹션 3-3 매핑 테이블 기반
  • 특수 케이스: auth_fail은 항상 L5

attemptAutoFix(error: ErrorLog, level: HealingLevel): Promise<FixResult>

등급에 따라 자동 교정을 실행한다.

  • 입력: ErrorLog, HealingLevel
  • 출력: { success: boolean, action: string, nextLevel?: HealingLevel }
  • L1: 동일 작업 즉시 재실행
  • L2: 백오프 대기 후 재시도 (파라미터 조정 포함)
  • L3: Fallback 경로 전환 후 재실행 (Phase 2)
  • L4: 품질 파라미터 조정 후 재생성 (Phase 2)
  • L5: { success: false, action: 'escalated' } 반환

escalateIfNeeded(error: ErrorLog): Promise<boolean>

에스컬레이션 필요 여부를 판단하고, 필요 시 escalated=1 설정.

  • 입력: ErrorLog
  • 출력: boolean (에스컬레이션 발생 여부)
  • 판단 기준:
    • error_type === 'auth_fail' → 즉시
    • 동일 component 24시간 내 3회 교정 실패 → 에스컬레이션
    • 전체 채널 실패 (content_distributions 전부 failed) → 에스컬레이션

runSelfHealingCycle(): Promise<HealingReport>

전체 자체교정 사이클을 실행한다. Cron 또는 파이프라인 시작 전에 호출.

  • 입력: 없음
  • 출력: { total: number, fixed: number, escalated: number, skipped: number }
  • 플로우:
    1. detectErrors() 호출 → 미해결 에러 목록
    2. 각 에러에 대해 classifyError()attemptAutoFix()logFixAttempt()
    3. 교정 실패 시 escalateIfNeeded() 호출
    4. 결과 리포트 반환 (pipeline_logs metadata에 기록)

4-3. 타입 정의

type HealingLevel = 'L1' | 'L2' | 'L3' | 'L4' | 'L5';

interface FixResult {
  success: boolean;
  action: string;         // 교정 액션 설명
  nextLevel?: HealingLevel;  // 실패 시 다음 시도 등급
}

interface HealingReport {
  total: number;      // 스캔된 에러 수
  fixed: number;      // 자동 교정 성공 수
  escalated: number;  // 에스컬레이션 수
  skipped: number;    // 교정 불필요/스킵 수
}

// 에러 분류 매핑 타입
interface ErrorClassification {
  component: string;
  errorType: string;
  level: HealingLevel;
  autoFixAction: string;
  maxRetries: number;
  backoffMs: number;
}

5. Cron 연계 방법

5-1. 파이프라인 실행 전 Self-Healing 선행

/api/cron/pipeline Cron 핸들러에서 파이프라인 실행 전에 자체교정 사이클을 먼저 실행한다.

/api/cron/pipeline 실행 (매일 KST 06:00, 월~금)
    │
    ├─ [1] runSelfHealingCycle()       ← 이전 실행 잔류 에러 교정
    │   │
    │   ├─ 미해결 에러 스캔 + 자동 교정 시도
    │   └─ 결과 pipeline_logs 기록 (pipeline_name='self-healing')
    │
    ├─ [2] Stage 1: collect            ← RSS 수집
    │   │
    │   └─ 수집 중 에러 → 즉시 L1/L2 교정 (인라인)
    │
    ├─ [3] Stage 2: generate           ← AI 콘텐츠 생성
    │   │
    │   └─ 생성 중 에러 → 즉시 L1/L2/L4 교정 (인라인)
    │
    ├─ [4] Stage 4: publish            ← 승인된 콘텐츠 배포
    │   │
    │   └─ 배포 중 에러 → 즉시 L1/L2 교정 (인라인)
    │
    └─ [5] 최종 결과 기록
        │
        └─ pipeline_logs (전체 실행 결과 + self-healing 결과 metadata)

5-2. 자체교정 전용 Cron 분리 여부

Phase 1: 파이프라인 Cron과 통합 (별도 Cron 불필요)

  • 파이프라인 실행이 1일 1회(KST 06:00)이므로, 그 시작 시 runSelfHealingCycle() 호출로 충분
  • 파이프라인 실행 중 발생하는 에러는 각 단계에서 인라인으로 L1/L2 교정

Phase 2+: 별도 Cron 고려

  • 파이프라인 실행 빈도가 높아지면 (예: 1일 3회), self-healing 전용 Cron을 분리할 수 있음
  • /api/cron/self-healing — 매 6시간 실행, 누적 에러 교정

5-3. pipeline_logs 기록 형식

{
  "pipeline_name": "self-healing",
  "status": "completed",
  "trigger_type": "scheduled",
  "items_processed": 5,
  "metadata": {
    "total_errors": 5,
    "fixed": 3,
    "escalated": 1,
    "skipped": 1,
    "details": [
      {"error_id": "err-001", "component": "rss_collector", "result": "success", "level": "L1"},
      {"error_id": "err-002", "component": "brevo", "result": "escalated", "level": "L5"}
    ]
  }
}

6. Phase별 구현 범위

Phase 1 MVP (1주): L1 + L2 + L5 에스컬레이션

구현 범위:

구현 항목상세
self-healing.ts 파일 생성detectErrors, classifyError, attemptAutoFix (L1/L2만), escalateIfNeeded, runSelfHealingCycle
L1 즉시 재시도RSS 재시도, DB 재연결, API 재시도, slug 변경
L2 백오프 재시도Rate Limit 대기, 타임아웃 확장, QA 재생성 (기존 2회 재시도 로직 연계)
L5 에스컬레이션 기록error_logs.escalated=1 설정, 대시보드 표시
Cron 연계/api/cron/pipeline 시작 시 runSelfHealingCycle() 호출
error_logs 자동 기록모든 파이프라인 단계에서 에러 발생 시 error_logs INSERT
pipeline_logs 기록self-healing 실행 결과를 pipeline_logs에 기록

Phase 1에서 하지 않는 것:

  • L3 대체 전략 (RSS 소스 자동 교체, AI 모델 전환)
  • L4 품질 강등 (프롬프트 파라미터 동적 조정)
  • Telegram 에스컬레이션 알림 (대시보드 표시만)
  • 자체교정 전용 Cron 분리
  • 자체교정 성공률 대시보드

Phase 2 (2주): L3 대체 전략 + L4 품질 강등 + 알림

구현 범위:

구현 항목상세
L3 대체 전략RSS 소스 자동 교체, SNS 플랫폼별 skip, AI 모델 fallback (Gemini→Claude)
L4 품질 강등프롬프트 온도/길이 동적 조정, content_generation_config 연계, 3회 실패 시 holding
Telegram 에스컬레이션 알림escalated=1 시 vice-reply.sh/ceo-reply.sh 자동 호출
대체 소스 매핑 DB화RSS 소스별 대체 URL을 channels config에 저장
optimization_history 연계L4 파라미터 변경 시 optimization_history에 기록
에러 패턴 분석동일 component/error_type 반복 횟수 추적, 패턴 기반 사전 교정

Phase 3 (3주+): 고도화

구현 범위:

구현 항목상세
자체교정 성공률 대시보드최근 7일/30일 교정 성공률 시각화 (목표 80%+)
자체교정 전용 Cron/api/cron/self-healing (매 6시간)
예측적 교정error_logs 패턴 학습 → 장애 예측 → 사전 조치 (특정 시간대 피드 실패 예측 등)
교정 히스토리 분석어떤 교정 액션이 가장 효과적인지 통계 분석
자동 채널 비활성화특정 채널 7일 연속 실패 시 channels.is_active=0 자동 전환

7. 전체 자체교정 데이터 흐름

파이프라인 실행 (Cron / 수동)
    │
    ├─ [선행] runSelfHealingCycle()
    │   ├─ error_logs 스캔 (미해결 건)
    │   ├─ 등급 판단 → 자동 교정 시도
    │   ├─ 성공: resolved_at 기록
    │   ├─ 실패: escalated=1
    │   └─ pipeline_logs 기록 (self-healing 결과)
    │
    ├─ Stage 1~4 실행
    │   ├─ 에러 발생 시:
    │   │   ├─ error_logs INSERT (component, error_type, error_message)
    │   │   ├─ 인라인 L1/L2 교정 시도
    │   │   ├─ 성공: auto_fix_result='success', resolved_at 기록
    │   │   └─ 실패: auto_fix_result='failed'
    │   │            (다음 runSelfHealingCycle에서 재시도)
    │   │
    │   └─ 정상 완료 시:
    │       └─ pipeline_logs 기록 (status='completed')
    │
    └─ 대시보드 반영
        ├─ /api/pipeline/errors → 미해결 에러 목록 (escalated 우선)
        ├─ /api/pipeline/logs → self-healing 실행 이력
        └─ 에러 카운트 배지 (미해결 N건 표시)

리뷰 로그

[self-healing-pl 초안 작성] 2026-02-25 19:30

  • L1~L5 등급별 자체교정 시나리오 상세 설계 완료 (파이프라인 설계서 섹션 3 기반 확장)
  • error_logs 기반 자동 교정 메커니즘: 스캔→분류→교정→기록 4단계 플로우
  • component + error_type → 교정 등급 매핑 테이블 18개 시나리오
  • self-healing.ts 코드 구조: 6개 핵심 함수 명세 (detectErrors, classifyError, attemptAutoFix, escalateIfNeeded, logFixAttempt, runSelfHealingCycle)
  • Cron 연계: 파이프라인 실행 전 self-healing 선행 실행 설계
  • Phase별 구현 범위: Phase 1(L1+L2+L5), Phase 2(L3+L4+알림), Phase 3(예측적 교정)
  • DB 설계서 error_logs 테이블과 완전 연계 (auto_fix_attempted, auto_fix_result, escalated, resolved_at, resolution_type)
  • 자비스 1차 검수 요청

[자비스 1차 검수] 2026-02-25 19:45

검수 결과: 수정 없이 승인 ✅ (9개 항목 전부 통과)

  1. L1~L5 등급 상세화 — 파이프라인 설계서 기반 적용 범위(Stage별/연동별) 완전 명세
  2. 18개 시나리오 매핑 — component+error_type 조합 테이블로 구현 모호성 제거
  3. auth_fail 통일 — 모든 component에서 L5 즉시 에스컬레이션으로 일관성 확보
  4. Phase MVP 범위 명확 — Phase 1(L1+L2+L5만), "하지 않는 것" 명시
  5. error_logs DB 완전 연계 — auto_fix_attempted/result/action, escalated, resolved_at, resolution_type 전부 활용 시점 명세
  6. self-healing.ts 6개 함수 — detectErrors/classifyError/attemptAutoFix/escalateIfNeeded/logFixAttempt/runSelfHealingCycle 명세 완전
  7. Cron 선행 실행 — 파이프라인 실행 전 runSelfHealingCycle() 호출로 잔류 에러 선처리
  8. Telegram 보안 준수 — Phase 2에서도 vice-reply.sh/ceo-reply.sh 간접 호출
  9. SQL 명세 완전 — 스캔 쿼리 + auto_fix 업데이트 3분기(성공/실패/에스컬레이션) SQL 포함

특이사항: sns_publisher auth_fail → L3(해당 플랫폼 skip) 처리는 이 경우가 실제 "인증 실패"가 아닌 "계정 미연결(NO_ACCOUNTS)"이어서 L3가 더 적절. 의도적 설계로 판단. ✅

plans/2026/02/25/content-orchestration-design-self-healing.md