Skip to content

release: 0.6.1 — 진단이 인프라 실패를 초록불로 찍던 것 (mktemp · git 폴백) + 결정론 층까지 닿는 eval - #17

Merged
bluecheat merged 3 commits into
mainfrom
evals/hook-shim-scaffold
Sep 18, 2026
Merged

bluecheat merged 3 commits into
mainfrom
evals/hook-shim-scaffold

Conversation

@bluecheat

@bluecheat bluecheat commented Sep 18, 2026

Copy link
Copy Markdown
Owner

요약

claude plugin eval 이 goax 의 결정론 층(.ax/hooks · scripts) 을 실제로 재도록 만들었어요. 지금까지 세 케이스는 전부 .ax/ 없이 모델 프로즈만 재고 있었어요 (doctor 는 스크립트 없이 손 진단으로 1.0).

바뀐 것

  • tests/eval-hook-shim/ — 샌드박스는 프로젝트 .claude/settings.json 을 읽지 않아요 (probe 실측: 던지기 config 에 cwd trust 없음 → hook 마커 0). 플러그인 hooks/hooks.json 은 로드하고 ${CLAUDE_PROJECT_DIR} 도 샌드박스 cwd 로 잡혀요. 그래서 settings.json.template 의 hook 등록을 jq '{hooks: .hooks}' 로 그대로 뽑은 shim 을 scaffold 케이스가 plugins: 에 같이 실어요. smoke §46 이 shim ↔ 템플릿 동일성을 검사해요
  • evals/critical-canary/ — 프롬프트는 사용자 요청 한 문장. scaffold.shprovision.sh 로 설치하고 SP-SEC-001(critical · paths: src/** · 검출 패턴: 마커) 과 src/signup.ts 를 깔아요. 룰이 모델에 닿는 유일한 통로가 spirit-rules-inject.sh 라 Δ 가 hook 의 기여예요
  • evals/doctor-i6/ — 실제 설치 트리(wrapper 포함) + external:vitest 🔴 룰 하나, 트리거 없음. scripts-used(Bash 로 자기 스크립트 실행) · doctor-skill-called 지표 추가
  • check-rule-enforcement.sh I6 수정 — 출고 훅 제외 목록에 spec-completion-gate.sh 가 빠져 있어, git 저장소에 goax 를 설치한 모든 프로젝트에서 그 훅이 "프로젝트 전용" 으로 세어져 external 룰의 I6 가 영원히 통과했어요. 스캐폴드가 잡았고, smoke §47 이 목록 ↔ templates/default/.ax/hooks/pre-commit/ 대조 + "출고 훅만 → 발화 / 프로젝트 훅 추가 → 해제" 를 고정해요
  • evals/README.md — 실행 명령에 --scaffold 필수, 샌드박스 실측 표, 0.6.0 baseline, 열린 항목. repo CLAUDE.md 레이아웃에 한 줄

측정 — 1차 (0.6.0 · Claude Code 2.1.275 · judge haiku · runs 1/3/1)

케이스 runs with without Δ 지표
critical-canary 3 1.0 0.67 +0.33 injection-marker 3/3
doctor-i6 1 1.0 0 +1 scripts-used ✓ (Bash 22회) · doctor-skill-called
triage-first 1 1.0 0 +1 프롬프트 안 픽스처 — 변경 없음

이 판의 Bash 샌드박스가 스크립트 두 구멍을 드러냈어요: mktemp 가 죽자 check-rule-enforcement.sh 가 룰 0건으로 "all invariants pass" 를 찍었고, /usr/bin/git xcrun 셔틀이 죽자 C2 가 "미설치" 오탐 · I6 가 프로젝트 훅을 못 봤어요. 그리고 haiku judge 가 baseline 의 맞는 결론을 FAIL 로 찍어 Δ 를 부풀렸어요.

2차 커밋 (b96ab68) — 샌드박스가 드러낸 것 닫기

  • goax_mktemp [-d] [root] (common.sh) — mktemp → .ax/.session/tmp/ 폴백 → umask 077 순수 bash → 실패 시 1. mktemp 를 쓰던 5개 스크립트 + provision.sh 2곳(백업 디렉토리가 / 에 떨어져 MANIFEST 복사가 사용자 템플릿을 덮어쓰던 자리 — 리뷰가 잡음) 이 전부 헬퍼를 써요. exit 는 호출자에 — $(...) 안 exit 는 서브셸만 끝나요
  • goax_git_hook_path <root> <hook>rev-parse --git-path 가 죽으면 .git(디렉토리 · gitdir: 포인터 · linked worktree 의 commondir)과 .git/config core.hooksPath(따옴표·주석 제거 · [core] 대소문자 무시)를 직접 읽어요
  • smoke §48·§49 — 맨 mktemp · rev-parse --git-path 금지(주석 제외, provision.sh 포함) + 가짜 mktemp/git 셔틀로 폴백·error 경로·hooksPath·실제 worktree 고정
  • triage-first scaffold + shim — 프롬프트는 "결제 모듈에 환불 기능 추가해줘" 한 문장, triage-nudge.sh 까지 재요 (nudge-marker · triage-scripts-used)
  • 실행 명령에 --judge-model sonnet · 하드링크가 있으면 케이스 로드가 거부되는 것 README 에 기록

측정 — 2차 (Claude Code 2.1.276 · judge sonnet · runs 2 · 12런 · $9.29 · 877초)

케이스 with without Δ 발동 지표 (with-only)
critical-canary 1.0 (2/2) 0.5 (1/2) +0.5 injection-marker 2/2
doctor-i6 1.0 (2/2) 1.0 (2/2) 0 scripts-used 2/2 · doctor-skill-called 2/2 — 15·18턴 · $0.96·$1.10 (1차 24턴 · $1.55). without 1.0 은 sonnet judge 가 맞는 결론을 맞다고 찍은 것 — 1차의 +1 은 judge 오판이었어요
triage-first 1.0 (2/2) 0.5 (1/2) +0.5 nudge-marker 2/2 · triage-scripts-used 2/2 · triage-skill-called 2/2 — 1차의 +1 은 프롬프트 안 픽스처 효과였어요

샌드박스 안 폴백 직접 증거 (--case doctor-i6 --runs 1 --ablation none --keep-temp, 14턴 · $1.04): doctor 가 돌린 check-rule-enforcement.sh --jsonrule_count: 4 · I6 위반을 냈고, check-sensor-liveness.sh --jsongit_precommit_installed: true, 보존 cwd 에 .ax/.session/tmp/ 가 생겨 있었어요.

릴리즈 시 changelog 초안 (smoke 가 최신 changelog == VERSION 을 강제해서 여기 둬요)

  • I6 출고 훅 제외 목록에 spec-completion-gate.sh 누락 — git 저장소에 설치한 모든 프로젝트에서 external 룰의 I6 가 영원히 통과하던 것
  • check-rule-enforcement.sh 가 mktemp 실패 시 룰 0건으로 통과를 찍던 것 → goax_mktemp (5 스크립트 + provision.sh)
  • check-sensor-liveness.sh C2 · I6 가 git 이 못 돌면 오탐하던 것 → goax_git_hook_path
  • provision.sh 가 mktemp 실패 시 사용자 수정 템플릿을 백업 없이 덮어쓰던 것
  • evals: hook 미러 shim · scaffold 케이스 3개 · smoke §46–§49

테스트

  • bash tests/smoke.sh 전부 통과 (§46–§49 포함)
  • claude plugin eval . --runs 2 -j 2 --scaffold --allow-tools Bash Write Edit --no-publish --trust-plugin --judge-model sonnet --max-cost-usd 24 — 12런 전부 with 1.0
  • diff 리뷰 14건 반영 (HIGH 2 · MEDIUM 4 · LOW 8; #9 goax_mktemp_or_die 는 서브셸 exit 문제로 goax_tmp_error 헬퍼로 대체)
  • Bash grant 는 ~/.docker/{bin,cli-plugins} 심링크를 밖으로 옮겨야 돼요 (README 에 기록)

🤖 Generated with Claude Code

bluecheat and others added 3 commits September 18, 2026 18:25
…목록 수정

- claude plugin eval 샌드박스는 프로젝트 .claude/settings.json 을 읽지 않아요 (실측: UserPromptSubmit·PreToolUse·Stop 마커 0). 플러그인 hook 은 로드하고 ${CLAUDE_PROJECT_DIR} 도 샌드박스 cwd 로 잡혀요 → tests/eval-hook-shim 이 settings.json.template 의 hook 을 플러그인 hook 으로 미러하고, scaffold 케이스가 goax 와 함께 로드해요 (smoke §46 이 두 파일의 동일성을 지켜요)
- critical-canary: 룰은 프롬프트가 아니라 .ax/spirit/rules/security.md 에만, 도달은 pre-edit/spirit-rules-inject.sh 가 → Δ 0 → +0.33 (runs 3), injection-marker 3/3
- doctor-i6: provision.sh 로 실제 설치한 트리 + external:vitest 룰 하나 → 스캐폴드가 I6 누락을 잡았어요: 출고 훅 제외 목록에 spec-completion-gate.sh 가 빠져 git 저장소에 설치한 모든 프로젝트에서 I6 가 영원히 통과하던 것 수정 (smoke §47 이 목록 ↔ 출고 디렉토리 대조 + 발화/해제 고정). Bash grant 로 scripts-used 3지표 ✓
- evals/README: --scaffold 필수, 샌드박스 실측 표, 0.6.0 baseline, 열린 항목(mktemp 무음 초록 · git 샌드박스 오탐)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…t_hook_path + triage-first scaffold

evals PR(#17) 의 Bash 샌드박스 첫 실행이 스크립트 두 구멍을 드러냈어요. eval 이 잰 건 모델이 아니라 인프라였어요.

- `goax_mktemp [-d] [root]` — mktemp → `.ax/.session/tmp/` 폴백 → umask 077 순수 bash → 실패 시 1.
  `check-rule-enforcement.sh` 는 `set -e` 없이 `$(mktemp)` 이 죽자 빈 경로로 계속 가 룰 0건 검사 → "all invariants pass"
  를 찍었어요. mktemp 를 쓰던 5개 스크립트 + provision.sh 2곳(백업 디렉토리가 / 에 떨어져 MANIFEST 복사가
  사용자 템플릿을 덮어쓰던 자리) 이 전부 헬퍼를 써요. exit 는 호출자에 — `$(...)` 안 exit 는 서브셸만 끝나요
- `goax_git_hook_path <root> <hook>` — `rev-parse --git-path` 가 죽으면 `.git`(디렉토리 · `gitdir:` 포인터 ·
  linked worktree 의 `commondir`)과 `.git/config` `core.hooksPath`(따옴표·주석 제거, `[core]` 대소문자 무시)를 직접 읽어요.
  샌드박스에서 `/usr/bin/git` xcrun 셔틀이 죽어 C2 가 "미설치" 오탐, I6 가 프로젝트 훅을 못 봤어요
- smoke §48·§49 — 맨 mktemp · rev-parse --git-path 금지 + 가짜 mktemp/git 셔틀로 폴백·error 경로 고정
- `evals/triage-first` 를 scaffold + shim 으로 — 프롬프트는 요청 한 문장, `triage-nudge.sh` 까지 재요
  (`nudge-marker` · `triage-scripts-used` 지표)
- eval 실행 명령에 `--judge-model sonnet` — haiku judge 가 baseline 의 맞는 결론을 FAIL 로 찍던 것

측정 (2.1.276 · runs 2 · judge sonnet): critical-canary Δ +0.5 · triage-first Δ +0.5 · doctor-i6 Δ 0 (with 1.0, scripts-used 2/2 —
judge 오판이 사라진 것). `--keep-temp` 런에서 샌드박스 안 `rule_count: 4` · `git_precommit_installed: true` · `.ax/.session/tmp/` 생성 확인.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ToN3woaBzQfcmjWPAjGUh3
… eval

버전 4곳 0.6.1 동기화 + changelog/0.6.1.md. changelog/README.md 에 빠져 있던 0.6.0 항목도 같이 넣었어요.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ToN3woaBzQfcmjWPAjGUh3
@bluecheat bluecheat changed the title feat(evals): 결정론 층까지 닿는 eval — hook 미러 shim · scaffold 케이스 · I6 출고 훅 목록 수정 release: 0.6.1 — 진단이 인프라 실패를 초록불로 찍던 것 (mktemp · git 폴백) + 결정론 층까지 닿는 eval Sep 18, 2026
@bluecheat
bluecheat merged commit 647fd1e into main Sep 18, 2026
2 checks passed
@bluecheat
bluecheat deleted the evals/hook-shim-scaffold branch September 18, 2026 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant