2026-04-04 CI 강화 및 규칙 품질 검증 로드맵
gstack/OSS 비교에서 도출된 CI 및 검증 강화 계획
changes 2026-04-04 docs/changes/2026-04-04-ci-and-eval-roadmap.md
작성일: 2026-04-04 목적: gstack/OSS 비교에서 도출된 CI 및 검증 강화 계획
배경
ai-rules는 "코드보다 프롬프트/규칙 품질이 결과를 좌우하는 저장소"다.
현재 CI는 sync-on-push.yml (main push → validate + sync + artifact) 하나뿐이다.
gstack의 CI 전략(gate/periodic 분리, freshness 강제, LLM eval)에서 ai-rules에 적합한 패턴을 선별했다.
Phase A: 생성물 freshness CI (가장 쉬움)
문제
core/.md나 extensions/.md를 수정하고 npm run sync를 안 돌리면, output/의 생성물이 stale해진다.
현재 CI는 main push에서만 sync를 돌리므로, PR 단계에서는 stale을 감지하지 못한다.
해결
PR 트리거 워크플로에서:
# .github/workflows/pr-check.yml
name: PR Check
on:
pull_request:
paths: ['core/**', 'extensions/**', 'profiles/**', 'adapters/**', 'agents/**']
jobs:
freshness:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20' }
- run: npm install
- run: node scripts/validate.mjs
- run: node scripts/sync.mjs
- name: Check for stale output
run: |
if ! git diff --quiet output/; then
echo "::error::output/ 디렉토리에 반영되지 않은 변경이 있습니다. npm run sync 후 커밋하세요."
git diff --stat output/
exit 1
fi
효과
- "sync 안 돌리고 PR 올리는 실수" 차단
- gstack의
skill-docs.yml(gen → diff --exit-code) 패턴과 동일
Phase B: diff 기반 선택 실행
문제
14개 프로파일 × 7개 어댑터 전체 sync는 점점 무거워진다. 변경된 파일과 무관한 프로파일까지 검증할 필요 없다.
해결
validate.mjs에 --changed-only 플래그 추가:
core/01-git.md 변경 → 01-git을 참조하는 profiles만 검증
extensions/aitem-backend.md 변경 → aitem profile만 검증
adapters/cursor.mjs 변경 → cursor enabled인 profiles만 검증
profiles/aitem.yaml 변경 → aitem만 검증
agents/*.md 변경 → agents.enabled인 profiles만 검증
구현 방향
// validate.mjs --changed-only
const changedFiles = execSync('git diff --name-only HEAD~1').toString().split('\n')
const affectedProfiles = resolveAffectedProfiles(changedFiles, allProfiles)
// affectedProfiles만 검증
효과
- CI 시간 단축 (14 profiles → 변경 관련 1~3 profiles)
- gstack의
touchfiles.ts(파일→테스트 맵) 패턴의 ai-rules 버전
Phase C: LLM 품질 회귀 검증 (핵심, 설계 필요)
문제
core/*.md 한 줄이 모호해지면 13개 프로젝트의 에이전트 행동이 흔들린다. tsc가 코드 품질을 보장하듯, LLM eval이 규칙 품질을 보장해야 한다.
평가 기준 (안)
| 기준 | 설명 | 측정 방법 |
|---|---|---|
| 명확성 | 규칙이 모호 없이 하나로 해석되는가 | LLM에게 "이 규칙의 의미를 3가지로 해석해봐" → 해석이 1개면 높음 |
| 완결성 | 빠진 예외 조건이나 경계 사례가 없는가 | LLM에게 "이 규칙이 커버하지 못하는 상황은?" → 답이 없으면 높음 |
| 실행가능성 | 에이전트가 이 규칙을 보고 즉시 행동할 수 있는가 | LLM에게 규칙 적용 시나리오 제시 → 올바른 행동 선택 비율 |
| NEXT_AGENT 유무 | 에이전트 정의에 NEXT_AGENT 블록이 있는가 | 정적 검사 (LLM 불필요) |
| 금지사항 구체성 | 금지사항이 패턴 수준으로 명시되어 있는가 | 정적 검사 + LLM 판정 |
대상 파일
core/*.md(12개) — 규칙 품질agents/*.md(9개) — 에이전트 정의 품질output/*/CLAUDE.md(14개) — 생성물 품질
baseline 관리
eval/
├── baselines/
│ ├── core-rules.json # core 규칙별 점수 baseline
│ ├── agent-defs.json # 에이전트 정의별 점수 baseline
│ └── generated-output.json # 생성물별 점수 baseline
├── eval-rules.mjs # 평가 스크립트
└── results/
└── 2026-04-04.json # 실행 결과 (날짜별 누적)
실행 주기
- PR에서: 정적 검사만 (NEXT_AGENT 유무, 필수 섹션 존재)
- 주간 cron에서: LLM eval 전체 (비용/속도 고려)
효과
- 규칙 리그레션 조기 발견
- gstack의
skill-llm-eval.test.ts+eval-baselines.json패턴의 ai-rules 버전
Phase D: gate / periodic CI 분리
Phase A~C를 아래 구조로 통합:
PR gate (매 PR):
├── validate.mjs --changed-only # Phase B: 영향 프로파일만
├── sync.mjs + diff --exit-code # Phase A: freshness
└── 정적 규칙 검사 # Phase C 일부: NEXT_AGENT, 필수 섹션
Periodic (주간 cron):
├── validate.mjs (전체)
├── sync.mjs (전체) + 생성물 비교
├── LLM eval (전체) # Phase C: 명확성/완결성/실행가능성
└── eval 결과 저장 + baseline 비교
우선순위 및 의존성
Phase A (freshness) ← 독립, 즉시 가능
Phase B (diff 선택) ← A 이후 (CI 기반 필요)
Phase C (LLM eval) ← 설계 선행 필요 (eval 기준 확정)
Phase D (gate/periodic) ← A+B+C 통합
안 하는 것
| 항목 | 이유 |
|---|---|
| 검증 결과 저장/비교 도구 독립 구현 | Phase C의 산출물로 자연스럽게 생김 |
| 구조화된 knowledge store (JSONL) | 4중 기록 구조로 충분 |
| 정식 정책 언어 전환 | safety-manifest.yaml이 현재 규모에서 최적 |