검색/공유 라이브러리나 SDK를 공개 API를 깨지 않고 고치기

공유 라이브러리나 SDK를 공개 API를 깨지 않고 고치기

AI 코딩 에이전트가 공유 라이브러리나 SDK를 고칠 때 쓴다. 완료라고 하기 전에 테스트와 빌드를 모두 돌리고, 지금 쓰는 사람을 위해 공개 API를 지키고, Git 브랜치나 worktree를 바꾸기 전에 묻고, 마지막에 풀 리퀘스트 인계 내용을 낸다.

이 AI 규칙을 사용하려면
## 완료라고 하기 전에 테스트와 빌드를 모두 돌리기 변경 사항이 런타임 코드, 테스트, 또는 빌드/테스트 동작에 영향을 미치는 경우, 어떤 변경이든 완료로 선언하기 전에 프로젝트의 전체 검증 스택을 실행한다. 다음을 수정할 때 검증이 적용된다: - 핵심 라이브러리 코드 또는 공유 유틸리티. - 스냅샷 테스트를 포함한 테스트. - 예제 프로젝트. - 빌드 또는 테스트 구성(의존성 매니페스트, 태스크 러너 파일, 문서 빌드 구성, CI 워크플로). 사용자가 명시적으로 전체 스택을 요청하지 않는 한, 문서 전용 변경이나 저장소 메타 변경(문서, 기여자 가이드, 메타데이터 파일)에 대해서는 전체 검증을 생략해도 된다. 검증 적용 여부는 변경 규모에 대한 주관적인 느낌이 아니라 실제로 변경된 파일을 기준으로 판단한다. 수정 사항을 적용한 후에는 전체 스택을 다시 실행한다 — 부분적인 재실행은 수정 자체로 인해 발생한 회귀를 숨긴다. 외부 플랫폼의 API와 통합할 때는 일반적인 API 가정에 의존하지 말고 해당 플랫폼의 공식 문서를 참조하며, 라이브러리 자체의 동작에 대해서는 로컬 코드 경로를 확인한다. ## 사용자 허락 없이 Git 브랜치나 worktree를 바꾸지 않기 기본적으로 사용자의 현재 체크아웃과 현재 브랜치에서 작업한다. 작업이 이미 선택된 worktree 내에서 실행 중이라면, 추가 권한을 요청하지 않고 그 worktree를 사용한다. 사용자가 현재 대화에서 정확히 그 작업을 명시적으로 요청하거나 승인하지 않는 한, 다른 worktree를 생성하거나 전환하지 않으며, 브랜치를 생성하거나 전환하지 않는다. 변경 사항을 구현, 조사, 리뷰, 테스트, 또는 검증해 달라는 요청 자체만으로는 활성 worktree나 브랜치를 변경할 권한이 주어지지 않는다. 격리나 다른 체크아웃이 정말로 필요한 경우, 이유를 설명하고 Git 상태를 변경하기 전에 먼저 물어본다. 이는 다른 규칙이나 워크플로가 연결된 worktree를 권장하는 경우에도 마찬가지다: 자동으로 worktree를 선택하거나 생성하지 말고, 멈춰서 승인을 요청한다. ## 새 공개 API 인자는 끝에 추가해 기존 호출을 깨지 않기 내보내진(export) 런타임 API의 매개변수 및 필드 순서는 구현 세부 사항이 아니라 계약이다. - 기존 공개 생성자 인자와 데이터클래스 필드의 위치적 의미를 보존한다. 기존 공개 순서 중간에 새 매개변수나 필드를 절대 삽입하지 않는다. - 새로운 선택적 공개 필드나 매개변수는 끝에 추가하고, 기존 필드는 원래 순서를 유지한다. - 순서 변경이 불가피한 경우, 명시적인 호환성 레이어와 함께 기존 위치 인자 호출 패턴을 검증하는 회귀 테스트를 추가한다. - 우발적인 손상을 줄이기 위해 호출 지점에서는 키워드 인자를 선호하되, 이를 근거로 위치 인자 호환성을 깨는 것을 정당화해서는 안 된다. - 의도된 임포트 경로와 공개 export 목록을 계약으로 취급한다. 공개 심볼을 추가하거나 이동할 때는 소유 모듈, 의도된 최상위 또는 하위 패키지 재내보내기(re-export), 그리고 임포트 회귀 테스트를 함께 업데이트한다. - 최상위 임포트는 선택적 의존성 실패와 런타임 부작용이 없도록 유지한다. 필요하다면 지연(lazy) export를 사용한다. ## 최신 릴리스를 기준으로 호환성을 판단하고 큰 작업은 계획 세우기 파괴적 변경(breaking change) 여부는 아직 릴리스되지 않은 브랜치 로컬의 변동이 아니라 최신 릴리스를 기준으로 판단한다. 최신 릴리스 이후에 도입되거나 변경된 인터페이스는, 릴리스되었거나 명시적으로 지원되는 영속적 외부 상태 경계를 정의하지 않는 한, 또는 사용자가 명시적으로 마이그레이션 경로를 요청하지 않는 한, 호환성 심(shim) 없이 직접 재작성해도 된다. 중간 스냅샷을 의도적으로 지원하지 않는 경우, 아직 릴리스되지 않은 영속화 포맷은 릴리스 전에 번호를 다시 매기거나 통합(squash)해도 된다. 릴리스 이후 브랜치 변동에 대해서는 호환성 레이어보다 직접 교체를 선호한다. 호환성 위험은 일찍 알린다 — 다만 변경 사항이 최신 릴리스에서 출시된 동작이나 릴리스되어 지원되는 영속적 상태 경계에 영향을 미치는 경우에만 해당한다 — 그리고 구현하기 전에 접근 방식을 확인받는다. 작업이 다단계이거나, 여러 파일에 걸쳐 있거나, 새로운 기능이나 리팩터링을 포함하거나, 대략 한 시간 이상 걸릴 가능성이 있는 경우 실행 계획(execution plan)을 사용한다. 실행하는 동안 계획의 살아있는 섹션(진행 상황, 발견 사항, 의사결정 기록, 결과)을 최신 상태로 유지하고, 범위가 바뀌면 계획을 다시 작성한다. 복잡한 작업에 대해 의도적으로 계획을 생략하는 경우, 리뷰어가 그 선택을 이해할 수 있도록 이유를 남긴다. ## 서브시스템 참조 문서를 먼저 읽고 변경이 닿는 곳을 모두 고치기 라이브러리의 런타임은 상호작용하는 여러 서브시스템의 집합이다 — 실행 루프, 도구 실행, 모델 및 프로바이더 어댑터, 트레이싱, 세션 및 영속성, 실시간 및 음성 파이프라인, 샌드박싱, 그리고 직렬화된 실행 상태. 이 중 하나를 변경하기 전에 해당 전용 아키텍처 참조 문서를 읽고, 자신이 건드리는 경계를 이해하고 있는지 확인한다. 시스템 전체에 파급 효과를 일으키는 변형을 추가하거나 변경할 때 — 새로운 모델 출력, 도구 호출, 승인, 또는 실행 항목(run-item) 타입 — 처리, 이벤트, 리플레이, 영속성, 트레이싱, 직렬화 등 적용 가능한 모든 표면을 업데이트한다. 표면 하나라도 빠뜨리면 미묘하고 추적하기 어려운 손상이 발생한다. 스트리밍 경로와 비스트리밍 경로의 동작을 일치시켜 유지한다. 연결, 태스크, 또는 기타 리소스를 소유하는 서브시스템에 대해서는 정상 경로와 실패 경로 양쪽 모두에서 리소스 소유권을 검증한다. 직렬화된 실행 상태(run-state)의 형태가 바뀔 때는 해당 포맷에 대한 릴리스 경계, 스키마 버전, 하위 호환 읽기(backward-read), 회귀 테스트 규칙을 따른다. ## 문서를 실제 코드에 맞추고 민감한 데이터를 로그에 남기지 않기 - 문서는 흔히 실제 운영 중인 사이트에 게시되므로, 동작 변경과 문서화를 신중하게 맞춰서 진행한다. 문서가 아직 릴리스되지 않은 동작을 설명하게 되는 경우, 릴리스가 제공될 때까지 문서 변경을 미루거나 후속 작업으로 분리한다. - 실행 가능한 문서 스니펫을 API 호환성 검사로 취급한다. 생성자나 API 예제를 추가하기 전에, 표시된 인자와 호출 형태를 실제 구현과 대조하여 검증한다. - 신뢰할 수 없는 샌드박스나 매니페스트 데이터가 스스로 호스트 파일시스템이나 기본 디렉터리 경계를 벗어나도록 허용하지 않는다. 로컬 구체화(materialization)를 위한 예외 통로(escape hatch)는 반드시 호출 지점의 신뢰된 애플리케이션 코드에 의해 제어되어야 하며, 직렬화된 매니페스트 데이터에 의해 제어되어서는 절대 안 된다. - 보안 권한(grant)이나 경계를 문서화할 때는, 실제 코드 경로가 이를 강제하는지 검증한다. 해당 경로가 실제로 그 권한을 참조하지 않는 한, 구체화 경로(로컬 디렉터리, 로컬 파일, 아카이브 추출)에 그 권한이 적용된다고 주장하지 않는다. - 민감한 페이로드를 마스킹(redact)할 때는 트레이스백 표시, 예외 체이닝, 보존된 예외 컨텍스트, 로그, 텔레메트리까지 고려한다. 원본 예외 객체가 여전히 민감한 입력을 담고 있다면, 트레이스백을 억제하는 것만으로는 충분하지 않다. ## 포맷과 테스트 검사를 통과하고 PR 인계 내용 쓰기 코드를 건드릴 때마다 테스트를 확장하고, 제출하기 전에 관련 검사가 통과하는지 확인한다. - 전체 테스트 스위트를 실행한다. 반복 작업 중에는 패턴별로 범위를 좁힌 테스트 실행을 사용한다. - 정적 타입 검사를 실행한다. 타입 힌트는 반드시 통과해야 한다. - 스냅샷 기반 테스트의 경우, 스냅샷을 의도적으로 재생성한 후 스위트를 다시 실행한다. - 커버리지는 프로젝트 기준치 이상을 유지해야 한다. - 포매터와 린터를 적용한다. 임포트는 정렬된 상태를 유지한다. 주석은 마침표로 끝나는 완전한 문장으로 작성한다. - 프로젝트가 정한 필수 순서대로 검사를 실행한다 — 포맷 → 린트 → 타입 체크 → 테스트 순. 풀 리퀘스트와 커밋에 대해: - 프로젝트의 PR 템플릿을 사용한다: 요약, 테스트 계획, 그리고 해당되는 경우 관련 이슈를 포함한다. - 간결한 커밋 메시지를 명령형으로 작성한다. 커밋은 작고 집중된 단위로 유지한다. - 새로운 동작에 대한 테스트를 추가하고, 사용자에게 노출되는 변경 사항에 대해서는 문서를 업데이트한다. - 해당되는 변경 사항에 대한 최종 응답 전에, PR 인계 블록(요약, 제안 브랜치 이름, 제목, 초안 설명)을 작성한다. 이 인계 블록을 작성하는 것 자체가 브랜치 생성, 커밋, 푸시, 또는 풀 리퀘스트 오픈을 승인하는 것은 아니다. 사소하거나 대화로만 끝나는 작업, 동작에 영향이 없는 메타/문서 전용 작업, 또는 사용자가 포함하지 말라고 한 경우에만 이를 생략한다. 리뷰어가 확인하는 항목: 검사 통과 여부, 새로운 동작과 엣지 케이스를 다루는 테스트, 읽기 쉽고 일관된 코드, 문서화된 공개 API 및 사용자에게 노출되는 변경 사항, 동작이 바뀔 때 업데이트된 예제, 그리고 명확한 설명이 담긴 깔끔한 히스토리.