feat(ads/seo/release): v1.2.0 with live Google Ads, isolated ad profile, ads.txt, and SEO/AEO/GEO optimization

This commit is contained in:
Yun Chan 2026-09-14 00:39:44 +09:00
parent a88aafa1e5
commit 0e568f1f0a
975 changed files with 130593 additions and 16783 deletions

View file

@ -1,151 +1,117 @@
# 개발 하네스 — 폐쇄루프 운영 지침
# 개발 하네스 — 폐쇄루프 운영 및 하네스 엔지니어링 지침
> 이 저장소에서 AI 코딩 에이전트가 **자율적으로, 그러나 검증 없이는 완료를 선언할 수 없게** 일하도록
> 짜 놓은 장치들의 설계와 운영법. 사람과 에이전트 모두 이 문서를 읽는 대상이다.
> 이 저장소에서 AI 코딩 에이전트(Antigravity, Claude Code, DeepSeek, Cursor 등)가
> **자율 루프로 저가형 모델(Flash, DeepSeek, Haiku)까지 완벽히 통제하여 고성능 극한 개발을 수행하도록**
> 구성한 하네스 엔지니어링(Harness Engineering) 설계와 운영법이다.
## 왜 필요한가
---
에이전트의 가장 흔한 실패는 코드를 못 짜는 게 아니라 **"됐습니다"라고 말해버리는 것**이다.
테스트가 깨진 채로, 실행해 보지도 않고, 문서는 옛날 상태인 채로 턴이 끝난다.
## 1. 패러다임의 진화: Prompting → Context → Harness
해법은 프롬프트로 더 강하게 부탁하는 게 아니라, **에이전트가 건너뛸 수 없는 결정적 층**을 두는 것이다.
확률적인 판단(모델)과 결정적인 검사(훅)를 분리한다.
| 시대 | 패러다임 | 핵심 질문 | 한계 |
|---|---|---|---|
| **2022 ~ 2024** | **Prompt Engineering** | "어떻게 말해야(프롬프트) 잘 알아들을까?" | 단일 턴 한계, 복잡한 프로젝트에서 망각 및 환각 |
| **2024 ~ 2025** | **Context Engineering** (안드레 카파시) | "모델의 컨텍스트 창에 무엇을 넣고 뺄 것인가?" | 컨텍스트가 길어지면 집중도 감쇠, 실행 검증 부재 |
| **2025 ~ 2026** | **Harness Engineering** (`Agent = Model + Harness`) | "어떤 제약과 피드백 루프로 모델을 가둘 것인가?" | **해결: 비결정적 모델을 결정적 시스템으로 완성** |
## 5계층 구조
안드레 카파시(Andrej Karpathy)와 업계 리더들이 정립한 핵심 공식은 다음과 같다:
| 계층 | 역할 | 이 저장소에서 |
$$\text{Agent} = \text{Model} + \text{Harness}$$
- **Model (커널/CPU)**: 비결정적(Stochastic) 추론 엔진. 아무리 좋은 프런티어 모델이라도 하네스가 없으면 "다 됐습니다"라고 거짓 보고(Vibe Coding)를 하거나 테스트를 무력화한다.
- **Harness (운영체제/제약계층)**: 도구 세트, 컨텍스트 스케줄러, 결정적 테스트 게이트, 린터, 상태 저장소. 모델의 출력을 기계적으로 검증하고 실패 시 에러를 피드백하여 자가수정(Self-Correction)을 강제한다.
---
## 2. 안드레 카파시의 에이전틱 코딩 4대 원칙
카파시가 제시한 에이전트의 실패 방지 원칙:
1. **Think Before Coding (생각 먼저, 코딩 나중)**:
추측으로 코드를 작성하지 않는다. 요구사항이 모호하면 먼저 조사하거나 명확히 질문하고, 파일 3개 이상 변경 시 플랜을 수립한다.
2. **Simplicity First (최소 구현 원칙)**:
미래를 위한 오버엔지니어링, 불필요한 추상화 계층을 금지한다. 실패한 테스트(RED)를 통과(GREEN)시키는 가장 단순한 코드를 작성한다.
3. **Surgical Changes (외과수술식 정밀 변경)**:
요청과 무관한 주변 코드, 주석, 포맷을 임의로 건드리지 않는다. Blast Radius(폭발 반경)을 극도로 제한한다.
4. **Goal-Driven Closed Loop (목표 주도 폐쇄 루프)**:
모호한 "수정"이 아니라, 기계적으로 검증 가능한 테스트(Exit Code 0)가 달성될 때까지 자율 루프를 돈다.
---
## 3. 저가형 모델(Flash, DeepSeek, Haiku)로 극한 개발을 하는 하네스 기법
프런티어 모델(Opus/GPT-4o) 대신 **Gemini Flash, DeepSeek-V3/R1, Claude Haiku 등 1/10~1/50 비용의 저가형 모델**로 최고 효율을 내기 위한 4가지 하네스 기법:
### ① Token Diet (컨텍스트 오염 차단)
- 저가형 모델은 컨텍스트가 20k~50k 토큰 이상 누적되면 지침 준수율(Instruction Following)이 급격히 저하된다.
- **규칙**: `MainWindow.xaml.cs`(86KB) 같은 대형 소스는 절대로 통째로 읽지 않는다. `grep_search`로 함수 라인을 파악하고 30~50줄 단위로 슬라이스 조회(`view_file`)한다.
- **전역 지침 압축**: `AGENTS.md`를 150줄 이내로 유지하고, 세부 규칙은 파일 열람 시 동적 주입(Path-Scoped Rules)한다.
### ② Anti-Cheating Guard (치팅 원천 차단)
- 저가형 모델이 자율 루프에서 막히면 흔히 시도하는 3대 꼼수:
1. 실패하는 테스트 코드를 삭제하거나 단정(Assert)을 완화
2. `[Fact(Skip = "...")]` 또는 `[Ignore]` 속성 추가
3. 실패하는 예외를 빈 `catch { }` 블록으로 삼킴
- **방어**: 정적 메타 테스트(`MetaTestQualityAndPruningTests`) 및 Stop 훅으로 테스트 수 감소 및 Skip 속성을 검출하여 즉시 실패 처리.
### ③ Error-Driven Hill Climbing (결정적 에러 피드백)
- 저가형 모델은 막연한 에러 설명보다 **정확한 컴파일러 진단 코드(`CS0246`, `CS8602`)와 파일:라인:컬럼, xUnit Expected/Actual 차이**를 주입받았을 때 1~2턴 만에 완벽히 교정한다.
- 하네스는 실패 시 빌드/테스트 출력의 핵심 30~50줄을 모델 컨텍스트에 즉시 주입한다.
### ④ Subagent Hierarchy (계층형 서브에이전트)
- 넓은 범위의 코드 검색, 문서 리서치 등 컨텍스트를 많이 소비하는 작업은 초경량 서브에이전트(`invoke_subagent`, flash/flash_lite)에 위임한다.
- 메인 에이전트의 컨텍스트는 순수한 아키텍처/코드 수정 상태로 깨끗하게 유지된다.
---
## 4. 5계층 하네스 아키텍처
| 계층 | 역할 | 이 저장소의 구현 |
|---|---|---|
| **① 하네스** | 에이전트가 사는 환경 | Claude Code + `.claude/settings.json` |
| **② 루프 계약** | "완료"의 정의 | `AGENTS.md` §4 완료 기준 · `CLAUDE.md` |
| **③ 상태층** | 세션이 끊겨도 남는 상태 | `docs/BACKLOG.md` 체크박스 · `docs/IMPLEMENTATION_AUDIT.md` · SessionStart 브리핑 |
| **④ 체커** | 에이전트가 못 건너뛰는 검사 | **Stop 훅 → `dotnet test`** |
| **⑤ 사람 관문** | 되돌릴 수 없는 일 앞의 확인 | 커밋·푸시·배포는 사용자 승인 (`/release` 스킬) |
| **① 하네스 환경** | 에이전트 런타임 & 도구 | Antigravity(AGY) · Claude Code (`.claude/settings.json`) |
| **② 루프 계약 (SSOT)** | 도구 중립 작업 헌법 | `AGENTS.md` (AAIF 표준, <150줄) |
| **③ 상태층 (External State)** | 세션 리셋에도 유지되는 상태 | `docs/BACKLOG.md` · `docs/IMPLEMENTATION_AUDIT.md` · `.verify-stamp` |
| **④ 결정적 체커** | 에이전트가 건너뛸 수 없는 게이트 | **Stop 훅 / 검증 게이트 → `dotnet test Paca.Tests`** |
| **⑤ 사람 관문** | 되돌릴 수 없는 결정 | 커밋·푸시·릴리스 승인 (`/release` 스킬) |
핵심은 ④다. 나머지는 ④가 있어야 의미가 생긴다.
---
## 구성 요소
## 5. 멀티 MD 파일 관리 표준
```
AGENTS.md ← 도구 중립 작업 계약 (Codex/Cursor 등도 읽음)
CLAUDE.md ← @AGENTS.md 임포트 + Claude Code 전용 지침
AGENTS.md ← 도구 중립 최상위 작업 계약 (AAIF 표준, 전역 상주, 150줄 이내)
CLAUDE.md ← @AGENTS.md 임포트 + 도구별 훅 바인딩
.claude/
settings.json ← 훅 등록 + 권한 (커밋됨, 팀 공유)
settings.json ← 훅 등록 + 권한 설정
hooks/
session-brief.sh ← SessionStart: 저장소 상태를 컨텍스트에 주입 (상태층)
verify-on-stop.sh ← Stop: 테스트 게이트 (체커)
rules/ ← 경로별 자동 로드 규칙 (해당 파일을 열 때만 컨텍스트에 들어옴)
desktop-wpf.md ← VideoDownloader.App/**, Browser/**
engine-core.md ← Core/**, Server/**
mobile-maui.md ← Mobile/**, Mobile.Core/**
tests.md ← Tests/**
skills/ ← 호출될 때만 로드되는 절차서
tdd/SKILL.md ← /tdd RED→GREEN→증거
session-brief.sh ← SessionStart: 브랜치/변경파일/미완료 백로그 자동 브리핑
verify-on-stop.sh ← Stop: 턴 종료 시 소스 변경 감지 → dotnet test 강제 게이트
rules/ ← [Path-Scoped] 해당 파일을 열 때만 로드되는 영역별 규칙
desktop-wpf.md ← Paca.App/**, Paca.Browser/**
engine-core.md ← Paca.Core/**, Paca.Server/**
mobile-maui.md ← Paca.Mobile/**, Paca.Mobile.Core/**
tests.md ← Paca.Tests/**
skills/ ← [On-Demand] 호출 시에만 컨텍스트에 들어오는 절차서
tdd/SKILL.md ← /tdd RED→GREEN→증거 사이클
verify/SKILL.md ← /verify 완료 기준 전수 점검
release/SKILL.md ← /release 배포
.verify-stamp ← 마지막 검증 성공 시점 (자동 생성, gitignore)
release/SKILL.md ← /release 배포 파이프라인
.verify-stamp ← 마지막 검증 성공 시각 타임스탬프 (자동 관리)
```
### 왜 이렇게 나눴나
### 왜 이렇게 분리하는가?
1. **전역 MD(`AGENTS.md`)는 항상 컨텍스트를 차지한다.** 여기에 수천 줄의 세부 룰을 넣으면 모든 대화 턴마다 토큰 비용이 발생하고 모델의 주의력이 흐려진다.
2. **경로별 룰(`rules/`)은 필요할 때만 들어온다.** WPF 창을 고칠 때만 WPF 룰이 들어오고, 백엔드 코어 엔진을 만질 때는 로드되지 않는다.
3. **절차서(`skills/`)는 트리거될 때만 들어온다.** 평소 대화에서는 토큰을 0바이트 소모한다.
4. **강제는 프롬프트가 아니라 훅과 게이트로 한다.** 프롬프트의 "반드시 테스트하세요"는 모델이 무시할 수 있지만, 훅의 `exit 2`는 물리적으로 턴 종료를 차단한다.
- **CLAUDE.md 는 짧게.** 매 세션 컨텍스트를 먹고, 길수록 지켜지지 않는다. 200줄 이내가 권장선이다.
- **경로별 규칙은 `rules/` 로.** WPF 함정은 WPF 파일을 열 때만 필요하다. 항상 로드하면 낭비다.
- **절차는 `skills/` 로.** 배포 순서 같은 건 배포할 때만 필요하다. 안 쓰면 토큰을 안 쓴다.
- **강제는 훅으로.** CLAUDE.md 는 부탁이고 훅은 강제다. "반드시 X 해라"가 지켜지길 원하면 훅에 넣는다.
## 훅 동작
### SessionStart — 상태 브리핑
세션이 시작되면 브랜치·마지막 커밋·변경 파일·검증 상태·미완료 백로그를 컨텍스트에 넣는다.
에이전트가 `git status` 를 따로 묻지 않고 현재 상황을 알고 시작한다.
### Stop — 테스트 게이트
턴을 끝내려 할 때:
1. `stop_hook_active` 가 `true` 면 즉시 통과 — **무한 루프 방지**.
(Claude Code 는 Stop 훅이 8회 연속 차단하면 강제로 넘긴다. 가드가 없으면 그 8회를 다 태운다.)
2. 소스(`.cs`/`.csproj`/`.xaml`/`.axaml`)의 최신 수정시각을 `.claude/.verify-stamp` 와 비교.
같으면 즉시 통과 — 대화만 한 턴은 지연 0.
3. 바뀌었으면 `dotnet test VideoDownloader.Tests` 실행 (증분 약 13초).
4. 통과 → 스탬프 갱신 후 종료 허용. 실패 → **exit 2 로 종료 차단**, 실패 출력 60줄을 에이전트에게 전달.
즉 **테스트를 깨둔 채로 턴을 끝낼 수 없다.**
## 사용법
### 에이전트 (자율 동작)
특별히 할 일이 없다. 세션을 열면 브리핑이 들어오고, 계약(`AGENTS.md`)이 로드되고,
파일을 열면 해당 영역 규칙이 붙고, 턴을 끝내면 테스트가 돈다.
기억할 것 세 가지:
1. 기능 작업은 `/tdd` 로 시작한다. 절차를 기억으로 재구성하지 않는다.
2. 마무리 전에 `/verify` 로 완료 기준을 전수 점검한다.
3. **Stop 훅이 막으면 우회하지 않는다.** 테스트를 지우거나 Skip 처리하는 것은 회귀를 숨기는 것이다.
못 고치면 못 고친다고 보고한다.
### 사람
```powershell
/hooks # 등록된 훅 확인
/context # 어떤 지침 파일이 실제 로드됐는지 확인
/memory # CLAUDE.md 등 열어서 편집
```
**게이트를 잠깐 끄고 싶을 때** — 실험 중이라 테스트가 깨진 게 정상인 상황:
```jsonc
// .claude/settings.local.json (gitignore 대상, 개인용)
{ "disableAllHooks": true }
```
작업이 끝나면 지운다. 켜 두는 게 기본이다.
**게이트가 느리다고 느껴지면** — 변경이 없으면 이미 스킵된다. 그래도 무거우면
`verify-on-stop.sh` 의 `dotnet test` 를 `--filter` 로 좁히는 대신, 전체 실행 유지를 권한다.
부분 검증은 회귀를 놓친다.
## 확장
### 새 경로 규칙 추가
`.claude/rules/<이름>.md` 에 프론트매터로 경로를 지정한다.
```markdown
---
paths:
- "VideoDownloader.Avalonia/**"
---
# Avalonia 영역 규칙
...
```
해당 경로 파일을 열 때만 컨텍스트에 들어온다. 30줄 안쪽으로 유지한다.
## 6. 결론: 하네스 기반 자율 개발 체크리스트
### 새 절차 스킬 추가
1. [ ] 세션 시작 시 상태 브리핑 확인
2. [ ] 변경 전 실패하는 테스트(RED) 확인
3. [ ] 최소한의 코드 수정(GREEN) 진행
4. [ ] 대용량 파일은 Grep/Slice로 토큰 절약
5. [ ] `dotnet test` 성공 후 턴 종료 (0 실패, 0 에러)
6. [ ] `docs/BACKLOG.md` 상태 동기화
`.claude/skills/<이름>/SKILL.md`. `description` 이 트리거를 결정하므로
**언제 쓰는지**를 구체적으로 쓴다 — "코드 리뷰용"보다 "PR 올리기 전 변경 diff 를 검토할 때".
### 새 게이트 추가
무거운 검사(전체 빌드, 통합 테스트)는 `Stop` 에 붙인다. `PostToolUse` 에는 붙이지 않는다 —
편집할 때마다 돌면 개발이 멈춘다. .NET 빌드는 특히 비싸다.
## 원칙
- **부탁은 CLAUDE.md, 강제는 훅.** 반드시 일어나야 하는 일을 프롬프트에 적어두고 기대하지 않는다.
- **게이트는 우회 대상이 아니라 계약이다.** 막히면 원인을 고친다.
- **완료 보고에는 실제 출력의 숫자를 인용한다.** 기억으로 쓴 "테스트 통과"는 근거가 아니다.
- **되돌릴 수 없는 일 앞에는 사람을 둔다.** 커밋·푸시·배포는 자동화하지 않는다.
## 참고
- [Claude Code — 메모리와 CLAUDE.md](https://code.claude.com/docs/en/memory)
- [Claude Code — 훅 레퍼런스](https://code.claude.com/docs/en/hooks)
- [Claude Code — 스킬](https://code.claude.com/docs/en/skills)
- [AGENTS.md 표준](https://agents.md) — 2025년 8월 공개 규격, 2025년 12월 Linux Foundation 산하
Agentic AI Foundation 으로 이관. Claude Code 는 `AGENTS.md` 를 직접 읽지 않으므로
`CLAUDE.md` 에서 `@AGENTS.md` 로 임포트하는 것이 공식 권장 방식이다.