


로봇과 AI용 Rust 데이터플로 프레임워크를 변경에 맞는 테스트로 개발하기
로봇과 AI용 Rust 데이터플로 프레임워크를 AI가 고칠 때 사용합니다. 메시지 규칙을 분명히 지키고, 커밋마다 검사를 통과시키며, 위험도에 따라 깊은 테스트를 고르고, 실제로 돌린 테스트를 보고합니다.
이 AI 규칙을 사용하려면
## Rust 워크스페이스를 구성하고 런타임을 네 가지 역할로 나누기
시스템을 Python, C, C++ 바인딩을 포함한 Rust 워크스페이스로 구성한다. 최소 도구 체인 버전과 공통 패키지 메타데이터는 워크스페이스 루트에 두되, 명시적으로 문서화된 크레이트나 예제는 독립적인 버전을 고정할 수 있게 한다.
책임이 명확한 네 가지 런타임 역할을 사용한다.
- 명령줄 클라이언트는 데이터플로를 빌드하고 시작하고 중지하고 검사한다.
- 코디네이터는 여러 머신에 걸친 분산 수명 주기를 관리한다.
- 머신마다 하나의 데몬이 노드를 생성하고 로컬 및 원격 통신을 관리한다.
- 노드는 사용자 코드를 프로세스로 실행하며, 더 적은 오버헤드가 필요할 때 오퍼레이터는 프로세스 내에서 실행한다.
메시지와 프로토콜 정의는 공통 라이브러리에, 디스크립터 파싱과 빌드 유틸리티는 코어 라이브러리에, 언어 API는 별도 패키지에 둔다. 언어 바인딩의 빌드 요구사항이 일반적인 Rust 전용 빌드에 섞이지 않게 한다.
## 언어 바인딩은 Rust 워크스페이스와 따로 빌드하기
별도의 패키징 도구가 필요한 언어 바인딩 패키지는 제외하고 Rust 워크스페이스를 빌드한다. 해당 패키지를 일반 워크스페이스 명령으로 억지로 빌드하지 말고 각각의 네이티브 바인딩 도구 체인으로 빌드한다.
전체 워크스페이스, 단일 패키지, 단일 테스트 대상의 세 가지 반복 작업 수준을 지원한다. 검사, 테스트, 린트, 포맷팅은 워크스페이스의 표준 명령으로 실행하고, 로컬 명령줄 도구는 잠긴 의존성을 사용해 설치한다.
린트, 테스트, 통합 스냅샷, 문서 검사를 실행하기 전에 빌드한다. 일반 워크스페이스 검사는 예제 대상을 컴파일하지 않을 수 있으므로 예제 대상에는 명시적인 예제 검사가 필요하다.
반복 작업 중에는 빠른 패키지 테스트를 유지하되, 배포하기 전에는 영향을 받는 전체 워크스페이스를 다시 검사한다. 새 예제 데이터플로가 추가되면 지원되는 언어 모드에서 예제 스모크 테스트 모음을 실행한다.
## 세 가지 통신 패턴과 공유 메모리 규칙을 분명히 하기
데이터플로를 선언적으로 정의한다. 노드는 이름이 지정된 출력에 구독하고 자체 출력을 선언한다. 타이머 소스를 제공하고 그 주파수나 간격을 디스크립터에 명시한다.
사용자에게 노출되는 서로 다른 세 가지 통신 패턴을 유지한다.
- Topic은 기본 발행/구독 흐름이다.
- Service는 요청/응답 방식이며 `request_id`로 메시지를 연계한다.
- Action은 `goal_id`와 `goal_status`를 통해 목표, 피드백, 결과, 취소를 나타낸다.
내부 이벤트 라우팅에는 용량이 제한된 다중 생산자 채널을 사용하고, 오케스트레이션에는 비동기 런타임을 사용한다. 여러 머신 사이에는 분산 발행/구독 전송을 사용하고, 인과 순서 지정에는 하이브리드 논리 시계를 사용한다.
로컬 노드 트래픽에서 4 KB보다 큰 메시지는 무복사 공유 메모리로 보내고, 더 작은 메시지는 TCP로 보낸다. 임계값, 소유권, 대체 동작을 명시해야 하며, 로컬 공유 메모리와 원격 네트워크의 의미 체계를 문서화되지 않은 단일 경로로 절대 합치지 않는다.
## 커밋마다 검토와 단순화를 먼저 하고 테스트 돌리기
모든 커밋은 배포 전에 다음 게이트를 완료해야 한다.
1. 구조, 보안, 로직 결함이 있는지 diff를 검토한다.
2. 불필요한 복잡성, 중복, 비효율을 줄인다.
3. 포맷팅을 확인하고 경고를 오류로 취급하여 린트를 실행하며, 최소한 영향을 받는 패키지의 테스트를 실행하고 배포 전에는 전체 워크스페이스 테스트를 실행한다.
4. API 시그니처 파손이 일반 워크스페이스 그래프 밖에 숨어 있지 않도록 예제 대상을 컴파일한다.
각 커밋 전에 포맷팅, 린트, 의존성 감사, 안전하지 않은 지름길 허용 한도, 오탈자 검사를 포함하는 빠른 로컬 게이트를 사용한다. 그런 다음 배포 전에 필수 전체 테스트 명령을 실행한다.
실패한 게이트를 건너뛰거나 더 느린 원격 CI가 문제를 찾아내리라 기대하지 않는다. 실패를 수정하고 영향을 받은 게이트를 다시 실행한다. 순서를 지켜야 한다. 광범위한 테스트 전에 검토와 단순화를 수행하면 설계 결함을 더 적은 비용으로 수정할 수 있다.
## 오래 걸리는 깊은 테스트는 매번이 아니라 위험도로 고르기
모든 커밋에서 모든 심층 테스트 모음을 실행하거나 그 전부를 풀 리퀘스트 CI에 추가하지 않는다. 변경 범위에 따라 선택한다.
- 추가적인 확신이 필요한 중요한 배포 전에는 커버리지를 포함한 전체 로컬 테스트 모음을 사용한다.
- 위험도가 높거나 Tier 1인 변경에는 변이 분석과 호환성 분석을 포함하는 심층 검증을 사용한다.
- 크로스 플랫폼, 속성, 인터프리터, 형식 증명, 엔드투엔드 커버리지에는 여러 시간에 걸친 야간 동등성 검사를 사용한다.
- 배포 전에는 릴리스 게이트를 사용하며, 독립적인 보안 검토, 내부 실사용, 마이그레이션 검증은 사람이 주도하는 별도 게이트로 유지한다.
- 전체 변이 감사는 릴리스 수준의 테스트 평가나 집중 조사에만 사용한다. 이 작업은 10~18시간이 걸릴 수 있기 때문이다.
- 노드 API, 명령 동작, 디스크립터를 변경한 뒤에는 예제 데이터플로를 엔드투엔드로 실행한다.
- 증명 게이트가 적용된 모듈을 변경할 때는 형식 증명을 실행하고, 프로파일은 이전할 수 없으므로 대상 OS와 아키텍처에서 프로파일 기반 최적화를 실행한다.
커버리지, 변이, 호환성, 예제, 형식 검증, 성능 프로파일링을 서로 대체할 수 있는 수단이 아니라 상호 보완적인 증거로 취급한다.
## 풀 리퀘스트 CI는 빠르게 두고 긴 작업은 야간에 돌리기
풀 리퀘스트 CI는 빠르게 차단 피드백을 제공할 수 있을 만큼 간결하게 유지한다. 포맷팅, 경고를 오류로 취급하는 린트, 코어 테스트, 엔드투엔드 장애 경로, 의미론적 계약, 벤치마크 회귀, 오탈자, 공급망 검사, 안전하지 않은 지름길 허용 한도, 라이선스를 포함해야 한다.
여러 시간이 걸리는 작업으로 차단 파이프라인을 확장하지 않는다. 광범위한 검증은 별도로 예약한다.
- Linux, macOS, Windows에서 플랫폼 테스트를 실행한다.
- 예제, 명령줄 템플릿, 동적 언어 노드, 벤치마크, 크로스 컴파일을 시험한다.
- 분산 수명 주기, 기록/재생, 재연결, 상태 재구성, CPU 선호도, 스토리지 백엔드, 브리지 어댑터를 다룬다.
- 지원되는 최소 컴파일러와 모든 형식 증명 하네스를 확인한다.
야간 작업의 실패는 추적되는 회귀 신호를 생성해야 하지만, 관련 없는 풀 리퀘스트를 반드시 차단할 필요는 없다. 변경이 해당 경로에 의존한다면 병합 전에 기본값이 아닌 플랫폼이나 예제 검사를 로컬에서 실행한다.
## 먼저 실패하는 테스트를 쓰고, 통과할 만큼만 코드 쓰기
모든 새 기능과 버그 수정은 RED-GREEN-IMPROVE를 따른다.
1. RED: 예상 동작을 정의하는 가장 작은 테스트를 작성하고 의도한 이유로 실패하는지 확인한다.
2. GREEN: 해당 테스트를 통과시키는 데 필요한 만큼만 코드를 구현한다.
3. IMPROVE: 집중 테스트와 영향을 받는 패키지 테스트를 통과 상태로 유지하면서 리팩터링한다.
동작에 따라 첫 테스트 계층을 선택한다. 라이브러리 함수는 단위 테스트로, 코디네이터나 데몬의 동작은 통합 테스트로, 명령 변경은 네트워크 스모크 테스트로, 데이터플로 기능은 네트워크 및 로컬 스모크 테스트로 시작하며, 버그 수정에는 결함을 재현하는 가장 좁은 범위의 회귀 테스트를 사용한다.
집중 테스트가 통과하면 영향을 받는 패키지의 테스트, 경고를 오류로 취급하는 린트, 포맷팅 검사를 실행한다. 변경이 명령 클라이언트, 코디네이터, 데몬에 영향을 준다면 공유 포트나 프로세스를 격리해야 하는 경우 스모크 테스트도 직렬로 실행한다.
## 예제 데이터플로를 네트워크와 로컬 두 스모크 모드로 돌리기
두 가지 스모크 모드를 제공한다.
- 네트워크 모드는 분산 런타임을 시작하고 분리된 데이터플로를 실행한 뒤 완료될 때까지 폴링하고, 런타임을 중지하고 해체한다.
- 로컬 모드는 명시적인 중지 기한을 두고 단일 프로세스에서 데이터플로를 실행한다.
새 예제 데이터플로는 두 모드를 모두 통과해야 한다. 테스트마다 다시 빌드하지 말고 일회성 가드를 통해 비용이 큰 빌드 준비를 공유한다.
명령 전송과 내결함성에 대한 엔드투엔드 테스트는 일반 단위 테스트와 분리한다. 이후 테스트가 오염되지 않도록 스모크 테스트 모음은 성공과 실패 모두에서 프로세스와 포트를 정리해야 한다.
사용할 수 없는 하드웨어, 대화형 입력, 다중 머신 설정, 지원되지 않는 네이티브 도구 체인이 필요한 예제는 기본 스모크 테스트 집합에서 제외하되, 제외 경계를 문서화하고 이를 실행할 수 있는 대상별 방법을 제공한다.
## 변경을 작게 유지하고 실제로 돌린 검사를 그대로 보고하기
변경 사항을 제출하기 전에 저장소의 기본 포매터로 포맷한다. 사소하지 않은 설계 변경은 구현 전에 프로젝트의 의사결정 채널에서 논의한다.
같은 변경에서 관련 없는 경고를 수정하거나 관련 없는 코드를 리팩터링하지 않는다. 실패, 검토, 롤백의 원인을 추적할 수 있도록 패치 범위를 제한한다.
언어 패키지와 명령줄 바이너리를 별도의 배포 표면으로 취급한다. 각각에 적절한 패키지, 바인딩, 호환성, 릴리스 검사를 확인한다.
정확성 게이트를 통과한 뒤에만 최적화된 릴리스 프로파일을 사용한다. 성능 작업에서는 대상 플랫폼을 보고하고 재현 가능한 기준선과 최적화된 빌드를 비교해야 한다.
인계 전에 빠른 게이트, 전체 게이트, 심층 게이트, 야간 게이트, 예제 게이트, 증명 게이트, 성능 게이트 중 실제로 실행한 것과 아직 검증하지 않은 것을 보고한다. 한 계층이 통과했다고 다른 계층도 통과했다고 절대 암시하지 않는다.
