Skip to content

v0.2.19 — 서비스 감사가 찾은 네 가지 실패

Choose a tag to compare

@xzawed xzawed released this 05 Sep 12:57
· 13 commits to main since this release
4960ae7

v0.2.19 — 서비스 감사가 찾은 네 가지 실패

2026-09-05. 배포 번들(0.2.18)을 stdio로 직접 구동해 53개 기능 항목을 실행하고 각 항목을
독립 재실행자가 재측정했다. PASS 29 · DEGRADED 20 · FAIL 4. 이 릴리스는 그 FAIL 4건이다.

핵심 안전 계약(구독 과금 보장, 자동 커밋 금지, worktree baseDir 가드, spawn 이전 검증)은
메커니즘 수준에서 전부 통과했다 — 실패는 그 바깥에 있었다.


1. /grok:plan이 read-only가 아니었다

빈 디렉터리에 plan을 돌리면 파일이 생성됐고, 응답은 filesChanged: []였다. 쓰고서 안
썼다고 보고한 것이다.

귀속을 갈랐다. 플러그인은 --permission-mode plan을 정확히 넘긴다(delegate.ts).
플러그인 없이 grok을 직접 돌려도 파일이 생겼다 — grok CLI 1.0.13이 그 플래그를
무시한다.
계약 §6이 1.0.3에서 기록한 동작의 회귀다. 이어서 측정한 결과:

시도 결과
--permission-mode plan 파일 생성
--sandbox read-only 파일 생성
--sandbox strict 파일 생성
--always-approve 생략 파일 생성 (Grok 확인)

즉 1.0.13에는 쓰기를 막는 플래그가 없다. 봉쇄 수단은 격리뿐이다.

플러그인은 막을 수 없으므로 숨기지 않기로 했다(오너 결정). plan 런도 delegate와 같은
before/after porcelain 차집합으로 filesChanged를 채운다. 그리고 그것만으로는 부족하다 —
Grok이 설계 리뷰에서 반박했듯, 경로 차집합은 이미 더티했던 파일의 추가 편집을 놓친다
(before === after). plan-before-delegate가 정확히 그 케이스다. 그래서 git diff HEAD 해시를
함께 비교한다.

응답에 planWroteFiles가 붙는다 — true(변경됨, 경고 message 동반) / false(변경 없음 확인) /
생략(cwd가 git 저장소가 아니라 확인 불가). 마지막 경우를 false로 적지 않는 것이 요점이다.
tool 설명에서 "WITHOUT editing any files" 약속도 내렸다.

2. 라우터의 보안 판정이 영어에만 있었다

9개 규칙 중 security 한국어 대체어가 없었다. UI 전체가 한국어인 제품에서, 하필
최고 위험 신호가.

입력
운영 서버의 인증 토큰 발급 로직을 바꿔라 MEDIUM HIGH / claude
(같은 뜻 영어) HIGH HIGH
운영 데이터베이스의 비밀번호 해시를 argon2로 마이그레이션 LOW / delegate HIGH / claude

3. 맨 bulk 동사가 파괴적 운영 작업을 통과시켰다

migrate the production customer database … and drop the old columnsLOW /
grok_build_delegate
, 인간 게이트 없음. migratebulk를 켜고, bulk 신호는 약한 LOW
강등을 건너뛴다. productiondrop도 신호 집합에 아예 없었다.

destructive·production 두 신호를 추가했다:

  • 둘 다 → HIGH. worktree 격리는 파일 편집만 되돌린다 — 삭제된 컬럼은 돌아오지 않는다.
  • 하나만 → MEDIUM 바닥. bulk 신호가 있어도 내려가지 않는다.
  • 명시 signalsfalse를 보내도 본문이 그렇게 말하면 꺼지지 않는다 — 모든 필드를 채우는
    구조체 직렬화(omitempty 없는 Go, Python asdict)가 세션 내내 안전망을 끄는 것을 막는다.

