grok v0.2.16 — 문서가 코드와 반대로 말하던 곳들
v0.2.16 — 문서가 코드와 반대로 말하던 곳들
2026-09-03. 세 번째 스윕은 결함이 아니라 드리프트를 찾았다. 7개 렌즈(로드맵 · 범위문서 ·
릴리스노트 · 계약 스펙 · 코드 · 테스트/CI · 문서와 소비자 키트)로 전수 스윕한 뒤, 후보 33건을
"이미 닫혔다고 가정하고 반증하라"는 검증에 통과시켜 23건을 남겼다. 그중 코드 동작을 바꾸는
것은 하나도 없었다 — 대신 사용자가 따라 하면 안 되는 안내와, 서로 다른 이야기를 하는 문서
세 벌이 나왔다.
이 릴리스가 범프인 이유는 배포되는 실행 표면 하나(commands/cli.md)가 바뀌었기 때문이다.
번들 쪽은 아니다 — esbuild가 주석을 제거하므로 소스 주석 재실측은 바이트를 바꾸지 않았고,
재빌드 후 실제 dist 델타는 두 파일 각각 버전 문자열 1행뿐이었다(git diff --numstat
실측). 캐시가 버전 키이므로, 실행 표면이 바뀐 이상 같은 번호로 재배포하지 않는다.
따라 하면 격리가 안 되던 안내 (README 두 벌)
두 README가 위험한 작업의 격리 방법으로 --worktree / --sandbox 플래그를 안내하고
있었다. 그런데 계약 문서(§6)와 delegate.ts:445-447 주석이 이미 적어둔 대로, grok 자신의
--worktree는 헤드리스 -p에서 no-op이고 이 래퍼는 그 플래그를 넘기지도 않는다
(실제로 붙는 것은 --sandbox 하나뿐이다). 격리는 tool 필드 worktree: true / sandbox: "…"로만
일어난다. 사용자가 실제로 읽는 표면이 또 한 번 뒤처져 있었다 — v0.2.13의 auth 우선순위 사고와
같은 유형이다.
코드와 반대로 적혀 있던 스니펫
docs/01·docs/04의 spawn 예시가 아직-p prompt였다. 코드는 v0.2.13에서
--single=${prompt}로 바뀌었다 — clap이 bare 옵션 값으로-로 시작하는 문자열을 거부해
"- Refactor …" 같은 프롬프트가 exit 2로 죽었기 때문이다.docs/04의 이력 마스킹 서술이 v0.2.13 시절(“xAI 키 대입문만”)에 머물러 있었다. 실제
redactSecrets는 PEM 블록 → Bearer →password:류 대입 → xAI·AWS·GitHub·Slack·JWT
형태 순으로 덮는다. 완화이지 보장이 아니라는 단서도 함께 넣었다.docs/04의GrokCliResult에 v0.2.14가 추가한stdoutTruncated/stdoutTotalChars가 없었다.docs/03의plugin.json예시 버전이0.2.11이었다. 이 스니펫은 버전 일치 테스트 밖이라
구조적으로 낡는다는 사실을 문서에 명시했다.docs/06의[~] check-auth체크박스는 삭제된 커맨드를 가리키고 있었다. 그 커맨드는
/grok:setup에 흡수됐고 done 정의의 네 실패 모드는 전부 코드에 있다.
같은 사실을 세 방향으로 말하던 문서
세션 만료 신호가 "왜 미검증인가"에 대해 docs/06은 개발 머신 keyring 폴백 탓,
docs/02는 정밀 앵커는 추후, docs/06의 다른 줄은 앵커 완료라고 적고 있었다.
2026-09-02 실측(계약 §8)은 그중 어느 것도 아니라고 말한다 — 격리 홈(GROK_HOME) 아래에는
폴백이 없다. 이번에 1.0.13에서 재확인했다: 유효한 ~/.grok/auth.json이 그대로 있는
상태에서 GROK_HOME=<tmp> grok models는 "You are not authenticated."를 낸다.
그래서 진짜 이유로 고쳤다: 재현되지 않는 것은 만료(≠부재)이고, 그것은 실계정과 시간
경과가 필요하다. 2026-07-25-auth-unauth-signals.md에도 그 노트의 HOME/USERPROFILE 방식이
격리가 아니라는 포인터를 달았다.
새로 실측한 것 — resume × sandbox (계약 §11)
tool은 resume과 sandbox를 각각 옵셔널로 받아 같은 argv에 싣는다. 그 조합을 재본 적이
없어서 재봤다(1.0.13):
grok --resume <id> --sandbox read-only → exit 1, stdout 0바이트, stderr:
"cannot resume this session under sandbox profile 'read-only' — it was created with 'workspace'."
grok --resume <id> --sandbox workspace → end_turn (같은 프로필은 허용)
grok --resume <id> → end_turn (저장된 프로필로 재개)
세션의 sandbox 프로필은 수명 동안 고정이다. 래퍼에서는 빈 stdout이 파싱 실패로 이어져
grok_error가 되지만, grok의 안내 문구가 rawStderrTail에 그대로 실린다(191자, 500자 컷
안). 호출자가 무엇을 고쳐야 하는지 받는다 — 그래서 별도 가드를 넣지 않았다. 재현 절차와
근거는 계약 §11과 sandbox 스펙에 남겼다.
실행 표면 — /grok:cli의 잘림 분기
commands/inspect.md는 v0.2.14부터 stdoutTruncated를 다루지만, 같은 크기의 출력을
통과시키는 /grok:cli 패스스루는 여전히 stdoutTail을 전체로 제시하라고 지시하고 있었다.
컷은 4,000자이고 inspect --json은 ~81 KB로 실측됐다. 잘렸을 때는 꼬리임을 밝히고
stdoutTotalChars를 인용하며 통째로 파싱하지 말라는 분기를 넣었다. 길이 실측이 없는 나머지
커맨드는 근거가 없어 건드리지 않았다.
소스 주석 — 1.0.5 스탬프를 1.0.13에서 재측정
세 곳이 "measured on 1.0.5"라고 적혀 있었지만 계약 문서의 해당 절은 1.0.13이었다. 세션 도중
CLI가 스스로 갱신된 흔적이다. 역사적 귀속을 추측하는 대신 오늘 다시 쟀다 — 세 주장 모두
1.0.13에서 그대로였다.
env.ts—GROK_HOME전면 이전 + 폴백 없음: 재확인.delegate.ts— 확인 프롬프트와 stdin: 격리 홈에서memory clear가 열린 stdin 아래서는
10초 상한까지 매달렸고, stdin이 EOF면 프롬프트를 찍은 뒤 "Cancelled."로 1초 만에 exit 0,
파일은 그대로였다. 헤드리스에서 stdin을 닫아두는 이유가 그대로 성립한다.grok-cli.ts— 값-플래그 목록: 사라진 항목 없음. 더해서-r/--resume·-w/--worktree가
옵셔널 값을 받는다는 것을 명시했다. 목록에 넣으면 자기 것이 아닌 토큰을 삼킬 수 있어
일부러 빼둔 것이고, 빠져 있으면 파싱이 "불확실"로 판정돼 fail CLOSED 된다.
복구 — v0.2.13이 가리키던 "세션 보고서"
docs/releases/v0.2.13.md는 감사 방법과 전체 목록의 원천으로 "세션 보고서"를 가리켰는데,
그런 파일은 레포에 없었다. 실제 원천은 그 세션이 발행한 감사 리포트 아티팩트였고,
CHANGELOG.md가 "반증 4건도 기록에 남겼다"고 적은 그 4건도 레포 어디에도 열거돼 있지
않았다. 아티팩트에서 되살려 릴리스 노트에 표로 옮겼다 — filesChanged: [] 계약, 중복 probe,
hook 모드 불일치, security: false 우선순위. 이제 레포만 읽고도 자립한다.
닫힌 채로 열려 있던 항목
CLAUDE.md가 "사람이 해야 할 미해결 2건"으로 이월하던 것 중 Dependabot 경보는 이미
닫혀 있었다 — state=open 0건, 전체 21건이 fixed. 남은 SCAManager 토큰 항목은 서술
자체가 CHANGELOG.md(PR #53)와 충돌했다: 그쪽은 발급처 revoke로 모든 사본이 무력해졌다고
기록한다. 사실 관계를 CHANGELOG에 맞추고, 귀속 오류(v0.2.13이 아니라 PR #53, 그리고 v0.2.13이
손댄 것은 토큰이 없는 install-hook.sh)도 정정했다. 남은 것은 사람이 발급처에서 한 번
확인하는 일뿐이다.
검증
npm test·npm run typecheck·npm run build— 번들 2개 재생성- 실측: grok 1.0.13 (5e9a58528b76), Windows 11.
--help전수,GROK_HOME격리 probe,
memory clearstdin 두 경로, resume × sandbox 4조합 - Grok 교차검증: 아래 "반증된 것도 남긴다" 참고
반증된 것도 남긴다
스윕이 올린 후보 중 7건은 검증에서 죽었다. 되살리려면 이 근거부터 반박해야 한다.
| 죽은 후보 | 왜 아닌가 |
|---|---|
| 오케스트레이터 실배선이 이 레포의 열린 잔여다 | 계약·grok_build_route·픽스처·소비자 키트가 전부 존재한다. 남은 것은 소비자 레포의 일이며 docs/09 §4.A가 이미 그렇게 분류했다 — 이 레포 PR로 닫히지 않는다. |
docs/09가 "버전을 박지 말라"면서 v0.2.x를 박아둔 자기모순 |
제안된 수정이 handoff-version.test.ts를 깨뜨린다. 15행은 게이트가 강제하는 자리, 19행은 가드가 없는 자리로 역할이 다르다. |
| 이력 마스킹 패턴을 Google·Stripe·Azure 등으로 확대 | v0.2.14가 근거와 함께 "하지 않는다"를 결정했다(과잉교정 전례: 프롬프트 45개 중 19개 훼손). |
CHANGELOG.md를 버전 드리프트 가드에 포함 |
현재 드리프트 0, 그 가드가 막았을 실패 사례 0. repo-scope의 red flag에 정면으로 해당한다. |
| 계약 §10의 "유효한 실제 API 키 미측정"이 미해결 항목 | 문서가 안전상 미측정을 의도적 선택으로 기록했고, 그 결과와 무관하게 절대 원칙 #1이 성립한다고 명시했다. 추적 체크박스도 없다. |
| resume × sandbox 불일치에 코드 가드가 필요하다 | 실측 결과 grok의 안내 문구가 rawStderrTail로 그대로 전달된다. 문서화로 충분하다. |
| 2차 감사에서 반증된 6건(CI 부동 태그·히스토리 읽기 비용 등) | v0.2.14가 측정치와 함께 이미 반증했다(13.6 ms 대 362.8 ms 등). |