Skip to content

v0.2.22 — 광고한 계약을 실제로 지키게 한다

Choose a tag to compare

@xzawed xzawed released this 06 Sep 03:12
· 7 commits to main since this release
dca344d

v0.2.22 — 광고한 계약을 실제로 지키게 한다

2026-09-06. 같은 날 v0.2.21이 기능 감사 큐(A7~A20)를 비운 뒤, 문서·코드 전수 감사를 돌렸다.
질문이 달랐다 — "각 기능이 동작하는가"가 아니라 "우리가 광고한 계약이 실제로 지켜지는가".
찾은 3건 중 A23은 발견과 동시에 닫혔고, 이 릴리스가 나머지 둘이다. 유닛 555 → 568.


1. 9개 중 8개 도구가 자기가 광고한 스키마를 지키지 않았다 (A21)

9개 도구 전부가 스키마에 additionalProperties: false를 싣는다. 실제로 거부하던 것은
grok_build_route 하나뿐이었다
— A1이 .strict()를 붙인 그 도구다. 나머지 8개는 미지의 키를
받아들이고 조용히 벗겨냈다. 즉 필드 이름을 오타 내면, 그 필드가 없는 채로 호출이 성공한다.

실사용 피해를 끝까지 쟀다. throwaway git repo에서 worktreee(e 3개)로 delegate:

before: isError false · status completed · worktreePath 없음 · filesChanged ["typo-probe.txt"]
        → 격리를 요청했는데 grok이 사용자의 작업 디렉터리를 직접 고쳤고, 응답은 성공이라 말한다
after : isError true · unrecognized_keys: ["worktreee"] · 작업 디렉터리에 아무것도 쓰이지 않음

안전 강등은 두 필드다. 처음엔 worktree뿐이라고 썼는데 Grok이 반증했다sandbox
같은 모양이다(오타 → --sandbox 미전달 → 프로파일 없이 실행). 확인해 보니 delegate.ts:391
실제로 플래그를 넘기고 Linux/macOS는 커널이 강제한다. 지적이 맞았고, 그래서 이 릴리스의 근거가
하나 더 늘었다. 나머지(timeout_ms·model·effort·resume·continue)는 취향이 무시될 뿐
보호가 사라지지는 않는다.

오차단 위험은 추측하지 않고 쟀다. MCP 스펙대로 params._meta에 실린 메타데이터는 이미
strict였던 route에서도 통과하고, arguments 안에 잘못 넣은 경우만 거부된다 — 스펙을 지키는
클라이언트는 영향이 없다. 배포 표면도 확인했다: examples/orchestrator-consumer.md(문서화된
기계 소비자)가 보내는 것은 task·signals·metered_billing·prompt·cwd·worktree뿐이고
전부 스키마 안에 있다.

Grok 정적 검증: .strict()가 바꾸는 것은 미지의 키 하나뿐이다. 음수 timeout_ms도, null
값도 전에도 후에도 똑같이 거부된다(BEFORE/AFTER 5행 대조, CLAIM_CONFIRMED).

새 도구를 추가할 때 .strict()를 빠뜨리지 말 것 — 광고하는 스키마와 강제하는 스키마는 같은
스키마여야 한다. 그 이유를 server.ts 등록부 맨 위 주석에 적어 두었다.

2. redactSecrets가 npm 토큰을 놓쳤다 (A22)

튜닝에 쓰지 않은 코퍼스로 재측정했다: 시크릿 18종 중 16종 마스킹, prose 12종 중 0종 훼손.
이전 라운드에서 Grok이 잡았던 과교정(api_key: required 류를 망가뜨리던 것)은 완전히 사라진 상태였다.
새는 것은 npm_... 하나였다.

절대 원칙 #4가 이미 "마스킹은 완화이지 보장이 아니다"라고 못박고 있으므로 계약 위반이 아니라
커버리지 한 칸이다. A6이 같은 종류를 같은 방식으로 닫았으므로 같은 방식으로 닫았다.

before: //registry.npmjs.org/:_authToken=npm_AbCdEf0123456789AbCdEf0123456789Ab
after : //registry.npmjs.org/:_authToken=<redacted>

레지스트리 호스트는 남는다 — 행을 통째로 지우는 마스킹은 누군가 결국 꺼 버린다(A6의 판단 그대로).

30자 하한이 이 규칙의 전부다. npm_은 흔한 식별자 접두사이고(npm_config_registry,
npm_package_version, npm_lifecycle_event), 하한이 없으면 A6 라운드의 과교정을 그대로
재현한다. 그 세 개를 회귀 테스트로 박았다. Grok 정적 검증도 같은 결론이다 — 실토큰 2행만
매치하고 환경변수 3행은 매치하지 않는다.

재측정 최종: leaked 0/17 · mangled 0/15.

⚠️ 처음엔 새는 것이 둘로 보였다. 다른 하나(ssh-rsa AAAA...)는 제 시험 케이스가 틀린
이었다 — 공개키는 시크릿이 아니고, 그걸 가리는 것이야말로 과교정이다. 나중에 누가
"고치지" 않도록 테스트로 못박았다.

3. 같은 감사에서 발견과 동시에 닫힌 것 (A23)

prompt-flags.ts가 CLAUDE.md 컴포넌트 지도에서 빠져 있었다(19개 중 18개만 적혀 있었다).
장식이 아니다 — hook.tsgrok-cli.ts가 둘 다 import 하고, hook 번들에 delegation 엔진이
딸려 들어오지 않게 하려고 일부러 떼어낸 리프 모듈
이다(v0.2.20). 지도만 보고 일하는 다음
세션은 그 의도를 못 본다. 한 줄이라 v0.2.21 감사 기록 커밋에서 바로 닫았다.


감사가 확인한 것 (다시 열지 않도록)

  • 도구 9개·커맨드 27개 수치가 주장되는 모든 곳에서 일치
  • 모든 live 입력 필드가 docs/04자기 도구 섹션에 문서화됨
  • 모든 /grok:<verb> 참조에 커맨드 파일 존재, 배포 표면에 없는 도구 이름 0건
  • 값 수준 검증은 원래 견고했다action은 진짜 enum(obliterate 거부), 타입 불일치와
    음수 limit도 거부. 새던 것은 미지의 키뿐이었다
  • 절대 원칙 10개가 소스와 번들 양쪽에서 성립(과금 env 정제 · --no-auto-update ·
    --always-approve/plan · exec 문자열 조립 없음 · 자격증명 미기록 · 자동 커밋 없음 ·
    hook 번들에 엔진 없음 · porcelain -z · 시간 제한)
  • 계약 §6을 오늘 다시 쟀다 — grok 1.0.13은 여전히 --permission-mode plan을 무시하고 파일을
    썼다. planWroteFiles 방어는 그대로 필요하다

자동 검사 1차 결과 24건은 전부 정규식 오탐이라 보고에서 뺐다 — grok_error·
grok_not_installed는 도구가 아니라 status 값이고, 끊긴 링크는 전부 "SHIPPED — historical
record"
배너가 붙은 문서 안에 있었다.

손대지 않은 것

docs/10 C 섹션(실측으로 견고함)과 B 섹션(측정 불가 5건)은 그대로다. B4(GUI 슬래시 커맨드
경로)는 오너가 Claude Code를 재시작한 뒤 /grok:status 한 번으로 닫힌다.