AI 지원 변경 후 수행해야 할 6가지 Git 확인 사항과 그 한계
요약
AI 코딩 어시스턴트가 제안한 코드 변경 사항이 실제 Git 상태와 워크플로우 승인 절차 사이에 불일치가 발생할 수 있음을 지적합니다. 이 글은 AI 생성 코드를 안전하게 통합하기 위해 'Git Safety Harness'라는 실패 종료(fail-closed) 워크플로우 제어 장치를 소개하며, 리포지토리 루트 확인, 스테이징 파일 관리 등 6가지 필수 Git 확인 사항을 제시합니다.
핵심 포인트
- AI 코드 변경은 승인된 워크플로우와 실제 Git 상태의 불일치에 주의해야 합니다.
- Git Safety Harness는 AI 생성 코드를 안전하게 통합하기 위한 실패 종료(fail-closed) 제어 장치입니다.
- Write Set (변경 가능 경로)과 Stage Set (스테이징 파일)을 분리하여 관리하는 것이 중요합니다.
- AI가 제시한 변경 사항이라도, 6가지 필수 Git 확인 절차를 거쳐야 합니다.
코딩 어시스턴트가 요청한 두 개의 파일을 수정합니다. diff는 합리적으로 보입니다. 다음 Git 작업도 진행해도 안전할까요?
반드시 그렇지는 않습니다. 잘못된 리포지토리에 있을 수 있습니다. 추가 파일이 이미 스테이징되었을 수도 있습니다. 브랜치나 설정된 push 목적지가 변경되었을 수도 있습니다. 또는 시크릿 스캐너가 아예 실행되지 않았을 수도 있습니다.
이것들은 반드시 생성된 코드의 오류는 아닙니다. 이것은 승인한 워크플로우와 실제 존재하는 Git 상태 사이의 불일치입니다.
저는 나중에 작업을 수행하기 전에 선택된 불일치를 확인하기 위해 작고 공개 참조 Git 안전 장치(public reference Git Safety Harness)를 만들었습니다. 이것은 샌드박스도, 독립적인 강제 경계도 아니며, 안전한 AI 생성 코드를 보장하는 것도 아닌 PowerShell 기반의 실패 종료(fail-closed) 워크플로우 제어 장치입니다.
두 파일 예시
승인된 작업이 다음과 같다고 가정해 봅시다:
- 특정 리포지토리에서
docs/article.md와public/article.html수정하기. main브랜치에 머무르기.- 다음 작업을 위해
docs/article.md만 스테이징하기. - 명시적으로 승인된 URL과 비교하여
origin의 설정된 push URL 확인하기. - 별도로 승인된 push 전에 staged-diff 시크릿 스캔 실행하기.
이 장치는 이러한 기대치를 임의로 만들어내지 않습니다. 인간이나 승인된 워크플로우가 먼저 정의해야 합니다. 그 후 이 장치가 관찰된 선택적 Git 상태와 이를 비교합니다.
6가지 확인 사항, 6가지 다른 질문
| 확인 항목 | 진행 전 질문 | 중단해야 하는 이유 예시 |
|---|---|---|
| 리포지토리 루트 | 이것이 의도된 Git 리포지토리인가? | 명령어가 다른 유효한 체크아웃에서 실행되고 있음. |
| ... | ||
| 각 질문은 서로 다른 실패 모드를 가집니다. 한 확인 항목에서의 PASS가 다른 항목들을 대체할 수는 없습니다. |
Write Set과 Stage Set이 분리되어야 하는 이유
Write Set은 어떤 경로들이 변경될 수 있는지 묻습니다. Stage Set은 다른 질문을 합니다. 다음 작업을 위해 어떤 경로들이 Git 인덱스에 포함되어야 하는지 말입니다.
참조 구현체는 git diff --cached --no-renames --name-only를 사용하여 실제 인덱스를 읽고, 스테이징된 경로와 별도의 허용 목록(allow-list)을 비교합니다. 이는 스테이지드 및 언스테이지드 추적 변경 사항뿐만 아니라 무시되지 않은 추적되지 않은 경로까지 포괄하는 Write Set과는 분리된 비교입니다. Write Set은 자체적인 허용 목록을 사용합니다.
예시: 허용된 변경이지만 승인되지 않은 스테이징 파일
승인된 Write Set에는 docs/article.md와 public/article.html가 모두 포함되어 있습니다. 반면, 승인된 Stage Set에는 docs/article.md만 포함되어 있습니다. 이제 다음의 가상의 출력(캡처된 테스트 기록이 아님)을 상상해 봅시다:
$ git diff --cached --no-renames --name-only
docs/article.md
public/article.html
두 경로 모두 변경하는 것은 허용되므로, 그 존재 자체만으로는 Write Set을 위반하지 않습니다. 그러나 public/article.html은 이 작업의 인덱스에 포함되는 것이 허용되지 않았습니다. 참조 구현체는 이를 Stage Set 불일치로 간주하여 스테이지된 상태를 수락하는 대신 GSH_STOP_STAGE_SET을 보고합니다.
다음에는 어떻게 될까요? 동일한 Git 상태에서 나온 두 가상의 경로를 고려해 봅시다:
- 효과적인 Stage Set 확인이 없는 경우: 만약 워크플로우가 인덱스를 변경하지 않고
git commit을 실행한다면, 두docs/article.md와public/article.html모두 해당 커밋에 포함됩니다. 두 번째 파일은 편집하는 것은 허용되었지만, 이 커밋을 위해 승인되지는 않았습니다. 만약 그 커밋이 나중에 별도의 승인을 받아 푸시된다면, 의도하지 않은 변경 사항이 원격 저장소에 도달할 수 있습니다. 이 예시에서는 커밋이나 푸시가 발생했다고 주장되지 않습니다. - 하네스(harness)를 호출하고 그 종료 결과를 존중하는 경우: Stage Set 불일치가
GSH_STOP_STAGE_SET과 0이 아닌 결과로 트리거됩니다. 호출된 워크플로우는 후속 커밋 또는 푸시 작업 이전에 중단되며, 스테이징된 파일은 검사를 위해 남아 있습니다—하네스는 이를 조용히 언스테이지하거나 복구하지 않습니다. 이후 사람이 스테이징을 수정할지, 승인을 변경할지, 아니면 작업을 중단할지를 결정할 수 있습니다.
이는 측정된 사고나 새로운 테스트 결과를 보여주는 것이 아니라 워크플로우 경계를 설명합니다. 또한 이는 harness 자체가 직접적인 Git 명령을 차단한다는 의미도 아닙니다. 만약 액터가 검사된 경로를 우회한다면, 로컬 Layer-2 harness는 그러한 중단을 강제할 수 없습니다.
마찬가지로, 원격 저장소의 fetch 주소를 확인하는 것만으로는 그 push 목적지를 확립하기에 충분하지 않습니다. 이 harness는 push URL을 검사하며 정확히 일치하는 하나를 요구합니다.
여기서 fail-closed가 의미하는 바
필요한 상태를 확인할 수 없을 경우, 정상적인 harness 경로는 누락된 증거를 성공으로 간주하기보다는 멈춥니다.
여기에는 해결할 수 없는 저장소 루트, 예상치 못한 브랜치, 사용 불가능한 Gitleaks 실행 파일, 그리고 스캐너 실행 실패가 포함됩니다. 검증된 PowerShell wrapper는 또한 호출 오류, 누락된 자식 종료 상태(child exit status), 그리고 0이 아닌 종료 코드도 실패로 간주합니다.
STOP은 어시스턴트에게 상황을 조용히 복구하고 계속하라는 지침이 아닙니다. 이는 관찰된 상태를 검사하고 필요한 인간의 결정을 얻기 위한 지점입니다.
실제로 테스트된 내용은 무엇인가?
commit-pinned Validation Record는 문서화된 Windows 참조 환경에서 식별된 구현에 대한 결과를 보고합니다:
- 28/28 fail-closed 케이스 통과: PowerShell 7에서 14개, Windows PowerShell 5.1에서 14개가 통과했습니다.
- 6/6 성공 경로(success-path) 케이스 통과: 실제 Gitleaks로 스캔된 비어있지 않은 허용 스테이징 diff를 포함하여 각 셸에서 세 가지가 통과했습니다.
- 해당 기록은 SHA-256 해시와 사용된 버전(Git 2.54.0.windows.1, PowerShell 7.6.5, Windows PowerShell 5.1.26100.9444, Gitleaks 8.30.1)을 사용하여 소스 및 테스트 파일을 식별합니다. 나중에 보존된 재검증(revalidation)에서는 동일한 소스/테스트 식별자를 사용했지만 PowerShell 7.6.6을 사용했습니다.
테스트는 합성 로컬 원격 저장소(synthetic local remotes)를 사용하고 식별된 구현 및 환경에 대한 경계가 지정된 결과(bounded results)를 기록했습니다. 이는 보편적인 호환성, 우회 불가능성 또는 나중에 실제 세계에서 푸시하거나 배포하는 것의 안전성을 확립하지는 못합니다.
나중 재검증의 증거 묶음 (Evidence Pack from that later revalidation)은 실행 출력, 케이스 결과, 종료 코드 및 SHA-256 매니페스트를 보존합니다. 이는 나중 실행의 기록일 뿐, 원래 실행의 원시 로그(raw logs)는 아닙니다.
하네스(harness)가 보장할 수 없는 것들
AI 지원 워크플로우에서는 특히 세 가지 한계가 중요합니다:
- 허용된다고 해서 올바른 것은 아니다.
docs/article.md내부의 변경 사항은 여전히 기술적 또는 의미적으로 틀릴 수 있습니다. - 로컬 검사는 우회될 수 있다. 사람이나 에이전트가 하네스 외부에서 원시 Git, 셸 명령어 또는 API를 호출할 수 있다면, 하네스 자체가 그러한 경로를 금지하지는 않습니다. 독립적인 제한은 이 로컬 워크플로우 제어(Layer 2) 외부에 있는 별도의 강제 계층에 속해야 합니다.
- 검사는 특정 시점의 상태이다. 검증 후에도 상태가 변경될 수 있습니다. 하네스는 구성된 푸시 URL을 확인하지만, 나중
git push를 수행하거나 승인하지는 않습니다. Gitleaks 검사는 스캐너가 검사하는 스테이징된 diff를 다루며, 모든 파일이나 모든 비밀 정보를 다루지는 않습니다.
이러한 한계점들은 인간의 승인을 독립적인 강제(enforcement)와 분리해야 하는 이유입니다. 인간의 승인은 워크플로우 결정이며, 독립적인 강제가 아닙니다. 로컬 하네스는 어느 쪽도 대체하지 못합니다.
유용한 경계
목표는 AI 어시스턴트가 안전하다는 것을 증명하는 것이 아닙니다. 목표는 더 좁습니다: 선택된 Git 워크플로우가 계속되기 전에, 불일치(mismatches)를 확실하게 관찰 가능하게 만들고 필요한 검사가 수용될 수 없을 때 중단시키는 것입니다.
전체 OSIIX의 영어 디자인 기사 (AI Git Safety Harness)에서 검사 내용을 자세히 설명합니다. 현재 구현—별도의 AllowedStagedFiles 매개변수를 포함하여—를 사용하려면, 이전 기사의 모든 예시 스니펫을 최신 테스트 코드로 간주하기보다는 커밋 고정 소스, 시작하기 가이드, 그리고 제한 사항을 사용하십시오.
AI 지원 Git 자동화를 사용할 경우, 이 검사들 중 어떤 것이 에이전트 제어 실행 경로 외부에서 강제되고, 어떤 것이 단지 에이전트가 따라야 할 관례에 불과한가요?
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기