@kaydash9999/banker-plugins 0.12.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.
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Claude Code skills + commands — QA, audit, docs, architecture, dependency setup, and wiki; the banker plugin marketplace.",
9
- "version": "0.12.0"
9
+ "version": "0.13.0"
10
10
  },
11
11
  "plugins": [
12
12
  {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "banker",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Claude Code plugin: QA/audit/docs/architecture skills + commands, a /banker:setup installer for OS dependencies (playwright, etc.), and wiki compaction.",
5
5
  "author": {
6
6
  "name": "smallOpenSource",
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.13.0] - 2026-08-12
4
+
5
+ ### Changed
6
+ - **`ralph-qa` 의 검증자 구성을 "우선순위 사다리"에서 "백본 + 좌석"으로 뒤집었다.**\
7
+ 이전에는 Codex CLI → 다른 모델 `curl` → 다중 에이전트 순으로 **사용 가능한 첫 경로 하나**만 썼고, 다중 에이전트는 다른-LLM 경로가 전무할 때만 도는 최종 수단이었다. 이제 **다중 에이전트 백본(`model: opus`, `--agents` 기본 3)이 조건 없이 항상 돌고**, 설치돼 있으면서 실제 유효성이 관측된 외부 LLM(Codex CLI · Gemini CLI · GPT/Gemini API)만 **각 1좌석**으로 합류한다. 외부 좌석의 부재는 실패나 열화가 아니라 "모델 축이 이번 실행에서 안 덮였다"는 커버리지 사실이다.\
8
+ 유효성은 **0토큰 HTTP 프리플라이트**(`references/verifier-probe.mjs`, provider `GET /models`)로 판정한다 — 설치 여부(`command -v`)와 유효 여부는 다르고, `codex login status`·`~/.codex/auth.json` 은 **거짓 음성**이라 근거로 쓰지 않는다(둘 다 미로그인이라 답하면서 codex 가 정상 동작하는 경우가 있다). 검증 실호출을 프로브로 쓰면 왕복 1회에 2만 토큰이 넘게 든다.\
9
+ 정족수는 좌석 **생애주기 전체**에 단조성을 건다: `내부 좌석 ≥ 1 ∧ 내부 과반 ∧ 실증된 외부 비-APPROVE 0 ∧ 미해소 blocker 0 ∧ ERROR 0 ∧ 좌석 상실 0`. 좌석 식별자를 `(종류, 렌즈)` 로 정의하고 반복 간 `S_k ⊆ S_{k+1}` 을 요구해 **좌석을 새로 굴려 반대를 지우는 경로**를 닫았고, 종결에 `INCONCLUSIVE` 를 더해 좌석이 사라지는 모든 경우를 APPROVE 밖으로 배출한다. `INCONCLUSIVE` 는 통과가 아니며 원인별 다음 행동이 규정된다.
10
+ - **`--effort` 를 외부 좌석(api·codex) 전용으로 축소했다.** 이전 표기는 전 경로에 적용되는 것처럼 보였지만 실제로는 아무 데도 전달되지 않았다.\
11
+ 백본 쪽 사정은 이렇다: **호출 단위** 지정 경로는 없고(Agent 도구 스키마에 effort 파라미터가 없다), effort 는 **에이전트 정의의 프론트매터**(`effort:`)나 세션 설정에서 온다. banker 는 에이전트를 배포하지 않으므로(`.claude-plugin/plugin.json` 에 `agents` 키 없음) 백본이 띄우는 것은 남의 정의이고, 따라서 이 스킬이 백본 effort 를 정할 수 없다. 백본에 실제로 영향을 주는 손잡이는 호출 전 **세션 effort** 뿐이며 SKILL.md 가 그렇게 안내한다.\
12
+ 플래그 표에 `전송 경로`·`확인 수준` 두 열을 두어, 전송 경로 칸을 채울 수 없는 능력은 표에 적지 못하게 했다.
13
+ - **백본의 모델을 선호 순서로 고르고, 실제로 쓴 것을 보고하게 했다.** ① Opus 계열 최신 → ② 없으면 가용한 것 중 가장 적합한 추론 모델 → ③ 그마저 없으면 기본값.\
14
+ **추론 강도는 이 사다리에 없다** — Agent 도구 스키마에 effort 파라미터가 없어 호출 단위로 지정할 수 없고, 강도는 세션 설정에서 물려받는다. 최대 강도가 필요하면 호출 전에 세션 강도를 올리는 것이 유일한 손잡이다.\
15
+ 보고에 `백본(선언): model=<실제 쓴 모델> — 모델 선호 <1|2|3>순위 · strength=세션 상속` 줄이 강제된다. 목표를 약속으로 적고 실제를 감추지 않기 위한 것이다.
16
+ - **외부 좌석끼리도 모델이 겹치지 않게 했다.** 저자의 codex 설정(`~/.codex/config.toml` 의 `model`)은 api 좌석의 선호 모델 출처이기도 해서, 그대로 두면 `external:api:<X>` 와 `external:codex`(같은 `<X>`)가 나란히 앉는다 — 좌석은 2인데 모델 축에서는 하나다. 승인 게이트가 넓어지지는 않지만(좌석이 늘면 APPROVE 는 더 어려워진다) 보고의 "외부 2" 가 두 개의 독립 검사로 읽히므로, 이 스킬이 defect 로 다루는 보고 정직성 문제다.\
17
+ 이제 codex 좌석이 서면 api 좌석은 **codex 가 돌릴 모델의 계열을 피해서** 고른다. 사다리는 `다른 계열 → 같은 계열의 다른 모델 → 같은 모델` 이고 내려간 단은 `modelPick` 으로 보고된다. codex 의 모델을 확인하지 못하면 fail-closed 로 codex 런타임 계열을 피한다.\
18
+ 대가는 명시한다 — 자동 선택은 카탈로그 순서를 따를 뿐 성능순이 아니라서 회피 결과가 더 작은 모델일 수 있다. 능력이 더 중요하면 `--model` 로 고정하며, 그 값이 회피보다 우선한다. 또한 `GET /models` 200 은 카탈로그 접근만 증명하므로, 고른 모델이 첫 호출에서 거절되면 **좌석 확정 전**이라 다음 후보로 갈아탄다(확정 후의 실패는 `ERROR` 이고 모델을 바꾸면 좌석 상실이다).
19
+ - **`--external=auto|off` 를 신설**하고 `--agents` 를 백본 상시 파라미터로 승격했다. 폐기한 플래그는 없다.
20
+
21
+ ### Added
22
+ - **gemini 모델 크리덴셜 좌석(`external:gemini-api`)을 CLI 좌석과 분리했다.** 처음 구현은 gemini 좌석을 CLI 존재 여부로 먼저 걸러서, 유효한 키가 있어도 CLI 가 없으면 좌석이 0이 되고 사유가 `cli-absent` 로 나갔다 — 그리고 그 토큰은 "모델 축이 환경 탓에 안 덮였다"로 매핑된다. **환경이 유효한 크리덴셜을 제공했는데 환경 탓으로 보고**하는 것이라, 이 스킬이 막겠다고 선언한 허위 커버리지였다. 이제 두 경로는 별개 좌석이고, 크리덴셜이 있으면 `cli-absent` 를 쓰지 않는다(생존 판정 실패는 `probe-unseated status=<code>`, 전송 수단 부재는 `no-transport`).
23
+ - `skills/ralph-qa/references/verifier-probe.mjs` — 의존성 0 · `node:http` 기반 유효성 프로브. provider 해석(`~/.codex/config.toml`), 0토큰 생존 판정, 상수 계열 필터(미분류는 fail-closed 제외), 전송 수단 탐지(`curl` → `python3` urllib ≥3.6 → `none`), 관측값(`observed`)과 선언값(`declared`) 분리 출력.
24
+
3
25
  ## [0.12.0] - 2026-08-09
4
26
 
5
27
  ### Added
package/README.md CHANGED
@@ -52,7 +52,7 @@ Claude Code는 `/banker:<이름>`, Codex는 `banker-<이름>` 으로 호출합
52
52
  | `ultra-init` | 프로젝트 기획이 충분히 구체적일 때 | 데모를 구현 |
53
53
  | `curation` | 질문에 답하기 어렵거나 의사결정이 어려울 때 | 합리적 선택지 제공 (`--perf` 옵션 = 품질 우선) |
54
54
  | `all-in-one` | 요건이 명확한 단계에서 | 계획 → 구현 → 검증 |
55
- | `ralph-qa` | 검증이 충분하지 않을 때 | 다중 Agent 논의 |
55
+ | `ralph-qa` | 검증이 충분하지 않을 때 | 다중 Agent 백본 + 유효한 외부 LLM 좌석 |
56
56
  | `smart-compact` | 컨텍스트 임계 초과로 맥락 단절이 걱정될 때 | 맥락을 더 잘 이어서 진행 |
57
57
  | `refresh-readme` | 프로젝트 배포 전 | README 최신화 |
58
58
  | `summary-wiki` | Agent가 아는 정보를 확인하고 싶을 때 | 요약 리포트 |
@@ -111,7 +111,7 @@ Claude Code는 `/banker:<이름>`, Codex는 `banker-<이름>` 으로 호출합
111
111
  | `refresh-git-ignore` | `.gitignore` 비파괴·반복가능 갱신 |
112
112
  | `omc-reference` | OMC/OMX 에이전트·툴·스킬 레퍼런스(양 런타임 병기) |
113
113
  | `curation` | 의사결정을 선택지·권고·확신수준으로 큐레이션(--perf=품질 우선) |
114
- | `ralph-qa` | 작업 결과를 다른 LLM·별도 세션으로 독립 교차검증 반복 |
114
+ | `ralph-qa` | 다중 Agent 백본이 항상 돌고, 실제로 유효한 외부 LLM 만 좌석으로 합류해 독립 검증 반복 |
115
115
  | `smart-compact` | 컨텍스트 임계 초과 시 위키·resume 저장 게이트 자동 무장 |
116
116
  | `deep-research` | 다중 소스 팬아웃 + 적대적 검증 인용 리서치 |
117
117
  | `ultra-interview` | 리서치 선행으로 사람 질문 최소화, 모호성 3% 이하까지 인터뷰 |
@@ -36,7 +36,7 @@
36
36
  { "name": "curation", "type": "skill", "target": "both", "reason": "decision-framing behavior (options/rec/confidence + --perf); no runtime deps; identical in both", "supportingFiles": [] },
37
37
  { "name": "deep-init", "type": "skill", "target": "both", "reason": "hierarchical AGENTS.md generation (port of OMC deepinit); runtime-agnostic fs+doc; subagents Claude=OMC/Codex=OMX", "supportingFiles": [] },
38
38
  { "name": "deep-research", "type": "skill", "target": "both", "reason": "fan-out + adversarial-verify web research (re-authored from bundled workflow); Claude WebSearch/Workflow, Codex OMX autoresearch; runtime-aware", "supportingFiles": [] },
39
- { "name": "ralph-qa", "type": "skill", "target": "both", "reason": "cross-LLM independent verify loop (ralplan+critic logic): prefers Codex CLI, else other model via curl, else self-spawned multi-agent consensus; runtime-aware", "supportingFiles": [] },
39
+ { "name": "ralph-qa", "type": "skill", "target": "both", "reason": "independent verify loop (ralplan+critic logic): multi-agent backbone always runs; externally-validated LLMs join as extra seats. Seat-lifecycle monotone gate (INCONCLUSIVE on seat loss) so adding or losing a seat can never widen it; runtime-aware", "supportingFiles": ["references/verifier-probe.mjs"] },
40
40
  { "name": "smart-compact", "type": "skill", "target": "both", "reason": "context-threshold compaction-hygiene gate (statusLine detect + hook bridge + assistant chain + TUI handoff); runtime-aware", "supportingFiles": [] },
41
41
  { "name": "visual-ralph", "type": "skill", "target": "both", "reason": "measured visual build loop (port of OMX visual-ralph); Claude ralph+visual-verdict+Stitch imagegen, Codex $ralph+$imagegen; runtime-aware", "supportingFiles": [] },
42
42
 
@@ -27,7 +27,7 @@ The generator (`banker setup --codex`) applies the rules below for `target: both
27
27
  - `visual-ralph` → OMX `$ralph`·`$imagegen`(+`omx imagegen continuation`)·Visual Verdict; Claude은 `ralph`+`visual-verdict`+Stitch/ccg imagegen.
28
28
  - `deep-init` → 서브에이전트 Claude=OMC explore/architect/writer, Codex=OMX worker/explore(부재 시 직접 수행). 순수 fs+doc.
29
29
  - `deep-research` → Claude 번들 워크플로/`WebSearch`, Codex OMX `autoresearch`/`best-practice-research`.
30
- - `ralph-qa` → 다른-LLM: Claude `omc ask codex`/`ccg`, Codex OMX `$ask`(Claude/Gemini).
30
+ - `ralph-qa` → 백본은 런타임 서브에이전트(Claude=Agent/Task `model: opus`, Codex=OMX 서브에이전트)로 양쪽 동일. 외부 좌석만 런타임별로 갈린다: Claude=`codex exec`/`omc ask codex`, Codex=`omx $ask claude`(Codex 런타임에서 `codex exec` 는 자기 자신이라 부적격).
31
31
  - `smart-compact` → Claude statusLine `context_window.used_percentage`+hook; Codex 신호 미확인 시 휴리스틱 폴백. TUI 3단(`/copy`·`/compact`·paste)은 유저.
32
32
  - `curation` → 런타임 무관(외부 의존 0, 양쪽 동일).
33
33
 
@@ -36,7 +36,7 @@ The generator (`banker setup --codex`) applies the rules below for `target: both
36
36
  - `audit-web-page`, `play-qa`, `ultra-ui-qa` — need playwright (install via `setup-playwright`).
37
37
  - `setup-playwright` — genericize the `/banker:setup` trigger phrasing for the Codex copy.
38
38
  - `visual-ralph` — needs an imagegen path (Stitch via `setup-stitch`, or `/ccg`/Gemini) + a frontend repo; static/live-URL reference works without imagegen.
39
- - `ralph-qa` — needs a *different* LLM provider auth (`omc ask codex` / OMX `$ask`); falls back to same-runtime `critic` if unavailable.
39
+ - `ralph-qa` — runs with no external dependency: the multi-agent backbone always runs, and external LLM seats join only when a 0-token probe observes them valid. Their absence is a coverage fact (model axis uncovered), not a degraded mode. A same-runtime `critic` is never substituted for an external seat — on Codex that would be GPT approving GPT, i.e. self-approval.
40
40
  - `deep-research` — needs web search/fetch (Claude WebSearch/WebFetch or bundled workflow; Codex OMX autoresearch).
41
41
  - `smart-compact` — Claude statusLine exposes context%; Codex signal unconfirmed → heuristic fallback; `/copy`·`/compact`·paste stay user-driven (TUI).
42
42
  - `obsidizer` — OMC-managed trees respect the 9-field frontmatter whitelist + reserved files + no-rename + bare `[[slug]]` links only; `aliases` are written in generic vaults only; Canvas sidecars and body-inline `::` are durable in-place; no `wiki_*` write dependency, `wiki_lint` read-only for verification. `--enable` is Claude-only (plugin-declared PostToolUse hook); Codex has no MCP tool hooks → honest no-op.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaydash9999/banker-plugins",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "banker — Claude Code + Codex CLI plugin (QA, audit, docs, architecture, wiki skills). Install via Claude Code marketplace, or `npm i -g @kaydash9999/banker-plugins` then `banker setup`.",
5
5
  "bin": {
6
6
  "banker": "bin/banker.js"
@@ -1,97 +1,273 @@
1
1
  ---
2
2
  name: ralph-qa
3
- description: "(banker) 작업 결과를 다른 LLM으로 독립 검증/개선 반복(자기승인 방지): Codex CLI 우선 → 없으면 GPT 등 다른 모델을 curl 로 직접 → 그것도 없으면 다중 에이전트 합의. 'ralph-qa'/'교차검증'/'다른 LLM으로 검증'/'독립 QA' 시 사용."
3
+ description: "(banker) 작업 결과를 자기채점하지 않게 독립 검증/개선 반복: 다중 에이전트 백본이 가장 강한 가용 모델로 항상 돌고, 실제로 유효한 외부 LLM(Codex CLI·Gemini CLI·GPT/Gemini API)만 추가 좌석으로 합류한다. 'ralph-qa'/'교차검증'/'다른 LLM으로 검증'/'독립 QA' 시 사용."
4
4
  ---
5
5
 
6
- # ralph-qa — 교차-LLM 독립 검증 루프
6
+ # ralph-qa — 독립 검증 루프 (백본 + 좌석)
7
7
 
8
- 방금 만든 작업 결과를 **같은 모델·같은 세션이 자기채점**하는 대신, **다른 모델**에 넘겨
9
- `ralplan --deliberate`(설계 optimal 검토)와 `ralph --critic=critic`(수용 기준 검증) 로직을 적용하고,
10
- 지적을 반영해 **APPROVE까지 반복**한다. 핵심 가치는 **독립성**(anti-self-approval): 저자와 검증자가
11
- 다른 모델이라야 편향·맹점이 드러난다.
8
+ 방금 만든 결과를 **같은 세션이 자기채점**하는 대신, 독립 좌석들에 넘겨
9
+ `ralplan --deliberate`(설계 최적성)와 `ralph --critic=critic`(수용 기준) 로직을 적용하고,
10
+ 지적을 반영해 **APPROVE까지 반복**한다.
12
11
 
13
- **검증자 우선순위 (한 줄 요약).** ① 다른-LLM CLI(**Codex CLI 우선**) → ② 다른 모델 직접 호출(`curl`,
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
- - 사소한 변경(교차-LLM 왕복 비용이 이득을 초과).
24
- - 어떤 독립 경로도 없을 때는 폴백(③ 다중 에이전트)이 있으나, 그마저 과하면 그냥 `critic` 한 번.
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
- 검증 대상 = {작업 결과 요약 + **수용 기준(acceptance criteria)** + 변경 파일 목록 + 관련 코드}.
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
- | `--model <id>` | 검증 LLM 모델 지정(경로 ①·②) | 환경/매핑 기본 |
81
- | `--effort xhigh` | effort 지원 모델에 전달 | 미지정 |
82
- | `--lens=critic\|plan\|both` | 적용 렌즈 | both |
83
- | `--agents=N` | 폴백(경로 ③) 에이전트 수 | 3 |
84
- | `--max=N` | 최대 반복 | 5 |
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
- - **경로 탐지 순서** — `command -v codex`(①) → 다른-모델 크리덴셜 유무(②, env/`config.toml` provider) →
90
- 둘 다 없으면 ③. "다중 에이전트"를 다른-LLM 이 있는데도 먼저 쓰지 말 것.
91
- - **curl 경로 auth** — 비대화형 셸은 `~/.bashrc` 미로드로 키가 없으면 `401`(스킬 문제 아님).
92
- `source ~/.bashrc` 후 호출. 엔드포인트/키/모델은 **환경값**으로만(하드코딩·커밋 금지).
93
- - **같은 모델 계열 금지(②)** — 저자와 같은 모델을 curl 로 불러오면 독립성이 없다. 계열이 다를 때만.
94
- - **모델명 하드코딩 금지** — 예시 모델 ID 를 리터럴로 박지 말고 파라미터화.
95
- - **수용 기준 없이 검증 금지** — "잘 됐나?"가 아니라 검증 가능한 기준 대비 판정.
96
-
97
- ARGUMENTS: [--model <id>] [--effort xhigh] [--lens=critic|plan|both] [--agents=N] [--max=N] [검증 대상/기준]
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] [검증 대상/기준]