저장소 CI와 full Nightly 검증¶
PR과 main push에서는 변경한 구성 요소에 해당하는 CI만 자동 실행합니다.
| 변경 파일 | 자동 검증 |
|---|---|
README* |
README 링크, 한·영 공개 계약, 보고서 정책, MCP Registry 메타데이터 |
docs/**, MkDocs 설정 |
full/public 문서 빌드, 링크, 한국어·공개 범위 검사 |
| Core 소스·제품 테스트 | 계약 4개 분할, fault/e2e, lint |
| MCP stream·Flight·스트리밍 검증기 | 전용 경량 loopback Flight·sync/async cursor·pipeline 회귀 |
MCP 소스·MCP 테스트·server.json |
Linux 단일 job의 실제 stdio·개인정보·오류·번들·Registry 계약 |
| 로컬 플러그인 정의·승인 | 플러그인 설치·실행 계약 |
| 벤치마크 구현·워크로드 | 벤치마크 단위·CLI 검사와 parity smoke |
| CI workflow·정책 helper | CI 정책·변경 경로 회귀 검사 |
여러 구성 요소가 바뀌면 해당 검증의 합집합을 실행합니다. 공통 패키지·의존성
변경은 Core·문서·MCP·벤치마크에 반영합니다. README만 수정하면 제품 전체
테스트·벤치마크·컨테이너 빌드·클라이언트 재설치를 실행하지 않습니다.
docs/assets의 README 이미지는 문서 자산 검증도 받습니다.
새 push로 대체된 PR 실행은 취소할 수 있지만 취소를 통과로 취급하지 않습니다.
merge queue에서는 각 workflow에 선언한 구성 요소 검증을 유지합니다.
전체 MCP 배포 행렬은 정기·명시적 수동 실행과 릴리스 검증에서 유지합니다. 일반 MCP 검사는 집중 회귀 검사이며 전체 의미 동등성·설치 인증이 아닙니다. 테스트 파일·검증문·제한 시간·릴리스 판정 기준은 제거하지 않습니다. 전체 Nightly·고정 러너 성능·OS/Python 설치 행렬·게시는 별도 workflow로 분리하며 게시에는 같은 SHA의 전체 릴리스 검증이 필요합니다.
엄격한 수동 nightly·릴리스 성능 suite는 같은 고정 benchmark 러너에서 배타적 잠금·새 소유 가상환경·명시한 하드웨어 메타데이터를 사용합니다. 입력·측정·판정 기준은 유지하며 실패한 hosted 측정은 별도 증거로 보존합니다.
PR과 full Nightly는 독립 실행이 검토된 test_mcp_algorithm_parity.py 사례에
같은 분할 규칙을 적용합니다. 수집한 정확한 node ID를 기존 contract 4개 분할에
분산하며, 다른 PR 파일은 공유 fixture 수명주기를 한 분할 안에서 유지합니다.
모든 알고리즘 사례는 정확히 한 번 실행하며 35분 제한·검증문·입력은 유지합니다.
실제 Ray 통계 회귀는 Dataset 집계 호출 수와 캐시 재조회·무효화·비활성화·명시적
ddof·빈/all-null 열·NaN·literal 열 이름을 검사하며 기존 응답 제한을 유지합니다.
로컬 설치형 SDK 증명은 패키지·launcher 검사가 끝난 뒤 실행해 JVM·Ray 시작 자원을
서로 경합하지 않게 합니다.
네이티브 SDK의 잘못된 응답은 진단에 바이트 수·빈 응답/줄 종료 여부·대기 시간만 남깁니다. 응답 내용은 공개하지 않으며 EOF·잘림·크기 초과·기존 30초 제한은 모두 실패로 유지합니다. 시작부터 치명적 SDK 스택을 기록하며, 실패한 응답에는 기존 소유 프로세스 정리 후의 종료 코드와 강제 종료 여부도 남깁니다. 성공한 응답의 대기·재시도는 늘리지 않습니다.
네이티브 벤치마크 worker는 zero-config 탐색 전에 지정된 작업 workspace 경계를 만듭니다. 기존 프로젝트 아래에서도 실행 JSON·metric 이력·HTML 문서는 그 workspace 안에 저장합니다. 문맥 초기화·영구 저장은 계속 측정 구간에서 실행하며 입력 행·warm 7회·wall-clock 시간·엄격한 성능 기준은 유지합니다.
전체 배포 검증에서 MCP는 verification/mcp_ci_gate.py에 명시한 모든 필수 테스트 파일을
Linux Python 3.11에서 8개 비중복 분할로 실행합니다.
알고리즘 사례는 제거하지 않습니다. 소스·실행 증명 집계는 누락·중복·실패·skip을
거부합니다. 다른 환경에서는 프로세스 정리·권한·UTF-8·자원·영속성·승인 경계
검증을 수행하며 이를 전체 의미 동등성 검증으로 대체하지 않습니다. 기존 job의
15분 제한을 유지합니다.
소스 배포본은 중첩 pyproject.toml이 있더라도 생성된 dist/ 출력을 제외합니다.
아카이브 검사는 생성된 배포 경로가 포함되면 실패합니다.
wheel·sdist·MCPB 4종(summary/Core, public/local)은 한 번 빌드합니다. 각 설치 job은 SHA256SUMS를 검사하고 동일 파일을 설치하며 MCPB 내장 wheel도 원본과 바이트 단위로 같아야 합니다. 명시적 호환성 실행에서는 8개 새 환경 설치·실행기 검증을 모두 유지합니다. 축소 호환성 수동 실행 환경은 Linux 3.11/3.13과 Windows/macOS 3.11입니다. 주간·릴리스에서는 지원 OS/Python 9개 조합을 모두 검증합니다. OS 독립적 의미 검증 전체를 9번 반복하지 않습니다. 공통 소스·의존성 변경은 집중 MCP 검사를 실행하며 관련 없는 문서·workflow·제품 테스트 변경은 전체 MCP 배포 검증을 시작하지 않습니다. 이 구성이 전체 Core 기능 동등성을 의미하지는 않습니다.
추가 OS·Python 환경의 경계 테스트는 각각 4개 비중복 분할로 실행합니다. 설치 전에 같은 환경의 분할을 집계하여 누락·중복·실패와 잘못된 검증 범위의 증거를 거부합니다. 테스트 범위와 15분 제한은 바뀌지 않으며 분할만으로 실패한 테스트를 통과한 것으로 처리하지 않습니다.
플랫폼 경계 검증은 전체 Linux 분할과 병렬로 실행하고 설치 검증과 job을 분리합니다. 각 job의 15분 한도는 유지합니다. 경계 테스트와 8개 설치가 하나의 한도를 소모하던 문제를 해결하며 테스트·환경을 제거하거나 반복하지 않습니다. 설치 job은 해당 환경의 경계 증거를 다운로드하고 최종 gate는 전체 테스트·빌드·플랫폼 계약· 설치를 모두 필수로 요구하여 실패·누락된 경계 검증을 우회하지 못하게 합니다.
release-verify.yml은 같은 SHA의 full Nightly·전체 MCP 호환성·strict 문서·기존
고정 runner 성능 gate·플러그인 설치·벤치마크 계약·lint ratchet을 모아 실행하며
게시하지 않습니다. release-pypi.yml은
정확히 같은 SHA에서 성공한 검증 run ID를 요구하고 해당 canonical 산출물을
다운로드하여 설치를 재확인한 뒤 게시합니다. 소스 재빌드와 전체 MCP 테스트의
중복 실행은 하지 않습니다. 게시 후 검사도 과거의 짧은 진단 제한 시간으로 전체
테스트를 재실행하지 않고 실제 릴리스 실행 증거를 확인합니다. 진단·실계정 검증은
수동 실행으로 유지하며 개발 필수 gate가 아닙니다.
원래 full 집합의 정확한 분할¶
Nightly는 기존 benchmarks/pdf extra와 nightly-local 개발 의존성 그룹의
OpenTelemetry SDK·Zstandard·pypdf를 설치합니다. Ubuntu는 Pango·Poppler·CJK
폰트를 설치하고 PDF smoke/render를 필수로 검증하며, 로컬 의존성 누락을 skip
면제로 바꾸지 않습니다.
dev 환경은 pytest 9를 사용합니다. native subtest는 부모의 setup/call/teardown과 분리하고 부모별 연속 순번을 기록하되 context·parameter 원문은 저장하지 않습니다. 부모 testcase 수와 부모+subtest JUnit 총계가 모두 일치해야 합니다. 실패·skip·xfail, 순번 누락·중복·다른 부모의 subtest는 거부하며, subtest를 무시하거나 별도의 최상위 선택 테스트로 중복 집계하지 않습니다. 수집 검증은 실행 전에 수행하여 finally hook이 pytest의 원래 missing-node 오류를 가리지 않게 합니다.
수집한 경로와 실제 import된 모듈 파일이 같은지 검사하고 소스 SHA-256을 기록합니다. 각 lane도 동일한 identity를 재검사하여 같은 파일명 때문에 다른 테스트가 대신 실행되지 않게 합니다. dev extra는 기본 압축 pipeline roundtrip에 필요한 LZ4 및 기본 키 저장소의 Argon2·cryptography를 명시적으로 설치합니다. 선택 의존성의 진단 정보 조회는 원래 테스트 결과를 지우지 않으며 full 수집·집계는 필수 MCP SDK 누락을 계속 거부합니다.
stress 지표는 중첩 property 조회가 가능한 재진입 잠금으로 일관된 summary를 만들고, 동시 기록 및 JSON/Markdown/HTML 보고서를 제한된 자식 프로세스에서 검증합니다. scale uniqueness fixture는 1억 행과 기존 300초 기준을 유지합니다. stress 결과의 실패율은 early-stop 경로를 포함한 실제 완료·실패 작업 수로 계산하며 누락된 결과 속성 때문에 검사가 중단되지 않게 합니다. Core HLL 검사가 아닌 정확한 Python set oracle이며, 기존 첫 1,000개 후보를 동일하게 사용하되 커지는 전체 set을 반복 복사하지 않습니다. HEAD/NONE 메모리 sampling 시간 검사는 기존 5배 overhead 기준을 유지하면서 양쪽 동일 warmup 1회와 순서를 번갈아 측정하는 고정 7쌍의 중앙값을 사용합니다. 생성·sampling·collect 비용과 실제 행수를 확인하고 인위적으로 느린 경로가 거부되는 반례를 둡니다. cold-start가 아닌 warm 상대 overhead 검증이며, 통과할 때까지 반복하거나 별도 고정 runner 릴리스 성능 기준을 바꾸지 않습니다.
예약 Nightly는 주 1회 전체 설정 범위를 실행합니다. integration-only 수동 진단은
유지하되 릴리스 증거가 될 수 없습니다. 릴리스 검증 워크플로는
run_full_suite=true로 호출합니다. 원래 marker 식
contract or fault or integration or soak or stress or scale_100m or e2e와
--run-integration --run-expensive --run-soak를 그대로 사용합니다.
이는 설정된 marker 집합이며 저장소 모든 테스트를 선택한다는 뜻은 아닙니다.
수집·실행 job은 같은 frozen dev/MCP 의존성을 설치합니다.
node ID는 scale → soak/stress → integration → fault/e2e → contract 순서로
단 하나의 lane에 배정됩니다. stress 경로에는 root conftest가 이미 soak를
붙이므로 marker별 독립 명령을 단순 나열하지 않습니다. contract는 4개 shard를
사용하고 일반 파일은 기존 PR의 파일 단위 균형 배정을 유지합니다.
test_mcp_algorithm_parity.py의 독립 실행 가능한 파라미터 사례만 기존 MCP
매트릭스처럼 같은 네 shard에 균등 분산합니다. 큰 네이티브 동등성 모듈 하나가
한 lane에 몰리지 않게 하며 테스트·네이티브 계산·fixture 행·assertion·시간
제한은 제거하거나 축소하지 않습니다. 분할 허용 목록은 명시적이고 나머지 파일의
fixture 지역성은 유지하며 수집 순서가 계획을 바꾸지 않습니다. 나머지 네 목적별 lane은
별도로 실행합니다. 수집 집합과 분할의 합집합 일치·교집합 0을 먼저 검증합니다.
동시에 최대 3개 lane만 실행하고 fail-fast는 끕니다. 각 job의 파일시스템, 의존성과 fixture는 독립적이며 session fixture·메모리 내 서비스는 공유되지 않습니다. setup 비용은 반복됩니다. 파일·테스트 수 균형이 실행시간 균형을 보장하지는 않습니다. 유료 runner나 서비스 계정을 새로 만들지 않습니다.
시간·자원과 실행 증거¶
| Lane | Job 분 | 테스트 강제 종료 초 | 진단 stack 초 |
|---|---|---|---|
| 각 contract shard | 35 | 120 | 60 |
| Fault/e2e | 25 | 180 | 90 |
| Integration | 35 | 180 | 90 |
| Soak/stress | 35 | 300 | 120 |
| 100M scale | 120 | 600 | 120 |
scale의 테스트별 600초는 기존 suite 실행 예시를 따르며 10개 테스트와 setup을 job 예산 안에 둡니다. 다른 예산은 수십 초 stress generator와 기존 fault deadline의 여유를 둔 공학적 설정이지 측정된 성능 약속이 아닙니다. 원래 데이터 규모·assertion·더 엄격한 throughput/runtime 기준은 바꾸지 않습니다. scale은 최소 논리 CPU 4개, 전체 RAM 16GB, 가용 RAM 12GB, 여유 디스크 10GB를 실제로 검사합니다. 단위는 GiB가 아닌 십진 byte입니다. 공개 Ubuntu 표준 runner의 명목 자원과 별개로 실제 가용량이 부족하면 실패합니다. 이 검사가 OOM을 보장하지는 않습니다.
테스트 시작 시 node ID를 출력하고 부분 NDJSON에 단계별 결과·시간을 즉시
기록합니다. JUnit, 최종 실행 manifest, 의존성 버전, 자원 관측과 수집 계획은
7일 보관합니다. manifest runner는 checkout root를 Python import 경로에 넣어
별도 native worker도 부모와 동일한 테스트 함수를 import하게 합니다.
Ray 런타임 패키지에도 빌드에 필요한 공개 JSON 리소스를 명시적으로 허용해
포함하며, 비공개 JSON 제외 규칙은 유지합니다.
native checkpoint와 atomic store는 Windows에서도 쓰기 가능한 descriptor로 staging
파일을 동기화합니다. 수동 실행 Windows native 회귀 workflow는 Python
3.11–3.13에서 실제 엔진과 설치형 operator 수명주기를 검사해 플랫폼 실패를
진단하며 전체 릴리스 검증을 대체하지 않습니다. 실패 진단에는 예외 타입,
구조적 stack frame과 고정된 원인 flag만 포함하며 native 원문과 전체 파일 경로를 제외합니다.
수집 단계에는 native PDF import 라이브러리를 설치합니다. 실행 레인은 실제
PDF 렌더링 검사용 Poppler·CJK font를 계속 설치합니다. APT 다운로드에는
제한된 timeout·retry를 적용하며 다운로드 실패는 그대로 job 실패입니다.
Windows native SDK scratch는 driver가 종료할 때까지 비공개 작업 디렉터리
아래에 유지합니다. 부모가 소유한 자식 프로세스를 회수한 뒤 작업 디렉터리를
삭제하므로 native 로그 handle과 디렉터리 삭제가 경합하지 않습니다.
Windows Spark checkpoint 검사는 SDK의 Hadoop native·winutils 가용성 검사를
먼저 통과해야 실제 checkpoint를 실행하며, 필수 의존성이 없으면 실패합니다.
진단은 SDK 예외의 원격 formatter를 호출하지 않습니다.
Windows SDK workflow는 Apache 소스 커밋
dbcc7cd797100e6b32cd84f85b53a5193a5f9af0의 Hadoop 3.5.0을 공식
native-win compile 단계로 빌드합니다. native binary·license·notice·소스/파일
hash provenance만 보존합니다. cache 식별자는 빌드 script와 runner image를
포함하며 복원된 파일을 검증한 뒤 실제 제품 검사를 실행합니다. SDK 설정은
운영자 factory에서 비공개로 고정하며 MCP 요청 경로로 받지 않습니다.
faulthandler의 soft timeout은 stack만 출력하며,
별도의 pytest-timeout thread deadline이 프로세스를 강제 종료합니다.
강제 종료로 최종 JSON/JUnit이 없을 수 있으므로 부분 증거는 보존하되 gate는 실패합니다.
항상 실행하는 최종 gate는 collector와 모든 matrix job 성공, 동일 checkout SHA· run ID·plan digest·의존성, 정확한 node ID와 setup/call/teardown, JUnit 일치를 요구합니다. 취소·누락·추가 실행·실패·xfail·예상치 않은 skip은 성공이 아닙니다. pytest가 수집 중 평가한 source skip/skipif만 optional 예상 skip으로 기록하고 사유·실행 일치를 확인하며 통과 수와 별도 집계합니다. 필수 MCP·scale에는 이 예외를 허용하지 않습니다. runtime skip을 자동 허용하지 않습니다. 수집 중 module skip도 별도 보존하며 실제 실행으로 세지 않습니다.
취소된 기존 단일 실행은 9,477개를 선택했고 19% 이후 진행 출력이 없었습니다. 이는 관측성 부족의 근거이지 특정 테스트 hang·OOM·제품 결함의 확정이 아닙니다. 새 lane 로그·stack으로 실제 장시간 구간을 확인해야 합니다.
설계 근거와 한계¶
GitHub workflow 계약, runner 자원 표, pytest fault-handler, pytest-timeout 종료 한계, SRE 22장의 관련 부분을 확인했습니다. 기존 PR manifest runner와 Workflow의 backend coverage·timeout 패턴을 참고했지만 그대로 복사하지 않았습니다. 제한된 공학적 조사이며 체계적 문헌고찰이나 속도 개선 실험 완료를 주장하지 않습니다.
dev extra는 공유 설치형 서비스 fixture가 일반 quality 레인에서도 수집·실행되도록
MCP SDK를 포함합니다. all extra도 MCP를 활성화합니다. 새 기본 패키지 설치 검사는
SDK가 없는 환경에서의 동작도 계속 확인합니다.
벤치마크 CLI 작업은 소스와 게시된 wheel 측정에 benchmarks 런타임 extra를 사용합니다.
워크로드·판정·고정 runner 식별자·기준값은 유지합니다. 산출물을 기록한 뒤 릴리스
작업은 자신이 소유권을 기록한 임시 런타임만 제거합니다. run ID·시도·커밋·canonical
경로가 일치해야 하며 별칭이나 변경된 소유권 기록은 거부합니다. 다른 run의
디렉터리와 공유 캐시는 보존합니다.
Windows SDK 26100과 충돌하는 내부 함수 이름은 Apache의 HADOOP-19977 수정만 적용하며 해당 커밋도 SDK 출처 기록에서 검증합니다.
네이티브 PDF·계보 작업은 CJK 글꼴을 유지합니다. 글꼴 다운로드는 APT 인덱스의 SHA-256을 검증하고 전송 속도·시간 한도와 공식 Ubuntu 미러 재시도를 적용합니다. 테스트 선택과 작업 제한 시간은 유지합니다. Reflex 소유자 사망 테스트는 각 분할에서 미시작·정지 상태를 독립적으로 구성합니다.
Redis Streams 중복 제거는 통합 작업에 명시된 폐기 가능한 Redis 서비스에서 실행합니다. 무조건 건너뜀을 사용하지 않으며 고유한 stream/hash 키를 만들고 해당 키만 정리합니다. 서비스 설정이 없거나 Redis에 연결할 수 없으면 선택된 테스트는 실패합니다.
세 행의 네이티브 SDK fixture는 Ray CPU 슬롯 2개와 Spark JVM의 C1 컴파일 단계를 사용해 CI의 초기 준비 비용을 제한합니다. 실제 partition·actor·체크포인트 I/O와 기존 30초 프로토콜 제한은 유지합니다. 제품 엔진 기본값과 벤치마크 JVM 설정은 바꾸지 않습니다.
CI 전용 nightly-local 그룹은 승인된 임시 Kafka·LocalStack 테스트용 aiokafka·
aiobotocore·Testcontainers도 설치합니다. Disposable broker integration 검증은
선택된 테스트의 건너뜀을 거부하고, 더미 AWS 키와 loopback 소켓만 사용합니다.
실제 계정이 필요한 웨어하우스·클라우드·유료 AI 검증은 활성화하지 않습니다.
임시 스트리밍 환경은 서비스 병렬 시작 전에 Testcontainers 정리 프로세스를 한 번 초기화합니다. Redis URL은 선택한 SDK 포트 매핑과 IPv6 표기를 사용합니다. 비동기 브로커 fixture는 이벤트 루프 범위를 명시하며 pytest의 엄격한 경고·오류 판정은 유지합니다. 네이티브 프로브 EOF 진단에는 고정된 단계 이름과 종료 코드만 남깁니다.
임시 브로커 비동기 fixture와 이를 사용하는 테스트는 같은 클래스 이벤트 루프를 사용하여 SDK 클라이언트가 루프를 넘지 않게 합니다. 상세 테스트 이름을 출력하여 강제 시간 초과 때 마지막 실행 항목을 보존합니다.
Kafka fixture 소비자는 earliest 오프셋을 명시하고 독립 시나리오마다 별도 토픽을 사용합니다. 배치 전송은 각 메시지의 라우팅과 serializer를 유지한 채 네이티브 producer에 전송을 큐잉하고 전달 실패를 포함한 모든 확인 응답을 관찰합니다.
브로커 통합은 네이티브 밀리초 윈도 설정, await한 aggregator-factory 처리와 정규화된 Kinesis stream-info 계약을 사용합니다. 모든 자동·강제 방출 결과의 메시지 수와 합계를 빠짐없이 검증합니다. macOS 클라이언트 fixture는 권한 부여 전에 소유한 임시 디렉터리의 실제 경로를 구하며 제품은 심볼릭 링크 별칭을 계속 거부합니다.
설치형 Core 데스크톱 스모크는 데스크톱 런처의 인자 배열과 독립적으로 신뢰된 Core worker CLI를 구성하여 반복 자동화를 실행합니다.
성능 실패 시 모든 반복의 wall-clock·프로세스 CPU 표본을 보존합니다. 별도 진단 프로파일은 스키마·복합·SQLite 외에 로컬 null·범위 검사도 포함하며 합격 측정을 대체하거나 임계값을 바꾸지 않습니다.
네이티브 검증은 venv를 유지하면서 실제 Windows 인터프리터를 소유하고 응답의 소유 PID를 대조합니다. 프로토콜과 SDK 로그는 별도 UTF-8 스트림을 사용합니다. 시간 초과 진단은 검토한 시작 표식과 숫자 종료 상태만 내보내며 AI fixture 실패는 비공개 소유자 오류 분류를 보존하고 유료 provider를 호출하지 않습니다.
Windows 네이티브 로그 descriptor는 바이너리 모드와 UTF-8/LF 텍스트 스트림을 사용하여 CRT 줄바꿈 이중 변환을 막습니다. 회귀는 정확한 로그 바이트와 오염되지 않은 별도 프로토콜 응답을 요구합니다.
자격증명 없는 LocalStack KMS fixture는 스트리밍 테스트와 같은 major-3 호환 이미지를 고정합니다. 2026년 latest 이미지는 계정 인증이 필요합니다. 브로커·KMS 집중 CI는 JUnit의 실제 Docker/LocalStack 제공자 증거와 loopback 클라이언트 연결을 요구하며 mock 대체를 네이티브 테스트 성공으로 취급하지 않습니다.
KMS 잘못된 키 검사는 네이티브 키·암호문 거부를 요구하며 자체 assertion이나 연결·인증 오류를 성공으로 삼킬 수 없습니다. 자격증명 없는 호환 fixture에서 latest를 사용하지 않는 이유는 LocalStack 이미지 변경 안내에 설명되어 있습니다.
Spark 시간 초과 진단은 SDK gateway 실행과 Spark 세션 생성을 구분하고 고정된 시작 표식만 노출합니다. 수동 spark-startup 범위는 지원 Windows Python 버전마다 새 프로세스의 cold start 5회를 모두 요구하며 한 번이라도 실패하면 진단이 실패합니다. 기존 30초 응답 제한을 늘리거나 전체 릴리스 검증을 대체하지 않습니다.
수동 spark-after-ray 진단은 원래의 Ray 테스트 3개와 이후 Spark 캐시 계약 순서를 Windows Python 버전마다 5회 반복합니다. 모든 반복이 통과해야 하며 이전 전체 실행의 실패를 지우지 않습니다.
네이티브 cold-start 진단은 고정 단계별 경과 시간과 소유 프로세스 감시의 CPU·wall 비용만 기록합니다. 20초 시점 관찰자는 검토한 SDK stack 위치만 분류하며 경로·frame 지역 변수·메시지·환경 값을 내보내지 않습니다. SDK를 종료하거나 재시도하지 않고 기존 30초 응답 제한을 유지합니다.
수동 Windows 진단은 uv의 지연 bytecode 생성과 bytecode=compiled 설치를 비교할 수 있습니다. 두 방식은 같은 5회 반복 테스트와 제한 시간을 사용하며 벤치마크 준비나 합격 기준을 바꾸지 않습니다.
네이티브 20초 traceback snapshot은 SDK가 Python GIL을 보유한 호출에서도 소유한 비공개 로그에만 남습니다. 외부 증거는 설치된 Ray/PySpark/Py4J SDK frame 최대 16개의 패키지·파일 basename·함수·행 번호만 포함하며 메시지·전체 경로·다른 코드 frame은 제외합니다.
수동 ray-startup 진단은 지원 Windows Python 버전마다 실제 Ray 캐시 계약을 새로운 driver 프로세스 20개에서 분리 실행하며 기존 응답·job 제한을 유지합니다. 모든 반복이 필수이며 전체 릴리스 게이트를 대체하지 않습니다.
Ray 준비 표식은 설치된 SDK의 Raylet 시작 문구와 노드 등록 완료 문구에 맞춥니다. 선택적 dashboard 모듈 import 경고만으로 시작 실패 원인을 판정하지 않으며 정상·실패 증거를 비교해야 합니다.
소유한 Spark fixture는 실행한 gateway의 stdin을 명시적으로 닫고 해당 launcher 프로세스의 종료를 기다린 뒤 정리를 마칩니다. 해당 launcher에서 포착한 PySpark Windows 종료 콜백만 해제하여 비동기 taskkill이 Python 소유자 밖으로 남지 않도록 합니다. 빌린 gateway나 다른 종료 콜백은 바꾸지 않으며 RPC·프로세스 회수 실패는 실패로 유지합니다.
소유한 Windows JVM이 stdin EOF를 감지하지 못하면 fixture는 여전히 소유한 launcher에 SDK의 프로세스 트리 종료 작업을 동기 실행하고 종료를 확인합니다. 종료 명령은 기존 소유자 수명 안에서 제한 시간과 join을 적용하며, launcher가 살아 있는데 종료 명령이 실패하면 정리 실패로 처리합니다.
동일한 20초 비공개 SDK snapshot은 네이티브 명령 대기도 관찰합니다. 고정된 명령 표식과 응답 경과 시간으로 초기화·집계 지연을 구분하며 기존 30초 프로토콜 제한을 유지합니다.
Windows Ray 2.58의 소유한 로컬 시작은 기존 SDK 노드 클라이언트로 정확한 ALIVE 노드와 유효한 관리 포트를 조회하여 네이티브 접근 위반이 발생한 임시 GlobalStateAccessor.GetNode 경로를 우회합니다. 범위를 제한한 훅은 성공·실패 모두 복원하며, 다른 스레드·외부 클러스터는 SDK 동작을 유지하고 시작 제한 시간을 늘리지 않습니다.
JUnit은 성공·실패 양쪽의 설치형 시작 단계 증거를 보존합니다. 설치형 네이티브 팩토리 시작도 20초에 크기를 제한한 SDK 스택 스냅샷과 단조 시계 기반 단계 시간을 기록합니다. 스냅샷은 SDK 패키지·파일명·함수·행 구조만 포함하고 절대 경로·프레임 지역 변수·인자를 제외합니다. 진단 타이머는 진입 또는 실패 시 취소하며 기존 작업 제한 시간은 유지합니다. 별도 Windows 설치형 Spark 진단은 Python 버전별 열기·사용·종료·재열기 전체 실행 5회가 모두 통과해야 합니다.
Spark 시작 실패 진단은 JVM 기반 예외 메시지를 포맷하지 않습니다. 포맷 과정이 응답 없는 게이트웨이에 추가 RPC를 보낼 수 있기 때문입니다. 소유 자원 정리 전에 구조적 실패 증거를 보존하며 원래 예외는 실패로 유지합니다.
Spark 프로브 진단은 소유한 자식 프로세스 최대 64개를 초당 한 번 관측합니다. 종료된 런처 단계도 마지막으로 관측한 역할·경과 시간·CPU·RSS·스레드 수만 보존하며 프로세스 ID·실행 파일 경로·인자는 제외합니다. 이는 진단 표본이며 프로세스 최종 합계나 벤치마크 측정값이 아닙니다.
별도 Windows Spark 콜드 스타트 진단은 Python 버전별 20회 시작이 모두 통과해야 하며 30초 응답·15분 작업 제한은 유지합니다. 고정된 전체 실행의 결과를 보존하며 실패한 시작을 재시도하지 않습니다.
대시보드 강제 종료 회귀는 상태 조회 사이에 프로세스가 사라지면 종료로 판정하며 접근 오류는 실패로 유지합니다. 기존 5초 종료 제한과 별도의 포트 폐쇄 확인을 모두 유지합니다.
소유한 Windows Spark 4.2 로컬 시작은 설치된 SDK 런처 JAR에서 NUL로 구분한 JVM 인자를 생성하고 셸 평가 없이 실제 JVM을 시작합니다. GUID 생성용 PowerShell 프로세스와 런처의 전체 JAR 검색을 줄이며, Spark가 원래 설정 읽기·게이트웨이 생성·인증·네이티브 계산을 수행합니다. 기존 30초 응답 제한은 유지합니다. 외부·빌린 세션, 다른 SDK 버전, 운영자 시작 스크립트·설정은 SDK 경로를 유지하고, 제한한 훅은 실패 시에도 복원하며 다른 스레드에 영향을 주지 않습니다. 부분 시작 실패도 수집한 SDK 종료 콜백만 해제하고 바깥 소유자가 기록한 자식을 정리합니다.
어댑터는 기본 SDK 스크립트 해시를 확인하며 수정된 스크립트나 사용자 지정 프로세스 시작 옵션은 SDK에 위임합니다. 상주 MCP 워커는 자신이 만든 정확한 프로세스를 참조하는 SDK 종료 콜백만 해제하고 프로세스 소유자가 정리합니다. 시작 실패 시 해당 소유 프로세스 핸들만 종료·회수하며 일반 SDK 수명 콜백과 빌린 게이트웨이는 유지합니다.
SDK는 Windows에서도 확장자 없는 bin/java 프로그램 이름을 생성합니다. 어댑터는 선택한 JDK의 동일한 java.exe와 검증한 뒤 해당 실행 파일을 명시하며 다른 실행 파일을 탐색하지 않습니다.
20초 프로브 스택 스냅샷은 GIL을 보유한 Python 감시 스레드에서 진입하여 오래된 인터프리터의 프레임·스레드 정리와 비동기 네이티브 스캔이 경쟁하는 경로를 피합니다. 실제 치명 오류 캡처와 30초 응답 제한은 유지합니다. CJK 글꼴은 러너가 연결 가능한 APT 미러 경로도 사용하되 설치 전에 서명된 APT 인덱스의 SHA-256과 일치해야 하며 기존 전송 제한과 렌더링 검사를 유지합니다.
상주 팩터리는 실제 선택적 SDK를 가져올 때만 Spark 시작 범위를 활성화합니다. Ray·Polars·SQL 팩터리는 PySpark를 미리 불러오지 않습니다. 네이티브 Ray 프로브는 동일한 응답 제한 시간 안에서 로컬 워커 시작 전에 ray.data를 가져오고, 가져오기 시작과 종료를 각각 기록합니다.
Ray 네이티브 시작 중 치명적 종료 진단은 크기가 제한된 에이전트 로그를 포함해 고정된 원인 표식과 검토된 SDK 소스 파일명·줄 번호만 유지합니다. 원문 메시지, ID, 명령 인자, 비공개 경로와 데이터는 제외하며, 이 진단으로 SDK의 조기 종료를 성공으로 처리하지 않습니다.
설치형 팩터리 회귀는 OS 파일 디스크립터 1·2에 직접 쓰고, Windows CRT와 Win32 표준 핸들이 일치하는지 확인한 뒤 온전한 JSON 프로토콜로 네이티브 계산과 종료를 수행합니다. Python 스트림만 리디렉션하는 구현으로는 이 검증을 통과할 수 없습니다.
진단용 ray-startup-compare 범위는 같은 Windows 러너에서 새 소유 프로세스로 Core·기본 SDK 경로를 교차 순서로 고정 20쌍 실행합니다. 각 경로는 기존 30초 응답 제한 안에서 실제 네이티브 통계와 정리를 수행하고, 실패한 쌍은 재시도 없이 중단하며 40회 모두 통과해야 성공입니다. 비식별 JSON·JUnit에는 고정된 프로세스 역할·상태, CPU·RSS·스레드·생존 시간과 제한된 SDK 소스 위치만 기록합니다. 원문 로그, 프로세스 ID, 전체 경로, 인자, 메시지와 행 데이터는 업로드하지 않습니다. 이 대조는 시작 지연 진단이며 제품 검증을 대체하지 않습니다.
SQL tenant 변경은 mcp-sql-isolation.yml에서 SQLite·DuckDB와 테스트가 생성한 임시 PostgreSQL·MySQL 및 설치형 운영자 worker 재시작을 검증합니다. 기존 DB나 운영 자격증명은 사용하지 않습니다.
Oracle tenant 변경은 mcp-oracle-isolation.yml에서 고정 Oracle Free 이미지와
thin driver를 사용합니다. 빌드한 wheel을 별도 클라이언트 환경에 설치한 뒤
native namespace·읽기 전용/DDL 경계·호출자 snapshot 보존·실제 SDK stdio·서버
세션 정리를 검증합니다. fixture가 컨테이너를 소유하고 삭제하며, 마스킹한 시작
로그·정리 증거·JUnit·wheel 해시만 업로드합니다. provider 통합 테스트 파일은
일반 Core 품질 suite 대신 전용 lane을 실행하고, 공통 SQL/worker 변경은 영향을
받는 lane을 함께 실행합니다.
SQL Server tenant 변경은 mcp-sqlserver-isolation.yml, 고정된 임시 이미지와 pymssql==2.3.13을 사용합니다. 네이티브 x86 Docker 엔진을 필수로 확인하고 별도 환경에 설치한 wheel의 SDK 종료·서버 세션 정리를 검증합니다. 공유 SDK 테스트 변경은 Oracle과 SQL Server 작업을 함께 선택합니다.