공유 속성 실패로부터 시작되는 Flake Freeze
요약
flake-freeze는 에이전트 패치가 플래키하게 되는 원인 중 하나인 '공유 속성 실패' 문제를 해결하기 위한 제안입니다. 이 게이트는 부모 커밋에서 이미 특정 속성이 실패했는지 여부를 엄격하게 확인하여, 회귀(regression)와 새로운 실패를 구분합니다.
핵심 포인트
- 패치 유효성은 부모 커밋의 동일한 계약 하에서의 속성 실패에 국한됩니다.
- 제안 파일 작성을 위해 7가지 필드(속성 스펙 해시 등)가 모두 일치해야 합니다.
- 실패 여부 확인을 위해 부모와 패치를 별도의 worktree에서 실행하는 것이 중요합니다.
- 이 체크는 기존의 fixture lock, input shrinking 등의 게이트를 대체하지 않습니다.
에이전트 패치가 플래키(flaky)하게 되는 이유는 새로운 트리가 특정 속성을 두 번 실패했기 때문입니다. flake-freeze 제안은 부모 커밋(parent commit)이 동일한 계약(contract) 하에서 해당 속성을 실패했을 때만 유효합니다. 만약 부모가 통과하고 패치가 실패한다면, 이는 회귀(regression)에 해당합니다. 패치에 대한 추가 실행은 이를 변경하지 않습니다.
이 게이트는 fixture lock, input shrinking, assertion-waiver 규칙 옆에 위치하며 이들을 대체하는 것은 아닙니다. 이 체크들은 열어두고 간 질문 하나에 답을 합니다: 실패가 부모에서 이미 존재했었는가?
하나의 결합(conjunction), 일곱 개의 필드
제안 파일이 작성되려면 모든 일곱 개의 필드가 충족되어야 합니다.
- 속성 스펙 해시(Property spec hash)가 부모와 패치에서 일치해야 합니다.
- Fixture 클로저 해시(Fixture closure hash)가 일치해야 합니다.
- 시드 스케줄(Seed schedule)이 순서와 개수를 포함하여 일치해야 합니다.
- 해당 속성에 대한 부모 상태가 실패(fail)여야 합니다.
- 해당 속성에 대한 패치 상태가 실패(fail)여야 합니다.
- 정규화된 증인 클래스(Normalized witness class)가 일치해야 합니다.
- 스케줄이 균일하게 빨간색(uniformly red)이 아니어야 합니다: 부모 또는 패치에서 적어도 하나의 시드가 다른 시드와 불일치를 보여야 합니다.
필드가 누락되면 거부됩니다. 충분히 비슷한 행은 없습니다.
첫 실행 전에 계약을 작성하세요
공유된 계약이 없는 두 개의 로그는 점수화될 수 없습니다. 계약을 검토 디렉터리(review directory)에 넣고 다른 해시를 인용하는 모든 실행은 무시하십시오.
contract_version: 1
parent_sha: "abc123"
patch_sha: "def456"
...
해당 해시는 이전 체크에서 가져온 입력값입니다. 이 메모는 이를 재정의하지 않습니다. 만약 에이전트가 속성 텍스트나 fixture 세트를 편집한다면, 해시가 달라지고 이 게이트는 작동을 멈춥니다. 스펙 검토(Spec review)는 다른 대기열입니다.
단계
1. 트리를 분리하세요
부모와 패치를 서로 다른 worktree에서 실행하십시오. 메모리로부터 부모 결과를 재구성하는 것은 기준선이 아닙니다.
git worktree add ../parent-tree "$PARENT_SHA"
git worktree add ../patch-tree "$PATCH_SHA"```
### 2. 시드당 하나의 JSON 객체를 내보내세요
누락된 줄은 통과가 아닌 불완전한 계약입니다. 상태는 `pass` 또는 `fail`로만 유지하십시오.
python3 run_properties.py
--tree ../parent-tree
--contract differential-contract.yaml
...
### 3. 정규화(Normalize), 축소하지 않기(do not shrink)
각 실패를 이미 신뢰하는 증인 클래스(witness class)에 매핑합니다: 속성 ID, 예외 유형, 그리고 안정적인 단언 ID입니다. 입력 최소화는 축소 게이트(shrinking gate)에 맡깁니다. 만약 클래스가 다르다면, 양쪽 모두 빨간색일 때도 패치(patch)가 새로운 실패 모드(failure mode)를 도입했음을 의미합니다.
### 4. 로컬에서 점수 매기기(Score locally)
스코어러는 두 개의 JSONL 파일과 시드 목록을 읽습니다. 그리고 결정 객체(decision object)를 작성합니다. 테스트를 수정하지 않으며, 실패하는 단언(failing assertion)을 삭제하지도 않습니다.
### 5. 사람의 검토와 만료일 요구하기(Require a human and an expiry)
`propose_freeze`는 검토 티켓입니다. 사람이 만료일과 사유 코드를 추가합니다. 만료일이 지나면 해당 티켓을 삭제해야 합니다. 다음 패치는 새로운 티켓을 획득해야만 합니다.
파일을 앞으로 복사하는 것은 프로세스 버그(process bug)이지, 갱신(renewal)이 아닙니다.
## 표 읽는 방법(How to read the table)
| Parent | Patch | Witness | Seed split | Result |
| :--- | :--- | :--- | :--- | :--- |
| pass | pass | n/a | n/a | accept, no freeze file |
| ... |
시드 분할(seed split)은 스케줄에 해당 속성에 대해 적어도 한쪽에서 `pass`와 `fail`을 모두 포함한다는 의미입니다. 균일한 빨간색(Uniform red)은 플레이크 증거가 아닙니다. 그것은 안정적인 누락(stable miss)이며, 이 경로는 안정적인 누락을 면제하지 않습니다.
하나의 회귀(regression)는 전체 패치를 거부합니다. 비록 두 번째 속성이 공유된 플레이크처럼 보일지라도 말입니다. 패치가 병합(merge)의 단위입니다. 부분 점수(Partial credit)를 부여하면, 실제 문제가 관련 없는 노이즈 체크 옆에 자리 잡고 지나갈 수 있게 됩니다.
## 참조 스코어러(Reference scorer)
이 모듈은 참조 구현체(reference implementation)입니다. 신뢰하기 전에 직접 실행해 보세요. 이것은 프로덕션 카운트의 보고서가 아니며, 원격 모델을 호출하지도 않습니다.
#!/usr/bin/env python3
"""Score parent vs patch property runs. Unexecuted until you run it."""
...
### 브랜치를 실행하는 명령어(Commands that exercise the branches)
회귀 사례입니다. 부모 라인(parent line)은 녹색이고, 패치 라인(patch line)은 빨간색입니다. 이 브랜치들을 읽으면 해당 쌍이 `regression`을 선택합니다.
Shared variant case.
Seed 11은 양쪽 모두에서 동일한 witness로 실패합니다. Seed 29는 parent에서는 통과하고 patch에서는 실패합니다. 이는 분기(split)이므로, 함수가 `propose_freeze`를 내보낼 수 있습니다. 이 파일은 여전히 제안(proposal)입니다.
cat > parent.jsonl <<'EOF'
{"prop":"prop.order_total_non_negative","seed":11,"status":"fail","witness":"AssertionError:total"}
{"prop":"prop.order_total_non_negative","seed":29,"status":"pass","witness":""}
...
색상에 대해 논쟁하기 전에 라인 수를 세십시오. 이러한 카운트를 보여줄 수 없는 검토 노트는 불완전합니다.
python3 - <<'PY'
import json
from collections import Counter
...
## 카운트가 의미할 수 있는 것들
측정하지 않은 flake rate(불안정 비율)이 아니라 객체 카운트를 게시하십시오. 2개의 시드 중 2개가 실패하는 것은 이 계약 하에서 균일한 실패입니다. 이는 전체 스위트의 flake rate가 아니며, 다른 속성에 대한 증거도 아닙니다.
스케줄을 늘리거나, 계약 내의 `seeds`를 변경하고 두 트리를 다시 실행하십시오. 녹색(green)이 나타날 때까지 patch-only 재실행을 추가하는 것은 측정(measurement)이 아니라 선택(selection)입니다.
해결된 parent 실패는 이 함수가 수행하지 않는 2차 검토가 필요합니다. `parent_fail_cleared`는 freeze를 열지 말라는 의미입니다. 이것이 patch가 oracle을 보존했다는 것을 의미하지는 않습니다. 만약 diff가 bound, comparator 또는 fixture를 수정한다면, 테이블이 수락(accept)한다고 하더라도 spec review로 보내야 합니다.
## Free model drafts, free server runs, local score
공개: 이 문서는 MonkeyCode의 제품 홍보의 일환으로 준비되었습니다.
게이트(gate)를 통과하기 전에 MonkeyCode의 무료 모델 액세스를 초안 작성 보조 도구로 사용하세요. 패치 요약에서 후보 속성(candidate properties)을 요청한 다음, 자신이 강제할 의사가 있는 오라클(oracle)이 될 때까지 해당 텍스트를 편집하세요. 편집된 사양(spec)을 커밋하세요. 스코어러는 모델 레이블을 입력으로 절대 받지 않습니다.
빨간색 로그의 타이밍 노이즈가 부모 패스(parent pass)를 무효화할 수 있다는 단락은 없습니다.
무료 서버 옵션은 로컬 CPU가 제약 사항일 때, 2단계의 용량으로만 사용하세요. 작업 사양(job spec)에는 `parent_sha`, `patch_sha`, `spec_hash`, `fixture_closure_hash` 및 시드 목록이 포함되어야 하며, JSONL 파일 두 개를 모두 반환해야 합니다. 이 문서에 있는 모듈을 사용하여 자신이 제어하는 머신에서 해당 파일을 스코어하세요. 비어 있거나, 부분적이거나, 제출하지 않은 계약 해시(contract hash)와 연결된 응답은 폐기하세요.
전송 성공(transport success)은 테스트 결과가 아닙니다.
이 메모는 모델 이름, 할당량(quotas), 하드웨어 크기 또는 종료 날짜를 명시하지 않습니다. 무료 액세스와 무료 서버는 운영자가 제공하는 옵션이며, 주어진 날에 둘 중 하나가 없을 수 있습니다. 만약 그것들이 없다면, 같은 계약을 다른 곳에서 실행하세요. 이 표는 장애에 맞추어 완화되지 않습니다.
클래시파이어(classifier)는 검토하는 저장소에 유지하고, 원격 실행은 대체 가능한 워커로 취급하세요.
## 제한 사항
짧은 스케줄은 희귀한 부모 실패를 놓칠 수 있습니다. 그러면 게이트는 공유되었을 수도 있는 패치 실패에 대해 `regression`을 보고합니다. 이 잘못된 차단(false block)이 보수적인 오류이며, 이는 허용됩니다. 반대로 실제 장애를 무시하는 오류는 허용되지 않습니다.
차단을 해제하기 위해 부모 실행을 제거하지 마세요.
증인 동등성(witness equality)은 정규화기(normalizer)만큼만 날카롭습니다. 타임스탬프, 메모리 주소 및 임시 경로가 하나의 실패를 여러 클래스로 분할하고 `witness_mismatch`를 강제합니다. 먼저 해당 필드들을 제거하세요.
공유 외부 서비스는 두 트리에 모두에서 실패하여 공유 변형(shared variant)처럼 보일 수 있습니다. 속성이 네트워크, 자신이 제어하지 않는 클럭 또는 다른 팀의 스테이징 호스트를 호출하는 경우, 이 게이트를 사용하지 마세요. 격리된 픽스처(Hermetic fixtures)는 각주가 아니라 전제 조건입니다.
해당 함수는 커버리지(coverage)도 무시합니다. 패치(patch)가 호출 지점(call site)을 삭제하더라도 더 이상 위험한 분기(risky branch)를 실행하지 않는 속성(property)에 대해 여전히 `both_pass`로 표시될 수 있습니다. 코드베이스에서 해당 위험이 중요하다면, 이 표와 커버리지 또는 뮤테이션 체크(mutation check)를 함께 사용하십시오. 본 문서는 그 두 번째 검사를 제공하지 않습니다.
## 누가 건너뛰어야 하는가 (Who should skip it)
생성된 테스트의 첫 임포트(import)처럼 부모 커밋(parent commit)이 없는 경우 게이트(gate)를 건너뜁니다. 차이를 비교할 기준선(baseline)이 없습니다. 스펙 해시(spec hash) 또는 피처 클로저 해시(fixture closure hash)가 변경되었을 때도 건너뜁니다.
안정적인 증인 클래스(stable witness class)로 축소되지 않는 스크린샷 및 픽셀 테스트의 실패에 대해서는 건너뜁니다. 병합 봇(merge bot)이 프리즈 파일(freeze file)을 자동 재정의(automatic override)로 취급하는 경우에도 건너뜁니다. 이 설계는 그러한 워크플로우를 거부합니다.
또한 JSONL 파일을 저장할 수 없는 경우에도 건너뜁니다. 부모가 실패했다는 산문 주석(prose comment)은 대체재가 될 수 없습니다. 파일이 없으면 나중에 읽는 사람이 결합(conjunction)을 감사할 수 없으므로, 해당 제안은 무효입니다.
## 검토 노트 (Review note), 네 줄
계약 해시(contract hash), 최상위 결정(top-level decision), 속성별 이유 코드(per-property reason codes), 그리고 JSONL 라인 수(JSONL line counts)를 저장해야 합니다. 이 네 줄이 증거 패킷입니다. 만약 어떤 줄이라도 누락된다면, 플레이크 레이블(flake label)의 강점만으로 병합해서는 안 됩니다.
부모 트리(parent tree)가 제어(control)이고, 패치 트리(patch tree)가 처리(treatment)입니다. 프리즈는 공유된 변형 실패에 대한 시간 제한이 걸린 티켓이지, 제어가 결코 보여주지 않은 회귀(regression)에 대한 음소거 버튼(mute button)이 아닙니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기