Skip to content

feat: Metal/CUDA GPU 전사와 Rust 오디오 백엔드 도입#250

Open
seonghobae wants to merge 63 commits into
mainfrom
feat/gpu-transcription-rust-backend
Open

feat: Metal/CUDA GPU 전사와 Rust 오디오 백엔드 도입#250
seonghobae wants to merge 63 commits into
mainfrom
feat/gpu-transcription-rust-backend

Conversation

@seonghobae

@seonghobae seonghobae commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

변경 사항

  • 전체 SHA-256, 최초 녹음 시각 증거, 알려진 장소, Sony TMK 마커를 보존하는 오디오 라이브러리 manifest를 추가했습니다.

  • YYYY-MM-DD_HH-MM-SS__장소?__전사설명__sha256-12.ext 이름과 복구 가능한 exact-duplicate quarantine 계획을 생성합니다.

  • Python API는 Apple MLX/Metal 또는 faster-whisper CUDA만 사용하며 Ollama와 CPU fallback을 사용하지 않습니다.

  • Rust backend가 병렬 inventory, 1 MiB bounded-buffer SHA-256, TMK 해석, dataless 단일-pass staging, 네이티브 iCloud eviction, 경로 검증, rollback 가능한 rename/quarantine를 담당합니다.

  • iCloud 원본은 시스템 scratch에 한 파일만 staging하며 같은 스트림에서 SHA-256을 계산합니다. 알려진 해시가 달라지면 전사를 중단합니다.

  • macOS dataless 파일은 Foundation FileManager.startDownloadingUbiquitousItem으로 다운로드를 요청하고 NSFileCoordinator accessor 안에서 copy-and-hash하여 현재 File Provider 요청을 유지합니다. 이미 local인 파일은 조정 오버헤드 없는 direct fast path를 사용합니다.

  • 전사와 inventory checkpoint가 durable해진 뒤 Rust evict 명령이 FileManager.evictUbiquitousItem으로 local block을 해제합니다. brctl download/brctl evict에 의존하지 않으며, 선택적 eviction 오류는 전사 실패와 분리해 기록합니다.

  • File Provider가 논리 크기만 노출하고 짧은/빈 EOF를 반환하면 Rust가 STAGE_SOURCE_NOT_READY로 거부하고, Python이 바이트 진행이 있는 동안만 bounded 재시도합니다.

  • 기본 greedy decoding과 opt-in --word-timestamps를 제공하고, 0.5초 미만 WAV는 모델 호출 없이 품질 플래그를 남깁니다.

  • 긴 전사는 전체 trusted segment의 주제 밀도로 대표 설명을 추출합니다. 주제 점수는 유지하면서 출력 전용 한국어 군더더기를 제거하고 핵심어를 6개로 제한하며, 이미 유효한 시각·장소·SHA 표준명은 이후 휴리스틱 변경에도 보존합니다.

  • Rust 장소 추론은 한국 주소 단위 뒤의 숫자·공백·구두점·문자열 끝 경계를 요구해 배동오 같은 연락처 이름의 부분 문자열을 장소로 오인하지 않습니다.

  • --prefetch-workers--prefetch-max-bytes는 총 staging 바이트를 제한하면서 worker 슬롯을 계속 재충전하는 rolling queue를 구성합니다. 선택 순서상 다음 파일이 준비되면 단일 GPU 전사를 즉시 시작해 남은 Rust stage와 중첩하고, 실제 중첩 횟수를 prefetch_transcription_overlaps로 기록합니다. bounded pool 밖 순차 stage는 기존 future 종료를 기다리며, native eviction도 진행 중 prefetch가 있으면 뒤로 미뤄 FileProvider 경합을 막습니다. 첫 직렬 timeout canary도 실패하면 같은 배치의 나머지 장시간 fallback은 억제합니다.

  • 실 iCloud 최초 바이트 지연 210초를 근거로 --stage-stall-timeout-seconds 기본값을 120초에서 420초로 높여 정상 다운로드의 오탐 실패를 방지합니다.

  • 병렬 prefetch가 TimeoutExpired로 끝나면 해당 항목만 직렬 staging으로 한 번 재시도하고, 일반 오류는 재시도하지 않습니다. run summary에 fallback 시도·회복 건수를 남깁니다.

  • Strix가 지적한 12개 경계를 보강했습니다. SHA·manifest·mutation 경로를 Python과 Rust 양쪽에서 검증하고, 비상주 파일의 이전 SHA는 미검증 힌트로만 취급하며, 전사 캐시·계획 전에 현재 바이트를 다시 inspect/stage합니다. 상태·전사 파일은 소유자 전용 권한과 검증된 부모 디렉터리 FD 상대 생성·교체로 기록해 symlink TOCTOU를 차단하고, staging cleanup은 디렉터리 FD와 no-follow 검사로 제한하며, backend/ffprobe는 명시적 또는 고정 절대 경로만 허용합니다. stall 재시도에는 독립적인 총 실행 상한도 적용합니다.

  • 전사 후 별도 describe 단계가 고정 리비전 mlx-community/gemma-4-e2b-it-4bit@238767527555cb75a05732a84dff5d6ba0dd6809를 MLX-VLM Python API로 한 번 로드해 파일명 주제를 생성합니다. 전사 원문은 프롬프트 지시로 신뢰하지 않고, 정보 밀도 기반 구간 선택·형식/범용어 품질 게이트·1회 교정 후 SHA sidecar에 캐시합니다. Ollama와 hosted inference 업로드는 사용하지 않습니다.

  • 재현 가능한 wheel 설치를 위해 mlx-vlm==0.6.4를 고정하고, 아직 PyPI에 배포되지 않은 공식 Gemma 4 오디오 가중치 배치 수정(PR #931)을 Codec Carver 런타임에서 좁게 backport합니다.

  • 최신 Strix 7건을 반영해 backend/ffprobe 실행 파일 allowlist·소유권·권한·SHA256 고정, 현재 inventory 기반 mutation 작업 재계산, Rust의 모든 audio/TMK 원본 실행 직전 재해시, journal SHA의 미검증 힌트 처리, Gemma 모델·revision allowlist와 tokenizer remote-code 차단, JSON prompt encoding과 전사 용어 grounding을 적용했습니다.

  • c81daee Strix가 새로 재현한 두 경계도 f414192에서 차단했습니다. Python은 backend가 반환한 scratch 경로를 직접 신뢰하지 않고 owner-only 디렉터리 FD에서 O_NOFOLLOW로 연 동일 파일의 실제 크기·SHA-256을 다시 계산해 GPU/TMK 전달 전에 backend·inventory 값과 대조합니다. Rust mutation은 루트 FD 배타 잠금, openat/mkdirat no-follow 순회, macOS renameatx_np(RENAME_EXCL)/Linux renameat2(RENAME_NOREPLACE)와 동일 방식 rollback으로 교체했습니다.

  • Gemma 파일명 생성은 중심 사상·결론·신뢰도·근거 segment ID를 먼저 검증한 뒤 별도 title pass를 수행합니다. 일반어 나열과 low-confidence 결과는 보류하고, 이전 keyword-only 캐시는 자동 승격하지 않습니다. 의미 분석이 명시적으로 실패한 녹음은 실패 이유를 checkpoint하고 keyword fallback으로 개명하지 않습니다.

  • hydrate-tmk --path를 반복 지정해 현재 bounded audio batch와 연결된 TMK만 current-byte SHA-256으로 재검증할 수 있습니다.

근거 자료

  • Whisper 논문 PDF docs/papers/2212.04356-whisper.pdf (SHA-256 6337bde031b2f237547a977b022f831169a7e05b4d9047f29501166d83594566)
  • NIST FIPS 180-4 PDF docs/standards/NIST.FIPS.180-4.pdf (SHA-256 0455b406d89648d20cbde375561e19c245b9815e894164c2670772e3d54deb82)
  • Git LFS는 사용하지 않았습니다.

검증

  • 로컬 Python 전체 회귀: pytest 543 passed, 39 subtests passed
  • 신규 audio_library.py: statement/branch coverage 100% (1,975 statements, 714 branches; audio_library 전용 테스트 80개)
  • 고정 Gemma 4 revision을 tokenizer trust_remote_code=False로 실제 MLX/Metal 로드했습니다. v5 회귀 검증은 중심 사상과 구체적 목적을 함께 요구합니다. 인용 근거의 명시적 목적을 일반적인 프로젝트 추진으로 축약한 결과와 목적이 빠진 제목은 거부하고, 전사 원문에 있는 대상·목적만으로 구성된 제목만 허용합니다.
  • batch CLI는 파일 실패가 있으면 JSON checkpoint를 보존하면서 process status 1 반환
  • cargo test --all-targets: macOS 18 passed; Linux 17 passed
  • Rust llvm-cov: lines 100%, functions 100% (macOS regions 97.92%, Linux regions 97.82%, 누락 라인 0)
  • cargo clippy --all-targets --all-features --locked -- -D warnings: passed
  • cargo build --release --locked: passed
  • Linux target dependency graph에서 macOS 전용 objc2 제외 확인
  • 변경 Python Ruff check/format 및 git diff --check: passed
  • Apple M1 실파일: 816.593초 녹음을 MLX large-v3-turbo-q4 greedy 경로에서 187.689초에 전사(약 4.35x realtime), 실패 0
  • Apple M1 최초 녹음 실파일: 3,291.392초를 391.401초에 전사(약 8.41x realtime), VOC-시스템-정말-중요한-시장-고객-정보 설명 생성, 실패 0
  • 0.028912초·0.028345초·0.029초대·0.031224초·0.031270초·0.031247초·0.031338초·0.085692초·0.035057초 WAV 실파일은 too_short_for_reliable_speech로 모델 추론을 생략하고 무음-또는-전사불명으로 표준화
  • 실제 iCloud File Provider에서 NSFileCoordinatorisDownloadRequested=1, isDownloading=1을 유지해 dataless placeholder 3개를 Rust staging했으며, FileManager.evictUbiquitousItemisDownloaded=0, isDownloading=0 복귀 확인
  • 신규 실파일 SHA-256: 7a69bb842a2260b1e67a508ad4fb94a4a4179baf3a809b6f8342dca9218a17b2, 965e8c64f7d9225579dfb60e92ec6ec0dfa3692d1a474b2bfb44a6bcf580f057, 6fd0bab7669e994caac1d93b4b26ae7a81697272dde6d72bdddbc161611036cb, 9e6ddd94b1f28d0b47a8d95a4bf3dc7e42d637e4d91e20ae81ddb66d66a333e0, b59e3d9465de7a163180ab5ed1ba413144ef8c5af00df32e64eb1b09c71c2c1b, 5f066430beaa42fbb6f1971687eda36fd713570cf8f886bb3b4c32111516b35f, c01d37491bd8c9640105a72fd04bf6b1363a0535aa06502f860099fd02ba48b9, e39cdab3b1119411f201724b6c995ceb0dc385b25a6dbb12f97ca4435641c151, 76d5deec9ac7df45c7c3b927c2ccbd6a9c8ce97cf46d453812123955e17f0681, 5fa32264e7b3b254cd0d2cbe5f8bc06e5ba1407df1083edfd253886f225421ee, 75f87befd86f0330837857a063ba61a669f66efc460cf3d0a7bb54304919926f, 245d96129a709c477a211596523d320c9982962d154fd11f2a148374108a4e0e, e963800209d7e0627e9691c9cd5f799216eed1985e08cc347c270683b4475faa
  • 1,429,856바이트 dataless WAV 4개를 4-worker Rust staging으로 약 4분 내 병렬 수집하고, 고유 SHA 2개만 MLX 전사한 뒤 복제본 2개를 격리
  • 129,840,258바이트 dataless M4A 4개를 4-worker bounded prefetch로 병렬 수집했습니다. 고유 SHA 2개만 MLX 전사했고 2개는 캐시 적중했으며 실패·eviction 실패는 0입니다.
  • 장시간 실파일 성능: 2,864.917초를 239.059초(약 11.98x realtime), 6,549.461초를 596.431초(약 10.98x realtime)에 MLX 전사했습니다.
  • 이번 구간 신규 실파일 SHA-256: bee17af8d1bf08efbd2d1f025438d55cf9f8832f3813696d0e02501780a0ab6c, 9a5d759cd9655badb1702e6f641b49a78f2ca180973afee3c4369622d3336889
  • 추가 실측: 186,440,802바이트 dataless M4A 3개를 새 420초 기본 한도와 3-worker prefetch로 수집해 고유 SHA 1개를 완료하고 2개를 캐시 적중했습니다. 실패·eviction 실패는 0입니다.
  • 7,894.955초 회현동1가 음원을 783.430초(약 10.08x realtime)에 MLX 전사했습니다. SHA-256은 f8048b1a34c6c8e696cb8f9052aaa2ca23ece4e1beb890bf75fee03af7ed969f입니다.
  • FileProvider 실측: 18MB M4A 두 개의 병렬 staging은 420초 timeout이었지만 단일 직렬 staging은 회복했습니다. 2,164.203초를 189.435초(약 11.42x realtime)에 MLX 전사했고 복제본은 캐시 적중했습니다.
  • 신규 실파일 SHA-256: 772b7e7e16340709ecc9261941b2b184f090b9bbb67065c3a02f6f305d2792d1
  • 2023-11-02 WAV 쌍은 직렬 staging에서 한쪽이 두 차례 420초 timeout, 다른 쪽이 성공했습니다. 성공한 1,530.218초 음원을 96.485초(약 15.86x realtime)에 MLX 전사했고, 미확정 복제 후보는 삭제하지 않고 timeout 근거와 함께 deferred로 보존했습니다.
  • 신규 오디오 SHA-256 efaf2692b8dd32abad3c4a35f1c906389b60db5dbdc87ab4af74e0b835bc16b1, 연결 TMK SHA-256 d0a6f922aefc257a63a29a32ebd7719f4bcb127285cbdbb9dbb4322ccf49dbf3, marker 0개
  • 2023-11-23 WAV 쌍도 한쪽 경로는 두 차례 420초 timeout, 다른 쪽은 성공했습니다. 1,470.838초 음원을 148.504초(약 9.90x realtime)에 MLX 전사했고 미확정 복제 후보는 timeout 근거와 함께 deferred로 보존했습니다.
  • 신규 오디오 SHA-256 20ef777682c1d921427fec9feb1ffc0b47d1fd90ea1e96da244a12585c0c9eca, 연결 TMK SHA-256 9e3e40e2fcc230c0247d9fb19f7e1f92637720fcd5ea210be13ae8dfdef9a45d, marker 0개
  • 2023-12-26 동일 크기 M4A 3개는 첫 경로 timeout 뒤 나머지 경로가 성공·캐시 적중했습니다. 4,585.387초를 424.855초(약 10.79x realtime)에 MLX 전사했고 동일 SHA 복제본 2개를 격리했습니다.
  • 신규 오디오 SHA-256 39b5616675e8c462c7e1c812252e2eca04daf635aff5a1c67cd75bbc73aa02da
  • 2023-12-27 동일 크기 M4A 2개는 직렬 staging에서 모두 성공했습니다. 1,802.795초를 218.314초(약 8.26x realtime)에 MLX 전사했고 2025년 중첩 사본은 동일 SHA로 확인해 격리했습니다. 출력 전용 설명어 필터로 의사결정-1세대-2세대-3세대-질문-전략 표준명을 생성했습니다.
  • 신규 오디오 SHA-256 0d01d778bccdf03a392bb43b73086bc1d73ea779f10a11b5e1a7217515ae56f2
  • 2024-02-01 13:46 WAV 쌍은 48.318초를 4.644초(약 10.40x realtime)에 MLX 전사했고 동일 SHA 복제본 1개를 격리했습니다. SHA-256은 4d532655ed1cb4a725a7037b2d4a3acc52a0c694067986bcb631006e4e862eff입니다.
  • 초소형 WAV/M4A 배치에서 82개를 추가 표준화했습니다. 0.5초 미만 녹음은 GPU 모델 호출 없이 too_short_for_reliable_speech로 처리했습니다. 이 실측에서 최초 4개만 prefetch하고 후속 파일을 직렬 처리하던 병목을 확인해 bounded rolling queue와 실패 canary 회로차단기를 추가했습니다. 개선 후 16파일 실배치는 prefetched=16, 5,032,347바이트, 완료 16, 실패·fallback·eviction 실패 0으로 worker 슬롯 재충전을 실증했습니다. 추가 32파일 실배치는 prefetched=32, 29,836,883바이트였고 최초 31개 성공·Rust stage 일시 실패 1개를 단일 120초 bounded retry로 회복해 최종 32개 모두 완료했습니다. fallback·eviction 실패는 0입니다. 이어서 64MiB 상한에 맞춘 20파일 실배치는 prefetched=20, 67,092,837바이트, 완료 20, 실패·fallback·eviction 실패 0이었습니다. 다음 9파일 실배치도 prefetched=9, 59,399,603바이트, 완료 9, 실패·fallback·eviction 실패 0이었습니다. 이어진 5파일 실배치는 prefetched=5, 59,931,008바이트, 완료 5, 오류 0이었습니다. 다음 4파일 실배치는 병렬 prefetch 4개가 420초 timeout이었지만 bounded 직렬 fallback 4개가 모두 회복해 완료 4, 실패·eviction 실패 0이었습니다. 이후 4파일 실배치도 fallback 4/4 회복으로 전사 완료했고 eviction timeout 1개는 fresh inventory에서 materialized 0으로 복귀했습니다. worker=2의 2파일·44,140,052바이트 배치는 fallback 없이 완료 2였고, 다음 2파일·46,201,772바이트 배치는 1개 완료·1개 병렬/직렬 timeout 뒤 단일 재시도로 회복했습니다. 동일 크기 선유동2로 M4A 2개는 기존 SHA-256 bee17af8… canonical과 일치해 GPU 재추론 없이 캐시 적중 2건으로 확인하고 복구 가능한 exact-duplicate quarantine에 격리했습니다. 최초 녹음과 동일 SHA 727b47…양평동4가.m4a·양평동4가 3.m4a도 각각 캐시 적중 후 격리했습니다. 실패 wave에서는 첫 직렬 canary timeout 후 후속 fallback 1개를 억제해 420초 추가 지연을 막았고, 성공 wave의 주소 파일은 57-선유동2로를 표준명에 보존했습니다.
  • 1.705GB dataless 실파일의 premature empty EOF를 empty SHA로 수락하지 않고 bounded retry 후 안전 중단 확인
  • 128MiB 상한의 실배치에서 dataless 3개·108,996,673바이트를 worker=2로 수집해 prefetched=3, completed=3, failed=0을 달성했습니다. 병렬 timeout 1개는 bounded 직렬 fallback 1/1로 회복했고 57-선유동2로 주소를 표준명에 보존했습니다. 전사와 SHA-256 checkpoint는 모두 durable하며, 이 주소 파일의 선택적 iCloud eviction 1건만 FileProvider 거부로 로컬 블록이 남았습니다.
  • 동일 크기 M4A 3개·115,248,765바이트의 다음 128MiB 배치는 병렬 지연 뒤 bounded 직렬 fallback 2/2로 회복했습니다. 세 파일 모두 기존 SHA-256 39b561… 전사 캐시와 일치해 GPU 재추론 없이 cached=3, failed=0으로 확인했고 복구 가능한 quarantine에 격리했습니다. 선택적 eviction 3건은 FileProvider가 거부했지만 격리 적용 후 로컬 블록과 함께 활성 라이브러리에서 제거됐습니다.
  • 115,662,137바이트 3파일 배치는 WAV 2개를 MLX GPU로 완료했고 주소 M4A 1개는 병렬·직렬 stage 모두 420초 제한을 넘어 원본 그대로 보류했습니다. 성공 WAV는 2라운드무음-또는-전사불명 설명으로 표준화했고 completed=2, failed=1의 부분 성공 checkpoint를 보존했습니다.
  • 128MiB를 거의 채운 WAV 3개·133,775,240바이트 배치는 bounded 직렬 fallback 2/2로 회복해 completed=3, failed=0이었고 세 전사명을 적용했습니다. ordered pipeline 커밋 ba15043의 첫 실배치는 WAV 2개·104,421,024바이트를 fallback 2/2로 완료했습니다. 두 병렬 요청이 모두 timeout이어서 실제 prefetch_transcription_overlaps=0을 정확히 기록했고 worker 상한 밖 stage는 발생하지 않았습니다.
  • 다음 2파일·90,568,317바이트 배치도 병렬 timeout 뒤 직렬 fallback 2/2로 회복해 completed=2, failed=0, prefetch_transcription_overlaps=0을 기록했습니다. 2025-11-24_22-32-00__무음-또는-전사불명__sha256-268d0cd30c49.wav2026-05-13_10-29-06__4-2-양평동4가__이걸-배포-테스트__sha256-2fd72d14058e.m4a로 표준화했으며, 선택적 eviction 2건 실패는 durable 전사와 분리해 로컬 블록만 유지했습니다.
  • 신규 129,006,440바이트 M4A 2개 배치는 병렬 timeout 뒤 bounded 직렬 fallback 2/2로 회복해 completed=2, failed=0이었고, 선택적 eviction 1건 실패만 durable 전사와 분리해 기록했습니다. SHA-256은 04d93e2e12fb611a6ab7e334967fe2cc57414e8feb337348153db143fd1da2ae, d807e3c6c2b0c7e39d1ddb02aeca3d1788a2f37f0da47dfd93973b6bec27c328입니다.
  • Gemma 4 로컬 Metal 설명으로 공정설비-데이터연동-분석기법-GPT, 비정형데이터분해-시장영향분석-화학공정이해-솔루션개발을 생성하고 각각 녹음시각·장소·SHA 결합 표준명으로 dry-run 후 적용했습니다.
  • 2023-11-01 09:17 WAV 쌍(각 222,432,148바이트)은 첫 경로가 420초 timeout이었고 대체 경로에서 1,260.93초 음원을 MLX GPU로 전사했습니다. 실제 SHA-256은 88c29225ce2f6a1acaca499958c7d5b23b79d09638d4ada896989a6e4bbc43d5입니다. 전사 품질로 중심 사상과 결론을 신뢰할 수 없어 Gemma 제목 검증이 실패했고, 해당 녹음은 파일명 변경 없이 명시적 deferred 상태로 보존됩니다. 연결된 67바이트 TMK도 420초 timeout이라 이전 SHA 힌트를 검증값으로 승격하지 않았습니다.
  • 실 라이브러리 재검증(2026-07-16 13:55 KST): 오디오 468개, TMK 195개, 표준화·전사 215개, exact duplicate 0그룹, 재계획 0건, iCloud 보류 253개, materialized 11개; 복구 가능한 exact-duplicate quarantine에 SHA256 동일 복제본 총 22개 보존

중심 사상 보정 (도입 c81daee, 보안 후속 f414192)

  • 시간 버킷만 사용하던 의미 표본 추출에 문제·결정·목적 cue 예약 슬롯을 추가해 짧은 결론 발화가 긴 설명에 밀리지 않도록 했습니다.
  • OUTCOME은 구체적인 목적 또는 결정 대상을 포함해야 하며, 인용한 그래야·위해·목적·목표 절의 원문 목적어를 생략할 수 없습니다.
  • 모델 근거 ID가 부정확해도 claim 용어가 모두 덮일 때까지 검증 가능한 전사 구간을 최대 6개로 확장합니다.
  • Gemma가 동일한 무효 답을 반복하면 모델이 직접 인용한 목적 절의 원문 단어만 보존하는 결정론적 rescue를 사용합니다. 전사에 없는 단어는 여전히 제목에 들어갈 수 없습니다.
  • 기존 SHA 표준명은 기본적으로 계속 보존합니다. 검토된 한 파일만 plan --refresh-standardized-path <정확한 상대경로>로 재계획할 수 있고, apply 시 현재 원본 바이트 SHA를 다시 검증합니다.
  • 실제 SHA 04d93e2e12fb611a6ab7e334967fe2cc57414e8feb337348153db143fd1da2ae에서 키워드 나열 제목 대신 바스고도화-상품화를 도출했습니다. 근거는 표준 화면 S002, BAS 제품 화면 S005, BAS 고도화 S012, “그래야 상품화” S016입니다.
  • 해당 실파일은 현재 iCloud dataless 상태에서 420초 동안 0B로 멈춰 SHA 재검증이 불가능했으므로 오디오 rename은 실행하지 않고 deferred로 보존했습니다. 전사 sidecar의 v5 제목·근거만 안전하게 교정했습니다.
  • 로컬 검증: Python 전체 543 tests, audio_library 1,975 statements/714 branches 100%, Ruff, interrogate 100%, Rust macOS 18 tests/Linux 17 tests, Clippy, release build 통과.

안전성

  • mutation은 dry-run이 기본이며 --execute가 있어야 적용됩니다.
  • exact duplicate는 삭제 대신 .codec-carver/quarantine/exact-duplicates/로 이동합니다.
  • absolute/parent escape, symlink root escape, 기존 목적지, 중복 목적지를 거부하고 부분 실패 시 역순 rollback합니다.
  • manifest와 mutation plan의 root·inventory digest·action·상대 경로·정규 SHA-256을 Python API에서 먼저 검증하고 Rust backend에서 다시 검증합니다.
  • 이전 inventory·전사 sidecar의 SHA는 비상주 원본의 신원 증거로 신뢰하지 않으며, 실제 staging/inspect로 재검증되기 전에는 중복 격리·새 이름 변경·캐시 사용을 허용하지 않습니다.
  • .codec-carver와 transcript는 0700/0600 권한을 사용하고 상태 파일은 검증된 부모 디렉터리 FD에 상대적으로 원자 교체하며, 임시 staging은 예측 불가능한 소유자 전용 디렉터리이며 symlink component와 no-follow cleanup 경계를 검사합니다.
  • eviction 같은 선택적 저용량 정리 실패는 eviction_failures에 남기되 이미 durable한 전사를 실패로 바꾸지 않습니다.
  • iCloud 복구 또는 서비스 재시작은 자동 실행하지 않고 운영자 승인을 요구합니다.
  • 로컬 scratch 부족(가용 100MiB)은 전사·원본 삭제 없이 Rust debug·llvm-cov 생성 산출물만 Cargo clean해 6.2GiB를 확보했고 release backend를 보존했습니다.

Strix 경계 보강 (기존 6건, f414192 후속 2건)

  • GPU TOCTOU: Rust가 각 상대 경로 구성요소를 openat/O_NOFOLLOW로 열고, 같은 descriptor에서 private scratch로 copy-and-hash한 뒤 GPU에는 그 복사본만 전달합니다.
  • staged response 위조: /etc/passwd 같은 scratch 외부 경로, symlink·directory, 위조 SHA/크기, 해시 중 변경을 fail-closed로 거부하며 전사기가 호출되지 않음을 회귀 테스트로 고정했습니다.
  • mutation parent swap: validation 뒤 목적지 부모가 symlink로 교체되는 실제 경합을 재현해도 외부 디렉터리에 파일이 생성되지 않으며, 목적지 덮어쓰기와 source/parent symlink를 descriptor-relative backend가 거부합니다.
  • stale SHA mutation: 비상주·dataless 원본은 persisted SHA가 content 표식이어도 rename/quarantine 권한을 얻지 못하며, apply 직전 현재 바이트를 다시 검증합니다.
  • Gemma grounding: 근거 ID는 줄 시작의 [S###] 라벨만 인정하고, 중심 사상·결론은 인용 구간에, 최종 제목의 모든 용어는 전사 원문 자체에 존재해야 합니다. 모델이 만든 분석 문구는 제목 grounding으로 사용하지 않습니다.
  • state symlink: Rust는 inventory/apply JSON을 stdout으로 반환하고 Python만 검증된 디렉터리 FD 상대 원자 교체로 상태를 커밋합니다. Rust의 선택적 직접 출력도 create_new 임시 파일과 최종 링크 교체를 사용합니다.
  • malformed journal: 부분 JSON, 비객체, 잘못된 executed/completed schema는 recovery/malformed-journals에 복구 가능하게 격리하고 state_recovery_events를 남긴 뒤 inventory를 계속합니다.
  • 회귀 증거: 위조 S999 발화, 원문에 없는 랜섬웨어/삭제 주장, state final symlink, malformed journal 4종, staging escape/symlink/hash drift, Rust parent/final symlink를 재현하는 테스트를 추가했습니다.

최신 Strix 실행 경계 후속 (ced9653)

  • e93ced8 Strix가 재현한 Rust backend 실행 파일 TOCTOU를 차단했습니다. Python은 승인된 원본 경로를 실행 때마다 다시 여는 대신, no-follow로 연 안정된 원본 descriptor의 정확한 바이트를 독립적인 owner-only inode로 한 번 복사하면서 SHA-256을 검증하고 디렉터리를 0500으로 봉인합니다.
  • inventory, inspect, stage, evict, apply의 모든 명령은 원본 인자가 전달돼도 검증된 private snapshot으로 강제 치환됩니다. 검증과 subprocess 실행 사이에 원본 파일을 악성 파일로 os.replace하는 결정론적 PoC에서도 good snapshot만 실행됨을 회귀 테스트로 고정했습니다.
  • 실제 release Rust backend를 봉인된 임시 경로에서 실행해 빈 라이브러리 inventory 성공과 원본/실행 inode 분리를 확인했습니다. 로컬 전체 회귀는 Python 543 passed + 39 subtests, audio_library 1,975 statements/714 branches 100%, Rust 18 passed이며 Ruff, interrogate, Clippy, release build, git diff check가 통과했습니다.

최신 Strix 4건 경계 보강 (e1ece23)

  • malformed-journal recovery는 검증된 state descriptor에서 recovery/malformed-journals 각 구성요소를 mkdirat/openat O_NOFOLLOW 방식으로 생성·개방해 중간 symlink의 외부 경로 이탈을 차단합니다.
  • transcript 읽기와 SHA hint 열거는 검증된 transcript directory descriptor와 final-name O_NOFOLLOW를 사용합니다. symlink·directory·손상 JSON·비객체·SHA 불일치는 외부 입력이나 복원 근거가 되지 않습니다.
  • MLX 경로는 승인된 절대 ffmpeg로 16kHz mono PCM을 한 번 디코드해 in-memory waveform을 mlx-whisper에 전달하므로 dependency가 caller PATH의 bare ffmpeg를 실행하지 않습니다.
  • Rust, ffprobe, ffmpeg 명시적 subprocess는 최소 allowlist 환경만 받아 LD_·DYLD_ loader injection 변수를 상속하지 않습니다.
  • Apple M1 실파일 218.961초를 승인 ffmpeg 디코드 4.507초, MLX large-v3-turbo-q4 전체 전사 25.219초(약 8.68x realtime)에 처리했습니다. hostile PATH/LD_PRELOAD/DYLD 주입 상태에서도 명시적 ffmpeg와 Rust inventory 경계가 고정됨을 확인했습니다.
  • 로컬 전체 회귀: Python 543 passed + 39 subtests, audio_library 1,975 statements/714 branches 100% (전용 80 tests), Rust 18 passed, Ruff·interrogate·Clippy·release build·git diff check 통과.

최신 Strix 7건 경계 보강 (eee0c47)

  • private state 경로는 루트 descriptor에서 모든 구성요소를 mkdirat/openat, O_DIRECTORY, O_NOFOLLOW로 순회해 중간 ancestor symlink 교체가 외부 쓰기로 이어지지 않습니다.
  • staged audio는 owner·regular file·단일 hardlink·이름과 inode 일치를 확인한 직후 이름을 제거합니다. SHA-256과 실제 크기는 외부에서 새로 열 수 없는 anonymous inode에서 검증하고, ffmpeg와 CUDA도 동일 열린 descriptor를 소비하며 inference 뒤 dev/inode/size/mtime/ctime/nlink를 재검증합니다. 외부 동일 사용자 파일의 hardlink와 검증 후 pathname 교체 PoC를 모두 차단했습니다.
  • Whisper 입력 모델은 MLX mlx-community/whisper-large-v3-turbo-q4@660c343bbf4e52ac257f0b7d952e5388e6f93bef 및 CUDA dropbox-dash/faster-whisper-large-v3-turbo@0a363e9161cbc7ed1431c9597a8ceaf0c4f78fcf만 허용합니다. huggingface-hub는 직접 고정 dependency이며 arbitrary repository와 mutable revision을 거부합니다.
  • inventory의 audio tmk_path는 kind=tmk record만 가리킬 수 있고 TMK record는 다시 tmk_path를 가질 수 없습니다. crafted audio-to-audio sidecar 관계가 canonical audio quarantine을 승인하지 못합니다.
  • Whisper segment 내부 CR/LF를 label 부여 전에 평탄화하고 근거 label을 S001부터 연속된 전체 행으로만 인정해 S999 주입을 차단했습니다. 제목 grounding은 source token 경계를 보존하며, 영어 임의 prefix나 alpha beta의 lphab 같은 cross-token substring을 허용하지 않습니다. 한국어 어미 prefix만 보수적으로 허용합니다.
  • 로컬 최신 회귀: Python 전체 546 tests 통과, audio_library 전용 83 tests, audio_library.py 2,082 statements/746 branches 100%, Ruff format/check, interrogate 100%, py_compile, dependency check, git diff check 통과. Rust 18 tests, Clippy -D warnings, release build 통과.
  • Apple M1 descriptor-bound 실파일 검증: GPU 호출 전에 staged pathname이 제거된 상태에서 SHA-256 4420fcdf34d3d10e82e845b61335d23bfbb479e9e2ce4504ddc3bc997bb24609와 고정 MLX revision을 확인했고, 218.961초 음원을 26.967초(약 8.12x realtime)에 전사했습니다.

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 884f6b20c8cab6df236c9ab0ea8e6f4933f8e456.

  • Head SHA: 884f6b20c8cab6df236c9ab0ea8e6f4933f8e456

  • Workflow run: 29396826480

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (9 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (9 files)"]
  R1 --> V1["required checks"]
  Evidence --> S2["Docs (3 files)"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs (3 files)"]
  R2 --> V2["docs review"]
  Evidence --> S3["Test: test_audio_library.py"]
  S3 --> I3["regression suite"]
  I3 --> R3["Review risk: Test: test_audio_library.py"]
  R3 --> V3["targeted test run"]
Loading

@opencode-agent

opencode-agent Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

  • Head SHA: 4ffe820524640c84f904d93900a735cd21e61375
  • Workflow run: 29676953842
  • Workflow attempt: 1
  • Gate result: REQUEST_CHANGES (approval step)

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 4ffe820524640c84f904d93900a735cd21e61375.

  • Head SHA: 4ffe820524640c84f904d93900a735cd21e61375

  • Workflow run: 29676953842

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (11 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (11 files)"]
  R1 --> V1["required checks"]
  Evidence --> S2["Docs (3 files)"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs (3 files)"]
  R2 --> V2["docs review"]
  Evidence --> S3["Test (2 files)"]
  S3 --> I3["regression suite"]
  I3 --> R3["Review risk: Test (2 files)"]
  R3 --> V3["targeted test run"]
Loading

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 4564c23998e315816ad4231525c6730e471bdef8.

  • Head SHA: 4564c23998e315816ad4231525c6730e471bdef8

  • Workflow run: 29413351250

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (9 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (9 files)"]
  R1 --> V1["required checks"]
  Evidence --> S2["Docs (3 files)"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs (3 files)"]
  R2 --> V2["docs review"]
  Evidence --> S3["Test: test_audio_library.py"]
  S3 --> I3["regression suite"]
  I3 --> R3["Review risk: Test: test_audio_library.py"]
  R3 --> V3["targeted test run"]
Loading

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head a7ea0fe9c15bab681a79deb37f486d745acacb15.

  • Head SHA: a7ea0fe9c15bab681a79deb37f486d745acacb15

  • Workflow run: 29423253758

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (9 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (9 files)"]
  R1 --> V1["required checks"]
  Evidence --> S2["Docs (3 files)"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs (3 files)"]
  R2 --> V2["docs review"]
  Evidence --> S3["Test: test_audio_library.py"]
  S3 --> I3["regression suite"]
  I3 --> R3["Review risk: Test: test_audio_library.py"]
  R3 --> V3["targeted test run"]
Loading

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

OpenCode could not approve from deterministic current-head evidence because GitHub Checks have failed.

Findings

1. HIGH Current-head GitHub Checks - Fix failed required checks before approval

  • Problem: Failed same-head checks remain for ba150431ce2c0ba0c5f6678c90d8820dad0739cd.
  • Root cause: The model-unavailable evidence fallback is allowed only when peer GitHub Checks are complete and clean.
  • Fix: Read and fix the failed check logs below, then rerun the current-head checks.
  • Regression test: Keep the model-unavailable fallback gated on an empty failed-check rollup.

Failed checks:

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (9 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (9 files)"]
  R1 --> V1["required checks"]
  Evidence --> S2["Docs (3 files)"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs (3 files)"]
  R2 --> V2["docs review"]
  Evidence --> S3["Test: test_audio_library.py"]
  S3 --> I3["regression suite"]
  I3 --> R3["Review risk: Test: test_audio_library.py"]
  R3 --> V3["targeted test run"]
Loading

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head c5b3e127ce3067fb3701a1cd713afe3108adfd5d.

  • Head SHA: c5b3e127ce3067fb3701a1cd713afe3108adfd5d

  • Workflow run: 29468399831

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (9 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (9 files)"]
  R1 --> V1["required checks"]
  Evidence --> S2["Docs (3 files)"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs (3 files)"]
  R2 --> V2["docs review"]
  Evidence --> S3["Test: test_audio_library.py"]
  S3 --> I3["regression suite"]
  I3 --> R3["Review risk: Test: test_audio_library.py"]
  R3 --> V3["targeted test run"]
Loading

@seonghobae

Copy link
Copy Markdown
Contributor Author

Current-head local regression evidence (32b309e):

  • Fixed seekable descriptor decoding for staged M4A input and fail-closed zero-sample handling.
  • Rejected unexplained empty transcript caches so fixed decoders retry; explicitly classified genuine no-speech results.
  • A 2,315.84-second local M4A (not uploaded) now decodes identically through direct and descriptor-bound staged paths, transcribes on MLX GPU in 276.655 seconds (~8.37x real time), and yields 581 timestamped segments / 13,424 text characters.
  • tests/test_audio_library.py: 85 passed, 43 subtests passed.
  • audio_library.py: 2,109 statements, 758 branches, 100% coverage.
  • Ruff check, Ruff format check, git diff --check, Rust tests, Clippy -D warnings, and Rust release build pass locally.

Comment thread scripts/bootstrap_macos_gpu_runtime.sh Fixed

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 115848eebb66249ba69182571bee3f70cd55a596.

  • Head SHA: 115848eebb66249ba69182571bee3f70cd55a596

  • Workflow run: 29555041904

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 2

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (11 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (11 files)"]
  R1 --> V1["required checks"]
  Evidence --> S2["Docs (3 files)"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs (3 files)"]
  R2 --> V2["docs review"]
  Evidence --> S3["Test (2 files)"]
  S3 --> I3["regression suite"]
  I3 --> R3["Review risk: Test (2 files)"]
  R3 --> V3["targeted test run"]
Loading

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head ce8972691ed41fe76ffaab50648877738aa03525.

  • Head SHA: ce8972691ed41fe76ffaab50648877738aa03525

  • Workflow run: 29569755858

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 2

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (11 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (11 files)"]
  R1 --> V1["required checks"]
  Evidence --> S2["Docs (3 files)"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs (3 files)"]
  R2 --> V2["docs review"]
  Evidence --> S3["Test (2 files)"]
  S3 --> I3["regression suite"]
  I3 --> R3["Review risk: Test (2 files)"]
  R3 --> V3["targeted test run"]
Loading

@seonghobae

Copy link
Copy Markdown
Contributor Author

Current-head evidence (4ffe820524640c84f904d93900a735cd21e61375):

  • Fixed idempotent TMK metadata synchronization for already content-verified sidecars. Cached transcripts are updated without rehashing; mismatched transcript SHA-256 evidence is rejected and reported separately.
  • Real-library verification repaired FOLDER01/231113_1242(1) from stale marker metadata to 21 markers / 6300.0 seconds; a second run reported synced_transcripts: 0.
  • Python full regression: 561 tests passed. audio_library.py: 2,456 statements + 874 branches, 100% coverage. Interrogate: 100%. Ruff check/format and git diff --check: passed. Rust: 18 tests and format check passed.
  • Same-head GitHub CI (3.10/3.11/3.12), fuzz, Strix, Semgrep, Trivy, OSV, dependency review, and Scorecard are all green.
  • Fresh safety plan: 0 mutation operations; 255 unresolved items remain deferred rather than renamed/deleted without current-byte SHA-256 evidence. Active duplicate groups remain 0; exact duplicates are retained in the recoverable quarantine.

The pull request is mergeable at the Git level. Remaining CHANGES_REQUESTED state is from older-head OpenCode reviews; the central ruleset still requires current-head approvals.

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 4ffe820524640c84f904d93900a735cd21e61375.

  • Head SHA: 4ffe820524640c84f904d93900a735cd21e61375

  • Workflow run: 29676953842

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (11 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (11 files)"]
  R1 --> V1["required checks"]
  Evidence --> S2["Docs (3 files)"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs (3 files)"]
  R2 --> V2["docs review"]
  Evidence --> S3["Test (2 files)"]
  S3 --> I3["regression suite"]
  I3 --> R3["Review risk: Test (2 files)"]
  R3 --> V3["targeted test run"]
Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants