[기술검토] 자동화 스킬 피드백 & 학습 루프 도입 방향성
파이프라인 자동화 스킬 결과에 점수·코멘트를 받아 KB-RAG에 누적하고 다음 실행 prompt에 자동 주입하는 학습 루프 설계. 스킬 파일 무수정 4-Layer 주입 전략과 KB poisoning 을 막는 자가 정제 메커니즘(3-Tier 상태머신·자가검증·LLM judge·시간감쇠)까지 다룬다.
자동화 스킬 피드백 & 학습 루프 도입 방향성
파이프라인 자동화 스킬(
자동기획_V4/자동개발_V4/주문파이프라인_개발검증등)의 결과물에 사용자 점수·코멘트를 받아 KB-RAG에 누적하고, 다음 실행 시 prompt에 자동 주입하는 학습 루프(Feedback → KB → Re-Skill) 설계 검토. 스킬 파일을 1개도 수정하지 않는 4-Layer 주입 전략과, 잘못된 피드백으로 인한 KB poisoning 을 차단하는 자가 정제 메커니즘까지 다룬다.
1. 배경 / 문제 정의
- 자동화 스킬은 1회 실행만으로 완벽한 결과가 나오지 않는다. (V4 기준 1차 통과율 체감 30~50%)
- 결과가 미진할 때 사용자가 구두로 "이 부분이 부족하다"고 말해도 휘발성 피드백으로 끝난다.
- 같은 이슈를 재실행하면 1차에서 지적된 결함이 동일하게 재현되는 경우가 잦다.
- 의사결정자는 스킬별 retry 횟수 / 성공 수율 가시화를 요구한다 (스킬 품질 KPI).
따라서 모든 결과물에 대해 구조화된 피드백(점수+코멘트) 을 받고, 이를 저장 → 학습 → 재주입 하는 표준 루프가 필요하다.
2. 한 줄 목표
모든 결과물에 점수와 코멘트를 남기고, 다음 실행 시 그 피드백이 prompt에 자동으로 들어가게 한다.
3. 사용자 시나리오 (ISSUE-1234 기준)
ISSUE-1234이슈에서자동개발_V41차 실행 → 결과물 미진- 카드의
결과확인클릭 → 모달개발탭에서 산출물 확인 - 모달 하단 피드백 패널: 점수 2/5, 코멘트 "OrderService 트랜잭션 처리 누락 / 주문 파이프라인 호출 timeout 미설정"
등록 & KB 반영클릭 →skill_feedback저장 + 비동기 KB-RAG 인덱싱- 같은 이슈에
자동개발_V42차 실행 트리거 - 스킬은 실행 직전 KB-RAG에서
issue_key=ISSUE-1234 / stage=dev의 이전 피드백을 조회 - prompt에
## 이전 시도 피드백블록이 자동 삽입된 채로 LLM 호출 - 2차 결과는 1차 결함을 보강한 상태로 산출 → 사용자 점수 4/5
- 누적된 피드백은 스킬 자체의 개선 포인트 TOP N 통계로도 집계됨
4. UI 변경안 — 카드 단순화 + 모달 탭화
4.1 현재 (복잡)
파이프라인 카드 하단에 단계별로 [기획결과] [개발결과] [검증결과] [분석결과] [정산결과] [▶기획확인]
등 다수의 버튼이 나열되어 시각적으로 혼잡하고, 단계 진입에 따라 버튼 종류가 달라져 사용자가 헷갈린다.
4.2 개선 (단순)
- 카드 하단 액션을
[LOG] [결과확인]2개로 통일 (단계 진입 직후 산출물이 없을 땐[실행]만 노출) 결과확인모달은 좌측(또는 상단) 탭으로기획 / 개발 / 검증 / 분석 / 정산을 분리- 각 탭은 다시 시도 히스토리 탭 으로
1차(점수) / 2차(점수) / 3차(점수) …노출 - 탭 본문 하단 고정 영역에 피드백 패널 (별점 0~5 + 텍스트 + 저장)
4.3 모달 골격(개념)
┌─ ISSUE-1234 · 결과확인 ─────────────────────────────────┐
│ [기획] [개발*] [검증] [분석] [정산] │
│ ────────────────────────────────────────────────────────── │
│ 시도 히스토리: 1차(05-12 · 2점) | 2차(05-15 · 4점) [▶지금] │
│ ────────────────────────────────────────────────────────── │
│ <산출물 본문 (마크다운 / JsonBlock / diff)> │
│ ────────────────────────────────────────────────────────── │
│ 피드백 입력 │
│ ⭐⭐⭐☆☆ ( 3 / 5 ) │
│ [텍스트 입력 …………………………………………] │
│ [임시저장] [등록 & KB 반영] │
└──────────────────────────────────────────────────────────┘
4.4 카드 표시 변경
- 단계별 결과 라벨 칩은 유지하되, 칩 옆에 마지막 시도 점수 뱃지 노출
예)
개발결과 4★ · 2회 - 점수 < 3 이면 카드 좌측에 노란/빨간 점등 → 다음 액션 우선순위 시각화
5. 데이터 모델 제안
5.1 신규 테이블 skill_feedback
| 컬럼 | 타입 | 비고 |
|---|---|---|
id | UUID | PK |
issue_key | VARCHAR(40) | 예: ISSUE-1234 |
stage | VARCHAR(20) | spec / dev / verification / analysis / bill |
skill_name | VARCHAR(80) | 자동개발_V4 등 |
attempt_no | INT | 해당 stage 의 N차 시도 |
skill_run_id | UUID FK NULL | skill_runs.id (연결 가능 시) |
score | INT | 0~5 |
comment | TEXT | 본문 |
kb_doc_id | VARCHAR(120) | KB-RAG 인덱싱 결과 doc id (NULL 이면 폴백 사용) |
kb_synced_at | TIMESTAMPTZ | 인덱싱 완료 시각 |
author | VARCHAR(120) | 작성자 식별자 |
created_at | TIMESTAMPTZ | 기본 now() |
인덱스: (issue_key, stage, attempt_no DESC), (skill_name, created_at DESC)
5.2 기존 모델 확장
skill_runs.attempt_no INT컬럼 추가 → retry 차수 명시 (현재는 누적이 명확치 않음)harness_issues.extra_data에attempt_count: { spec: 2, dev: 1, ... }누적- WebSocket 이벤트 추가:
feedback_created,feedback_kb_synced
5.3 외부 API (X-API-Key)
backend/app/api/routes/external.py 에 다음 추가:
POST /api/v1/external/skill-feedback— 등록 (스킬 저장소 측에서도 사용 가능)GET /api/v1/external/skill-feedback?issue_key=…&stage=…&limit=5— 최근 피드백 조회
6. KB-RAG 연동 (학습 루프의 핵심)
6.1 인덱싱 흐름
- 피드백 저장 (
POST /skill-feedback) 시 비동기 태스크로rag_client호출 - 문서 본문 =
"[stage={stage} attempt={n} score={s}] {comment}" - 문서 메타 =
{ issue_key, stage, skill_name, attempt_no, score, created_at, author } - 컬렉션:
skill_feedback전용 컬렉션 1개 권장- 프로필별 KB 와 섞이지 않아 retrieval 노이즈가 적다
- 권한이 동일한 사내 데이터이므로 단일 컬렉션이 운영상 단순함
6.2 스킬 실행 직전 컨텍스트 주입
백엔드 harness.py 라우트의 스킬 트리거 직전 훅에서:
prior = await kb_service.search(
collection_ids=[SKILL_FEEDBACK_COLLECTION_ID],
query=f"issue:{issue_key} stage:{stage}",
topk=5,
)
input_data["prior_feedback"] = [
{"attempt": d["attempt_no"], "score": d["score"], "comment": d["comment"]}
for d in prior
]
스킬 저장소 측 자동개발_V4 prompt 템플릿에 다음 블록을 표준화하여 삽입:
## 이전 시도 피드백 (반드시 반영)
{{#prior_feedback}}
- [{{attempt}}차 · {{score}}점] {{comment}}
{{/prior_feedback}}
6.3 폴백 경로
⚠️ KB-RAG 인덱싱이 비동기라 race condition 가능 → DB 직접 조회 폴백 병행:
SELECT … FROM skill_feedback WHERE issue_key=? AND stage=? ORDER BY attempt_no DESC LIMIT 5
스킬 측은 prior_feedback 이 비어있으면 자연스럽게 무시되도록 prompt 작성.
7. 지표 & 한눈에 보기 대시보드
지표는 두 축이 필요하다 — 스킬 관점(어떤 스킬이 잘/못 동작) 과 이슈 관점(어떤 이슈가 골치). 페이지를 2개로 분리해 각각 다른 의사결정에 활용한다.
7.1 스킬별 KPI — /settings/skill-metrics (신규)
| 지표 | 정의 |
|---|---|
| 평균 시도 횟수 | 최근 30일 stage별 평균 — 1에 가까울수록 우수 |
| 평균 사용자 점수 | 0~5 평균 |
| Pass@1 비율 | 1차 시도에서 점수 ≥4 받은 비율 |
| 재시도 분포 | 1회 / 2회 / 3+회 비중 |
| 자주 지적된 항목 TOP 5 | 피드백 텍스트 임베딩 클러스터링 |
| 주간 추이 라인 차트 | 점수 / 재시도 횟수 추이 |
뷰: 스킬별(자동개발_V4, 자동기획_V4 …) 필터 + 단계별 필터.
→ 의사결정자·플랫폼팀이 스킬별 수율 을 한눈에 본다.
7.2 이슈별 시도·점수 보드 — /harness/issue-board (신규)
"ISSUE-1234 의 자동개발이 몇 번 돌았고 점수가 어땠는지, ISSUE-99XX 는 어떤 단계에서 막혔는지" 를 표 한 장 으로 본다. 이슈 단위 운영·회고용.
컬럼 구성
| 컬럼 | 표시 예시 |
|---|---|
issue_key | ISSUE-1234 (행 클릭 → 결과확인 모달) |
| 제목 | 이슈 요약 (말줄임) |
| 현재 단계 | 대기 / 준비 / 기획 / 개발 / 검증 / 배포 |
| 기획 | 2회 · 4★ (시도수 · 마지막 점수) |
| 개발 | 3회 · 2★ ⚠ |
| 검증 | 1회 · 5★ |
| 분석 | – (피드백 없음) |
| 평균 점수 | 3.2 + 색 점등 (<3 빨강 / 3~4 노랑 / ≥4 초록) |
| 총 시도 | 모든 단계 합산 (6) |
| 점수 추이 | sparkline (시도별) |
| 마지막 코멘트 | 최근 피드백 1줄 (hover → popover) |
| 상태 | 진행중 / 잠김(error_locked) / 완료 |
정렬 · 필터
- 평균 점수 ASC — 우선 개선 대상 보기
- 총 시도 DESC — 재시도 많은 골치 이슈 모아 보기
- 단계 필터 (
개발만,검증만…) - 작성자·담당자 필터
- 기간 필터 (오늘 / 이번주 / 최근 30일 / 사용자 지정)
- 점수 범위 필터 (
0~2/3/4~5) - 상태 필터 (잠김만, 완료 제외 등)
인터랙션
- 행 클릭 → 결과확인 모달 오픈 + 단계 탭은 평균 점수 최저인 단계 로 자동 선택
- 단계 칩 클릭 → 해당 단계 탭으로 진입
- 점수 셀 클릭 → 해당 attempt 의 산출물로 직접 점프
- 코멘트 hover → 전체 피드백 popover
모드 (토글)
- 이슈 요약 모드 (기본): 1 row = 1 이슈, 단계별 최신 시도 요약
- 시도 상세 모드: 1 row = 1 attempt, 이슈별 그룹핑 (시간순 펼침)
데이터 소스 (단일 쿼리 패턴)
WITH latest AS (
SELECT issue_key, stage,
MAX(attempt_no) AS last_attempt,
COUNT(*) AS attempts
FROM skill_feedback
GROUP BY issue_key, stage
)
SELECT
i.issue_key, i.title, i.current_stage,
l_spec.attempts AS spec_n, f_spec.score AS spec_score,
l_dev.attempts AS dev_n, f_dev.score AS dev_score,
l_ver.attempts AS ver_n, f_ver.score AS ver_score,
l_ana.attempts AS ana_n, f_ana.score AS ana_score,
AVG(f.score) AS avg_score,
SUM(l.attempts) AS total_attempts,
MAX(f.created_at) AS last_feedback_at
FROM harness_issues i
LEFT JOIN latest l USING (issue_key)
LEFT JOIN skill_feedback f
ON f.issue_key = i.issue_key
AND f.stage = l.stage
AND f.attempt_no= l.last_attempt
GROUP BY i.issue_key, i.title, i.current_stage
ORDER BY avg_score ASC NULLS LAST;
페이지 보조 위젯
- 상단 미니 KPI 4개: 총 이슈 / 평균 점수 / 잠김 수 / 이번 주 재시도 합계
- 우측 "주의 이슈" 카드뷰: 평균 점수 최저 3건 카드 (모바일에선 상단으로 이동)
- 하단 CSV/Excel 다운로드: 외부 보고용
활용 시나리오
- Lead 운영: 이번 주 자동개발이 잘 안 된 이슈 TOP 5 → 평균 점수 ASC + 최근 7일 + 단계=개발
- 담당자 회고: 내 이슈 중 retry는 많은데 점수 낮은 것 → 작성자 필터 + 총시도 DESC + 점수<3
- 스킬 개선 회고: stage=개발 + 평균<3 인 이슈만 →
자동개발_V4개선 포인트 도출 - 경영 보고: 한 페이지 캡처로 자동화 품질 현황 공유 (점수 분포 + 골치 이슈 명단)
- 잠김 이슈 일괄 처리: 상태=잠김 → 다중 선택 → 일괄 재실행 트리거
사이드바 진입점
- 상단 메뉴
Harness아래파이프라인 / 이슈 보드 / 이슈 분석 / 워크스페이스로 노출 - 파이프라인 카드의
LOG옆에📊아이콘 → 해당 이슈로 필터된 보드로 점프
8. 단계적 도입 계획
| Phase | 산출물 | 추정 |
|---|---|---|
| P1. 데이터 골격 | skill_feedback 테이블 + 외부 API + WS 이벤트 + skill_runs.attempt_no | 2일 |
| P2. UI 통합 | 카드 풋터 단일화(결과확인) + 모달 탭화 + 시도 히스토리 + 피드백 패널 | 3일 |
| P3. KB-RAG 연동 | 피드백 인덱싱 + 스킬 실행 직전 컨텍스트 주입 + 스킬 저장소 prompt 템플릿 수정 | 3일 |
| P4. 지표 대시보드 | /settings/skill-metrics (스킬 KPI) + /harness/issue-board (이슈 보드) 페이지 | 3일 |
| P5. 자동 개선 포인트 | 피드백 텍스트 임베딩 클러스터링으로 스킬 개선 항목 자동 추출 (옵션) | 추후 |
⚠️ P1 은 스킬 저장소 측과 동시 변경 필요. dual-repo sync 원칙 준수.
9. 리스크 / 고려사항
-
컨텍스트 폭증 동일 이슈를 5~10회 반복하면 prompt 토큰 한계 위험. → 최근 N건만 주입(기본 5),
score < 3항목 우선 정렬, 8회 초과 시 요약 도큐먼트로 압축. -
점수 편차(주관성) 사용자별 평가 기준이 다르면 KPI 신뢰도 저하. → 점수 가이드라인 명문화:
0=실행 불가/1=거의 모두 재작업/2=절반 이상 수정/3=일부 보강 필요/4=경미 수정 후 머지 가능/5=즉시 머지 가능 -
dual-repo 변경 비용 각 스킬 prompt 템플릿에
prior_feedback블록을 일관되게 삽입해야 함. → P3 시작 전 스킬 저장소 측 prompt 표준화 PR 선행. -
악성·저질 피드백
"안됨"같은 짧은 코멘트가 prompt에 주입되면 오히려 결과 품질 저하. → 최소 글자수(20자) 검증 + 점수-코멘트 일관성 휴리스틱 (점수 ≤2 인데 코멘트 비어있으면 등록 거부). -
개인정보·민감정보 피드백 본문에 토큰/계정정보가 들어갈 수 있음. → 등록 시 자동 마스킹(이메일/토큰 패턴) + KB 컬렉션 권한을 사내 사용자로 제한.
10. 의사결정 요청 항목
| # | 결정 사항 | 제안 |
|---|---|---|
| 1 | UI 골격(결과확인 모달 탭 + 시도 히스토리) 방향 동의 여부 | 동의 |
| 2 | KB 컬렉션 구조: skill_feedback 단일 vs 프로필별 분리 | 단일 |
| 3 | 점수 척도: 0~5 vs 1~5 vs 👍/👎 + 코멘트 | 0~5 |
| 4 | P1~P4 우선순위: 데이터 모델 → UI → KB-RAG → 지표 순서 OK? | OK |
| 5 | 스킬 저장소 측 자동개발_V4 prompt 수정 책임자/일정 | TBD |
11. 스킬 무수정 적용 전략 (Skill-agnostic Injection)
스킬 저장소(스킬·커맨드 전용 리포지토리, 이하 "스킬 저장소")에는 자동기획_V4, 자동개발_V4, 자동검증_V4, 검증, CS분석 등 수십 개의 스킬·커맨드가 있고
계속 추가된다. 각 스킬 prompt 템플릿에 일일이 prior_feedback 블록을 끼워 넣는 방식은
유지보수 비용·드리프트 가 크다. 따라서 스킬 파일을 단 1개도 수정하지 않고
모든 커맨드/스킬에 동일한 학습 루프를 적용하는 4-Layer 전략을 사용한다.
11.1 전체 그림
핵심 원칙:
- 주입 지점은 prompt 헤더 단 1곳 — 스킬 본체는 그대로 둔다
- 인식 규칙은 글로벌 CLAUDE.md 1곳 — 스킬마다 가르칠 필요가 없다
- 각 Layer는 독립적으로 동작 → 부분 도입 가능, 일부 실패해도 폴백 동작
11.2 Layer 1 — Gateway 자동 주입 (필수 / 단일 진입점)
위치: 백엔드 게이트웨이 클라이언트의 execute_skill()
또는 헤드리스 실행 워커 스크립트의 스킬 실행 직전 hook.
동작:
- 호출 인자에서
issue_key,stage,skill_name추출 kb_service.search()로skill_feedback컬렉션 최근 N건 조회 (점수<3 우선)- KB 미동기 시:
skill_feedback테이블 DB 직접 조회로 폴백 - 표준 블록을 user prompt 의 맨 앞(또는 system append)에 prepend
표준 블록 포맷 — 스킬과 무관하게 동일:
<prior_feedback issue="ISSUE-1234" stage="dev" attempts="2">
<attempt n="1" score="2" at="2026-05-12">
OrderService 트랜잭션 처리 누락 / 주문 파이프라인 호출 timeout 미설정
</attempt>
<attempt n="2" score="3" at="2026-05-14">
주문 파이프라인 timeout 보강했으나 재시도 backoff 미적용
</attempt>
</prior_feedback>
효과: 스킬 저장소 측 스킬 파일을 0개 수정하고 100% 커버.
11.3 Layer 2 — 글로벌 시스템 규칙 (필수 보강)
Layer 1 이 블록을 넣어도 스킬 본문이 그 형식을 모르면 무시할 수 있다.
→ 스킬 저장소의 CLAUDE.md (또는 .claude/settings.json 의 systemPrompt) 에
한 번만 다음 규칙을 추가하면 모든 스킬이 자동 인지한다:
## prior_feedback 처리 규칙 (전역)
- 사용자 prompt에 `<prior_feedback>` 블록이 있으면 반드시
**작업 계획**과 **산출물**에 반영해야 한다.
- 각 `<attempt>` 항목의 코멘트는 "이전 결함" 으로 명시 인지하고,
같은 결함을 재현하지 말 것.
- 산출물 끝에 `## 이전 피드백 반영 내역` 섹션을 추가하여
attempt 별로 "어떻게 보강했는지" 한 줄씩 적어야 한다.
- 블록이 비어있거나 없으면 이 규칙은 무시한다.
스킬 저장소의 CLAUDE.md 는 모든 Claude Code 실행에 자동 로드되므로 스킬 N개를 건드릴 필요가 없다.
11.4 Layer 3 — UserPromptSubmit Hook (백업 / 직접 실행 대응)
사용자가 파이프라인을 거치지 않고 스킬 저장소 디렉토리에서 직접
/자동개발_V4 ISSUE-1234 를 실행하는 경우 Layer 1 이 동작하지 않는다.
이를 보강하기 위해 hook 추가:
위치: 스킬 저장소의 .claude/settings.json
{
"hooks": {
"UserPromptSubmit": [
{ "type": "command",
"command": "python3 .claude/hooks/inject_prior_feedback.py" }
]
}
}
inject_prior_feedback.py 동작:
- prompt 에서
/자동XXX ISSUE-NNNN패턴 추출 →(skill_name, issue_key)도출 - 파이프라인 외부 API 호출
GET /api/v1/external/skill-feedback?issue_key=…&stage=…&limit=5 <prior_feedback>블록을 stdout 으로 출력 → Claude Code 가 prompt 에 자동 prepend- 멱등성: prompt 에
<prior_feedback문자열이 이미 있으면 skip (Gateway 주입과 중복돼도 안전) - 추출 실패/API 실패 시 silent (스킬은 정상 진행)
11.5 Layer 4 — Stop Hook (자동 종결)
스킬 실행이 끝나는 시점도 hook 으로 표준화:
위치: 스킬 저장소의 .claude/settings.json
{
"hooks": {
"Stop": [
{ "type": "command",
"command": "python3 .claude/hooks/finalize_skill_run.py" }
]
}
}
동작:
- 실행 컨텍스트에서
skill_run_id회수 → 파이프라인PATCH /external/skill-runs/{id}호출 attempt_no자동 +1 (이슈+스테이지 기준)- WS 이벤트
skill_completed발행 - 종료 사유(정상 / 사용자 중단 / 에러) 기록
스킬 본체 수정 없이 모든 스킬에 attempt 카운팅 / 종결 추적이 자동으로 들어간다.
11.6 권장 도입 순서 (점진 적용)
| Step | 작업 | 효과 | 스킬 수정 |
|---|---|---|---|
| 1 | Layer 2: 스킬 저장소 CLAUDE.md 에 전역 규칙 추가 | LLM 이 <prior_feedback> 자동 인지 | 0 |
| 2 | Layer 1: Gateway 자동 주입 구현 | 파이프라인 경유 실행 100% 커버 | 0 |
| 3 | Layer 3: UserPromptSubmit Hook 추가 | 직접 실행도 커버 | 0 |
| 4 | Layer 4: Stop Hook 추가 | attempt 자동 카운트 / 자동 종결 | 0 |
→ 4단계 모두 적용해도 스킬 저장소의 스킬 파일은 1줄도 바뀌지 않는다.
11.7 리스크 / 운영 고려사항
- 블록 중복 주입
Layer 1 + 3 동시 동작 시 prompt 에
<prior_feedback>이 두 번 들어갈 위험 → hook 은 항상<prior_feedback문자열 선검사 후 skip (멱등) - 이슈키 추출 실패
prompt 패턴이 불규칙(
/자동개발 ISSUE-1234 추가설명…)이면 hook 이 issue_key 를 못 잡을 수 있음 →--issue ISSUE-1234인자 표준화 권장. 또는CLAUDE_HARNESS_ISSUE_KEY환경변수 폴백 - 토큰 비용 모든 스킬 호출에 prepend → 1차 실행(피드백 0건)은 비용 0 누적 다건 이슈는 최근 5건 + score<3 우선 + 8건 초과 시 요약 압축으로 캡
- 글로벌 CLAUDE.md 변경 안전성 전역 규칙이 다른 스킬 동작을 방해할 위험 → "블록 없으면 무시" 조항으로 비파괴
- race condition (Layer 1 주입 ↔ KB 인덱싱 지연)
방금 등록한 피드백이 KB에 색인되기 전 다음 실행이 시작될 수 있음
→ Gateway 는 KB 우선, 미동기 시
skill_feedback테이블 폴백 (6.3 절 참고)
11.8 새 스킬 추가 시 비용
기존 방식: 새 스킬마다 prompt 템플릿에 prior_feedback 블록 + 처리 지시 N줄 추가 → N×스킬개수
이 전략: 새 스킬을 추가해도 추가 작업 0 (이슈키 패턴만 표준 따르면 자동 적용)
12. 피드백 품질 관리 & KB 노이즈 방지 (Poisoning 대응)
⚠️ 사용자가 점수를 낮게 주고 "X 가 안된다" 고 했지만 실제로는 X 가 맞았던 경우, 그 잘못된 피드백이 KB에 누적되면 다음 실행을 오히려 망친다 (= KB poisoning). 그래서 KB는 단순 누적 저장소가 아니라 신뢰도 가중 + 자가 검증 + 시간 감쇠 가 결합된 자가 정제 시스템으로 설계되어야 한다.
12.1 핵심 원리 — 3-Tier 상태 머신
피드백은 등록 즉시 KB 정식 인덱싱되지 않고, 다음 상태를 거친다.
| 상태 | 의미 | retrieval 가중치 |
|---|---|---|
pending | 등록 직후, 미검증 | 0.3 (약한 참고용) |
verified | 자가 검증 / AI judge / 동료 승인 통과 | 1.0 (정식 컨텍스트) |
archived | 해결됐거나 시간 경과 | 0 (retrieval 제외, 통계엔 유지) |
invalid | AI judge 가 명백히 거짓이라 판정 | 0 (영구 제외) |
withdrawn | 작성자가 명시 철회 ("내가 잘못 짚었어요") | 0 (영구 제외, audit 보존) |
12.2 자동 검증 트리거 (세 갈래)
A. 후속 시도 결과로 자가 검증 (가장 강력, 무인 동작)
같은 issue+stage 의 다음 attempt 결과를 보고 자동 판정:
| 조건 | 처리 |
|---|---|
| 다음 시도 점수 ≥ 이전 + 2 (예: 2★ → 4★) | 이전 피드백 → verified (적중 입증) |
| 다음 시도 점수 ≥ 4 (해결됨) | 이전 피드백 → archived (resolved) |
| 다음 시도에서 동일 코멘트 키워드 또 지적됨 | 신뢰도 ↑ (반복 결함 확정) |
| 다음 시도 점수가 이전과 같거나 더 낮음 | 신뢰도 ↓ (피드백이 무의미했을 가능성) |
| 다음 시도가 피드백 키워드를 prompt 에 반영했음에도 점수 하락 | questionable 플래그 |
→ 별도 입력 없이도 시간이 가면 자동으로 KB가 정화된다.
B. LLM-as-Judge 사전 검증 (등록 직후, 비동기)
피드백 등록 시 백그라운드 태스크:
입력: 산출물 본문 + 피드백 코멘트 + 점수
프롬프트: "이 코멘트가 산출물에 비추어 사실인가?
- 코멘트가 지적한 요소가 산출물에 실제 누락/존재하는가?
- 점수와 코멘트의 강도가 일치하는가?
confidence 0~1 와 근거를 JSON 으로 답하라."
출력: { "valid": true|false, "confidence": 0.72, "reason": "..." }
| confidence 구간 | 처리 |
|---|---|
≥ 0.7 | verified 후보 (자가 검증 결과까지 보고 최종) |
0.3 ~ 0.7 | pending 유지, 큐레이션 큐 노출 |
< 0.3 | questionable 플래그, 작성자에게 알림, retrieval 가중치 0.1 |
C. 산출물-코멘트 일치성 휴리스틱 (값싼 사전 필터)
코멘트의 키워드·엔티티가 산출물에 존재해야 가능성 ↑.
예: 코멘트 "OrderService 트랜잭션 처리 누락" → 산출물에 OrderService 토큰이 0건 → 의심.
💡 LLM 호출 전에 동작하므로 비용이 거의 없다.
12.3 라벨링으로 노이즈 분리
피드백 등록 폼에 라벨 다중 선택 (LLM judge 가 미선택 시 자동 분류):
| 라벨 | 기본 가중치 | 의미 |
|---|---|---|
버그 | 1.0 | 명백한 결함 (트랜잭션 누락 등) |
누락 | 1.0 | 요구사항 미반영 |
비효율 | 0.8 | 동작은 하지만 개선 여지 |
스타일 | 0.5 | 네이밍·포맷 선호 |
개인 선호 | 0.3 | "내 취향엔..." 류 |
사용자 오해 | 0.0 | 사후 인지된 자가 철회 (withdrawn 으로 자동 전환) |
→ 라벨이 retrieval 가중치 베이스라인 + KPI 집계에서 "스타일 노이즈" 를 분리해 보여줄 수 있다.
12.4 명시적 철회 / 수정 UX
결과확인 모달의 피드백 카드 우측 액션:
- 수정 — 코멘트/점수 갱신, 이전 버전은
parent_id로 history 보존 - 철회 (
withdrawn) — KB 즉시 deindex + audit log 남김 - 해결됨 표시 (
archived: resolved) — 사용자가 직접 마감
💡 핵심: "이 피드백은 사실 제가 잘못 짚었어요" 를 한 번의 클릭으로 처리할 수 있어야 한다. 철회 비용이 높으면 사용자는 그냥 방치하고 KB는 오염된 채로 남는다.
12.5 시간 감쇠 (Time Decay)
effective_weight = base_weight * exp(-age_days / 180)
- 6개월 경과 시 가중치 ≈ 0.37 배
- 1년 미참조 피드백 자동
archived - 단, 재참조될 때마다 reset → 살아있는 피드백은 살아남고, 죽은 피드백은 자연 소멸
12.6 작성자 편향 보정
특정 사용자가 결과물 전반에 0~2점만 주는 경향이면 시스템적 편향:
- 사용자별 평균·표준편차 추적 → KPI 집계 시 z-score 표준화
- raw 점수는 화면에 표시, 집계만 보정
- 한 사용자의 피드백이 KB의 N% (예 20%) 초과 시 경고 → 개인 의견 과대표집 방지
- 보정 후에도 일관되게 저점이면 그대로 신뢰
12.7 prompt 주입 시 신뢰도 가시화
스킬 prompt 의 <prior_feedback> 블록(섹션 11.2)에 메타 노출:
<prior_feedback>
<attempt n="1" score="2" status="verified" confidence="0.85" label="버그">
OrderService 트랜잭션 처리 누락
</attempt>
<attempt n="2" score="2" status="pending" confidence="0.4" label="스타일">
네이밍이 마음에 안 듦
</attempt>
</prior_feedback>
스킬 저장소의 글로벌 규칙(섹션 11.3) 에 추가 1줄:
status="verified"+confidence ≥ 0.7항목은 반드시 반영.status="pending"또는confidence < 0.5항목은 참고 사항 으로 다루되 무비판 수용 금지.
→ LLM 자체가 의심하면서 활용 → poisoning 영향이 거의 사라진다.
12.8 큐레이션 운영 페이지 — /settings/feedback-curation (보조)
신뢰도 관리 전용 화면:
- 검토 대기 큐 (
pending+ confidence 중간 구간) 리스트 - 충돌 피드백 알림 — 같은 issue+stage 에 모순되는 코멘트가 공존하는 경우
- 최근 1주 자동 무효화 / 자동 verified 통계
- 사용자별 채점 편향 차트 (z-score 분포)
- 한 줄 액션: 승인 / 거부 / 라벨 변경 / 철회
💡 운영자가 주 1회 5분만 봐도 시스템이 자가 정화된다.
12.9 데이터 모델 확장 (5절 보강)
skill_feedback 테이블에 다음 컬럼 추가:
| 컬럼 | 타입 | 기본값 | 비고 |
|---|---|---|---|
status | VARCHAR(20) | pending | pending/verified/archived/invalid/withdrawn |
confidence | NUMERIC(3,2) | NULL | LLM-as-Judge 0.00~1.00 |
labels | JSONB | [] | 라벨 배열 |
verified_at | TIMESTAMPTZ | NULL | 검증 통과 시각 |
verified_by | VARCHAR(40) | NULL | auto / judge / 사용자 식별자 |
archive_reason | VARCHAR(40) | NULL | resolved / expired / superseded |
parent_id | UUID FK | NULL | 수정/대체된 이전 버전 추적 |
withdrawn_at | TIMESTAMPTZ | NULL | 철회 시각 |
effective_weight | NUMERIC(3,2) | 0.30 | retrieval 시 적용 가중치 (캐시된 계산값) |
WS 이벤트 추가: feedback_verified, feedback_archived, feedback_withdrawn.
12.10 단계적 도입 (낮은 비용 → 큰 효과 순)
| Step | 작업 | 효과 | 비용 |
|---|---|---|---|
| 1 | 라벨링 UI + status/labels 컬럼 추가 | 즉각 노이즈 분리 + retrieval 가중치 적용 | 낮음 |
| 2 | 명시적 철회 / 수정 UX | 사용자 자가 정정 경로 확보 | 낮음 |
| 3 | 후속 시도 기반 자가 검증 (트리거 A) | 무인 자동 정제 | 중간 |
| 4 | prompt 에 신뢰도 메타 노출 + 글로벌 규칙 1줄 추가 | LLM이 의심하며 활용 → poisoning 면역 | 낮음 |
| 5 | LLM-as-Judge 비동기 사전 검증 (트리거 B) | 사전 노이즈 차단 | 중간 (LLM 비용) |
| 6 | 시간 감쇠 + 작성자 편향 보정 | 장기 품질 유지 | 낮음 |
| 7 | /settings/feedback-curation 페이지 | 사람 손 큐레이션 | 중간 |
Step 1~4 만 적용해도 poisoning 위험의 80% 이상은 차단된다. Step 5~7 은 데이터가 누적된 후(예: 피드백 500건 이상) 도입해도 충분.
12.11 핵심 메시지
누적 ≠ 학습. KB는 단순 저장소가 아니라 자가 정제 시스템 이다.
- 3-Tier 상태 (pending → verified → archived)
- 자가 검증 (후속 시도 점수가 진실을 말한다)
- AI judge (등록 직후 사전 필터)
- 라벨 (스타일·개인선호 노이즈 분리)
- 시간 감쇠 (오래된 피드백은 자연 소멸)
- 철회 UX (1클릭으로 자정)
- prompt 신뢰도 가시화 (LLM이 의심하며 활용)
이 7가지 메커니즘이 결합되면, 잘못된 피드백이 들어와도 KB 가 자가 정화 되어 다음 실행에 악영향을 미치지 않는다.
13. 다음 액션
- 본 문서 검토 후 P1 작업 티켓 분리 (백엔드 / 프론트 / 스킬 저장소)
-
skill_feedback마이그레이션 작성 (backend/migrations/NNN_add_skill_feedback.sql) -
/external/skill-feedback엔드포인트 PR - 결과확인 모달 단일화 — 디자인 시안 1차 (Figma 또는 모달 mock)
- 스킬 저장소 측
prior_feedbackprompt 블록 표준 PR -
/settings/skill-metrics와이어프레임
14. 요약
| 축 | 결론 |
|---|---|
| 학습 루프 | 점수+코멘트 → skill_feedback 저장 → KB-RAG 인덱싱 → 다음 실행 prompt 자동 주입 |
| UI | 카드 액션 LOG / 결과확인 2개로 단일화, 모달 탭 + 시도 히스토리 + 피드백 패널 |
| 주입 전략 | 4-Layer (Gateway / 글로벌 CLAUDE.md / UserPromptSubmit Hook / Stop Hook) — 스킬 파일 수정 0 |
| 지표 | 스킬 KPI 페이지 + 이슈별 시도·점수 보드, 2페이지 분리 |
| Poisoning 대응 | 3-Tier 상태머신 + 후속시도 자가검증 + LLM judge + 라벨 + 시간감쇠 + 철회 UX |
| 도입 | P1 데이터 골격 2일 → P2 UI 3일 → P3 KB-RAG 3일 → P4 지표 3일, P5 옵션 |
Comments
No comments yet. Be the first to comment!
★Reviews for this material
Write a reviewNo reviews for this material yet.