


오래 유지된 이식 가능한 C 프로젝트를 호환성을 깨지 않고 고치기
AI가 오래된 컴파일러, 여러 플랫폼, 선택 기능에서 계속 빌드되어야 하는 성숙한 C 코드를 고칠 때 쓴다. 영향받는 구성을 빌드하고 테스트하며, 스타일·메모리·커밋·문서·릴리스 규칙을 지키고, 패치마다 작고 단독으로 유효하게 만든다.
이 AI 규칙을 사용하려면
## 변경 전에 계속 동작해야 할 플랫폼과 기능 조합 확인하기
- 이식성, 안정성, 견고성, 하위 호환성을 핵심 설계 제약으로 취급한다.
- 최소한의 표준 호환 구성부터 선택적 스크립팅 인터페이스가 포함된 완전한 그래픽 구성까지 다양한 빌드를 고려한다.
- 아키텍처나 공개 동작을 변경하기 전에 저장소의 상위 수준 설계 정책을 읽는다.
- 핵심 소스, 런타임 자산, 번역, 테스트, 문서, 하위 프로젝트, 공급업체에서 가져온 업스트림 코드를 구분한다.
- 최신 컴파일러, 운영 체제, 기능 집합 또는 그래픽 환경을 전제로 하지 않는다.
- 변경 사항에 명시적인 기능 게이트가 적용되지 않는 한 지원되는 변형 전반에서 동작의 일관성을 유지한다.
## 영향받는 구성을 새 경고 없이 빌드하고 테스트하기
- 현재 플랫폼과 툴체인에 대해 문서화된 빌드 경로를 사용한다.
- 함수 선언이나 그 밖의 파생 인터페이스는 생성된 출력을 직접 편집하지 말고 해당 생성기를 통해 다시 생성한다.
- 반복 작업 중에는 초점을 맞춘 테스트 파일을 실행하고 메시지 출력과 상세 테스트 로그를 모두 살펴본다.
- 제출 전에는 새 경고가 없는 깨끗한 빌드, 관련 테스트 통과, 편집한 파일과 일치하는 소스 스타일을 필수로 확인한다.
- 플랫폼별 빌드 절차가 다르면 명령을 추측으로 바꾸지 말고 해당 플랫폼의 설치 가이드를 참조한다.
- 공유 코드, 기능 조합 또는 런타임 파일이 영향을 받으면 더 넓은 범위의 테스트로 확대한다.
## 생성 파일은 생성기로만 다시 만들고 파일 담당자의 절차 따르기
- 어떤 디렉터리가 생성되거나, 업스트림에서 가져오거나, 관련 프로젝트와 공유되거나, 지정된 소유자가 관리하는지 파악한다.
- 생성 파일은 그 소스가 변경된 경우에만 바꾸고, 기능 패치에 관련 없는 재생성 결과를 포함하지 않는다.
- 관리되는 런타임 변경은 소유권을 우회하지 말고 문서화된 소유자 워크플로를 따른다.
- 배포되는 런타임 및 도움말 파일을 편집할 때는 필수 변경 날짜나 설명을 갱신한다.
- 명시적인 디렉터리 예외가 적용되는 경우를 제외하고, 핵심 소스 변경에는 저장소에서 요구하는 패치 추적 항목을 추가한다.
- 공급업체 업데이트, 생성 과정의 잡음, 번역, 관련 없는 소스 정리를 하나의 패치에 절대 섞지 않는다.
## 커밋 제목에 해결 방법이 아니라 문제 쓰기
- 저장소에서 정한 정확한 패치 제목 및 본문 구조를 따른다.
- 제목에는 해결책의 구현이 아니라 문제를 적는다.
- 필수 출처 표기와 문장 부호를 포함하여 완전한 문제 문장과 간결한 해결책 문장을 작성한다.
- 형식에서 요구한다면 필수 문제 및 해결책 머리말 뒤에 선택적 설명을 두고, 글머리표 목록이 아닌 산문을 사용한다.
- 수정, 종료, 관련 참조에는 각각의 고유한 의미에 맞는 레이블을 붙인다.
- 필수 개발자 인증을 포함하고, AI 지원은 허용된 공동 작성자 방식으로만 밝힌다.
## 기존 C 스타일에 맞추고 오래된 컴파일러가 못 읽는 문법 피하기
- 파일별 탭 또는 공백 전용 규칙을 지키면서 논리적 들여쓰기는 공백 4칸으로 유지한다.
- 함수와 제어 흐름의 여는 중괄호는 별도 줄에 둔다.
- 함수 정의의 반환형과 함수 이름은 저장소에서 확립된 배치 방식으로 서식을 맞춘다.
- 주변 파일의 선언 배치를 따르고 기회가 생겼다는 이유로 현대화하지 않는다.
- 문서화된 기준 C 언어와 승인된 최신 기능만 사용하며, 레거시 컴파일러가 지원하지 않는 구문을 도입하지 않는다.
- 편집 후 파일별 포매터가 있으면 실행하고 그 diff를 검토한다.
## 프로젝트의 타입을 쓰고 이미 아는 문자열 길이를 헬퍼에 넘기기
- 저장소의 사용자 정의 타입 접미사를 사용하고 시스템 표준이 예약한 접미사는 피한다.
- 진행 중인 불리언 마이그레이션을 보존한다. 하나의 패치 안에서는 로컬에서 확립된 불리언 형식을 일관되게 사용하고 대규모 변환을 피한다.
- 최초 할당 위치를 찾기 어려운 지역 변수는 초기화하되, 초기화되지 않은 읽기 결함을 감출 수 있는 중복 초기화는 추가하지 않는다.
- 문자열 리터럴에는 리터럴 길이 헬퍼를 사용하고, 기록된 크기가 필요할 때는 길이를 반환하는 포매터를 사용한다.
- 문자열 길이를 이미 알고 있다면 다시 스캔하지 말고 길이 인식 연산에 그 길이를 전달한다.
- 각 바이트 버퍼 포인터를 해당 `size_t` 길이와 나란히 두며, 더 좁은 정수형은 레거시 인터페이스가 요구하는 곳에서만 사용한다.
## 프로젝트 래퍼로 메모리를 다루고 오류가 나도 반드시 해제하기
- 원시 표준 라이브러리의 할당, 해제, 복사, 이동, 문자, 공백 연산보다 저장소 래퍼를 우선한다.
- 문서화된 null 처리, 메모리 부족 시 동작, 중첩 안전성, 인코딩 동작, 플랫폼 일관성을 기준으로 래퍼를 선택한다.
- 앞선 복합 조건이 0이 아님을 암시하는 것처럼 보여도 모든 나눗셈 전에 나누는 수를 명시적으로 확인한다.
- 새 할당마다 성공, 조기 반환, 각 오류 분기에서 정리가 이루어지는지 확인한다.
- 버퍼 크기는 바이트 단위로 유지하고 잘림, 종료, 기록된 길이의 동작을 명시한다.
- 익숙하다는 이유만으로 더 안전한 프로젝트 래퍼를 범용 라이브러리 호출로 바꾸지 않는다.
## 이름과 매크로 규칙을 지키고 make 파일을 이식 가능하게 유지하기
- 예약 이름 제한, 금지 식별자, 함수 이름 길이 제한, 간격, 한 줄에 하나의 명령문 규칙을 따른다.
- 확립된 기능 접두사와 대문자 매크로 규칙을 사용한다.
- 저장소에서 지원하는 조건부 패턴으로 기능 매크로를 테스트한다.
- 기본 빌드 파일은 문서화된 이식 가능 make 방언을 따르게 하고, 구현체에 종속된 할당, 패턴, 셸, 조건부 확장은 피한다.
- 프로젝트의 문자열 및 바이트 타입과 이에 대응하는 매크로를 재사용한다.
- 새 식별자, 매크로 또는 빌드 규칙을 도입하기 전에 권위 있는 스타일 참조 문서를 읽는다.
## 관련 런타임과 포크에서도 동작하는 런타임 스크립트 작성하기
- 새 파일에는 현재 스크립트 스타일을 사용하되 관련 런타임 및 포크와의 호환성을 고려한다.
- 호환성이 불확실하면 더 새로운 언어 구문을 채택하기 전에 묻는다.
- 스크립트 테스트의 지역 변수 명명 규칙을 따른다.
- 파일에서 이미 해당 기능을 게이트한다면 개별 테스트 안에서 기능 게이트를 반복하지 않는다.
- 파일에 최상위 게이트가 없다면 선택적 기능이 필요한 테스트에만 집중된 게이트를 추가한다.
- 런타임 스크립트 변경은 관련 없는 핵심 언어 현대화와 분리한다.
## 보고된 결함을 그대로 재현하는 회귀 테스트 작성하기
- 프로그램이 충돌하지 않는지만 확인하는 테스트보다 결정론적 어설션을 우선한다.
- 렌더링 결함에는 화면 캡처 비교를 추가하고, 잘못된 데이터에는 정확한 출력을 어설션한다.
- 새 동작에 대한 포괄적인 검증 범위를 추가하며, 가능하면 기존의 관련 테스트 파일에 넣는다.
- 보고된 결함을 수정할 때는 단순화한 합성 사례만 다루지 말고 원래 시나리오를 재현한다.
- 터미널 세션, 화면 덤프, 스크립트 로드 성공, 예상된 스크립트 로드 실패에는 표준 헬퍼를 사용한다.
- 구문 및 들여쓰기 런타임 테스트는 각각의 전용 테스트 스위트에 둔다.
## 같은 패치에서 도움말 문서를 고치고 형식 유지하기
- 옵션이나 기능을 변경할 때는 같은 패치에서 사용자용 문서를 갱신한다.
- 기존 문서를 편집할 때는 도움말 파일의 변경 머리말을 갱신한다.
- 파일 머리말, 모드라인, 너비, 탭 정렬, 고유 태그, 상호 참조, 제목, 코드 예제, 강조 표기에 관한 권위 있는 도움말 형식을 보존한다.
- 안전한 retab 연산을 사용하고 그 diff를 검토하며, 광범위한 공백 재작성을 강제하지 않는다.
- 링크 태그는 전체에서 고유하게 유지하고 필요하면 확장 기능별 태그에 접두사를 붙인다.
- 해당 목적만으로 영향을 받지 않은 텍스트를 다시 쓰지 않으면서 새 텍스트나 수정한 텍스트에는 성 중립적 표현을 우선한다.
## 릴리스 단계를 먼저 확인하고 사용 중단된 동작도 쓸 수 있게 두기
- 범위를 제안하기 전에 프로젝트가 개발 주기인지 안정화 기간인지 확인한다.
- 안정화 기간에는 허용되는 변경을 명확한 결함, 보안 수정, 문서, 번역, 런타임 유지 관리로 제한한다.
- 안정화 중에는 새 기능이나 하위 호환되지 않는 핵심 변경을 도입하지 않는다.
- 마이너 버전 전반에서 릴리스된 핵심 동작을 보존한다.
- 사용 중단된 동작은 구성을 통해 계속 사용할 수 있게 하고, 사용 중단으로 문서화하며, 지원되는 경우 컴파일 시 비활성화를 허용하고, 나중에 허용된 주기에서만 제거한다.
- 핵심 보장을 약화시키지 않으면서 런타임 자산에는 문서화된 유지 관리 유연성을 적용한다.
## 모든 커밋이 단독으로 빌드와 테스트를 통과하는 패치 제출하기
- 의심되는 취약점을 보고하거나 보안에 민감한 코드를 변경하기 전에 보안 정책을 읽는다.
- 커밋 형식, 깨끗한 빌드, 관련 테스트, 회귀 검증 범위, 문서, 인증을 모두 완료한다.
- diff는 명시된 문제로 제한한다. 불필요한 공백, 관련 없는 리팩터링, 관련 없는 생성 출력을 포함하지 않는다.
- 여러 패치로 구성된 시리즈에서는 모든 커밋이 자체적으로 컴파일되고 자체 테스트를 통과하게 한다.
- 나중 커밋에서 고치도록 의도적으로 깨진 중간 커밋을 남기지 말고, 대신 둘을 결합한다.
- 문서화된 동작과 실제로 강제되는 동작이 여전히 일치하는지 확인하고, 의도한 변경을 문제 및 해결책 기록에 설명한다.
## 변경은 최소로 하고 작업 트리 밖의 작업 전에는 먼저 묻기
- 목표를 달성하는 가장 작은 변경을 만들고 광범위한 개선을 강요하지 말고 주변 코드에 맞춘다.
- 여러 독립된 문제를 해결하는 패치는 분리한다.
- 패치가 증상만 해결한다면 더 근본적인 문제와 선택한 범위 제한을 명시한다.
- 결함이 있다고 주장하기 전에 재현하고, 코드의 동작을 주장하기 전에 구현을 읽는다.
- 현재 소스를 사용할 수 있을 때 기억에 의존한 파일 내용을 사용하지 않는다.
- 패키지를 설치하거나, 작업 트리 밖의 파일을 수정하거나, 브랜치를 push하거나, 네트워크 작업을 사용하기 전에 사용자에게 확인한다.
