AI CLI가 Dry-Run을 벗어나기 전에 실패 시 안전한 배포 카드 만들기
요약
AI CLI의 안전한 배포를 위해 '배포 카드(ship card)'라는 개념을 제안합니다. 이 카드는 JSON 파일 형태로 커밋되며, 게이트(gates), 증명 파일(proof files), 중단 규칙(stop rule) 등을 명시하여 AI가 생성한 코드가 실제 환경에 미치는 위험을 최소화하는 것을 목표로 합니다. 주요 내용은 경로 잠금, Dry-run 저장, 폭발 반경 제한, 종료 선언 등 네 가지 필수 게이트를 통해 안전성을 검증하는 워크플로우입니다.
핵심 포인트
- AI CLI의 배포는 '배포 카드'를 통해 안전하게 관리해야 합니다.
- CLI가 접근 가능한 경로와 쓰기 권한을 명확히 잠그는 것이 중요합니다 (Path lock).
- Dry-run 실행 결과(stdout, patch, exit code)를 반드시 증거로 저장해야 합니다.
- 최대 변경 파일 개수 등 '폭발 반경'을 제한하여 위험을 통제할 수 있습니다.
저는 녹색 'dry-run' 상태를 보고도 여전히 출시하는 것을 망설입니다. 테스트 케이스 하나가 통과했다고 해서 쓰기 모드(write-mode) 신호가 되는 것은 아닙니다. 오늘 밤 그 도우미가 공유 브랜치에 손대도록 허용하시겠어요?
단독으로 작동하는 CLI는 완성된 것처럼 보일 수 있지만, 여전히 실행하기에는 안전하지 않을 수 있습니다. 부족한 부분은 또 다른 기발한 프롬프트가 아니라, 저장된 증거입니다. 저는 그 잠시 멈춤을 위해 도구 옆에 '배포 카드(ship card)'를 두고 있습니다.
카드가 결정하는 것
이 카드는 CLI 옆에 커밋되는 작은 JSON 파일입니다. 이 파일은 게이트(gates), 증명 파일(proof files), 그리고 중단 규칙(stop rule)을 명시합니다. 만약 어떤 증명이 누락되면, 프로세스는 종료됩니다.
저는 모델에게 스스로를 축복해달라고 요청하는 것이 아닙니다. 로컬 스크립트가 실행을 거부하도록 요청하는 것입니다. 증명 파일이 누락되는 것을 여기서 기능으로 간주할 수 있을까요?
이것은 오늘 밤 복사하여 사용할 수 있는 템플릿입니다. 제 노트북에서 가져온 벤치마크는 아닙니다. 실제로 저장한 실행 기록의 모든 필드를 채우세요.
네 가지 게이트, 그리고 쓰기 모드
1. 경로 잠금(Lock the paths)
CLI가 읽을 수 있도록 허용된 모든 디렉터리를 명시하세요. CLI가 쓸 수 있도록 허용된 모든 파일을 명시하세요. 이 목록 밖에 있는 것은 범위를 벗어납니다.
저는 의도적으로 쓰기 목록을 매우 짧게 유지합니다. 전체 레포지토리에 손댈 수도 있는 도우미는 아직 준비되지 않았습니다. 왜 이렇게 일찍 전체 트리를 넘겨주나요?
2. Dry-run 저장(Save the dry-run)
쓰기를 비활성화한 상태로 도우미를 한 번 실행하세요. 표준 출력(stdout), 패치(patch), 그리고 종료 코드를 저장하세요. 이 세 파일을 'evidence' 디렉터리 아래에 넣으세요.
빈 evidence 디렉터리는 즉시 중단을 의미합니다. 채팅 로그는 검토할 수 있는 패치가 아닙니다. 이번에는 정말로 diff를 저장했나요?
3. 폭발 반경 제한(Bound the blast radius)
카드에 최대 변경 파일 개수를 설정하세요. 그 옆에 최대 추가 라인 개수도 설정하세요. 카드가 명시적으로 허용하지 않는 한 삭제는 거부하세요.
예상치 못한 이름 변경은 이 게이트에서 즉시 실패해야 합니다. 패치 내의 비밀스러운 모양의 문자열 역시 실패하게 해야 합니다. 반쯤 졸린 상태에서 그런 변경 사항을 병합하시겠어요?
4. 종료 선언(Declare the exit)
트리를 복원하는 정확한 명령어를 작성하세요. 전체 실험을 포기하는 조건을 작성하세요. 실행 환경이 사라졌을 때 무엇을 할지 작성하세요.
종료 계획이 없다는 것은 카드가 여전히 불완전하다는 의미입니다. 즉흥적으로 처리하기보다는 브랜치를 보류하는 편이 낫습니다. 롤백 기능 없이 배포하는 것이 작은 도구들이 남아있는 방식입니다.
결정 테이블 (Decision table)
| 게이트 (Gate) | 커밋할 증거 (Evidence you commit) | 실패 시 동작 (Fail closed when) |
| :--- | :--- |
| Path lock | 읽기 및 쓰기 허용 목록 (allowed reads and writes) | 리스트가 비어 있거나, 패치 경로가 범위를 벗어날 때 |
| ... |
스크립트와 논쟁하기 전에 해당 행을 읽으세요. 이 워크플로우에서 스크립트는 지루한 동료입니다. 당신은 그것과의 논쟁에서 질 의향이 있습니까?
쓰기 모드 전 단계 (Steps before write mode)
- 브랜치를 생성하고 새로운 증거 디렉터리를 만듭니다.
- CLI를 dry-run으로 실행하고 표준 출력(stdout)을 파일로 리디렉션합니다.
- diff가 비어 있더라도 git diff를 저장합니다.
- 추가적인 단어 없이 exit_code.txt에 종료 코드를 작성합니다.
- 메모리가 아닌 해당 파일들로부터 ship-card.json을 채웁니다.
- 체커(checker)를 실행하고 빨간색 결과도 실제 게이트로 받아들입니다.
- 동일한 허용 목록(allowlist)에서만 쓰기 모드를 고려합니다.
단계를 건너뛰면 카드는 연극이 됩니다. 건너뛴 단계는 나중 리뷰를 엉망으로 만듭니다. 시간적 압박 속에서 보통 어떤 단계를 건너뛰나요?
체커 복사하기 (Copy the checker)
이 스크립트는 샌드박스 제품이 아니라 시작점입니다. 존재 여부, 0 종료 코드, 삭제 경로, 쓰기 경로를 확인합니다. 네트워크를 호출하지 않으며 모델을 점수화하지도 않습니다.
#!/usr/bin/env python3
"""Fail-closed ship card checker. Template, not a benchmark."""
import json
...
샘플 카드 (Sample card)
{
"allowed_reads": ["src/", "tests/fixtures/"],
"allowed_writes": ["src/format.py"]
...
숫자 제한(numeric caps)은 정수여야 하며, 그렇지 않으면 체커가 멈춥니다. 여전히 패치 내부의 라인 수는 계산하지 않습니다. 쓰기 모드를 신뢰하기 전에 해당 카운터를 추가하세요.
명령어 (Commands)
증거 폴더를 만든 다음 체커를 실행합니다. 누락된 패치는 종료 코드 2로 끝나야 합니다. 그 오류를 잡고 계속 진행해서는 안 됩니다.
mkdir -p evidence/dry-run-01
python3 ship_card.py ship-card.json
echo $?
아래 명령어로 실제 dry-run을 캡처하세요. CLI 이름은 사용 중인 도구에 맞게 조정하세요. 카드가 녹색(green)이 될 때까지 쓰기는 하지 마세요.
python3 rewrite_cli.py --dry-run src/format.py > evidence/dry-run-01/stdout.txt
printf '%s\n' "?" > evidence/dry-run-01/exit_code.txt
git diff -- src/format.py > evidence/dry-run-01/diff.patch
나중에 명령을 실행하기 전에 CLI 상태를 저장하세요. 그렇지 않으면 헬퍼가 아닌 git이 기록됩니다. rewrite_cli.py는 단지 플레이스홀더 이름일 뿐입니다.
실패 테스트 케이스 (Failure fixture)
확실한 빨간색(fail) 결과를 원할 때 나쁜 패치(bad patch)를 사용하세요. 이 패치는 카드(card)가 보호해야 하는 파일을 삭제합니다. 만약 삭제가 금지된 경우, 당신의 카드는 이를 거부해야 합니다.
diff --git a/src/format.py b/src/format.py
deleted file mode 100644
index 1111111..0000000
...
evidence_dir을 해당 폴더로 지정하고 검사기(checker)를 다시 실행하세요. 출력된 실패와 0이 아닌 종료 코드(non-zero exit)를 확인합니다. 그런 다음 카드를 원래의 좋은 폴더로 되돌리세요.
또한 쓰기 범위를 넓히기 전에 패치도 검색하세요. 시작 스크립트는 비밀 정보(secrets)를 스캔하지 않습니다. 녹색 카드(green card)라도 유출된 키를 숨길 수 있습니다.
rg -n "AKIA|sk-|BEGIN PRIVATE" evidence || echo "no obvious token"
이 검색을 당신의 로컬 래퍼(wrapper)에 추가하세요. 저는 이것 없이는 카드가 완료되었다고 말하지 않을 것입니다. 당신의 머신에서 나쁜 테스트 케이스가 큰 소리로 실패했나요?
무료 러너는 또 다른 필드일 뿐입니다 (A free runner is just another field)
공개합니다: 이 기사는 MonkeyCode의 제품 홍보(product outreach)의 일환으로 준비되었습니다. 저는 MonkeyCode 무료 모델 액세스를 선택적인 건조 실행(optional dry-run) 러너로 취급합니다. 무료 서버 옵션은 당신의 노트북에서 그 작은 카나리아(canary)를 호스팅할 수 있습니다.
저는 토큰 제한, 모델 이름 또는 하드웨어 등급을 지어내지 않을 것입니다. 이 두 가지 가용성 주장은 오늘 읽은 후에만 유용합니다. 오래된 스크린샷은 실패한 증거 게이트입니다.
쿼터(Quotas), 이름 및 기간은 이 기사가 업데이트되지 않아도 변경될 수 있습니다. 만약 그 경로를 사용한다면, 개인적으로 검증한 필드만 추가하세요. 페이지가 로드되지 않을 때는 빈칸으로 두세요.
빈칸은 제한을 추측하는 것이 아니라 쓰기를 포기한다는 의미입니다. 검사기는 당신을 대신하여 MonkeyCode를 호출하지 않습니다. 여전히 기계에서 자체 명령을 실행합니다.
{
"model_access": "free-model-access",
"compute": "free-server-option",
...
이 카드는 단순히 제한 사항을 조회했다는 기록만 남깁니다. 제품 이름은 제거하고 네 가지 게이트는 그대로 유지됩니다. 경로 잠금(Path locks)은 공급업체(vendor)가 중요하지 않습니다.
MonkeyCode가 선택한 실행기(runner)라면, 먼저 계정 페이지를 여세요. 오늘 볼 수 있는 무료 모델 및 무료 서버 사실만 붙여넣으세요. 그런 다음 기억이 아닌 검사기(checker)에 논쟁하게 하세요.
시간 제한 및 롤백 (Time box and rollback)
이 실험에는 무한정인 주가 아니라 저녁 시간을 할애하세요. 저는 연속으로 빨간색 표시가 두 번 나오면 중단할 것입니다. 더 많은 재시도(retries)는 보통 작업 자체에 문제가 있다는 것을 의미합니다.
실제 필요하기 전에 롤백을 연습하세요. 롤백 후의 지저분한 상태(Dirty status)는 포기 신호입니다. 설명할 수 없는 트리는 계속 진행하지 마세요.
git status --short
git checkout -- src/format.py
git status --short
만약 두 번째 상태가 깨끗하지 않다면, 브랜치를 보류(shelve)하세요. 이유를 abandon_if 필드에 작성하세요. 내일은 왜 멈췄는지 추측할 필요가 없어야 합니다.
사용해서는 안 되는 경우 (Who should not use this)
이 카드를 고객 데이터, 결제 또는 인증 코드(auth code)에는 사용하지 마세요. 보안 감사나 규정 준수 패키지로는 사용하지 마세요. 비밀 정보(secrets)나 운영 자격 증명(production credentials)을 가리키는 데도 사용하지 마세요.
팀이 이미 필수 변경 도구(required change tool)를 가지고 있다면 건너뛰세요. 두 번째 체크리스트는 일주일 안에 썩어버릴 것입니다. 또한 로컬 diff를 저장할 수 없다면 건너뛰세요.
무료 모델 액세스는 잘못되거나, 느리거나, 단순히 이용 불가능할 수 있습니다. 무료 서버 옵션은 카나리아 배포(canary) 중에 사라질 수 있습니다. 이 카드는 가동 시간(uptime), 용량(capacity), 또는 지속적인 무료 등급을 보장하지 않습니다.
알아야 할 제한 사항 (Limits you should know)
경로 확인(path check)은 실제 샌드박스(sandbox)가 아닌 단순 문자열 일치입니다. 까다로운 상대 경로(relative path)도 여전히 통과할 수 있습니다. 허용 목록(allowlist)을 금고가 아니라 안전벨트처럼 취급하세요.
라인 제한(Line caps) 및 파일 제한(file caps)은 이 버전에서 계산되지 않고 저장됩니다. 이것은 무시해도 될 각주가 아니라 실제 격차입니다. 쓰기 모드(write mode) 전에 카운터를 추가하거나, 건조 실행(dry-run) 상태를 유지하세요.
저는 여기에서 타이밍, 가격 또는 모델 비교를 게시하지 않습니다. 인용할 신선한 주요 측정값(primary measurement)이 없습니다. 숫자가 필요하다면 직접 측정하고 날짜를 기록하세요.
체커(checker), 샘플 카드(sample card), 그리고 잘못된 픽스처(bad fixture)를 복사하세요. 먼저 빨간 케이스(red case)를 실행한 다음, 직접 작성한 CLI의 드라이-런(dry-run)을 한 번 수행하세요. 필수 필드가 여전히 비어 있는 지점에서 중단하세요.
쓰기를 허용하기 전에 어떤 증거 파일(evidence file)이 아직 누락되어 있나요? 그 간극이야말로 새로운 기능이 아니라 다음 빌드입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기