@kaydash9999/banker-plugins 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +52 -0
- package/README.md +28 -8
- package/codex/manifest.json +8 -1
- package/codex/transform-matrix.md +2 -2
- package/commands/setup.md +2 -0
- package/package.json +6 -1
- package/skills/3d-intro-build/SKILL.md +214 -0
- package/skills/3d-intro-build/references/LICENSE +21 -0
- package/skills/3d-intro-build/references/NOTICE.md +32 -0
- package/skills/3d-intro-build/references/assemble.mjs +252 -0
- package/skills/3d-intro-build/references/azure-adapter.mjs +495 -0
- package/skills/3d-intro-build/references/curate.mjs +301 -0
- package/skills/3d-intro-build/references/index-template.html +73 -0
- package/skills/3d-intro-build/references/prompts.md +171 -0
- package/skills/3d-intro-build/references/scrub-engine.js +448 -0
- package/skills/3d-intro-build/references/serve.mjs +123 -0
- package/skills/3d-intro-setup/SKILL.md +196 -0
- package/skills/3d-intro-setup/references/azure-adapter.mjs +495 -0
- package/skills/lineage/SKILL.md +126 -134
- package/skills/lineage/lineage.py +1041 -354
- package/skills/motion-graphic-make/SKILL.md +57 -0
- package/skills/motion-graphic-setup/SKILL.md +141 -0
- package/skills/ralph-qa/SKILL.md +253 -77
- package/skills/ralph-qa/references/verifier-probe.mjs +860 -0
- package/skills/refresh-readme/SKILL.md +3 -3
- package/skills/vertical-pptx/SKILL.md +409 -0
- package/skills/vertical-pptx/build_a4p.js +923 -0
- package/skills/vertical-pptx/build_a4p.py +916 -0
- package/skills/vertical-pptx/verify_a4p.mjs +2168 -0
- package/skills/vertical-pptx-setup/SKILL.md +223 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: motion-graphic-make
|
|
3
|
+
description: "(banker) 10초 내외 내레이션 없는 무료 모션 그래픽(킨네틱 타이포·통계·차트·로고·하단자막·지도)을 hyperframes motion-graphics 워크플로에 위임 제작 — 렌더링 로직은 소유하지 않는 얇은 래퍼. 'motion-graphic-make'/'모션 그래픽 만들어줘'/'모션 그래픽 제작'/'motion graphics' 시 사용."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# motion-graphic-make — 무료 모션 그래픽 제작 (hyperframes 위임)
|
|
7
|
+
|
|
8
|
+
짧고(약 10초 내외, 최대 ~30초) 내레이션 없는 디자인-주도 모션 그래픽을 만든다.
|
|
9
|
+
이 스킬은 **얇은 래퍼(thin wrapper)** 다 — 실제 창작·렌더링 로직을 전혀 소유하지 않고, hyperframes(Apache-2.0, HeyGen 오픈소스)의 `/motion-graphics` 워크플로에 그대로 위임한다.
|
|
10
|
+
전제조건(Node≥22·ffmpeg) 설치는 `motion-graphic-setup` 스킬이 담당한다.
|
|
11
|
+
답변은 한글(기술 토큰 영문).
|
|
12
|
+
|
|
13
|
+
## 0. 전제조건: hyperframes (없으면 설치부터)
|
|
14
|
+
이 스킬은 hyperframes CLI 가 설치·정상 동작해야 한다.
|
|
15
|
+
**진행 전 가용성을 먼저 확인**하고, 문제가 있으면 **설치부터 안내**한다(추정·임의 재설치 금지):
|
|
16
|
+
- 확인: `npx hyperframes doctor`
|
|
17
|
+
- 실패/미설치면 먼저 `motion-graphic-setup` 스킬로 설치(Claude Code: `/banker:setup` → motion-graphic-setup / Codex: `banker-motion-graphic-setup`). 설치·검증 후 이 스킬을 이어서 진행한다.
|
|
18
|
+
|
|
19
|
+
## hyperframes 란 (요약)
|
|
20
|
+
hyperframes 는 HTML/CSS + 시크(seek) 가능한 애니메이션(GSAP·CSS·Lottie·Three.js 등)을 결정론적 MP4/투명 오버레이 비디오로 렌더링하는 오픈소스 프레임워크다.
|
|
21
|
+
진입점은 `/hyperframes` 라우터다 — 모든 "영상/애니메이션 만들어줘" 요청을 적절한 창작 워크플로로 분기하는 역량 지도다.
|
|
22
|
+
이 스킬이 다루는 대상은 그 창작 워크플로 중 하나인 `/motion-graphics` — 짧고 내레이션 없는 디자인-주도 모션 그래픽 하나로 한정된다.
|
|
23
|
+
더 길거나·내레이션이 있거나·멀티씬이면 hyperframes 자신이 `/general-video` 등 다른 워크플로로 재라우팅한다(이 스킬이 판단하지 않는다).
|
|
24
|
+
|
|
25
|
+
## 무료 폼 카테고리 (검색 불필요 · 유료 API 없음)
|
|
26
|
+
`asset_needs` 가 비어 있어 사용자가 콘텐츠를 직접 제공하는 6개 카테고리 — 전부 무료로 동작한다.
|
|
27
|
+
|
|
28
|
+
| 카테고리 | 내용 |
|
|
29
|
+
|---|---|
|
|
30
|
+
| `kinetic-type` | 문구/제목의 모션 타이포그래피 |
|
|
31
|
+
| `stat` | 히어로 숫자 카운트업 + 링 |
|
|
32
|
+
| `charts` | 막대/선/원형/레이스 차트 |
|
|
33
|
+
| `logo-reveal` | 로고 스팅 / 브랜드 락업 |
|
|
34
|
+
| `lower-thirds` | 이름/직함 바, 콜아웃, 소셜 오버레이 |
|
|
35
|
+
| `maps` | 지역 하이라이트 · 지점 연결 · 위치 줌 |
|
|
36
|
+
|
|
37
|
+
검색이 필요한 카테고리(웹페이지/뉴스/트윗/이미지 합성)도 hyperframes 안에 존재하지만, 검색 프로바이더가 없으면 자동으로 asset-free 로 성능이 저하(degrade)한다 — 이 스킬의 초점은 위 6개 무료 폼 카테고리다.
|
|
38
|
+
이미지 생성이 필요한 경우에 한해 `GEMINI_API_KEY`/`GOOGLE_API_KEY` 를 선택적으로 쓰며, 없으면 생성 단계를 건너뛸 뿐 실패하지 않는다.
|
|
39
|
+
|
|
40
|
+
## 이 스킬이 소유하지 않는 것
|
|
41
|
+
**GSAP 애니메이션 작성, HTML 컴포지션 코딩, ffmpeg 인코딩, headless Chrome 캡처 — 이 중 어느 것도 이 스킬이 직접 구현하지 않는다.**
|
|
42
|
+
전부 hyperframes 자체 서브에이전트(director/builder)와 CLI(`lint`/`check`/`snapshot`/`render`)가 수행한다.
|
|
43
|
+
이 규칙을 여기서 재서술하면 hyperframes 본체와 어긋나는 사본이 생긴다 — 정본은 항상 hyperframes 쪽이다.
|
|
44
|
+
이 스킬의 역할은 **호출 · 전제조건 확인 · 렌더 승인 게이트 강제**뿐이다.
|
|
45
|
+
|
|
46
|
+
## 흐름
|
|
47
|
+
1. **plan** — 사용자 요청(브리프)을 그대로 hyperframes `/motion-graphics`(필요시 `/hyperframes` 라우터 경유)에 전달한다. 카테고리 자동 분류와 초안 계획은 hyperframes 가 수행한다.
|
|
48
|
+
2. **build** — hyperframes 가 카탈로그 블록을 재사용해 컴포지션 HTML 을 만든다(이 스킬의 직접 코드 작성 없음).
|
|
49
|
+
3. **lint / check / snapshot** — hyperframes CLI 가 결함을 사전 검출하고, 필요하면 자체 리페어 패스를 한 번 더 돈다.
|
|
50
|
+
4. **사용자 승인 게이트** — "미리보기 먼저 볼지, 바로 렌더할지" 하나만 묻는다. 미리보기를 고르면 hyperframes Studio 로 보여주고 다시 같은 질문으로 돌아온다.
|
|
51
|
+
5. **render** — **명시적 렌더 승인 이후에만** 실행한다. 불투명 결과는 MP4, 오버레이가 필요하면 투명 webm/mov 로 렌더한다.
|
|
52
|
+
|
|
53
|
+
**렌더는 사용자의 명시적 승인 없이는 절대 실행하지 않는다** — 승인 전에는 미리보기 단계에서 멈추는 것이 기본값이다.
|
|
54
|
+
|
|
55
|
+
## 완료 보고
|
|
56
|
+
렌더가 끝나면 산출물 경로, 실제 길이(duration), 사용된 컴포지션/프레임 id, 확인에 쓴 스냅샷 시점을 함께 보고한다.
|
|
57
|
+
렌더 없이 미리보기에서 멈췄다면, 어디까지 진행됐고 다음에 무엇을 승인하면 렌더로 이어지는지만 짧게 보고한다.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: motion-graphic-setup
|
|
3
|
+
description: "(banker) 모션 그래픽 제작 도구 hyperframes 설치 전제조건 확보: Node>=22 + ffmpeg(OS 패키지 우선, project-local ffmpeg-static 폴백) 후 npx hyperframes init/skills update/doctor. 'motion-graphic-setup'/'모션 그래픽 설치'/'hyperframes 설치' 또는 /banker:setup 시 사용."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# motion-graphic-setup — hyperframes(모션 그래픽 CLI) 설치
|
|
7
|
+
|
|
8
|
+
무료(free) 모션 그래픽 제작 도구 hyperframes 의 실행 전제조건을 설치한다.
|
|
9
|
+
hyperframes 는 Node.js CLI 로, HTML/CSS/GSAP 로 만든 애니메이션을 headless Chrome + ffmpeg 로 MP4/투명 오버레이 비디오로 렌더링한다.
|
|
10
|
+
실제 모션 그래픽 제작은 `motion-graphic-make` 스킬(hyperframes `/motion-graphics` 위임)이 담당하고, 이 스킬은 그 전제조건만 갖춘다.
|
|
11
|
+
**OS·arch·기존 설치 여부를 먼저 감지**해 알맞은 경로를 고른다.
|
|
12
|
+
설치는 **멱등**(이미 있으면 skip·검증만). 답변은 한글(기술 토큰 영문).
|
|
13
|
+
|
|
14
|
+
## 0. 감지 (먼저, 추정 금지)
|
|
15
|
+
```bash
|
|
16
|
+
echo "OS=$(uname -s)"
|
|
17
|
+
echo "ARCH=$(uname -m)"
|
|
18
|
+
echo "root=$([ "$(id -u)" = 0 ] && echo yes || echo no)"
|
|
19
|
+
[ -f /etc/os-release ] && . /etc/os-release && echo "distro=$ID ${VERSION_ID}"
|
|
20
|
+
command -v node >/dev/null && echo "node=$(node -v)" || echo "node=미설치"
|
|
21
|
+
command -v npx >/dev/null && echo "npx=yes" || echo "npx=미설치"
|
|
22
|
+
command -v npm >/dev/null && echo "npm=$(npm -v)" || echo "npm=미설치"
|
|
23
|
+
command -v ffmpeg >/dev/null && ffmpeg -version 2>&1 | head -1 || echo "ffmpeg=미설치"
|
|
24
|
+
```
|
|
25
|
+
```powershell
|
|
26
|
+
$PSVersionTable.PSVersion
|
|
27
|
+
winget --version
|
|
28
|
+
if (Get-Command node -ErrorAction SilentlyContinue) { node -v } else { "node: 미설치" }
|
|
29
|
+
if (Get-Command ffmpeg -ErrorAction SilentlyContinue) { (ffmpeg -version)[0] } else { "ffmpeg: 미설치" }
|
|
30
|
+
```
|
|
31
|
+
**이미 설치 확인**: `node -v` 가 22 이상 **이고** `ffmpeg` 가 존재 **이고** `npx hyperframes doctor` 가 통과하면, 아래 §1~§3 은 건너뛰고 §4 검증만 수행한다.
|
|
32
|
+
|
|
33
|
+
## 1. Node ≥22 확보
|
|
34
|
+
목적은 Node>=22 확보이지 특정 설치 경로 강제가 아니다.
|
|
35
|
+
이미 nvm 등 버전 매니저로 관리 중이면 `nvm install --lts && nvm alias default 'lts/*'` 로 충분하다(멀티버전 관리·RHEL8 glibc 사전확인 등 상세 절차는 `setup-node` 스킬 참조).
|
|
36
|
+
|
|
37
|
+
### macOS (Apple Silicon / Intel)
|
|
38
|
+
```bash
|
|
39
|
+
brew install node
|
|
40
|
+
node -v
|
|
41
|
+
```
|
|
42
|
+
Apple Silicon(`/opt/homebrew`)·Intel(`/usr/local`) 차이는 `brew` 가 자동 흡수 — 스크립트는 두 아키텍처에 동일 적용.
|
|
43
|
+
|
|
44
|
+
### Linux — Ubuntu / Debian
|
|
45
|
+
```bash
|
|
46
|
+
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
|
|
47
|
+
sudo apt-get install -y nodejs
|
|
48
|
+
node -v
|
|
49
|
+
```
|
|
50
|
+
배포 기본 apt 저장소의 `nodejs` 는 버전이 낮은 경우가 많아 NodeSource 22.x 저장소를 사용한다.
|
|
51
|
+
|
|
52
|
+
### Linux — RHEL8 / Rocky8
|
|
53
|
+
⚠️ dnf AppStream 모듈의 `nodejs` 스트림은 미러 구성에 따라 22 미만일 수 있다 — 사전 확인: `dnf module list nodejs`.
|
|
54
|
+
```bash
|
|
55
|
+
sudo dnf module reset -y nodejs
|
|
56
|
+
sudo dnf module enable -y nodejs:22 2>/dev/null || \
|
|
57
|
+
curl -fsSL https://rpm.nodesource.com/setup_22.x | sudo -E bash -
|
|
58
|
+
sudo dnf install -y nodejs
|
|
59
|
+
node -v
|
|
60
|
+
```
|
|
61
|
+
22 스트림이 없거나 sudo 가 불가하면 **`setup-node` 스킬로 위임**(nvm 경로, RHEL8 glibc 2.28 사전확인 포함) — 이쪽이 더 안전하다.
|
|
62
|
+
|
|
63
|
+
### Windows
|
|
64
|
+
```powershell
|
|
65
|
+
winget install --id OpenJS.NodeJS.LTS -e
|
|
66
|
+
node -v
|
|
67
|
+
```
|
|
68
|
+
여러 Node 버전을 넘나들어야 하면 nvm-windows: `winget install --id CoreyButler.NVMforWindows -e` 후 `nvm install lts && nvm use <설치된 버전>`.
|
|
69
|
+
> ⚠️ winget Node 와 nvm-windows 를 동시에 설치하지 않는다(PATH 충돌 — 상세는 `setup-node` 함정 참조).
|
|
70
|
+
|
|
71
|
+
**위 경로가 모두 막히면(권한 없음·미러 문제 등) → `setup-node` 스킬로 위임한다.**
|
|
72
|
+
|
|
73
|
+
## 2. ffmpeg 확보
|
|
74
|
+
hyperframes 렌더러(headless Chrome 캡처 + ffmpeg 인코딩)가 요구하는 `ffmpeg` 실행 파일을 확보한다.
|
|
75
|
+
1순위는 시스템 패키지, 2순위(권한 없음/오프라인/저장소 미제공)는 프로젝트-로컬 `ffmpeg-static` npm 폴백이다.
|
|
76
|
+
|
|
77
|
+
**★ banker 플러그인 자체(스킬 파일·npm 패키지 배포물)에는 ffmpeg 바이너리를 절대 번들하지 않는다.** 아래 폴백은 사용자 프로젝트의 `node_modules` 에만 설치된다.
|
|
78
|
+
|
|
79
|
+
### macOS
|
|
80
|
+
```bash
|
|
81
|
+
brew install ffmpeg
|
|
82
|
+
ffmpeg -version | head -1
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Linux — Ubuntu / Debian
|
|
86
|
+
```bash
|
|
87
|
+
sudo apt-get install -y ffmpeg
|
|
88
|
+
ffmpeg -version | head -1
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Linux — RHEL8 / Rocky8
|
|
92
|
+
⚠️ 기본 BaseOS/AppStream 저장소에는 `ffmpeg` 가 없다(라이선스 문제로 RPM Fusion 필요).
|
|
93
|
+
```bash
|
|
94
|
+
sudo dnf install -y https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm
|
|
95
|
+
sudo dnf install -y ffmpeg
|
|
96
|
+
ffmpeg -version | head -1
|
|
97
|
+
```
|
|
98
|
+
사내망/에어갭 등으로 RPM Fusion 접근이 막히면 dnf 를 포기하고 바로 아래 폴백으로 진행한다.
|
|
99
|
+
|
|
100
|
+
### Windows
|
|
101
|
+
```powershell
|
|
102
|
+
winget install --id Gyan.FFmpeg -e
|
|
103
|
+
ffmpeg -version
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 폴백 — project-local `ffmpeg-static` (시스템 패키지 설치가 불가할 때만)
|
|
107
|
+
```bash
|
|
108
|
+
npm install --no-save ffmpeg-static
|
|
109
|
+
export FFMPEG_PATH="$(node -e "console.log(require('ffmpeg-static'))")"
|
|
110
|
+
"$FFMPEG_PATH" -version | head -1
|
|
111
|
+
```
|
|
112
|
+
- `--no-save`: 전역이 아니라 **현재 프로젝트의 `node_modules`** 에만 받는다 — 사용자 워크스페이스 소관이며 banker 플러그인 소관이 아니다.
|
|
113
|
+
- hyperframes 가 이 바이너리를 인식하는지는 §3 의 `npx hyperframes doctor` 로 확인한다.
|
|
114
|
+
- 재강조: 이 폴백은 사용자 프로젝트에 설치되는 npm 의존성일 뿐, banker 플러그인 저장소(`skills/`)나 배포 아티팩트에는 어떤 ffmpeg 바이너리도 포함되지 않는다.
|
|
115
|
+
|
|
116
|
+
## 3. hyperframes 설치 · 최신화
|
|
117
|
+
```bash
|
|
118
|
+
npx hyperframes init
|
|
119
|
+
npx hyperframes skills update
|
|
120
|
+
npx hyperframes doctor
|
|
121
|
+
```
|
|
122
|
+
- `init`: 최초 실행 시 스캐폴딩과 함께 전역 스킬셋(라우터 `/hyperframes` + `hyperframes-*` 도메인 스킬 + `media-use`)을 설치하고, 이미 있으면 최신 여부만 GitHub 기준으로 확인한다.
|
|
123
|
+
- `skills update`: 코어 스킬만 골라 최신화한다(비대화형 환경 권장 경로) — 이미 최신이면 no-op.
|
|
124
|
+
- `doctor`: Node·ffmpeg·설치된 스킬 등 실행 환경을 종합 진단한다.
|
|
125
|
+
|
|
126
|
+
## 4. 검증 (보고 의무)
|
|
127
|
+
```bash
|
|
128
|
+
node -v # v22.x.x 이상 기대
|
|
129
|
+
command -v ffmpeg >/dev/null && ffmpeg -version | head -1 || echo "시스템 ffmpeg 없음 — ffmpeg-static 폴백 확인"
|
|
130
|
+
npx hyperframes doctor # 종합 진단(node/ffmpeg/스킬셋)
|
|
131
|
+
```
|
|
132
|
+
4-field 보고: 변경(설치 경로·ffmpeg 확보 방식) / Evidence(위 출력) / 검증(`node -v`≥22 + `hyperframes doctor` 통과) / Unknown(권한·네트워크 제약으로 시스템 ffmpeg 불가 등, 가짜 성공 금지).
|
|
133
|
+
|
|
134
|
+
## 함정
|
|
135
|
+
- **RHEL8/Rocky8 dnf 모듈 nodejs 버전**: AppStream 스트림이 22 미만일 수 있음(사전 `dnf module list nodejs` 확인) → NodeSource 저장소 또는 `setup-node`(nvm) 로 위임.
|
|
136
|
+
- **RHEL8/Rocky8 ffmpeg 미제공**: BaseOS/AppStream 에 없음(라이선스) → RPM Fusion 필요, 접근 막히면 `ffmpeg-static` 폴백.
|
|
137
|
+
- **ffmpeg 바이너리 미번들 원칙**: `ffmpeg-static` 폴백은 사용자 프로젝트 `node_modules` 한정 — banker 플러그인 배포물에는 절대 포함하지 않는다(라이선스·배포 크기·플랫폼별 바이너리 불일치 회피).
|
|
138
|
+
- **GEMINI_API_KEY 는 선택**: AI 이미지 생성이 필요한 카테고리에서만 쓰이고, 무료 폼 카테고리(kinetic-type·stat·charts·logo-reveal·lower-thirds·maps)는 키 없이 전부 동작한다 — 이 스킬은 어떤 API 키도 요구하지 않는다.
|
|
139
|
+
- **Windows PATH 충돌**: winget Node 와 nvm-windows 동시 설치 금지(상세는 `setup-node` 함정 참조).
|
|
140
|
+
- **새 셸에만 반영**: NodeSource/dnf 모듈 설치 직후 PATH 갱신은 새 터미널이 필요할 수 있다.
|
|
141
|
+
- **hyperframes 스킬 갱신은 네트워크 필요**: `hyperframes init`/`skills update` 는 GitHub 에서 최신 스킬을 당겨온다 — 오프라인/에어갭 환경이면 실패를 정직히 보고(가짜 성공 금지).
|
package/skills/ralph-qa/SKILL.md
CHANGED
|
@@ -1,97 +1,273 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ralph-qa
|
|
3
|
-
description: "(banker) 작업 결과를
|
|
3
|
+
description: "(banker) 작업 결과를 자기채점하지 않게 독립 검증/개선 반복: 다중 에이전트 백본이 가장 강한 가용 모델로 항상 돌고, 실제로 유효한 외부 LLM(Codex CLI·Gemini CLI·GPT/Gemini API)만 추가 좌석으로 합류한다. 'ralph-qa'/'교차검증'/'다른 LLM으로 검증'/'독립 QA' 시 사용."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# ralph-qa —
|
|
6
|
+
# ralph-qa — 독립 검증 루프 (백본 + 좌석)
|
|
7
7
|
|
|
8
|
-
방금 만든
|
|
9
|
-
`ralplan --deliberate`(설계
|
|
10
|
-
지적을 반영해 **APPROVE까지 반복**한다.
|
|
11
|
-
다른 모델이라야 편향·맹점이 드러난다.
|
|
8
|
+
방금 만든 결과를 **같은 세션이 자기채점**하는 대신, 독립 좌석들에 넘겨
|
|
9
|
+
`ralplan --deliberate`(설계 최적성)와 `ralph --critic=critic`(수용 기준) 로직을 적용하고,
|
|
10
|
+
지적을 반영해 **APPROVE까지 반복**한다.
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
모델이 닿으면 그걸 쓰고, 다중 에이전트 합의는 다른-LLM 경로가 전무할 때만.
|
|
12
|
+
**구성.** 다중 에이전트 **백본이 조건 없이 항상 돈다**. 여기에 실제 유효성이 관측된 외부 LLM 이 **각 1좌석**으로 합류한다.
|
|
13
|
+
용어: 외부 좌석의 부재는 실패도 열화도 아니다 — 그 축이 이번 실행에서 안 덮였다는 커버리지 사실일 뿐이다.
|
|
16
14
|
|
|
17
15
|
## 언제 쓰나
|
|
18
16
|
- 방금 완성한 구현/설계/문서를 **배포·확정 전** 독립 검증하고 싶을 때.
|
|
19
|
-
- ralph/all-in-one이 끝난 뒤 **다른
|
|
17
|
+
- ralph/all-in-one이 끝난 뒤 **다른 시각**으로 한 번 더 거르고 싶을 때.
|
|
20
18
|
- 되돌리기 어렵거나 파급 큰 산출물(마이그레이션·공개 API·배포물).
|
|
21
19
|
|
|
22
20
|
## 쓰지 않을 때
|
|
23
|
-
- 사소한 변경(
|
|
24
|
-
-
|
|
21
|
+
- 사소한 변경(왕복 비용이 이득을 초과).
|
|
22
|
+
- 수용 기준을 세울 수 없는 대상("잘 됐나?"는 검증 대상이 아니다).
|
|
23
|
+
|
|
24
|
+
## 독립성 3축
|
|
25
|
+
|
|
26
|
+
| 축 | 무엇을 제거하나 | 백본 일반 좌석 | 출처-독립 좌석 | 외부 좌석 |
|
|
27
|
+
|---|---|---|---|---|
|
|
28
|
+
| **컨텍스트-독립** | 저자 세션의 앵커링·매몰비용 | ◐ 계약상 성립(관측 불가) | ◐ | ◐ |
|
|
29
|
+
| **프레이밍-독립** | 저자가 고른 기준·증거·프롬프트 | ❌ 미확보 | ✅ 확보 | ❌ 미확보 |
|
|
30
|
+
| **모델-독립** | 베이스 모델 고유의 체계적 맹점 | ❌ 미확보 | ❌ 미확보 | ✅ 확보 |
|
|
31
|
+
|
|
32
|
+
`◐` = 계약상 성립하되 **관측 불가**. 서브에이전트가 저자 컨텍스트를 실제로 안 보는지는 하네스 내부 동작이라 이 스킬이 관측할 수 없다.
|
|
33
|
+
외부 좌석도 페이로드를 **저자가 구성**하므로 컨텍스트 배제는 저자 준수에 의존한다.
|
|
34
|
+
|
|
35
|
+
## 검증자 구성
|
|
36
|
+
|
|
37
|
+
- **백본**: 서브에이전트 `N`개(`--agents`, 기본 3). 렌즈를 나눠 배정한다 — ① 설계 최적성 ② 수용 기준 ③ 적대적 반증.
|
|
38
|
+
- **모델은 선호 순서로 내려간다.** ① Opus 계열 최신 → ② 그게 없으면 **가용한 것 중 가장 적합한 추론 모델** → ③ 그마저 없으면 기본값. 이건 실제로 고를 수 있다(Agent 도구 `model`).
|
|
39
|
+
- **추론 강도는 고르는 것이 아니라 물려받는 것이다.** 세션 설정이 지배하고 이 스킬에는 손잡이가 없다. 최대 강도로 검증받고 싶으면 **호출 전에 세션 강도를 올려라.**
|
|
40
|
+
- 어느 단계로 갔든 **실제로 쓴 모델과 물려받은 강도를 보고의 선언 블록에 적는다.** 목표를 적고 실제를 감추는 것이 이 스킬에서 가장 나쁜 실패다.
|
|
41
|
+
- **출처-독립 좌석**: 백본 중 **최소 1개**. `N ≥ 1` 이면 항상 1개 이상 존재한다.
|
|
42
|
+
- **외부 좌석**: `external:api:<model>` · `external:codex` · `external:gemini`(CLI) · `external:gemini-api`(크리덴셜). **유효성이 관측된 것만** 착석한다.
|
|
43
|
+
- **CLI 경로와 크리덴셜 경로는 별개 좌석이다.** CLI 부재가 크리덴셜 경로를 가리면 안 된다 — 유효한 키가 있는데 "CLI 가 없어서 못 썼다"고 보고하는 것은 허위 커버리지다.
|
|
44
|
+
- **외부 좌석끼리도 같은 모델이면 안 된다.** codex 좌석이 함께 서면 api 좌석은 **codex 가 돌릴 모델의 계열을 피해서** 고른다. 저자의 codex 설정이 api 좌석의 선호 모델 출처이기도 해서, 그대로 두면 좌석은 2인데 모델 축에서는 하나가 된다 — 승인 게이트가 넓어지지는 않지만 보고의 "외부 2" 가 실제보다 독립적으로 읽힌다.
|
|
45
|
+
회피 사다리는 **다른 계열 → 같은 계열의 다른 모델 → 같은 모델** 이고, 프로브가 내려간 단계를 `modelPick` 으로 돌려준다. codex 의 모델을 확인하지 못하면 fail-closed 로 codex 런타임 계열을 피한다.
|
|
46
|
+
|
|
47
|
+
## 유효성 판정
|
|
48
|
+
|
|
49
|
+
유효성 판정은 `references/verifier-probe.mjs` 가 한다(0토큰 HTTP 프리플라이트). 판정 근거는 그 출력이다.
|
|
50
|
+
|
|
51
|
+
**무엇이 어디로 나가는지 먼저 밝힌다.** 프로브는 프로바이더의 **모델 목록 GET** 만 낸다 — 작업 내용·프롬프트·코드는 나가지 않고, 나가는 것은 인증 헤더뿐이다.
|
|
52
|
+
목적지는 설정에서 해석한 base URL 이고, base URL 을 못 찾으면 **키 env 이름이 지목하는 표준 벤더 엔드포인트로 내려간다.** 이 경우 `source` 가 `default:*` 로 표시되고 `notes` 에 사유가 남는다.
|
|
53
|
+
- 이 내려감이 싫으면 `RALPH_QA_NO_DEFAULT_ENDPOINT` 를 설정한다. 그러면 목적지가 없어 좌석이 서지 않고, 보고 사유는 `default-endpoint-off` 다(원인이 저자 설정이므로 환경 계열로 분류하지 않는다).
|
|
54
|
+
- `--external=off` 는 **HTTP 를 한 건도 내지 않는다.** 정적 탐지까지만 하고 멈춘다.
|
|
55
|
+
|
|
56
|
+
| 프로브 출력 필드 | 뜻 | 좌석에 미치는 영향 |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| `observed.api.status` | provider `GET /models` 응답 코드 | 2xx 만 착석 |
|
|
59
|
+
| `observed.api.live` + `reason` | 생존 판정 | `dead-credential`(401/403)·`unreachable`·`timeout` 이면 미착석 |
|
|
60
|
+
| `observed.transport` | 외부 호출이 나갈 경로 `curl`\|`python3`\|`none` | `none` 이면 api 좌석 무효(`no-transport`) |
|
|
61
|
+
| `observed.candidates` / `unclassified` | 저자 계열을 뺀 후보 / fail-closed 로 제외된 미분류 수 | 후보 0 이면 `no-independent-model` |
|
|
62
|
+
| `declared.seats.external[].modelPick` | api 좌석이 codex 회피 사다리의 어느 단으로 앉았는지 — `unconstrained`(codex 좌석 없음) \| `independent-family` \| `same-family-different-model` \| `same-model` | 좌석 수는 안 바뀌고 **보고 문구가 바뀐다** |
|
|
63
|
+
| `observed.cli.gemini.liveChecked` | **항상 `false`** | gemini 는 첫 호출이 곧 프로브 |
|
|
64
|
+
|
|
65
|
+
gemini **CLI** 좌석은 프로브가 `G0 → G1 → (G2 없음) → G3` 사다리의 G0·G1 까지만 판정하고 `liveChecked:false` 다. 첫 검증 호출이 곧 프로브이며 실패는 미착석이다(미검증 경로).
|
|
66
|
+
이 사다리는 `T0~T4` 와 **비대칭**이다 — (i) 인증 출처가 다르고(프로바이더 env → 자체 인증), (ii) OpenAI 호환 `/models` 가 없어 계열 필터를 못 돌리며, (iii) 그래서 "저자 계열 배제"를 카탈로그로 강제하지 못하고 CLI 자체가 다른 벤더라는 사실에 의존한다.
|
|
67
|
+
|
|
68
|
+
gemini **크리덴셜** 좌석은 이와 별개로 판정한다. CLI 가 없어도 인증 env 가 있으면 자체 모델 목록 GET 으로 0토큰 생존 판정을 하고 착석한다.
|
|
69
|
+
**크리덴셜이 있으면 사유 토큰 `cli-absent` 를 쓰지 않는다** — 생존 판정 실패는 `probe-unseated status=<code>`, 전송 수단 부재는 `no-transport` 다. `cli-absent` 는 CLI 도 크리덴셜도 없을 때만 쓴다.
|
|
70
|
+
|
|
71
|
+
`transport` 가 `python3` 이면 외부 호출은 3.6 호환 부분집합으로 낸다(`urllib.request`·`json`·f-string 까지만):
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import json, urllib.request
|
|
75
|
+
req = urllib.request.Request(
|
|
76
|
+
endpoint, method="POST",
|
|
77
|
+
headers={"Authorization": "Bearer " + key, "Content-Type": "application/json"},
|
|
78
|
+
data=json.dumps({"model": model, "messages": [{"role": "user", "content": prompt}]}).encode())
|
|
79
|
+
with urllib.request.urlopen(req, timeout=120) as r:
|
|
80
|
+
print(json.load(r)["choices"][0]["message"]["content"])
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
위 형태는 **OpenAI 호환 좌석(`external:api`)** 용이다. `external:gemini-api` 는 요청·응답 스키마가 다르므로 같은 본문을 재사용하지 마라 — 엔드포인트·인증 위치·응답 경로를 그 벤더 규격대로 맞춘다.
|
|
84
|
+
|
|
85
|
+
## 정족수
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
좌석 판정 정의역: {APPROVE, ITERATE, REJECT, ERROR}
|
|
89
|
+
· 외부 좌석은 단독 줄 `VERDICT: <값>` 필수. 부재·중복·절단·파싱실패·거부 = ERROR
|
|
90
|
+
· ERROR = 좌석 유지 + APPROVE 차단 (드롭 금지)
|
|
91
|
+
|
|
92
|
+
좌석 식별자: (종류, 렌즈)
|
|
93
|
+
· 종류 ∈ {backbone#i, backbone-si#i, external:api:<model>, external:codex,
|
|
94
|
+
external:gemini, external:gemini-api}
|
|
95
|
+
· 반복 k 의 식별자 집합 S_k 에 대해 S_k ⊆ S_{k+1} 이어야 한다
|
|
96
|
+
· S_k \ S_{k+1} ≠ ∅ = 좌석 상실 (원인 불문 — T4 강등은 원인의 한 예시)
|
|
97
|
+
· 같은 식별자로 다시 선 좌석 = 동일 계열 대체 좌석
|
|
98
|
+
(끈끈한 반대의 유일한 해제 주체 → 좌석을 새로 굴려 반대를 지울 수 없다)
|
|
99
|
+
· 백본 좌석의 blocker 도 좌석 재생성으로 소멸하지 않는다
|
|
100
|
+
· 렌즈 재배정도 좌석 상실이다 — 렌즈를 바꾸려면 기존 좌석을 유지한 채 추가하라
|
|
101
|
+
|
|
102
|
+
APPROVE ⟺ (내부 좌석 ≥ 1)
|
|
103
|
+
∧ (내부 좌석의 과반이 APPROVE)
|
|
104
|
+
∧ (실증된 외부 비-APPROVE 0건)
|
|
105
|
+
∧ (미해소 blocker 0건 — 외부는 실증 필터를 통과한 것,
|
|
106
|
+
백본은 전부. 좌석이 죽어도 유지되는 끈끈한 반대 포함)
|
|
107
|
+
∧ (이번 반복에 ERROR 좌석 0건)
|
|
108
|
+
∧ (이번 실행에 좌석 상실 0건 — 원인 불문)
|
|
109
|
+
|
|
110
|
+
종결어: APPROVE(3축) — 외부 좌석이 착석해 완주
|
|
111
|
+
APPROVE(모델축 미커버 — 환경) — 외부 0, 사유가 환경
|
|
112
|
+
APPROVE(모델축 미커버 — 저자 요청) — 외부 0, 사유가 저자 설정
|
|
113
|
+
(--external=off · RALPH_QA_NO_DEFAULT_ENDPOINT)
|
|
114
|
+
※ 외부 0 이면 사유 토큰을 보고에 반드시 적는다
|
|
115
|
+
※ 종결어 분화를 소비하는 주체는 하류다 — 내부 게이트는 셋을 동일
|
|
116
|
+
취급한다(셋 다 APPROVE). 목적은 게이트를 좁히는 것이 아니라 한 줄
|
|
117
|
+
요약으로 인용될 때 무엇이 안 덮였는지가 살아남게 하는 것이다
|
|
118
|
+
|
|
119
|
+
INCONCLUSIVE ⟸ 좌석 상실 (원인 불문)
|
|
120
|
+
∨ 동일 좌석 ERROR 2연속
|
|
121
|
+
∨ 좌석 총합 0
|
|
122
|
+
∨ --max 소진 + 미해소 blocker 잔존
|
|
123
|
+
|
|
124
|
+
--max 소진은 항상 종결이다 (어느 갈래도 통과가 아니다)
|
|
125
|
+
· 미해소 blocker 잔존 → INCONCLUSIVE
|
|
126
|
+
· 그 외 미해결(내부 과반 미달) → ITERATE(한도 소진) — 루프 재개 없음
|
|
127
|
+
|
|
128
|
+
조기 종결 (--max 소진 전)
|
|
129
|
+
· 같은 이슈가 3회+ 재발 → INCONCLUSIVE + 사람 에스컬레이션
|
|
130
|
+
|
|
131
|
+
INCONCLUSIVE 소비 규칙 — 통과가 아니다
|
|
132
|
+
· 배포·머지·릴리스 게이트를 통과시키지 않는다. APPROVE 취급 금지
|
|
133
|
+
· 좌석 상실·ERROR 2연속 → 환경 복구 후 재실행
|
|
134
|
+
(--external=off 로 우회하면 그 사실을 보고에 남긴다)
|
|
135
|
+
· 좌석 총합 0 → --agents 확인 후 재실행
|
|
136
|
+
· --max 소진 → 잔존 blocker 를 사람에게 에스컬레이션
|
|
137
|
+
· 재실행해도 같은 INCONCLUSIVE → 사람의 명시적 판단을 요구하고 멈춘다
|
|
138
|
+
|
|
139
|
+
그 외 → ITERATE
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## 런타임 대칭
|
|
143
|
+
|
|
144
|
+
무엇이 "다른 모델"인지는 저자 런타임마다 뒤집힌다.
|
|
145
|
+
|
|
146
|
+
| 저자 런타임 | 백본 | **자기 자신 — 외부 좌석 부적격** | 외부 좌석 후보 |
|
|
147
|
+
|---|---|---|---|
|
|
148
|
+
| **Claude Code (OMC)** | Agent/Task 서브에이전트 (모델은 선호 순서로 선택) | Claude 계열 전부 — `curl` 로 `claude-*` 호출 금지 | `external:codex` · `external:api`(비-Claude 계열) · `external:gemini`(CLI) · `external:gemini-api` |
|
|
149
|
+
| **Codex CLI (OMX)** | OMX 서브에이전트 (동일) | **GPT 계열 전부 — `codex exec` 는 자기 자신이라 외부 좌석 부적격** | `omx $ask claude` · `external:api`(비-GPT 계열) · `external:gemini`(CLI) · `external:gemini-api` |
|
|
150
|
+
|
|
151
|
+
## 플래그
|
|
152
|
+
|
|
153
|
+
| 플래그 | 적용 좌석 | 효과 | 기본 | 전송 경로 | 확인 수준 |
|
|
154
|
+
|---|---|---|---|---|---|
|
|
155
|
+
| `--agents=N` | 백본 | 내부 좌석 수 (N≥1). 그중 최소 1개가 출처-독립 좌석. 좌석 식별자는 반복 간 유지 — 하향은 좌석 상실 | 3 | Agent 도구 `model` (선호 순서로 선택) | 모델 전달 확인 / **강도는 선택만, 지정 아님** |
|
|
156
|
+
| `--external=auto\|off` | 외부 | auto=유효하면 합류 / off=강제 미사용(HTTP 0건). 0이면 사유 토큰을 보고에 강제 | auto | api·codex·gemini-api = 프로브 결과 게이트 · gemini(CLI) = G1 까지만 게이트, 첫 호출이 곧 프로브 | api·codex 전달 확인 · gemini-api 인증만 확인 / gemini(CLI) 미검증 |
|
|
157
|
+
| `--model <id>` | 외부 | 외부 모델 고정(미지정 시 계열 필터 + codex 회피가 자동 선택). **고정 값이 회피보다 우선** | 자동 | `curl`(없으면 `python3` urllib) body `model` · `codex exec -m` · `gemini -p`(모델 선택 문법 미검증) | api·codex 전달 확인 / gemini 미검증 |
|
|
158
|
+
| `--effort <v>` | **외부 전용 (api·codex)** | 추론 강도. 백본에는 전송 경로가 없다. gemini 좌석에도 전달하지 않는다 | 미지정 | curl `reasoning_effort` · `codex exec -c model_reasoning_effort=` · gemini = 전송 경로 없음 | **전송 확인 / 적용 미확인** |
|
|
159
|
+
| `--lens=critic\|plan\|both` | 전 좌석 | 적용 렌즈. 렌즈는 좌석 식별자의 구성요소다 | both | 프롬프트 | 전달 확인 |
|
|
160
|
+
| `--max=N` | 루프 | 최대 반복. 소진은 항상 종결이며 갈래가 둘이다 | 5 | — | — |
|
|
161
|
+
|
|
162
|
+
**외부 좌석 종류별:**
|
|
163
|
+
|
|
164
|
+
| 좌석 종류 | 유효성 사다리 | 전송 경로 | 확인 수준 |
|
|
165
|
+
|---|---|---|---|
|
|
166
|
+
| `external:api:<model>` | T0-b → T1 → T2 → T3 → T4 | `curl`(없으면 `python3` urllib, ≥3.6) | 실측 확인 |
|
|
167
|
+
| `external:codex` | T0 → T1 → T2 → T4 | `codex exec -m … -c model_reasoning_effort=…` | 실측 확인 |
|
|
168
|
+
| `external:gemini` | `G0 → G1 → (G2 없음) → G3` | `gemini -p "<프롬프트>"` | **미검증 — 실행 환경에 `gemini` 부재** |
|
|
169
|
+
| `external:gemini-api` | G1 → 모델목록 GET → T4 | `curl`(없으면 `python3` urllib) — **요청 형태가 OpenAI 호환이 아니다** | 인증 생존은 0토큰 판정 / 전송 형태는 미검증 |
|
|
25
170
|
|
|
26
171
|
## 워크플로
|
|
27
172
|
|
|
28
173
|
### 1. 입력 확보
|
|
29
|
-
검증 대상 = {작업 결과
|
|
30
|
-
기준이 없으면 원 작업에서 도출(vague "잘 됐나?" 금지 — 검증 가능한 기준으로).
|
|
31
|
-
|
|
32
|
-
### 2. 검증자 선택 — 다른-LLM 우선, 다중 에이전트 합의는 최후 (독립성)
|
|
33
|
-
목적은 **저자 모델과 다른 모델**로 검증하는 것. 아래 우선순위로 **사용 가능한 첫 경로**를 택한다:
|
|
34
|
-
|
|
35
|
-
1. **다른-LLM CLI — Codex CLI 우선.** `command -v codex` 로 사용 가능하면 Codex 에 위임한다.
|
|
36
|
-
- Claude Code(OMC) 저자: `omc ask codex --agent-prompt critic "..."`(= ralph 의 `--critic=codex` 경로),
|
|
37
|
-
또는 `/ccg`(Codex+Gemini+Claude 합의 레인).
|
|
38
|
-
- 저자가 **이미 Codex** 면 Codex 는 "다른 모델"이 아니므로 건너뛰고 Claude/Gemini(OMX `$ask`)를 ①로 삼는다.
|
|
39
|
-
|
|
40
|
-
2. **다른 모델 직접 호출 via `curl` (Codex CLI 가 없을 때).** 저자와 **다른** 모델(예: GPT)의
|
|
41
|
-
OpenAI 호환 엔드포인트+API 키가 환경/설정에 있으면 `curl` 로 직접 그 모델을 검증자로 쓴다 —
|
|
42
|
-
CLI 래퍼 없이도 진짜 다른 모델이라 독립성이 산다.
|
|
43
|
-
- 엔드포인트·키·모델 ID 는 **환경에서 읽어 파라미터화**한다(하드코딩 금지). 예:
|
|
44
|
-
`"${OPENAI_BASE_URL:?}"`·`"${OPENAI_API_KEY:?}"`·`"${RALPH_QA_MODEL:?}"`, 또는 Codex 설정
|
|
45
|
-
`~/.codex/config.toml` 의 provider(`[model_providers.*]` 의 `base_url`·`env_key`).
|
|
46
|
-
- 호출 예(모델·엔드포인트는 환경값; 프롬프트에 수용 기준 + 두 렌즈를 담아 판정을 JSON 으로 받는다):
|
|
47
|
-
```bash
|
|
48
|
-
curl -sS "${OPENAI_BASE_URL:?}/chat/completions" \
|
|
49
|
-
-H "Authorization: Bearer ${OPENAI_API_KEY:?}" -H 'Content-Type: application/json' \
|
|
50
|
-
-d "$(jq -n --arg m "${RALPH_QA_MODEL:?}" --arg p "$PROMPT" \
|
|
51
|
-
'{model:$m, messages:[{role:"user", content:$p}]}')"
|
|
52
|
-
```
|
|
53
|
-
(`jq` 로 페이로드를 안전 구성 — 없으면 동등한 JSON 이스케이프로 대체.)
|
|
54
|
-
- ⚠️ 저자와 **같은 모델 계열이면 독립성이 없으므로 이 경로를 쓰지 않는다**(예: 저자=Codex(GPT)
|
|
55
|
-
에서 GPT-curl 금지 — 그땐 Claude/Gemini 로).
|
|
56
|
-
|
|
57
|
-
3. **자체 다중 에이전트 합의 루프 (다른-LLM 경로가 전무할 때, 최후).** 독립 에이전트 **N개(기본 3)** 를
|
|
58
|
-
서로 다른 렌즈로 띄워 **정족수 합의**로 판정한다:
|
|
59
|
-
- 렌즈: ① ralplan 최적성(더 단순·빠른 대안?) ② critic 수용기준(기준 하나하나 신선한 증거로)
|
|
60
|
-
③ 적대적 반증(REJECT 를 적극 시도).
|
|
61
|
-
- 판정: **과반 APPROVE** 여야 통과. 확인된 블로커가 **1건이라도** 있으면 ITERATE.
|
|
62
|
-
- 같은 베이스 모델이라 **완전 독립은 아님**(다양성+정족수로 근사) — 단일 자기채점보다 훨씬 강하지만
|
|
63
|
-
①·② 가 가능하면 반드시 그쪽을 먼저 쓴다.
|
|
64
|
-
|
|
65
|
-
경로 ①·② 는 **두 렌즈**(ralplan 최적성 + critic 수용기준)를 함께 요청한다(`--lens` 로 선택, 기본 both).
|
|
66
|
-
경로 ③ 은 렌즈를 에이전트로 분담한다.
|
|
67
|
-
|
|
68
|
-
### 3. 판정 수신 → 반영
|
|
69
|
-
검증자(경로 ①~③)의 판정(`APPROVE` / `ITERATE` / `REJECT`)과 구체 이슈를 받는다. `APPROVE` 아니면:
|
|
70
|
-
원 런타임에서 이슈 수정 → **같은 검증 경로로 재검증**(2단계 반복).
|
|
71
|
-
|
|
72
|
-
### 4. 종료
|
|
73
|
-
- `APPROVE`(경로 ③ 은 과반) → 검증 통과 보고(**검증 경로·검증자 모델·판정 근거** 명시).
|
|
74
|
-
- 같은 이슈가 **3회+ 재발** → 근본 블로커로 보고(무한루프 금지).
|
|
75
|
-
- 다른-LLM auth/프로바이더 장애 → 정직히 보고하고 **경로 ③(다중 에이전트)** 으로 폴백.
|
|
174
|
+
검증 대상 = {작업 결과 + **수용 기준** + 변경 파일 목록 + 관련 코드}. 기준이 없으면 원 작업에서 도출한다.
|
|
76
175
|
|
|
77
|
-
|
|
78
|
-
|
|
176
|
+
**출처-독립 좌석은 저자가 쓴 요약을 받지 않는다.**
|
|
177
|
+
입력 = `git diff` 원문 + 사용자 원 요청 문장 **그대로** + 저장소의 기준 파일(SKILL.md·README·매니페스트).
|
|
178
|
+
지시 = "스스로 수용 기준을 도출하고, **저자가 주장한 기준과의 차이를 보고**하라." `--agents=1` 이면 그 단일 좌석이 출처-독립 좌석이다.
|
|
179
|
+
**이 좌석이 보고한 차이는 blocker 로 취급한다** — 저자가 기준에서 빠뜨린 요구가 곧 검증 공백이므로, 조언으로 흘리면 이 좌석을 두는 이유가 사라진다.
|
|
180
|
+
|
|
181
|
+
### 2. 좌석 착석
|
|
182
|
+
프로브를 **호출당 1회** 돌린다(루프 반복에서 재프로브 금지). 결과대로 외부 좌석을 착석시킨다.
|
|
183
|
+
|
|
184
|
+
**모델 부적격은 착석 전에만 갈아탈 수 있다.** 프로브의 `GET /models` 200 은 카탈로그 접근을 증명할 뿐 **그 모델의 호출 권한을 증명하지 않는다** — 계열 회피로 고른 모델이 첫 호출에서 권한·미존재로 거절될 수 있다(`404` · `400 model_not_found` · 배포 미존재).
|
|
185
|
+
그 경우 그 모델을 후보에서 빼고 **같은 사다리로 다음 후보에 좌석을 세운다.** 좌석 식별자가 아직 확정되지 않았으므로 좌석 상실이 아니다.
|
|
186
|
+
**확정 시점은 그 좌석이 첫 `VERDICT` 를 낸 때다.** 그 뒤의 실패는 갈아타기가 아니라 `ERROR` 이며, 모델을 바꾸면 식별자가 바뀌어 좌석 상실이 된다.
|
|
187
|
+
후보가 고갈되면 api 좌석은 미착석이고 사유는 `no-independent-model` 이다. 갈아탄 사실과 최종 모델은 보고에 적는다.
|
|
188
|
+
`--model` 로 고정하면 그 값이 계열 회피보다 우선한다 — codex 좌석과 겹치면 겹친다는 사실을 보고에 적는다.
|
|
189
|
+
|
|
190
|
+
### 3. 판정 수신
|
|
191
|
+
각 좌석에서 4값 중 하나를 받는다. 외부 좌석은 **단독 줄 `VERDICT: <값>`** 이 필수이며, 부재·중복·절단·파싱실패·거부는 `ERROR` 다.
|
|
192
|
+
|
|
193
|
+
**실증 필터(외부 좌석 전용).** 외부 비-APPROVE 가 거부권을 가지려면 구조화된 `blockers[]` 에 **실재하는 파일 경로 또는 제시된 수용 기준 ID** 를 인용한 항목이 최소 1개 있어야 한다. 확인은 기계적이며 사안의 옳고 그름이 아니라 **주장의 구체성**만 본다.
|
|
194
|
+
실증되지 않은 외부 반대는 `dissent-unsubstantiated` 로 원문 그대로 기록하되 교착시키지 않는다.
|
|
195
|
+
|
|
196
|
+
**적용 범위.** 거부권의 *제한*(실증 요구)은 **외부 좌석 전용**이고, blocker 의 *지속성*(끈끈한 반대)은 **전 좌석**에 적용된다.
|
|
197
|
+
|
|
198
|
+
### 4. 반영과 종료
|
|
199
|
+
`APPROVE` 가 아니면 이슈를 수정하고 **같은 좌석 구성으로** 재검증한다(2단계 반복, `S_k ⊆ S_{k+1}` 유지).
|
|
200
|
+
끈끈한 반대의 해제는 **그 blocker 를 낸 좌석(또는 동일 식별자의 대체 좌석)의 APPROVE 재투표**로만 된다 — 저자의 "고쳤다" 선언으로는 해제되지 않는다.
|
|
201
|
+
종결은 정족수 절의 3값(`APPROVE` · `ITERATE` · `INCONCLUSIVE`)과 그 소비 규칙을 따른다.
|
|
202
|
+
|
|
203
|
+
## 보고 계약
|
|
204
|
+
|
|
205
|
+
관측값과 선언값을 라벨로 나누고, 관측 블록은 **축약하지 않는다.**
|
|
206
|
+
|
|
207
|
+
**정상 — 외부 착석:**
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
프로브(관측): status=200 probeMs=1180 source=codex:azure transport=curl unclassified=3
|
|
211
|
+
후보(관측): <model-a>(gpt), <model-b>(llama) — claude 계열 0건 제외, unclassified 3건 제외
|
|
212
|
+
좌석(선언): 내부 3 (출처-독립 1 포함) / 외부 2 = api:<model-b>(modelPick=independent-family) · codex
|
|
213
|
+
— authorFamily=claude(runtime)
|
|
214
|
+
백본(선언): model=<실제 쓴 모델> — 모델 선호 <1|2|3>순위 · strength=세션 상속(값을 알 수 없으면 "미상")
|
|
215
|
+
독립성 축: 컨텍스트 ◐ / 프레이밍 ✅ / 모델 ✅
|
|
216
|
+
판정: APPROVE(3축) — 내부 3/3, 외부 2/2, 미해소 blocker 0, ERROR 0, 좌석 상실 0
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
api 좌석과 codex 좌석이 함께 서면 좌석 줄에 **`modelPick=<값>` 을 적는다.** 값이 `independent-family` 가 아니면 두 좌석이 모델 축에서 겹친다는 사실을 한 줄 더 적는다 — 그 문장은 프로브의 `notes` 가 준다.
|
|
220
|
+
`<model-b>` 가 gpt 가 아닌 계열인 것은 예시가 아니라 규칙이다. codex 가 gpt 를 돌리므로 api 좌석은 그 계열을 피한 결과다.
|
|
221
|
+
|
|
222
|
+
**좌석 상실:**
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
좌석(선언): 반복 1 = {backbone#1(critic), backbone#2(plan), backbone-si#3(critic),
|
|
226
|
+
external:api:<model-a>}
|
|
227
|
+
반복 2 = {backbone#1(critic), backbone#2(plan)}
|
|
228
|
+
← backbone-si#3 미재생성 · external 429 로 소멸
|
|
229
|
+
판정: INCONCLUSIVE — 좌석 상실(backbone-si#3 원인 불문 / external:api:<model-a> rate-limit)
|
|
230
|
+
반복 1 의 미해소 blocker 2건 유지
|
|
231
|
+
다음 행동: 환경 복구 + 좌석 식별자 재생성 후 재실행.
|
|
232
|
+
--external=off 로 우회하면 그 사실을 보고에 남긴다
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**외부 0 의 두 변형**은 정상 템플릿에서 좌석 줄·판정 줄만 바뀐다:
|
|
236
|
+
|
|
237
|
+
| 외부 0 사유 | 좌석 줄 | 판정 줄 |
|
|
79
238
|
|---|---|---|
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
239
|
+
| 저자 설정 2종 — `author-off` · `default-endpoint-off` | `외부 0 (사유: <토큰>)` | `APPROVE(모델축 미커버 — 저자 요청)` |
|
|
240
|
+
| 환경 7종 — `probe-unseated status=<code>` 외 6종 | `외부 0 (사유: <토큰>)` | `APPROVE(모델축 미커버 — 환경)` |
|
|
241
|
+
|
|
242
|
+
**사유 토큰 9종.** `author-off` · `default-endpoint-off`(앞 2종 → 저자 요청) · `probe-unseated status=<code>` · `no-credential` · `no-independent-model` · `unclassifiable-catalog` · `no-transport` · `cli-absent` · `gemini-call-failed`(뒤 7종 → 환경).
|
|
243
|
+
`probe-unseated status=<code>` 는 **프로브를 실제로 낸 뒤** 착석에 실패한 경우만이다. 목적지는 있는데 키 env 가 비어 프로브를 아예 못 낸 경우는 `no-credential` 이다 — HTTP 를 한 건도 안 내고 "프로브가 착석시키지 못했다"고 말하지 않는다.
|
|
244
|
+
`default-endpoint-off` 는 키가 있는데 저자가 `RALPH_QA_NO_DEFAULT_ENDPOINT` 로 목적지를 없애 좌석이 못 선 경우다 — 원인이 환경이 아니라 저자 설정이므로 `cli-absent` 로 흘리지 않는다.
|
|
245
|
+
직전 실행이 `INCONCLUSIVE` 인데 `--external=off` 로 우회했다면 그 사실을 보고에 남긴다.
|
|
246
|
+
`⬜` 는 실패 표시가 아니라 커버리지 표시다. `--external=off` 여도 `프로브(관측): 미실행 (--external=off)` 로 미실행 사실 자체를 적는다 — 줄 생략은 축약이다.
|
|
247
|
+
선언 블록은 프로브가 되받아 적는 값이므로 **"증거"라고 부르지 않는다**.
|
|
248
|
+
|
|
249
|
+
## 한계
|
|
250
|
+
|
|
251
|
+
- **백본의 reasoning effort 는 이 스킬이 호출 단위로 지정하지 못한다.** Agent 도구 스키마에 effort 파라미터가 없다. effort 는 **에이전트 정의의 프론트매터**(`effort:`)나 세션 설정에서 오고, banker 는 에이전트를 배포하지 않으므로(`.claude-plugin/plugin.json` 에 `agents` 없음) 백본이 띄우는 것은 남의 정의다.
|
|
252
|
+
그래서 백본은 모델만 선호 순서로 고르고 **실제로 쓴 것을 보고한다** — 목표를 약속으로 적지 않는다. 세션 강도를 올리는 것이 백본에 영향을 주는 유일한 손잡이이며, 최대 강도가 필요하면 **호출 전에 그것을 올려라.**
|
|
253
|
+
**에이전트 정의를 배포해 강도를 박는 길은 의도적으로 닫혀 있다.** `effort:` 프론트매터는 Claude 전용이라, 그 길을 열면 백본 강도가 런타임별로 갈려 이 스킬이 기대고 선 런타임 대칭이 깨지고 매니페스트의 "모든 표면이 양 런타임 대상" 성질도 무너진다. 사고가 아니라 결정이다.
|
|
254
|
+
- `--effort` 는 전송 경로가 실재하는 외부 좌석(api·codex)에만 적용된다. 백본 강도를 이 플래그로 바꿀 수는 없다.
|
|
255
|
+
- `--effort` 는 **전송 확인 / 적용 미확인**이다 — 값을 보냈다는 사실만 확인 가능하고 모델이 그것을 적용했는지는 응답에서 관측할 수 없다.
|
|
256
|
+
- 백본은 같은 베이스 모델이라 **모델-독립이 아니다**. 3축 표가 이를 숨기지 않을 뿐 해결하지는 않는다.
|
|
257
|
+
- **계열 회피는 독립성을 얻는 대신 모델 능력을 보장하지 않는다.** 자동 선택은 통과 후보의 카탈로그 순서를 따를 뿐 성능순이 아니라서, codex 를 피한 결과가 훨씬 작은 모델일 수 있다.
|
|
258
|
+
그럼에도 회피가 기본인 이유는 실증 필터가 비대칭이기 때문이다 — 약한 좌석의 근거 없는 반대는 `dissent-unsubstantiated` 로 걸러지고 파일·기준을 짚은 지적만 살아남으므로, 능력을 잃는 비용보다 맹점을 갈라 얻는 이득이 크다.
|
|
259
|
+
능력이 더 중요한 상황이면 `--model` 로 고정하라. 그 값은 회피보다 우선한다.
|
|
260
|
+
- 규칙의 상태(좌석 집합·끈끈한 반대·ERROR 카운트)는 **실행 단위**다. 새 실행은 상태를 리셋하며 이를 막을 수단이 없다.
|
|
85
261
|
|
|
86
262
|
## 함정
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
-
|
|
90
|
-
|
|
91
|
-
-
|
|
92
|
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
- **수용 기준 없이
|
|
96
|
-
|
|
97
|
-
ARGUMENTS: [--model <id>] [--effort
|
|
263
|
+
|
|
264
|
+
- **`codex login status` 와 `~/.codex/auth.json` 을 유효성 근거로 쓰지 마라.** 둘 다 거짓 음성이다 — `Not logged in` 을 exit 0 으로 답하면서 codex 가 정상 동작하는 경우가 있다(인증이 ChatGPT 로그인이 아니라 프로바이더 env 키에서 올 때). 유효성은 프로브의 HTTP 판정으로만 정한다.
|
|
265
|
+
- **`codex exec` 왕복을 프로브로 쓰지 마라.** 실측 25,478 토큰이다. 프로브가 검증보다 비싸면 도구가 아니다.
|
|
266
|
+
- **같은 계열 금지.** 저자와 같은 모델 계열을 외부 좌석에 앉히면 독립성이 없다. 계열 필터는 프로브의 상수 표가 강제하며 env 로 끌 수 없다. 미분류 계열은 fail-closed 로 제외된다.
|
|
267
|
+
- **외부 좌석 둘이 같은 모델이 되는 경로를 조심하라.** 저자의 codex 설정은 api 좌석의 선호 모델 출처이기도 해서, 회피가 없으면 `api:<X>` 와 `codex(<X>)` 가 나란히 앉는다. 좌석 수는 2인데 모델 축은 1이고, 게이트는 그대로인데 보고만 독립적으로 읽힌다.
|
|
268
|
+
- **`GET /models` 200 을 호출 권한으로 읽지 마라.** 카탈로그가 보인다는 것과 그 모델을 부를 수 있다는 것은 다르다. 계열 회피로 고른 모델이 첫 호출에서 거절되면 착석 전이므로 다음 후보로 갈아탄다(워크플로 2단계).
|
|
269
|
+
- **`ERROR` 를 드롭하지 마라.** 좌석을 지우면 정족수의 해당 연언항이 공허하게 참이 되어 게이트가 넓어진다.
|
|
270
|
+
- **`OPENAI_API_KEY` 가 OpenAI 키가 아닐 수 있다.** LiteLLM·OpenRouter·사내 게이트웨이 구성에서는 이 이름에 **다른 프로바이더의 키**가 들어 있고, base URL 은 보통 앱 설정에 있지 env 에 없다. 그 상태로 기본 엔드포인트로 내려가면 남의 키가 엉뚱한 벤더로 나간다. 그런 환경이면 base URL 을 env 로 명시하거나 `RALPH_QA_NO_DEFAULT_ENDPOINT` 로 끈다. `GOOGLE_API_KEY` 계열도 Maps·Translate 등 범용 키 이름이라 같은 성질이 있다.
|
|
271
|
+
- **수용 기준 없이 검증하지 마라.** 검증 가능한 기준 대비 판정이어야 한다.
|
|
272
|
+
|
|
273
|
+
ARGUMENTS: [--agents=N] [--external=auto|off] [--model <id>] [--effort <v>] [--lens=critic|plan|both] [--max=N] [검증 대상/기준]
|