Grok이 첫 초안을 반박했고, 양방향 모두 실측으로 재현됐다.

  • 너무 넓었다. 드롭드롭다운 안에서, 초기화가 "폼 상태 초기화" 안에서, 맨
    purge가 "purge unused CSS" 안에서 발동했다. 한국어는 단어 경계가 없어 짧은 어간은 구조적으로
    부분일치 함정이다 — 짧은 어간을 버리고 목적어를 요구하는 형태로 바꿨다
    (테이블·디비·DB·데이터베이스·버킷·인덱스 뒤에 오는 삭제/드롭만 잡고,
    초기화는 2차 라운드에서 데이터베이스 목적어로 더 좁혔다).
  • 너무 좁았다. 실제 인프라 파괴가 취하는 형태 — terraform destroy, kubectl delete namespace, aws s3 rb, dropdb — 가 하나도 안 잡혔다. migrate 40 files then terraform destroy against the prod workspaceLOW/delegate였다. 그리고 운영 리소스는 산문이 아니라
    식별자로 등장한다(prod-customer-backups, customer_live) — 그것도 추가했다.

그리고 2차로 다시 반박했다 — "출하 부적합" 판정. 이번엔 더 현실적인 반례였다:
목차 테이블 드롭다운(테이블 + 드롭다운), zod 스키마 초기화, 비프로덕션(= NON-production인데
프로덕션을 포함), go-live checklist, 그리고 delete all unused imports — 마지막은 흔한
정리 작업이다. 미탐 쪽도 운영 DB(디비가 아님)·테이블은(조사 은/는)·pulumi destroy·
rails db:drop·rm -fr가 남아 있었다.

고친 방식은 키워드 추가가 아니라 문법을 요구하는 것이다:
초기화는 데이터베이스에만, 삭제 동사는 데이터 목적어를 요구(코드 삭제는 제외),
드롭(?!다운) 부정 전방탐색, (?<!비)프로덕션·(?<!non-)production 부정 후방탐색,
하이픈 식별자(go-live)는 제외하고 prod- 접두·_live 접미만, 조사 은/는/도와 DB 약어 추가.

최종 실측: Grok의 2라운드 반례 13건이 전부 올바른 등급이 됐고 기존 케이스는 불변이다.

4. 같은 디렉터리가 대시보드에서 여러 프로젝트로 갈렸다

cwd 필터가 정확한 문자열 일치였다. 실제 1779행 이력에서 386행(21.7%)이 가려졌다.

f:\DEVELOPMENT\SOURCE\CLAUDE\SCAManager   377건
F:\DEVELOPMENT\SOURCE\CLAUDE\SCAManager    79건
f:/DEVELOPMENT/SOURCE/CLAUDE/SCAManager    37건
                                    → 493건 (수정 후, 네 표기 모두 동일)

성공률도 72.7% / 36.7% / 40.5%로 갈렸다. 구분자·후행 슬래시는 어디서도 의미가 없고,
대소문자는 win32에서만 접는다 — POSIX에서 접으면 /srv/A/srv/a가 합쳐진다.


바뀐 것

파일 변경
src/routing.ts 한국어 보안 키워드, destructive·production 신호, HIGH/MEDIUM 게이트, 위험 신호 OR 병합
src/delegate.ts defaultGitDirtyFingerprint, plan 런의 before/after 스냅샷, planWroteFiles
src/usage.ts normalizeCwd + 두 필터 지점
src/types.ts · src/server.ts planWroteFiles 필드, plan tool 설명 정정
docs/specs/grok-cli-contract.md §6 — plan 모드 쓰기 방지 실패 (§6 행 2026-09-05)
docs/04 · docs/05 · commands/plan.md plan 계약·위험 조건 갱신

검증

  • npm test 407 passed / 1 skipped (v0.2.18 시점 382 — 회귀 25건 추가)
  • npm run typecheck, npm run build — 번들 2개 재생성
  • 라이브 재현: 수정 전 filesChanged: [] 침묵 → 수정 후 planWroteFiles: true + 경고
  • cwd 4가지 표기 → 전부 493건 / 64.5%로 일치
  • 라우팅 스윕 2라운드 — Grok 반례 포함 전 케이스에서 위험 LOW 0건, 정상 오탐 0건